@@ -43,19 +43,42 @@ self.MonacoEnvironment = {
43
43
} ,
44
44
}
45
45
46
- const initialContent = `void ColorPass(in float r, in float g, in float b, in float p, in int width, in int height, sampler2D background, out vec4 out_color)
46
+ const initialContent = `void ColorPass(
47
+ in float r,
48
+ in float g,
49
+ in float b,
50
+ in float p,
51
+ in int width,
52
+ in int height,
53
+ sampler2D background,
54
+ sampler2D tex1,
55
+ sampler2D tex2,
56
+ out vec4 out_color
57
+ )
47
58
{{
48
59
vec2 complex_sqr(vec2 z) { return vec2(z[0] * z[0] - z[1] * z[1], z[1] * z[0] * 2.); }
49
60
void main()
50
61
{
51
62
vec2 res = vec2(width, height);
63
+ if (gl_FragCoord.x > res.x - 200.0 && gl_FragCoord.y > res.y - 200.0) {
64
+
65
+ float mult = 0.2;
66
+ vec2 rel = gl_FragCoord.xy - (res - 200.0);
67
+ vec2 checkerboard = round(fract(rel * mult));
68
+ vec4 a = texelFetch(tex1, ivec2(rel.xy), 0);
69
+ vec4 b = texelFetch(tex2, ivec2(rel.xy), 0);
70
+
71
+ out_color = mix(a, b, checkerboard.x * checkerboard.y);
72
+ return;
73
+ }
74
+
52
75
vec2 uv = gl_FragCoord.xy / res.xy;
53
76
float i = gl_FragCoord.x;
54
77
float j = gl_FragCoord.y;
55
78
vec2 s = res;
56
79
int n = int(s.x * 0.5);
57
80
vec2 c = vec2(-0.8, cos(2. * p));
58
- vec2 z = vec2(i / float(n) - 1., j / float(n) - 1.) * 2.;
81
+ vec2 z = vec2(i / float(n) - 1., j / float(n) - 1.0 ) * 2.;
59
82
int iterations = 0;
60
83
while (sqrt(dot(z, z)) < 20. && iterations < 50) {
61
84
z = complex_sqr(z) + c;
@@ -80,6 +103,16 @@ void DEBUGPassUV(in int width, in int height, out vec4 out_color)
80
103
}
81
104
}}
82
105
106
+ void TwoOutputsShader(out vec4 out_color1, out vec4 out_color2)
107
+ {{
108
+ void main()
109
+ {
110
+ out_color1 = vec4(1.0f, 0.5f, 0.0f, 1.0f);
111
+ out_color2 = vec4(0.0f, 0.5f, 1.0f, 1.0f);
112
+ }
113
+ }}
114
+
115
+
83
116
[declaration: "smoothing"]
84
117
{{
85
118
float SmoothOverTime(float val, string name, float ratio = 0.95)
@@ -109,6 +142,14 @@ void RenderGraphMain()
109
142
uvImage
110
143
);
111
144
145
+
146
+ Image img1 = GetImage(GetSwapchainImage().GetSize(), rgba16f);
147
+ Image img2 = GetImage(GetSwapchainImage().GetSize(), rgba16f);
148
+ TwoOutputsShader(
149
+ img1,
150
+ img2
151
+ );
152
+
112
153
ColorPass(
113
154
SliderFloat("R", 0.0f, 1.0f, 0.5f),
114
155
SliderFloat("G", 0.0f, 1.0f, 0.5f),
@@ -117,6 +158,8 @@ void RenderGraphMain()
117
158
sc.GetSize().x,
118
159
sc.GetSize().y,
119
160
uvImage,
161
+ img1,
162
+ img2,
120
163
sc
121
164
);
122
165
@@ -247,7 +290,10 @@ function CreateRasterProgram(
247
290
return program
248
291
}
249
292
250
- function InitWebGL ( canvas : HTMLCanvasElement ) : GPUState {
293
+ function InitWebGL (
294
+ canvas : HTMLCanvasElement ,
295
+ raiseError : RaisesErrorFN
296
+ ) : GPUState {
251
297
const options = {
252
298
premultipliedAlpha : true ,
253
299
alpha : true ,
@@ -264,6 +310,15 @@ function InitWebGL(canvas: HTMLCanvasElement): GPUState {
264
310
} )
265
311
266
312
const gl = canvas . getContext ( "webgl2" , options ) as WebGL2RenderingContext
313
+
314
+ const extensions = [ "EXT_color_buffer_float" , "EXT_color_buffer_half_float" ]
315
+ for ( const extensionName of extensions ) {
316
+ const extension = gl . getExtension ( extensionName )
317
+ if ( ! extension ) {
318
+ raiseError ( `${ extensionName } could not be loaded` )
319
+ }
320
+ }
321
+
267
322
// a reusable fbo
268
323
const fbo = gl . createFramebuffer ( )
269
324
if ( ! fbo ) {
@@ -296,7 +351,10 @@ function UpdateFramegraph(
296
351
}
297
352
298
353
for ( const desc of result . shader_descs || [ ] ) {
299
- const outputs = desc . outs . map ( ( { name, type } ) => `out ${ type } ${ name } ;\n` )
354
+ const outputs = desc . outs . map (
355
+ ( { name, type } , index ) =>
356
+ `layout(location=${ index } ) out ${ type } ${ name } ;\n`
357
+ )
300
358
const uniforms = desc . uniforms . map (
301
359
( { name, type } ) => `uniform ${ type } ${ name } ;\n`
302
360
)
@@ -342,6 +400,7 @@ function UpdateFramegraph(
342
400
samplers : desc . samplers . map ( ( { name } ) => {
343
401
return gl . getUniformLocation ( program , name )
344
402
} ) ,
403
+ fboAttachmentIds : desc . outs . map ( ( _ , i ) => gl . COLOR_ATTACHMENT0 + i ) ,
345
404
}
346
405
}
347
406
}
@@ -350,6 +409,42 @@ function RaiseError(err: string) {
350
409
console . error ( "RaiseError:" , err )
351
410
}
352
411
412
+ function AttachDragger (
413
+ dragEl : HTMLElement ,
414
+ resizeTarget : HTMLElement ,
415
+ cb : ( rect : DOMRect ) => void
416
+ ) {
417
+
418
+ const dragWidth = dragEl . getBoundingClientRect ( ) . width
419
+
420
+ let down = false
421
+ dragEl . addEventListener (
422
+ "mousedown" ,
423
+ ( e ) => {
424
+ down = true
425
+ e . preventDefault ( )
426
+ } ,
427
+ { passive : false }
428
+ )
429
+ window . addEventListener ( "mouseup" , ( _ ) => {
430
+ down = false
431
+ } )
432
+ window . addEventListener ( "mousemove" , ( e ) => {
433
+ const parentEl = dragEl . parentElement
434
+ if ( ! down || ! parentEl ) {
435
+ return
436
+ }
437
+
438
+ const parentRect = parentEl . getBoundingClientRect ( )
439
+ const parentLeft = parentRect . left
440
+ const newWidth = e . clientX - parentLeft - dragWidth / 2
441
+ resizeTarget . style . width = `${ newWidth . toFixed ( 0 ) } px`
442
+ resizeTarget . style . flexGrow = "0"
443
+ parentRect . width = newWidth
444
+ cb ( parentRect )
445
+ } )
446
+ }
447
+
353
448
function SliderControlCreate (
354
449
name : string ,
355
450
value : string ,
@@ -383,9 +478,10 @@ function SliderControlCreate(
383
478
async function Init (
384
479
editorEl : HTMLElement | null ,
385
480
canvasEl : HTMLElement | null ,
386
- controlsEl : HTMLElement | null
481
+ controlsEl : HTMLElement | null ,
482
+ draggerEl : HTMLElement | null
387
483
) {
388
- if ( ! editorEl || ! canvasEl || ! controlsEl ) {
484
+ if ( ! editorEl || ! canvasEl || ! controlsEl || ! draggerEl ) {
389
485
throw new Error ( "please provide an editor element and canvas element" )
390
486
}
391
487
@@ -396,6 +492,14 @@ async function Init(
396
492
throw new Error ( "could not initialize monaco" )
397
493
}
398
494
495
+ const editorResizeHandler = CreateEditorResizeHandler ( editor , editorEl )
496
+ window . addEventListener ( "resize" , editorResizeHandler )
497
+ editorResizeHandler ( )
498
+
499
+ AttachDragger ( draggerEl , editorEl , ( rect : DOMRect ) => {
500
+ editor . layout ( { width : rect . width , height : rect . height } )
501
+ } )
502
+
399
503
editor . focus ( )
400
504
401
505
function Control (
@@ -466,10 +570,10 @@ async function Init(
466
570
control . el . innerText = value
467
571
} ,
468
572
}
469
-
573
+
470
574
const state : State = {
471
575
editor,
472
- gpu : InitWebGL ( canvasEl as HTMLCanvasElement ) ,
576
+ gpu : InitWebGL ( canvasEl as HTMLCanvasElement , console . error ) ,
473
577
framegraph : {
474
578
passes : { } ,
475
579
} ,
@@ -557,7 +661,6 @@ function ExecuteFrame(dt: number, state: State) {
557
661
558
662
const gpu = state . gpu
559
663
560
- // TODO: fix this, position:relative causes pain w.r.t. flexbox
561
664
// Ensure we're sized properly w.r.t. pixel ratio
562
665
const rect = gpu . container . getBoundingClientRect ( )
563
666
if ( gpu . dims [ 0 ] !== rect . width || gpu . dims [ 1 ] !== rect . height ) {
@@ -711,18 +814,23 @@ function ExecuteFrame(dt: number, state: State) {
711
814
} else {
712
815
// TODO: bind more than one output
713
816
gl . bindFramebuffer ( gl . FRAMEBUFFER , state . gpu . fbo )
714
- const target = ImageCacheGetImage (
715
- state . imageCache ,
716
- invocation . color_attachments [ 0 ] . id
717
- )
718
- gl . framebufferTexture2D (
719
- gl . FRAMEBUFFER ,
720
- // TODO: MRT
721
- gl . COLOR_ATTACHMENT0 ,
722
- gl . TEXTURE_2D ,
723
- target ,
724
- 0
725
- )
817
+ for (
818
+ let attachmentIndex = 0 ;
819
+ attachmentIndex < invocation . color_attachments . length ;
820
+ attachmentIndex ++
821
+ ) {
822
+ const attachment = invocation . color_attachments [ attachmentIndex ]
823
+ const target = ImageCacheGetImage ( state . imageCache , attachment . id )
824
+ gl . framebufferTexture2D (
825
+ gl . FRAMEBUFFER ,
826
+ pass . fboAttachmentIds [ attachmentIndex ] ,
827
+ gl . TEXTURE_2D ,
828
+ target ,
829
+ 0
830
+ )
831
+ }
832
+ // TODO: handle framebuffer completeness
833
+ gl . drawBuffers ( pass . fboAttachmentIds )
726
834
}
727
835
728
836
gl . viewport ( 0 , 0 , gpu . canvas . width , gpu . canvas . height )
@@ -747,16 +855,30 @@ function InitEditor(editorEl: HTMLElement) {
747
855
enabled : false ,
748
856
} ,
749
857
tabSize : 2 ,
750
- automaticLayout : true ,
858
+ automaticLayout : false ,
751
859
theme : "vs-dark" ,
752
- glyphMargin : true ,
860
+ glyphMargin : false ,
753
861
} )
754
862
755
863
return editor
756
864
}
757
865
866
+ function CreateEditorResizeHandler (
867
+ editor : monaco . editor . IStandaloneCodeEditor ,
868
+ editorEl : HTMLElement
869
+ ) {
870
+ return ( ) => {
871
+ // editor.layout({ width: 0, height: 0 })
872
+ window . requestAnimationFrame ( ( ) => {
873
+ const { width, height } = editorEl . getBoundingClientRect ( )
874
+ editor . layout ( { width, height } )
875
+ } )
876
+ }
877
+ }
878
+
758
879
Init (
759
880
document . querySelector ( "#editor" ) ,
760
881
document . querySelector ( "output canvas" ) ,
761
- document . querySelector ( "controls" )
882
+ document . querySelector ( "controls" ) ,
883
+ document . querySelector ( "divider" )
762
884
)
0 commit comments