Sign in to follow this  
JvdWulp

Geometry shader erases normals

Recommended Posts

JvdWulp    191
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[i];
		EmitVertex();
	}
	EndPrimitive();
}
I hope someone can help me with this, I was really looking forward to making eye candy with geometry shaders XD

Share this post


Link to post
Share on other sites
Krohm    5031
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.

Share this post


Link to post
Share on other sites
JvdWulp    191
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?

Share this post


Link to post
Share on other sites
_the_phantom_    11250
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.

Share this post


Link to post
Share on other sites
JvdWulp    191
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 : enable

varying vec3 normal;

void main(void)
{
for(int i=0; i< gl_VerticesIn; i++)
{
// normal = vec3(1.0);
gl_Position = gl_PositionIn[i];
gl_TexCoord = gl_TexCoordIn[i];
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?

Share this post


Link to post
Share on other sites
_the_phantom_    11250
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 : enable

varying in vec3 normal[gl_VerticesIn];
varying out vec3 oNormal;

void main(void)
{
for(int i=0; i< gl_VerticesIn; i++)
{
oNormal = normal[i];
gl_Position = gl_PositionIn[i];
gl_TexCoord = gl_TexCoordIn[i];
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.

Share this post


Link to post
Share on other sites
JvdWulp    191
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).

Share this post


Link to post
Share on other sites
JvdWulp    191
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!

Share this post


Link to post
Share on other sites
_the_phantom_    11250
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.

Share this post


Link to post
Share on other sites
_the_phantom_    11250
Right now you have to have a GF 8*00 series card in order to use Geometry shaders; ATI/AMD doesn't expose the extension for their DX10 class hardware and no hardware before the latest series of chips has geo-shader support.

Share this post


Link to post
Share on other sites
patrrr    1323
Most current Mac OS X drivers support geoshaders, emulating in software when needed and it's actually pretty fast. I guess Mesa has something similar.

Share this post


Link to post
Share on other sites
Krohm    5031
Quote:
Original post by patrrr
Most current Mac OS X drivers support geoshaders, emulating in software when needed and it's actually pretty fast. I guess Mesa has something similar.
VS emulation was pretty ok. Good to know Apple is providing this value!

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this