Multitexturing shader on heightfield doesn't work

I’m trying to apply a shader for multitexturing to a node generated by a HeightfieldTesselator and having no luck.
It works to some (very very small) degree, the highest part of terrain is brown, middle is green and lowest is grey. However, there is no texture detail at all, just these 3 colors.

I know the shader works, because when I apply it to a model it works perfectly.

Here is my code:

		self.hf = HeightfieldTesselator("Terrain")
		self.hf.setHeightfield(Filename("data/terrain.png"))		
		self.hf.setHorizontalScale(HORIZONTALSCALE)
		self.hf.setVerticalScale(VERTICALSCALE)
					
		self.tex0 = loader.loadTexture('data/dirt.png')
		self.tex1 = loader.loadTexture('data/fungus.png')
		self.tex2 = loader.loadTexture('data/grass.png')

		self.ts0 = TextureStage('dirt')
		self.ts1 = TextureStage('fungus')
		self.ts2 = TextureStage('grass')
		
		render.setShaderInput( 'fog', Vec4( 0.16, 0.32, 0.36, 0.0002 ) )
		render.setShaderInput( 'lightvec', Vec4( 1, 0, 1, 0 ) )

# THIS WORKS PERFECTLY
		np = loader.loadModel('data/terrain.bam.pz')
		np.reparentTo(render)
		np.setPos( 0, 0, 0 )
		np.setShader(loader.loadShader("shaders/terrain.sha"))
		np.setTexture(self.ts0, self.tex0)
		np.setTexture(self.ts1, self.tex1)
		np.setTexture(self.ts2, self.tex2)
		np.setShaderInput('terrain', Vec4( 46, 66, 0, 0 ))

# This is broken?
		self.hf.setFocalPoint(camera.getX(), -camera.getY())
		node = self.hf.generate()			
		node.reparentTo(render)
		node.setPos(0, 0, 0)
		node.setShader(loader.loadShader("shaders/terrain.sha"))
		node.setTexture(self.ts0, self.tex0)
		node.setTexture(self.ts1, self.tex1)
		node.setTexture(self.ts2, self.tex2)
		node.setShaderInput('terrain', Vec4( 46, 66, 0, 0 ))	

Oh and btw it doesn’t matter if I load model or heightfield first. The model always works, heightfield never does :slight_smile:

Can anyone shed a light?
I’m thinking that I need to generate texture coords for the heigthfield or something like that.
I however did try something like this:

            node.setTexGen( TextureStage.getDefault( ), TexGenAttrib.MWorldPosition )
            node.setTexScale( TextureStage.getDefault( ), 1.0, 1.0 )

With no luck. Maybe the params are not right… I’m not sure how they work

Yup, the heightfieldtesselator generates no or wrong texture coordinates.
The texture coordinates you generate in your python code are not interpreted by the shader. From within the shader, you’d have to divide (or multiply, dont really remember) the vertex’s texcoords by the terrain size. That method works for me.
Or, you can use the PGMM terrain module instead. It does generate correct texture coordinates. (drool)

Thanks alot. I was suspecting something like this.

I’ve tried this solution, but I can’t get it to work… I’ve reduced the shader to an extremtly simple texturing shader (no multitexturing) and still no luck.
The heightmap png file is 512x512

I’ve tried to multiply and divide l_texcoord0 with all kinds of numbers, ranging from 4 to 500000 with no apparent change on my heightfield (but I see differences in the model).

This is the shader:

//Cg
//Cg profile arbvp1 arbfp1

void vshader( in float4 vtx_position : POSITION,
              in float3 vtx_normal : NORMAL,
              in float2 vtx_texcoord0 : TEXCOORD0,
              in uniform float4x4 mat_modelproj,
              in uniform float4x4 mat_modelview,
              in uniform float4 k_terrain,

              out float2 l_texcoord0 : TEXCOORD0,
              out float4 l_position : POSITION )
{
    l_position = mul( mat_modelproj, vtx_position );
    l_texcoord0 = vtx_texcoord0;
}

void fshader( in float4 l_position : POSITION,
              in float2 l_texcoord0 : TEXCOORD0,

              in uniform sampler2D tex_0 : TEXUNIT0,

              out float4 o_color : COLOR )
{
    float4 dirtSample = tex2D(tex_0, l_texcoord0);
    o_color = dirtSample;
}

I’m a bit of a shader noob so i’m not entierly sure how (or if it’s even possible) to calculate the coords from scratch in a shader, if that is what I need to do.

I’ll give PGMM a look, but I don’t think I can use because it’s not in the panda base :neutral_face:

PGMM is found here and I’ll try to have it ready to be put in panda base soon.

About your ‘multi’-texturing shader (I see just one texture in the shader, but anyways.)
Sorry, the vertex coordinates were zero, so multiplying or dividing them wouldn’t do any good at all. So you should first give them coordinates. You can do that for example based on the vertex position.
Try to alter this line:

    l_texcoord0 = vtx_texcoord0; 

replace it with this:

    l_texcoord0 = vtx_position.xy/512.0; 

You might want to try other values as well.

Thanks.

I tried out PPGM but it game me an error when loading the test test.py. I suspect I’ll have to build it with the latest panda version for it to work.

And I got the shader working thanks to you!
I’ll have to learn how to debug shaders, I would’ve caught this problem quickly If i has known how to print out values :slight_smile:

About PGMM, if you’re on windows, you can download a dll which works with the latest version here. (put it in panda’s site-packages dir.)

If anybody knows a good way to debug shaders, tell me! I’d gladly use it as well.
Now, if I want to debug a shader, I have to set the value I want to know as o_color, then use a color picker to get the values :slight_smile: