GLSL help

Howdy. I’ve got a GLSL problem I need help with.

Basically I have a shader that operates on 5 active texture units & 5 texture coordinate sets. I’m pretty sure that all 5 texture units are properly activated on the code-side. I’m positive that all 5 texture coordinate sets are coming in. However, when I assign gl_TexCoord values for indices 0-4, the value in gl_TexCoord[0] basically overwrites what in one of my other, user-defined varying variables (in this case, normal).

I’ve stripped down my shaders to isolate the problem. The vertex program just sets a varying normal, and assigns 0-4 gl_TexCoord values. The fragment program just renders the value of the normal, which allows me to see that the register has been filled with the value of gl_TexCoord[0]. (I confirmed this by messing around with the 0th texture coordinate to see the results).

I’m going to keep looking into the code, because it really seems like the vertex program is mis-allocating the gl_TexCoord array, in a way such that gl_TexCoord[0] is aliasing my other varying register (normal).

In the meantime, if this problem rings any bells for anyone, please let me know.


varying vec3 normal_c;

void main()
{	
	normal_c = normalize(gl_NormalMatrix * gl_Normal);	
		
	gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
	gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;
	gl_TexCoord[2] = gl_TextureMatrix[2] * gl_MultiTexCoord2;
	gl_TexCoord[3] = gl_TextureMatrix[3] * gl_MultiTexCoord3;
	gl_TexCoord[4] = gl_TextureMatrix[4] * gl_MultiTexCoord4;

	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}


varying vec3 normal_c;

void main()
{	
	gl_FragColor = vec4(normal_c, 0.0);
}

FWIW, I can confirm this behavior by changing the vertex program like below. Now when the fragment program renders from normal_c, it is correct!.


varying vec3 normal_c;

void main()
{	
	normal_c = normalize(gl_NormalMatrix * gl_Normal);	
		
        ///-------
	gl_TexCoord[0] = vec4(normal_c, 0.0);
        ///-------

	gl_TexCoord[1] = gl_TextureMatrix[1] * gl_MultiTexCoord1;
	gl_TexCoord[2] = gl_TextureMatrix[2] * gl_MultiTexCoord2;
	gl_TexCoord[3] = gl_TextureMatrix[3] * gl_MultiTexCoord3;
	gl_TexCoord[4] = gl_TextureMatrix[4] * gl_MultiTexCoord4;

	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

Sorry for the spam, but I took a look at the cgc output for my vertex & fragment program. Vertex program looks ok. Fragment program looks like this, clearly pulling the normal_c varying variable from the TEX0 register.


fs_broken.fsh
5 lines, 0 errors.
!!ARBfp1.0
# cgc version 1.4.0000, build date Jun  9 2005 12:09:02
# command line args: -oglsl -profile arbfp1
# source file: fs_broken.fsh
#vendor NVIDIA Corporation
#version 1.0.02
#profile arbfp1
#program main
#var float4 gl_FragColor : $vout.COLOR : COL : -1 : 1
#var float3 normal_c : $vin.TEX0 : TEX0 : -1 : 1
#const c[0] = 0
PARAM c[1] = { { 0 } };
MOV result.color.xyz, fragment.texcoord[0];
MOV result.color.w, c[0].x;
END
# 2 instructions, 0 R-regs

Hi anarchotron,

[quote]# cgc version 1.4.0000, build date Jun 9 2005 12:09:02
[/quote]
First of all, try a newer driver. The original shader should be working as expected and the behavior you’re seeing seems like a bug.

The cgc output you’re getting is actually correct. When you link these two shaders, the linker sees that you’re not using the gl_TexCoords and optimizes them away. So, only the normal_c remains and is correctly put in TEX0.

You may be able to work around this bug by either assigning normal_c to a spare gl_TexCoord, or using custom varyings for the TexCoords.

Aye I got the newest driver (Catalyst 5.10) as soon as this started happening, with no luck.

Very annoying little bug. I worked around it for now by using fewer gl_TexCoord elements for my actual TCs, as well as packing my declared varyings a little better (like merging fog into one of the unused elements in a varying declared as vec3).

If I ever stumble across what’s actually happening I’ll let you know!

Thanks!

Hmmm, ATI… :wink:

Were you using gl_FogFragCoord?

Nope. I did try to shift over to using that instead of my own varying variable. I’ve used it before with no problems. However, the cgc compiler claims something to the effect of “not available with this shader version” or something. (I don’t have the error right in front of me).

In the past, gl_FogFragCoord has worked properly using the GL GLSL compiler, even if cgc refuses to compile with it. I figured that might be a good way to free up a interpolant.

Is there something dangerous I should know about gl_FogFragCoord?

I had reported a bug to ATI with a very similar behaviour (last March IIRC). When I was accessing gl_FogFragCoord (even if it didn’t contribute to the shader output), all the varyings “shifted” one position. So, given there were 3 varyings A, B, C, I was getting the following behaviour:

  • A contained random values
  • B contained the value of A
  • C contained the value of B
  • The C value was lost

Anyway, that’s an old bug and should be fixed by now.

Are you sure you were not exceeding MAX_VARYING_FLOATS before reducing/packing your varyings?