Intervals and shaders

Hello, I’m having problems when I combine intervals and shaders. I’ve a water shader (I used this one, I only made it a bit more modular), and in my application I use intervals. This is a little example:

import direct.directbase.DirectStart
from pandac.PandaModules import DirectionalLight
from direct.interval.IntervalGlobal import Sequence
from direct.interval.FunctionInterval import Func
from Water import WaterNode

def buildWorld():
  WaterNode( 0, 0, 24, 24, 12, ( .045, -.022, 16, 0 ), ( .4, 8, .4, .45 ) )

  dlight = DirectionalLight( 'dlight' )
  dlight.setColor( ( .74, .7, .7, 1 ) )
  dlnp = render.attachNewNode( dlight )
  dlnp.setHpr( ( .7, .2, -.2 ) )
  render.setLight( dlnp )

  t2 = loader.loadModel( 'teapot' )
  t2.reparentTo( render )
  t2.setPos( 10, 10, 11 )

  base.disableMouse()
  base.camera.setPosHpr( ( 12.5, -1.8, 18.9 ), ( 13.5, -32.5, 0 ) )

#Sequence( Func( buildWorld ) ).start()
buildWorld()

run()

This code works. The problem is when I call buildWorld in a Sequence, uncommenting the line

#Sequence( Func( buildWorld ) ).start()

(and commenting the next line buildWorld()). In this case I obtain:

Assertion failed: Shader input time is not present.
 at line 382 of c:\panda3d-1.7.0\panda\src\pgraph\shaderAttrib.cxx
Assertion failed: Shader input time is not present.
 at line 382 of c:\panda3d-1.7.0\panda\src\pgraph\shaderAttrib.cxx
Traceback (most recent call last):
  File "C:\Panda3D-1.7.0\direct\showbase\ShowBase.py", line 1678, in __igLoop
    self.graphicsEngine.renderFrame()
AssertionError: Shader input time is not present.
 at line 382 of c:\panda3d-1.7.0\panda\src\pgraph\shaderAttrib.cxx
:task(error): Exception occurred in PythonTask igLoop
Traceback (most recent call last):
  File "test.py", line 26, in <module>
    run()
  File "C:\Panda3D-1.7.0\direct\showbase\ShowBase.py", line 2531, in run
    self.taskMgr.run()
  File "C:\Panda3D-1.7.0\direct\task\Task.py", line 496, in run
    self.step()
  File "C:\Panda3D-1.7.0\direct\task\Task.py", line 454, in step
    self.mgr.poll()
  File "C:\Panda3D-1.7.0\direct\showbase\ShowBase.py", line 1678, in __igLoop
    self.graphicsEngine.renderFrame()
AssertionError: Shader input time is not present.
 at line 382 of c:\panda3d-1.7.0\panda\src\pgraph\shaderAttrib.cxx

How can I get working both interval and shader? Here are the files of this example. Very thanks!
(Obviously in this case the interval is useless, but in my larger application it is important.)

Intervals’ update is done in a task (ivalLoop), so at the time you call start(), the interval is not yet ran, because that ivalLoop is called by taskMgr.step(), which is started by run().

When you call buildWorld() directly, WaterNode.init creates the shader update task at once, so at frame #1, that task is called, in which the shader input is set for the 1st time.

But when you put buildWorld in an interval, that shader update task is created at frame #1, so the 1st update() is called at frame #2, which is too late because the shader input is missing at frame #1.

To solve this, just set the shader input in WaterNode.init :

    self.waterNP.setShaderInput( 'time', 0 )

Very thanks! You’re really saving me! :slight_smile: