Odd behavior with shaders and render to texture

I’m attempting to use Tobias excellent atmospheric scattering shaders but at a planetary scale.


When the “planet” has no shaders attached the panda view updates normally, although the happy sphere is not drawn.


When I add setShaderAuto() on the smile sphere the main panda view does not update when I move the camera, or the sun position sliders. If I sphere.hide() the view updates normally.

I’m using the latest cvs version of panda

Link to files. I can make a video of the behaviour if that will help.

Here is the code of basic.py
[spoiler]

import sys
from os import remove
from shutil import copyfile
import random
from os.path import isfile, isdir, join
import time

from panda3d.core import *
from direct.showbase.ShowBase import ShowBase
from direct.stdpy import thread


from direct.filter.FilterManager import FilterManager

from AtmosphericScattering import AtmosphericScattering

from direct.gui.DirectSlider import DirectSlider

def file_get_contents(filename):
    with open(filename) as f:
        return f.read()

loadPrcFileData('', file_get_contents('config.prc'))

print "Panda3D version: ",PandaSystem.getVersionString()



def normalized(v):
    v.normalize()
    return v

class MyApp(ShowBase):
    isscattering = False
    def __init__(self):
        ShowBase.__init__(self)

        self.fxManager = FilterManager(base.win, base.cam)

        self.baseInit()
        self.initMouseControll()

        self.initScattering()


        self.speed = 0.5
        self.accept("+", self.multiplySpeed, [1.5])
        self.accept("-", self.multiplySpeed, [0.75])
     
        self.addTask(self.updateMouse, "updateMouse", priority=30)
        self.addTask(self.update, "updatePosition", priority=20)
        self.addTask(self.updateTerrain, "updateTerrain", priority=10)

        thread.start_new_thread(self.updateTexturesThread, ())

    
        self.reloadShader()

        print "Initializsation done"
        planet = loader.loadModel('smiley')
        planet.set_scale(6360)
        planet.set_shader_auto()
        planet.reparent_to(self.baseNode)
        base.accept('x', self.toggleWireframe)
        base.accept('h', self.hidePlanet)

        from panda3d.core import PointLight
        light = PointLight('light')
        lightnp = self.baseNode.attachNewNode(light)
        lightnp.set_pos(0, -8000, 0)
        self.baseNode.set_light(lightnp)
        self.wire = False
        self.hideP = False


    def hidePlanet(self):
        self.hideP = not self.hideP
        if self.hideP:
            self.baseNode.hide()
        else:
            self.baseNode.show()

    def toggleWireframe(self):
        self.wire = not self.wire
        if self.wire:
            self.baseNode.setRenderModeWireframe() 
        else:
            self.baseNode.clearRenderMode()


    def initScattering(self):
        self.scattering = AtmosphericScattering()
        self.scattering.setOutputTextures(False)
        self.scattering.precompute()
        
        colortex = Texture("colortex")
        depthtex = Texture("depthtex")
        normals  = Texture("normals")
        depthtex.setFormat(Texture.F_depth_component32)



        quad = self.fxManager.renderSceneInto(colortex=colortex, depthtex=depthtex, auxtex = normals)
        quad.setShader(self.scattering.getPostProcessingShader())
        quad.setShaderInput("depthSampler", depthtex)
        quad.setShaderInput("colorSampler", colortex)
        quad.setShaderInput("normalSampler", normals)
        quad.setShaderInput("transmittanceSampler", self.scattering.getTransmittanceTexture())
        quad.setShaderInput("inscatterSampler", self.scattering.getInscatterTexture())
        quad.setShaderInput("irradianceSampler", self.scattering.getIrradianceTexture())
        quad.setShaderInput("sunVector", normalized(Vec3(1.0, 1.0, 1.0)))


        quad.setShaderInput("camera", base.cam)
        quad.setShaderInput("render", render)

        self.quad_scattering = quad

        self.sunPos = Vec3(0)

        self.xpos_slider = DirectSlider(range=(-2,2), value=1.5, pageSize=0.001,pos=(-1.2,0,0.6),scale=0.3, command=self.setSunXPos)
        self.ypos_slider = DirectSlider(range=(-2,2), value=-0.5, pageSize=0.001,pos=(-1.2,0,0.5),scale=0.3, command=self.setSunYPos)
        self.zpos_slider = DirectSlider(range=(-2,2), value=0.2, pageSize=0.001,pos=(-1.2,0,0.4),scale=0.3, command=self.setSunZPos)
        self.isscattering = True


    def setSunXPos(self):
        self.sunPos.setX(self.xpos_slider['value'])


    def setSunYPos(self):
        self.sunPos.setY(self.ypos_slider['value'])


    def setSunZPos(self):
        self.sunPos.setZ(self.zpos_slider['value'])


    def baseInit(self):

        base.disableMouse()
        base.cam.setPos(0,0,0)
        base.camera.setPos(0,-15000,0)
        self.baseNode = render.attachNewNode("baseTerrainNode")

        def prepTex(tx):
            tx.setMinfilter(Texture.FT_linear_mipmap_linear)
            tx.setMagfilter(Texture.FT_linear)
            tx.setAnisotropicDegree(2)

    def initMouseControll(self):
        self.movement = [0,0]
        self.lastMousePos = [0,0]
        self.mouseEnabled = False

        self.accept("w",self.setMovement,[0,1,])
        self.accept("w-up",self.setMovement,[0,0,])
        self.accept("s",self.setMovement,[0,-1,])
        self.accept("s-up",self.setMovement,[0,0,])
        self.accept("a",self.setMovement,[1,-1,])
        self.accept("a-up",self.setMovement,[1,0,])
        self.accept("d",self.setMovement,[1,1,])
        self.accept("d-up",self.setMovement,[1,0,])
        self.accept("r",self.reloadShader)
        self.accept("f3", base.toggleWireframe)
        self.accept("v", base.bufferViewer.toggleEnable)

        self.accept("mouse1",self.setMouseEnabled,[True])
        self.accept("mouse1-up",self.setMouseEnabled,[False])



    # TASKS
    def updateTexturesThread(self):
        return
        while True:
            begin = time.time()
            self.terrain.streamTextures()
            diff = (time.time() - begin) * 1000.0
            if diff > 0.5:
                print "PEAK @",diff
            time.sleep(1.0 / 30.0)

    def updateTexturesTask(self, task):
        return task.cont
        begin = time.time()
        self.terrain.streamTextures()
        diff = (time.time() - begin) * 1000.0
        if diff > 0.5:
            print "PEAK @",diff

        return task.cont

    def updateTerrain(self, task=None):
        return task.cont
        self.terrain.update()        
        return task.cont


    def updateMouse(self, task):
        #return task.cont
        if base.mouseWatcherNode.hasMouse():
            x = base.mouseWatcherNode.getMouseX()
            y = base.mouseWatcherNode.getMouseY()
            self.currentMousePos = [x*90, y*70]
            
            if self.mouseEnabled:
                diffx = self.lastMousePos[0]-self.currentMousePos[0]
                diffy = self.lastMousePos[1]-self.currentMousePos[1]
                base.cam.setH(base.cam.getH() + diffx)
                base.cam.setP(base.cam.getP() - diffy)

                    
            self.lastMousePos = self.currentMousePos[:]
        return task.cont


    # EVENT HANDLERS
    def multiplySpeed(self, factor):
        self.speed *= factor

    def setMovement(self, direction, amount):
        self.movement[direction] = amount
          
    def setMouseEnabled(self, enabled ):
        self.mouseEnabled = enabled
        
    def reloadShader(self):
        print "updating shaders .."
        try:
            rn = "stuff/texcoord_display.cg" + str(random.randint(1000000000,99999999999))
            copyfile("stuff/texcoord_display.cg", rn)
            #self.baseNode.setShader(loader.loadShader(rn))
            remove(rn)
        except Exception, msg:
            print msg

        #self.quad_scattering.setShader(self.scattering.getPostProcessingShader())


    def update(self,task):

        direction = (Vec3(self.movement[1],self.movement[0],0) 
                    * self.speed 
                    * globalClock.getFrameTime())

        cameraQuat = base.cam.getQuat(render)
        velocity = cameraQuat.xform(direction)
        base.camera.setPos(base.camera.getPos() + velocity)
        s = Vec3(0,1,0)

        zFar = 70000.0
        zNear = 100.0

        p_cameraFar = cameraQuat.xform(Vec3(0,zFar, 0))
        p_cameraNear = cameraQuat.xform(Vec3(0,zNear, 0))

        cameraToNear = p_cameraNear;
        cameraNearToFar  = p_cameraFar - p_cameraNear;
        if self.isscattering:
            self.quad_scattering.setShaderInput("exposure", 0.4)
            self.quad_scattering.setShaderInput("s", s)
            self.quad_scattering.setShaderInput("cameraPos", base.camera.getPos(render))
            self.quad_scattering.setShaderInput("cameraToNear", cameraToNear)
            self.quad_scattering.setShaderInput("cameraNearToFar", cameraNearToFar)

            p = Vec3(self.sunPos)


            self.quad_scattering.setShaderInput("sunVector", normalized(p))

        print base.camera.getPos(), base.cam.getHpr(), velocity

        return task.cont


app = MyApp()
app.run()

[/spoiler]

Are you using a custom source build or a buildbot build?

I compile/install it from cvs, which I update every morning. The buildbot doesn’t serve arch builds :slight_smile:

Right-oh. Try undoing this change:

panda3d.cvs.sourceforge.net/view … 4&r2=1.455

and then removing the comment block. So, to be clear, that entire block should be moved back to end_scene, and the /* */ removed so that the code is executed.

Reverted the change and uncommented the block. Same issue.

It’d be great if you could try it with a recent development build and see if the issue persists. A lot of changes have happened since the last update to this thread.

IIRC, wasn’t it already fixed? It was some bug in end_frame or something similar …