shader noob

I am attempting to modify the yarr sample to make the geomipterrain do what I want it to, and I am running into a roadblock with the shader.

basically I modified the shader to accept 6 textures and 2 rgb maps for multitexturing. however when I load the textures and try to pass them to the shader, they are lost completely, like they never make it to the shader as parameters.

Enough babble, here is a snippit of what I have.

#somewhere in the init...

render.setShader( loader.loadShader( "shaders/splut3.sha" ) )

root.setShaderInput('lightvec', Vec4(0.7, 0.2, -0.2, 1))
root.setShaderInput('lightcolor', direct)
root.setShaderInput('ambientlight', ambient)
root.setShaderInput('tscale', Vec4(256.0, 256.0, 256.0, 1.0))    # texture scaling

# We MUST have 6 textures and 2 alpha maps.  The shader requires it
texture1 = loader.loadTexture('textures/grass_thick_512.tga')
texture1.setMinfilter(Texture.FTNearestMipmapLinear)
texture1.setMagfilter(Texture.FTLinear)

texture2 = loader.loadTexture('textures/gravel_gray_512.tga')
texture2.setMinfilter(Texture.FTNearestMipmapLinear)
texture2.setMagfilter(Texture.FTLinear)

texture3 = loader.loadTexture('textures/dirt_512.tga')
texture3.setMinfilter(Texture.FTNearestMipmapLinear)
texture3.setMagfilter(Texture.FTLinear)

texture4 = loader.loadTexture('textures/sand_512.tga')
texture4.setMinfilter(Texture.FTNearestMipmapLinear)
texture4.setMagfilter(Texture.FTLinear)

texture5 = loader.loadTexture('textures/sand_512.tga')
texture5.setMinfilter(Texture.FTNearestMipmapLinear)
texture5.setMagfilter(Texture.FTLinear)

texture6 = loader.loadTexture('textures/sand_512.tga')
texture6.setMinfilter(Texture.FTNearestMipmapLinear)
texture6.setMagfilter(Texture.FTLinear)

alphamap1 = loader.loadTexture('textures/Combined_Alpha_1.png')
alphamap2 = loader.loadTexture('textures/Combined_Alpha_2.png')

root.setShaderInput("tex_0", texture1)
root.setShaderInput("tex_1", texture2)
root.setShaderInput("tex_2", texture3)
root.setShaderInput("tex_3", texture4)
root.setShaderInput("tex_4", texture5)
root.setShaderInput("tex_5", texture6)
root.setShaderInput("tex_6", alphamap1)
root.setShaderInput("tex_7", alphamap2)

and the shader looks like this

void vshader( in float4 vtx_position : POSITION,
	      in float3 vtx_normal : NORMAL,
              in float2 vtx_texcoord0 : TEXCOORD0,
              in float2 vtx_texcoord3 : TEXCOORD3,
              in uniform float4x4 mat_modelproj,
		  in uniform float4x4 trans_model_to_world,
	      in uniform float4 k_lightvec,
	      in uniform float4 k_lightcolor,
	      in uniform float4 k_ambientlight,
	      in uniform float4 k_tscale,
	      out float l_brightness,
		  out float4 l_mpos,
              out float2 l_texcoord0 : TEXCOORD0,
              out float2 l_texcoord3 : TEXCOORD3,
              out float4 l_position : POSITION)
{

  // worldspace position, for clipping in the fragment shader
  l_mpos = mul(trans_model_to_world, vtx_position);

  l_position=mul(mat_modelproj,vtx_position);
  l_texcoord0=vtx_texcoord0*k_tscale;
  l_texcoord3=vtx_texcoord3;

  // lighting
  float3 N = normalize( vtx_normal );
  float3 L = normalize( k_lightvec.xyz );
  l_brightness = (max( dot( -N, L ), 0.0f )*k_lightcolor)+k_ambientlight;

}

void fshader( in float4 l_position : POSITION,
              in float2 l_texcoord0 : TEXCOORD0,
              in float2 l_texcoord3 : TEXCOORD3,
	      in float  l_brightness,
              in uniform sampler2D k_tex_0 : TEXUNIT0,
              in uniform sampler2D k_tex_1 : TEXUNIT1,
              in uniform sampler2D k_tex_2 : TEXUNIT2,
              in uniform sampler2D k_tex_3 : TEXUNIT3,
              in uniform sampler2D k_tex_4 : TEXUNIT4,
              in uniform sampler2D k_tex_5 : TEXUNIT5,
			  in uniform sampler2D k_tex_6 : TEXUNIT6,
			  in uniform sampler2D k_tex_7 : TEXUNIT7,
              out float4 o_color : COLOR )
{
  float4 tex1=tex2D(k_tex_0,l_texcoord0);
  float4 tex2=tex2D(k_tex_1,l_texcoord0);
  float4 tex3=tex2D(k_tex_2,l_texcoord0);
  float4 tex4=tex2D(k_tex_3,l_texcoord0);
  float4 tex5=tex2D(k_tex_4,l_texcoord0);
  float4 tex6=tex2D(k_tex_5,l_texcoord0);

  float alpha1r=tex2D(k_tex_6,l_texcoord3).r;
  float alpha1g=tex2D(k_tex_6,l_texcoord3).g;
  float alpha1b=tex2D(k_tex_6,l_texcoord3).b;
  float alpha2r=tex2D(k_tex_7,l_texcoord3).r;
  float alpha2g=tex2D(k_tex_7,l_texcoord3).g;
  float alpha2b=tex2D(k_tex_7,l_texcoord3).b;

  o_color =tex1*alpha1r;
  o_color+=tex2*alpha1g;
  o_color+=tex3*alpha1b;
  o_color+=tex4*alpha2r;
  o_color+=tex5*alpha2g;
  o_color+=tex6*alpha2b;
  o_color=o_color*(l_brightness);
  o_color.a=1.0;
}

I can provide the entire file, but the rest is really messy due to my attempts at getting somethign to show up

Thanks in advance!

EDIT:

Ok I figured out that I forgot to put the k_ in front of some of my variables… fixed. Now I am getting:

Assertion failed: Shader input lightvec is not present.
at line 356 of c:\p\p3d\panda3d-1.6.2\panda\src\pgraph\shaderAttrib.cxx

Make sure you are setting the lightvec parameter before the shader is being used (the object is being rendered). So if you’re going to set it in a task, set it initially to some value as well.

Thanks, I figured out what was wrong in the wee hours… then decided I didn’t like the path I was going down.

Can you explain to me what the difference is between
setShaderInput(“tex_0”, tex0)
and
setTexture( TextureStage(‘tex_0’), tex0)
?

It’s being passed to the shader differently. And in the first case, the parameter will be called “k_tex_0”.

Thanks again pro-rsoft, but that only opens up more questions :confused:

I gathered that it was a different way of passing to the shader, as I got them to work both ways, but what is the fundamental difference? When I start the app, this (base.win.getGsg().getMaxTextureStages()) reports 4 texture stages available.

Doing things this way

root.setTexture( TextureStage('tex0'),tex0 )

seems like it is utilizing those texture stages, whereas

root.setShaderInput("tex0", tex0)

does not.

However even though it says I have 4 texture stages available, the first way still works just fine.

So I guess my question is, if I only have 4 texture stages, is the first way breaking it up into 2 passes internally or what? And is the second method using the texture stages like the first, only hiding it?

Actually, once you enable shaders, the 4-stage-limit ping suddenly disappears.
(Therefore, one way to fix it when you hit the limit is to call .setShaderAuto().)

Internally, Panda then passes the tex_# stage inputs to the shader instead of going through the OpenGL interface for setting texture stages.

so there is really no difference whatsoever to using one way versus another, other than the k_ being prepended in the parameters.

very interesting, and wonderful!

Thanks!