PDA

View Full Version : Problem using a Vertex Shader with glTexGen (with GL_LINE_STRIP and 1D texture)



ewmailing
01-23-2007, 03:52 PM
I am trying to produce a simple cheesy effect. I am trying to make a moving dotted line (think similar to a barber shop pole).

- I start with a GL_LINE_STRIP.

- Then I add a 1D texture to it so I can control how it looks and how it moves. (Currently it is an alternating off-on texture so it looks like a dotted line.)

- I use glTexGen to generate texture coordinates for me. (In my general case, I may add or subtract points to my line so I didn't want to have to manually set TexCoords myself.)

- I then use glMatrixMode(GL_TEXTURE) with a glTranslatef() to generate movement

This all seems to work well enough.

But my final step is where things seem to break. I then add a Vertex Shader to the mix. When I do this, my line does not render correctly. Often I seem to get a line that completely flashes off or on, rather than seeing the animated dots.

To start with, I'm just trying to write a simple vertex shader that is effectively a pass-through program so it should look identical to the fixed pipeline program. I have been able to reproduce the problem on both Mac and Windows (with different video cards). So I'm guess I'm missing something important.

If I remove the glTexGen stuff and set the glTexCoord manually, things seem to work, but I would like to know how to get it to work with glTexGen as well. (It makes my general case easier.)


Can anybody tell me what I'm doing wrong?
I have uploaded the source code to my simple test program here:
http://www.geocities.com/ewing2121/LineShader.zip

It uses GLUT (with a #define for GLEW if you need it). The program lets you toggle between no-shader and shader by pressing the 's' key.

For convenience, the crux of my code is this:


void DrawSine()
{
float i;
const GLfloat tex_gen_params[] = { 1.0f,0.0f,0.0f,0.0f };

if(g_USE_SHADER)
{
// Turn on shader for the sine wave
glUseProgram(g_LINE_PROGRAM);
}

glEnable(GL_TEXTURE_GEN_S);
glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR);
glTexGenfv(GL_S, GL_OBJECT_PLANE, tex_gen_params);

glColor3f (1.0, 1.0, 1.0);
glLineWidth(3.0);

glEnable(GL_TEXTURE_1D);
glBindTexture(GL_TEXTURE_1D, g_TEXTURE);

glBegin(GL_LINE_STRIP);
for (i = 1.0; i <= 360.0; i++)
{
glVertex2f(i, sin(i/180.0 * M_PI));
}
glEnd();


// Use texture mode to manipulate the texture
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
// Translate by some factor to see texture animation
glTranslatef(glutGet(GLUT_ELAPSED_TIME)/1000.0f, 0, 0);

// Reset to modelview
glMatrixMode(GL_MODELVIEW);

if(g_USE_SHADER)
{
// Turn off the shader so it doesn't affect other parts of the code
glUseProgram(0);
}

glDisable(GL_TEXTURE_1D);
glDisable(GL_TEXTURE_GEN_S);

}And the Vertex Program is:


void main()
{
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;
vec4 v = vec4(gl_Vertex);

gl_ClipVertex = gl_ModelViewMatrix * v;
gl_Position = gl_ModelViewProjectionMatrix * v;
}Thank you

Komat
01-24-2007, 03:40 AM
When vertex shader is active, the fixed function texgen functionality is disabled. You need to emulate it within the shader.

Xmas
01-24-2007, 03:58 AM
You have to realize that a vertex shader replaces almost the whole fixed function vertex processing pipeline. That includes application of ModelView, Projection and Texture matrices, all fixed function lighting, and also TexGen. Thus when you use a vertex shader, TexGen is ignored.

But since all you do with TexGen is use the object X position as texcoord S, and you only use the texture matrix to add the time to that, I'd suggest you use a shader like this:


uniform float elapsedTime;

void main(){
gl_TexCoord[0] = vec4(gl_Vertex.x + elapsedTime, 0.0, 0.0, 0.0);
gl_FrontColor = gl_Color;
gl_BackColor = gl_Color;
gl_ClipVertex = gl_ModelViewMatrix * gl_Vertex;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}You can then set the elapsedTime uniform by using this code:

glUniform1f(glGetUniformLocation(g_LINE_PROGRAM, "elapsedTime"), glutGet(GLUT_ELAPSED_TIME)/1000.0f);

ewmailing
01-24-2007, 02:48 PM
Thank you for the replies. Yes, I noticed that shaders replace the fixed functionality, but I haven't yet figured out all the shader ways to emulate/pass-through the fixed functionality.

(I originally had a Fragment program too, but I discovered that for my lines, all the anti-aliasing went away so all my lines looked really ugly. I haven't found a shader way to pass-through the fixed pipeline anti-aliasing.)

So here's a follow up question. Thanks to the code snippets in the response, I have an animating dotted texture on my line. Now I would like to manipulate it slightly so that when I zoom the camera in or out, the size of the dots stays constant. So for example, currently, if I zoom-out the camera, all the dots become really small so I can't see them. Or if I zoom in, I get too close I can only see a few giant dots. (Now that I think about it, I think I am kind of emulating the glLineStipple effect except that I animate it.)

Thanks