Hi,
(running some of this code requires the dev version of Panda 1.9) This post looks like a lot of code, but it is basically the standard water plane code. If you’ve ever worked with reflective water you’ve probably come accros it somewhere.
Im trying to convert some code from cg to glsl, but im running into some problems with the reflection of my water plane. The problem lies in the glsl code (last two code blocks) but im posting a runnable example.
The panda code for the waterplane reduced to a minimum looks like:
from panda3d.core import *
import direct.directbase.DirectStart
class Water(object):
def __init__(self):
#Create the plane geometry and add it to the scene
maker = CardMaker("grid")
maker.setFrame( 0, 1, 0, 1)
self.waterNP = NodePath('waterSurface')
node = self.waterNP.attachNewNode(maker.generate())
node.setHpr(0,-90,0)
node.setScale(20)
self.waterNP.reparentTo(render)
self.waterNP.setLightOff(1)
#Add a buffer and camera that will render the reflection texture
wBuffer = base.win.makeTextureBuffer("water", 512, 512)
wBuffer.setClearColorActive(True)
wBuffer.setClearColor(base.win.getClearColor())
self.wCamera = base.makeCamera(wBuffer)
self.wCamera.reparentTo(render)
self.wCamera.node().setLens(base.camLens)
self.wCamera.node().setCameraMask(BitMask32.bit(1))
self.waterNP.hide(BitMask32.bit(1))
#Create this texture and apply settings
wTexture = wBuffer.getTexture()
wTexture.setWrapU(Texture.WMClamp)
wTexture.setWrapV(Texture.WMClamp)
wTexture.setMinfilter(Texture.FTLinearMipmapLinear)
#Create plane for clipping and for reflection matrix
self.wPlane = Plane(Vec3(0, 0, 1), Point3(0, 0, self.waterNP.getZ()))
wPlaneNP = render.attachNewNode(PlaneNode("water", self.wPlane))
tmpNP = NodePath("StateInitializer")
tmpNP.setClipPlane(wPlaneNP)
tmpNP.setAttrib(CullFaceAttrib.makeReverse())
self.wCamera.node().setInitialState(tmpNP.getState())
self.waterNP.projectTexture(TextureStage("reflection"), wTexture, self.wCamera)
#self.waterNP.setShader(loader.loadShader("waterShader.cg"))
#self.waterNP.setShader(Shader.load(Shader.SLGLSL, "waterV.glsl", "waterF.glsl"))
taskMgr.add(self.updateWater,"updateWater")
def updateWater(self, task):
#Set the camera to the correct position
self.wCamera.setMat(base.cam.getMat(render)*self.wPlane.getReflectionMat())
return task.cont
# To test the reflection, add a model
class RandomModel(object):
def __init__(self):
self.model = loader.loadModel('???')
self.model.setLightOff()
self.model.reparentTo(render)
M = RandomModel()
W = Water()
base.run()
Just running that code should work. The cg shader can now be implemented by uncommenting the corresponding line in the above code and adding this file to the directory:
//Cg
void vshader(
in float2 vtx_texcoord0 : TEXCOORD0,
in float4 vtx_position : POSITION,
uniform float4x4 mat_modelproj,
uniform float4x4 trans_model_to_world,
out float4 l_worldPos : TEXCOORD1,
out float4 l_position : POSITION,
out float2 l_texcoord0 : TEXCOORD0
) {
l_worldPos = mul(trans_model_to_world, vtx_position);
l_position = mul(mat_modelproj, vtx_position);
l_texcoord0 = vtx_texcoord0;
}
void fshader(
in float4 l_worldPos : TEXCOORD1,
in float2 l_texcoord0 : TEXCOORD0,
uniform sampler2D tex_0 : TEXUNIT0,
uniform float4x4 texmat_0,
out float4 o_color : COLOR0
) {
float4 texCoordReflec = mul(texmat_0, l_worldPos);
texCoordReflec.xyz /= texCoordReflec.w;
o_color = tex2D(tex_0, texCoordReflec.xy);
}
This should still work… If i now, however, want to apply the equivalent glsl shader it gives some strangely warped reflection (this part requires the dev version due to the call to “mat4 trans_model_to_world”):
Vertex:
//GLSL
#version 120
attribute vec4 p3d_MultiTexCoord0;
attribute vec4 p3d_Vertex;
uniform mat4 trans_model_to_world;
out vec4 worldPos;
void main(){
worldPos = mul(trans_model_to_world, p3d_Vertex);
gl_Position = mul(gl_ModelViewProjectionMatrix, p3d_Vertex);
gl_TexCoord[0] = p3d_MultiTexCoord0;
}
Fragment:
//GLSL
#version 120
in vec4 worldPos;
uniform sampler2D p3d_Texture0;
void main(){
vec4 texCoordReflec = mul(gl_TextureMatrix[0], worldPos);
texCoordReflec.xyz /= texCoordReflec.w;
gl_FragColor = texture2D(p3d_Texture0, texCoordReflec.xy);
}
Does anyone know what is going wrong? What is the difference between the Cg and glsl code? It seems to be the same thing…
Much appreciated!
Stein