Geometry shader erases normals

Started by
15 comments, last by Krohm 16 years, 2 months ago
Hello everybody, I am having a little problem with the use of geometry shaders. When I use geometry shaders the normals of my meshes are all set too 0 in the pixel shader. But when I don't use the geometry shaders everything is normal(heh normal :P). For the code I bind the shaders as usual then set the output of the geometry shader:

glProgramParameteriEXT(this->program,GL_GEOMETRY_INPUT_TYPE_EXT,GL_TRIANGLES);
glProgramParameteriEXT(this->program,GL_GEOMETRY_OUTPUT_TYPE_EXT,GL_TRIANGLES);

int temp;
glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT,&temp);
glProgramParameteriEXT(this->program,GL_GEOMETRY_VERTICES_OUT_EXT,temp);
After that I link the shaders and ready to go(if no errors). This is my geometry shader:

#version 120 
#extension GL_EXT_geometry_shader4 : enable

void main(void)
{
	//increment variable
	int i;

	//Pass-thru!
	for(i=0; i< gl_VerticesIn; i++)
	{
		gl_Position = gl_PositionIn;
		EmitVertex();
	}
	EndPrimitive();
}
I hope someone can help me with this, I was really looking forward to making eye candy with geometry shaders XD
Advertisement
I suppose emitting a varying-out attribute is going to help. How could your PS get the normal without an output from the previous stage?
Your pass-thuru really isn't. It's a forwarder for gl_Position only.

Previously "Krohm"

Thanks for the response.

I send the vertexes, normals and texcoord arrays and I assume they get processed as following(just shaders)

geometry shader -> vertex shader -> pixel shader

I can't do anything with the normals in the geometry shader so I assign them to a varying in the vertex shader and use that to fetch them in the pixel shader.

Withouth the geomtry shader it works and with it does not. Does this mean I have to do something with the normals in the geometry shader too?

How am I supposed to do it because gl_Normal is not available in the geomtry shader?
Your understanding of the pipeline is wrong;

Vertex Shader => Geometry Shader => Pixel Shader.

Information must flow right to left, as such you must pass the normals to the Geo-Shader from the Vertex Shader and to the Pixel Shader from the Geo-shader.
I am sure you mean left to right XD.

So if I set the normal uniform in the vertex shader it should be the geometry shader and also the pixelshader?

meaning this should work:

vertex shader:
varying vec3 normal;void main(){	normal = normalize(gl_NormalMatrix * gl_Normal);		gl_Position = ftransform();} 


fragment shader:
varying vec3 normal;void main(){	gl_FragColor = vec4(normal, 1.0);}


geomtry shader:
#version 120 #extension GL_EXT_geometry_shader4 : enablevarying vec3 normal;void main(void){	for(int i=0; i< gl_VerticesIn; i++)	{//		normal = vec3(1.0);		gl_Position = gl_PositionIn;		gl_TexCoord = gl_TexCoordIn;		EmitVertex();	}	EndPrimitive();}


Now the mesh is black but if I don't use the geomtry shader the mesh is colored using the normals.

If I uncomment the "normal = vec3(1.0);" the mesh is black.

So what am I doing wrong?
yes, left to right, heh, sorry I'd only been awake like 15mins when I wrote that [grin]

Anyways, you've been tripped up by something which caught me as well when I first used Geo-shaders; in and out varyings.

With a Geo-shader you have to specifiy which varyings are inputs from the VS and which are outputs to the VS.

With that in mind your code becomes;
#version 120 #extension GL_EXT_geometry_shader4 : enablevarying in vec3 normal[gl_VerticesIn];varying out vec3 oNormal;void main(void){	for(int i=0; i< gl_VerticesIn; i++)	{		oNormal = normal;		gl_Position = gl_PositionIn;		gl_TexCoord = gl_TexCoordIn;		EmitVertex();	}	EndPrimitive();}


Note the extra varyings and the addition of the in and out qualifiers on the types to tell the compiler how we are using them. Also, note that the in varying is an array, just like the built in vars you already read; this is because we are operating at geometry level so you, of course, have access to the varyings of the vertices in your primative.

Then in the main loop you just pass through the data as before so that you can get at it in the fragment shader (which needs the varying changed from 'normal' to 'oNormal' to match the output from the Geo-Shader.

Also, an important thing to remember is there is no 'magic' here; if you don't read something in a stage and pass it on then a latter stage can't get at it. So, if you don't read the normals in the geo-shader and pass them on the pixel shader won't magically get a copy; the pipeline has effectively just forgotten about it. Always pass the data down the line; uniforms are the only thing every stage can get to globally.
Thanks you!

That was it, now it works but I still have an question.

Does "
varying in vec3 normal[gl_VerticesIn];
" work with you? I get an error that I can't use a non constant for array size... So I replaced VerticesIn with 3(since I am using triangles).
Hmm, I thought it should have worked, however looking at my code shows that I just did;

varying in vec3 soemthing[];

which worked fine for me.
Once again thanks, that works here too(I hope ATI accepts it aswel).

Now that I think of it the order vs->gs->ps makes sence since I can't use attributes in the geometry shader. Couse there is no need too XD!
Quote:Original post by JvdWulp
Once again thanks, that works here too(I hope ATI accepts it aswel).



Currently you are out of luck with ATI as, last I checked, they don't support the extension required to use Geo-Shaders even on their hardware which can do it.

This topic is closed to new replies.

Advertisement