@@ -251,18 +251,20 @@ type
251
251
source* : string
252
252
setupProc* : proc (cc: CompiledComposition )
253
253
mainProcName* : string
254
+ seenFlag: bool # Used on compilation phase, should not be used elsewhere.
254
255
id* : int
255
256
256
257
CompiledComposition = ref object
257
258
program* : ProgramRef
258
- uniformLocations: seq [UniformLocation ]
259
+ uniformLocations* : seq [UniformLocation ]
259
260
iTexIndex* : GLint
260
261
iUniform* : int
261
262
262
263
var programCache = initTable [Hash , CompiledComposition ]()
263
264
264
265
type Composition * = object
265
266
definition: string
267
+ vsDefinition: string # Vertex shader source code
266
268
requiresPrequel: bool
267
269
id* : int
268
270
@@ -311,19 +313,27 @@ proc newPostEffect*(definition: static[string], mainProcName: string): PostEffec
311
313
result .mainProcName = mainProcName
312
314
result .id = hash (preprocessedDefinition)
313
315
314
- proc newComposition * (definition : static [string ], requiresPrequel: bool = true ): Composition =
315
- const preprocessedDefinition = preprocessDefinition (definition )
316
+ proc newComposition * (vsDef, fsDef : static [string ], requiresPrequel: bool = true ): Composition =
317
+ const preprocessedDefinition = preprocessDefinition (fsDef )
316
318
result .definition = preprocessedDefinition
319
+ result .vsDefinition = vsDef
317
320
result .requiresPrequel = requiresPrequel
318
321
result .id = hash (preprocessedDefinition)
319
322
323
+ template newComposition * (definition: static [string ], requiresPrequel: bool = true ): Composition =
324
+ newComposition (nil , definition, requiresPrequel)
325
+
320
326
template newCompositionWithNimsl * (mainProc: typed ): Composition =
321
327
newComposition (getGLSLFragmentShader (mainProc, " compose" ), false )
322
328
323
- var postEffectStack = newSeq [PostEffect ]()
329
+ type PostEffectStackElem = object
330
+ postEffect: PostEffect
331
+ setupProc* : proc (cc: CompiledComposition )
332
+
333
+ var postEffectStack = newSeq [PostEffectStackElem ]()
324
334
var postEffectIdStack = newSeq [Hash ]()
325
335
326
- proc compileComposition * (gl: GL , comp: var Composition , cchash: Hash ): CompiledComposition =
336
+ proc compileComposition * (gl: GL , comp: Composition , cchash: Hash ): CompiledComposition =
327
337
var fragmentShaderCode = " "
328
338
if comp.requiresPrequel:
329
339
fragmentShaderCode = """
@@ -342,18 +352,29 @@ uniform vec4 bounds;
342
352
343
353
fragmentShaderCode &= comp.definition
344
354
345
- for pe in postEffectStack:
346
- fragmentShaderCode &= pe.source
355
+ let ln = postEffectStack.len
356
+ var i = 0
357
+ while i < ln:
358
+ let pe = postEffectStack[i].postEffect
359
+ if not pe.seenFlag:
360
+ fragmentShaderCode &= pe.source
361
+ pe.seenFlag = true
362
+ inc i
363
+
364
+ i = 0
365
+ while i < ln:
366
+ postEffectStack[i].postEffect.seenFlag = false
367
+ inc i
347
368
348
369
fragmentShaderCode &= """ void main() { gl_FragColor = vec4(0.0); compose(); """
349
- var i = postEffectStack.len - 1
370
+ i = postEffectStack.len - 1
350
371
while i >= 0 :
351
- fragmentShaderCode &= postEffectStack[i].mainProcName & " ();"
372
+ fragmentShaderCode &= postEffectStack[i].postEffect. mainProcName & " ();"
352
373
dec i
353
374
fragmentShaderCode &= " }"
354
375
355
376
result .new ()
356
- result .program = gl.newShaderProgram (vertexShaderCode, fragmentShaderCode, [(posAttr, " aPosition" )])
377
+ result .program = gl.newShaderProgram (if comp.vsDefinition.isNil: vertexShaderCode else : comp.vsDefinition , fragmentShaderCode, [(posAttr, " aPosition" )])
357
378
result .uniformLocations = newSeq [UniformLocation ]()
358
379
programCache[cchash] = result
359
380
@@ -368,7 +389,7 @@ proc unwrapPointArray(a: openarray[Point]): seq[GLfloat] =
368
389
369
390
var texQuad : array [4 , GLfloat ]
370
391
371
- template compositionDrawingDefinitions (cc: CompiledComposition , ctx: GraphicsContext , gl: GL ) =
392
+ template compositionDrawingDefinitions * (cc: CompiledComposition , ctx: GraphicsContext , gl: GL ) =
372
393
template uniformLocation (name: string ): UniformLocation =
373
394
inc cc.iUniform
374
395
if cc.uniformLocations.len - 1 < cc.iUniform:
@@ -407,29 +428,38 @@ template compositionDrawingDefinitions(cc: CompiledComposition, ctx: GraphicsCon
407
428
inc cc.iTexIndex
408
429
409
430
template pushPostEffect * (pe: PostEffect , body: untyped ) =
410
- pe.setupProc = proc (cc: CompiledComposition ) =
431
+ postEffectStack. add ( PostEffectStackElem (postEffect: pe, setupProc: proc (cc: CompiledComposition ) =
411
432
let ctx = currentContext ()
412
433
let gl = ctx.gl
413
434
compositionDrawingDefinitions (cc, ctx, gl)
414
435
body
436
+ ))
415
437
416
- postEffectStack.add (pe)
417
438
let oh = if postEffectIdStack.len > 0 : postEffectIdStack[^ 1 ] else : 0
418
439
postEffectIdStack.add (oh !& pe.id)
419
440
420
441
template popPostEffect * () =
421
442
postEffectStack.setLen (postEffectStack.len - 1 )
422
443
postEffectIdStack.setLen (postEffectIdStack.len - 1 )
423
444
424
- template draw * (comp: var Composition , r: Rect , code: untyped ): stmt =
425
- let ctx = currentContext ()
426
- let gl = ctx.gl
445
+ template getCompiledComposition * (gl: GL , comp: Composition ): CompiledComposition =
427
446
let pehash = if postEffectIdStack.len > 0 : postEffectIdStack[^ 1 ] else : 0
428
447
let cchash = !$ (pehash !& comp.id)
429
-
430
448
var cc = programCache.getOrDefault (cchash)
431
449
if cc.isNil:
432
450
cc = gl.compileComposition (comp, cchash)
451
+ cc.iUniform = - 1
452
+ cc.iTexIndex = 0
453
+ cc
454
+
455
+ template setupPosteffectUniforms * (cc: CompiledComposition ) =
456
+ for pe in postEffectStack:
457
+ pe.setupProc (cc)
458
+
459
+ template draw * (comp: var Composition , r: Rect , code: untyped ): stmt =
460
+ let ctx = currentContext ()
461
+ let gl = ctx.gl
462
+ let cc = gl.getCompiledComposition (comp)
433
463
gl.useProgram (cc.program)
434
464
var points : array [8 , GLfloat ]
435
465
points[0 ] = r.minX; points[1 ] = r.minY
@@ -440,17 +470,14 @@ template draw*(comp: var Composition, r: Rect, code: untyped): stmt =
440
470
const componentCount : GLint = 2
441
471
gl.enableVertexAttribArray (posAttr)
442
472
gl.vertexAttribPointer (posAttr, componentCount, false , 0 , points)
443
- cc.iUniform = - 1
444
- cc.iTexIndex = 0
445
473
446
474
compositionDrawingDefinitions (cc, ctx, gl)
447
475
448
476
gl.uniformMatrix4fv (uniformLocation (" uModelViewProjectionMatrix" ), false , ctx.transform)
449
477
450
478
setUniform (" bounds" , r)
451
479
452
- for pe in postEffectStack:
453
- pe.setupProc (cc)
480
+ setupPosteffectUniforms (cc)
454
481
455
482
block :
456
483
code
0 commit comments