@@ -251,18 +251,20 @@ type
251251 source* : string
252252 setupProc* : proc (cc: CompiledComposition )
253253 mainProcName* : string
254+ seenFlag: bool # Used on compilation phase, should not be used elsewhere.
254255 id* : int
255256
256257 CompiledComposition = ref object
257258 program* : ProgramRef
258- uniformLocations: seq [UniformLocation ]
259+ uniformLocations* : seq [UniformLocation ]
259260 iTexIndex* : GLint
260261 iUniform* : int
261262
262263var programCache = initTable [Hash , CompiledComposition ]()
263264
264265type Composition * = object
265266 definition: string
267+ vsDefinition: string # Vertex shader source code
266268 requiresPrequel: bool
267269 id* : int
268270
@@ -311,19 +313,27 @@ proc newPostEffect*(definition: static[string], mainProcName: string): PostEffec
311313 result .mainProcName = mainProcName
312314 result .id = hash (preprocessedDefinition)
313315
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 )
316318 result .definition = preprocessedDefinition
319+ result .vsDefinition = vsDef
317320 result .requiresPrequel = requiresPrequel
318321 result .id = hash (preprocessedDefinition)
319322
323+ template newComposition * (definition: static [string ], requiresPrequel: bool = true ): Composition =
324+ newComposition (nil , definition, requiresPrequel)
325+
320326template newCompositionWithNimsl * (mainProc: typed ): Composition =
321327 newComposition (getGLSLFragmentShader (mainProc, " compose" ), false )
322328
323- var postEffectStack = newSeq [PostEffect ]()
329+ type PostEffectStackElem = object
330+ postEffect: PostEffect
331+ setupProc* : proc (cc: CompiledComposition )
332+
333+ var postEffectStack = newSeq [PostEffectStackElem ]()
324334var postEffectIdStack = newSeq [Hash ]()
325335
326- proc compileComposition * (gl: GL , comp: var Composition , cchash: Hash ): CompiledComposition =
336+ proc compileComposition * (gl: GL , comp: Composition , cchash: Hash ): CompiledComposition =
327337 var fragmentShaderCode = " "
328338 if comp.requiresPrequel:
329339 fragmentShaderCode = """
@@ -342,18 +352,29 @@ uniform vec4 bounds;
342352
343353 fragmentShaderCode &= comp.definition
344354
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
347368
348369 fragmentShaderCode &= """ void main() { gl_FragColor = vec4(0.0); compose(); """
349- var i = postEffectStack.len - 1
370+ i = postEffectStack.len - 1
350371 while i >= 0 :
351- fragmentShaderCode &= postEffectStack[i].mainProcName & " ();"
372+ fragmentShaderCode &= postEffectStack[i].postEffect. mainProcName & " ();"
352373 dec i
353374 fragmentShaderCode &= " }"
354375
355376 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" )])
357378 result .uniformLocations = newSeq [UniformLocation ]()
358379 programCache[cchash] = result
359380
@@ -368,7 +389,7 @@ proc unwrapPointArray(a: openarray[Point]): seq[GLfloat] =
368389
369390var texQuad : array [4 , GLfloat ]
370391
371- template compositionDrawingDefinitions (cc: CompiledComposition , ctx: GraphicsContext , gl: GL ) =
392+ template compositionDrawingDefinitions * (cc: CompiledComposition , ctx: GraphicsContext , gl: GL ) =
372393 template uniformLocation (name: string ): UniformLocation =
373394 inc cc.iUniform
374395 if cc.uniformLocations.len - 1 < cc.iUniform:
@@ -407,29 +428,38 @@ template compositionDrawingDefinitions(cc: CompiledComposition, ctx: GraphicsCon
407428 inc cc.iTexIndex
408429
409430template pushPostEffect * (pe: PostEffect , body: untyped ) =
410- pe.setupProc = proc (cc: CompiledComposition ) =
431+ postEffectStack. add ( PostEffectStackElem (postEffect: pe, setupProc: proc (cc: CompiledComposition ) =
411432 let ctx = currentContext ()
412433 let gl = ctx.gl
413434 compositionDrawingDefinitions (cc, ctx, gl)
414435 body
436+ ))
415437
416- postEffectStack.add (pe)
417438 let oh = if postEffectIdStack.len > 0 : postEffectIdStack[^ 1 ] else : 0
418439 postEffectIdStack.add (oh !& pe.id)
419440
420441template popPostEffect * () =
421442 postEffectStack.setLen (postEffectStack.len - 1 )
422443 postEffectIdStack.setLen (postEffectIdStack.len - 1 )
423444
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 =
427446 let pehash = if postEffectIdStack.len > 0 : postEffectIdStack[^ 1 ] else : 0
428447 let cchash = !$ (pehash !& comp.id)
429-
430448 var cc = programCache.getOrDefault (cchash)
431449 if cc.isNil:
432450 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)
433463 gl.useProgram (cc.program)
434464 var points : array [8 , GLfloat ]
435465 points[0 ] = r.minX; points[1 ] = r.minY
@@ -440,17 +470,14 @@ template draw*(comp: var Composition, r: Rect, code: untyped): stmt =
440470 const componentCount : GLint = 2
441471 gl.enableVertexAttribArray (posAttr)
442472 gl.vertexAttribPointer (posAttr, componentCount, false , 0 , points)
443- cc.iUniform = - 1
444- cc.iTexIndex = 0
445473
446474 compositionDrawingDefinitions (cc, ctx, gl)
447475
448476 gl.uniformMatrix4fv (uniformLocation (" uModelViewProjectionMatrix" ), false , ctx.transform)
449477
450478 setUniform (" bounds" , r)
451479
452- for pe in postEffectStack:
453- pe.setupProc (cc)
480+ setupPosteffectUniforms (cc)
454481
455482 block :
456483 code
0 commit comments