SOLVED (Crappy ATI): varing variables in GLSL

Started by
17 comments, last by V-man 18 years, 5 months ago
EDIT: I posted my solution as post#11 Hello - I'm pretty new to pixel shaders and have been having some troubles lately. All I'm trying to do is shade a sphere but I can only seem to get it to 'work' in a hacked-up-way. I think I've tracked down the problem to the normals being used. So if I do something like this in the vertex shader:

varying vec3 n

void main (void)
{
    n = gl_Normal;
    gl_Position = ftransform();
}


and use that variable 'n' in the fragment shader it appears to be wrong. However, if I use a uniform variable in the fragment shader and set my normal manually on a per face basis, it looks correct. (So I do something like this in the program):

while(vertices to render)
{
    glUniform3fARB(my_normal, nx,ny,nz);
    /*glNormal3f(nx,ny,nz);*.

    glBegin(GL_TRIANGLES)

    glVertex3f()...glVertex3f()...glVertex3f()

    glEnd()
}


and then access the my_normal variable in the fragment shader in place of the normal specified via glNormal3f it shades correctly. So I'm wondering, how does the varying variable work? I have an idea of how it works, but I'm thinking I must be wrong because otherwise my shader would work. If I set a varying variable to 0.0 for the vertices in the vertex shader, will it always be 0.0 in the fragment shader? Also, does the varying variable interpolate on a per triangle basis? Thanks --Andrew [Edited by - Assembler015 on November 13, 2005 12:47:31 PM]
Advertisement
You forget to transform your normal in the vertex shader. You transform the position, but not the normal:
void main (void){    n = gl_Normal;    gl_Position = ftransform();}

should read
void main (void){    n = gl_NormalMatrix * gl_Normal;    gl_Position = ftransform();}

fttransform() does the following calculation: gl_ModelViewProjectionMatrix * gl_Vertex. The reason that there is a special function for it is to ensure compability with fixed-function hardware. It will probably be the same result on your machine.

EDIT: oh, btw, gl_NormalMatrix is the transpose of the inverse of the upper 3x3 bit of gl_ModelViewMatrix (Phew!). Some more info here...
Thanks for the reply,

I've tried multiplying by the normal matrix as well with no success. I must be doing something obviously wrong...I just tried this test program and the results weren't what I expected...


vertex shader:
varying vec3 n;void main (){    n = vec3(0,0,0);    gl_Position = ftransform();}


fragment shader:
varying vec3 n;void main (){    if(n.x == 0.0 && n.y == 0.0 && n.z == 0.0)        gl_FragColor = vec4(1,0,0,1);    else        gl_FragColor = vec4(0,1,0,1);}



I expected my model to always be red, but it's not. It's solid green and periodically it flashed red.

Does that make sense? :-/

--Andrew
in the shader if u use gl_Normal then this reads whatever the current normal is
ie glNormal3fv( normal );
it doesnt take a uniform as input like youre doing
Quote:Original post by zedzeek
in the shader if u use gl_Normal then this reads whatever the current normal is
ie glNormal3fv( normal );
it doesnt take a uniform as input like youre doing


I was only using the uniform as a test. I would set a uniform to the normal vector *instead of* calling glNormal3f and using gl_Normal in the shader.

However, it is looking like it is the varying variable that are causing the problem. I thought I understood them but I guess I don't. For instance...


If I do..

varying vec3 n;void main (void){    n = vec3(0, 0, 0);    gl_Position = ftransform();}


and

varying vec3 n;void main (void){    if(n.x == 0.0 && n.y == 0.0 && n.z == 0.0)        gl_FragColor = vec4(1,0,0,1);    else        gl_FragColor = vec4(0,1,0,1);}


I see the model color as GREEN. If I change the code to...

varying float nx;varying float ny;varying float nz;void main (void){    nx = 0.0;    ny = 0.0;    nz = 0.0;    gl_Position = ftransform();}


and

varying float nx;varying float ny;varying float nz;void main (void){    if(nx == 0.0 && ny == 0.0 && nz == 0.0)        gl_FragColor = vec4(1,0,0,1);    else        gl_FragColor = vec4(0,1,0,1);}


It works as I expect and the result is a RED model.

Can some one plllleeeeaaassseee explain this to me? :-)

Thanks for all your help so far,
--Andrew
I have the same problem.
I set the texcoord in vertex shader like

gl_TexCoord[1] = gl_TextureMatrix[1] * gl_Vertex;
ProjTexCoord = gl_TextureMatrix[1] * gl_Vertex;

Then in the fragment shader i use it :
This works
vec4 reflectionValue = vec4(texture2DProj(reflection, gl_TexCoord[1]));
but this does not work.
vec4 reflectionValue = vec4(texture2DProj(reflection, ProjTexCoord));

ProjTexCoord is a varying variable :
varying vec4 ProjTexCoord;
I dont know why it doesnt work :(

Did you tried?
n = vec3(0.0, 0.0, 0.0);




Quote:Original post by Black Knight
I have the same problem.
I set the texcoord in vertex shader like

gl_TexCoord[1] = gl_TextureMatrix[1] * gl_Vertex;
ProjTexCoord = gl_TextureMatrix[1] * gl_Vertex;

Then in the fragment shader i use it :
This works
vec4 reflectionValue = vec4(texture2DProj(reflection, gl_TexCoord[1]));
but this does not work.
vec4 reflectionValue = vec4(texture2DProj(reflection, ProjTexCoord));

ProjTexCoord is a varying variable :
varying vec4 ProjTexCoord;
I dont know why it doesnt work :(

Did you tried?
n = vec3(0.0, 0.0, 0.0);


I have tried setting the normal a dozen diffent ways. Including...


n = vec3(0, 0, 0);

and

n.x = 0;
n.y = 0;
n.z = 0;

and

n[0] = 0;
n[1] = 0;
n[2] = 0;


The only way I can get n.xyz = 0.0 is by declaring them as individual floats.

Also, does any one know what position gl_FragCoord represents? Does it represent an interpolated point inside the triangle specified by the 3 vertices or is it an adjust coordinate?

--Andrew
I think vec3(0,0,0) and vec3(0.0,0.0,0.0) are different.
My shaders dont work if I specify 0.0 as 0.
watch out with float equality! Maybe the fragment shader can't represent 0.0 properly, or the way its represented in vectors and scalars are different. You really should put in some epsilons to be safe. So try this instead:
void main (void){    if (length(n) < 0.001)        gl_FragColor = vec4(1,0,0,1);    else        gl_FragColor = vec4(0,1,0,1);}
Quote:Original post by rollo
watch out with float equality! Maybe the fragment shader can't represent 0.0 properly, or the way its represented in vectors and scalars are different. You really should put in some epsilons to be safe. So try this instead:
*** Source Snippet Removed ***


I tried something similar to that. After some playing around I found that when the variable is declared as:

varying vec3 n;

and set in the vertex shader as:

n.x = 0.0;
n.y = 0.0;
n.z = 0.0;

That n.x and n.y are always 0 in the shader. However, n.z is a larger value. I tried ruling out rounding error by saying:

if(abs(n.z) < 0.0001){}

But the value was significantly larger than that. So why would n.xy stay constant (like I expected) but n.z be changing?


EDIT: Also, the output is inconsistent. The model is output as solid green one second, and solid red the next.

This topic is closed to new replies.

Advertisement