OpenGL 2.1 GLSL 1.2 Texturing/Understanding Help

I’m having a little trouble understanding how to use OpenGL 2.1 with GLSL 1.2 in C++. I’m looking at code I wrote (or pasted from online together…) and I don’t understand it and I can’t get texturing to work. Right now, it all appears white. Yes, my shaders compile properly and my texture image is loaded correctly (I checked using immediate mode).

Anyways, my vertex shader is this:


#version 120
in vec4 PositionVec;
uniform mat4 ModelViewMat;
uniform mat4 ProjMat;"
void main()
{
	gl_TexCoord[0]=gl_MultiTexCoord0;
	gl_Position=ProjMat*ModelViewMat*PositionVec;
}

And my fragment:


#version 120
uniform sampler2D tex;
void main()
{
    gl_FragColor = texture2D(tex, gl_TexCoord[0].st);
}

My coordinates:


float data[]={ 160.0f, 120.0f, -1.0f,
	       480.0f, 120.0f, -1.0f,
	       480.0f, 320.0f, -1.0f,
	       160.0f, 320.0f, -1.0f,};
float colors[]={154.0f/256.0f, 206.0f/256.0f, 236.0f/235.0f, 1.0f,
		154.0f/256.0f, 206.0f/256.0f, 236.0f/235.0f, 0.5f,
		154.0f/256.0f, 206.0f/256.0f, 236.0f/235.0f, 1.0f,
		154.0f/256.0f, 206.0f/256.0f, 236.0f/235.0f, 0.5f,
		1.0f, 0.0f, 0.0f, 1.0f};
float newTexCoord[]={0.0f,0.0f,
		     1.0f,0.0f,
		     1.0f,1.0f,
		     0.0f,1.0f};

And my drawing(the texture is called newTexture, by the way):


glClearColor(100.0f/256.0f,149.0f/256.0f,236.0f/256.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);

glUseProgram(mainProgram.program);
modelView=glm::mat4(1.0);
modelView*=glm::translate<float>(glm::vec3(-320+x,-240.0+y,0.0));
modelView*=glm::translate<float>(glm::vec3(0.0,0.0,0.0));

glUniformMatrix4fv(glGetUniformLocation(mainProgram.program,"ModelViewMat"),1,false,glm::value_ptr(modelView));
glActiveTexture(GL_TEXTURE0);
int texture_location = glGetUniformLocation(mainProgram.program,"color_texture");
glUniform1i(texture_location, 0);
glBindTexture(GL_TEXTURE_2D,newTexture);

glEnableClientState(GL_COLOR_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER,vertexBuffer[1]);
glColorPointer(4,GL_FLOAT,0,0);

glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER,vertexBuffer[0]);
glVertexPointer(3,GL_FLOAT,0,0);

glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture( GL_TEXTURE_2D, newTexture);
glTexCoordPointer(2,GL_FLOAT,0,newTexCoord);

GLubyte indices[] = {0,1,2,3};
glEnableClientState( GL_INDEX_ARRAY );
glIndexPointer( GL_UNSIGNED_BYTE, 0, indices );

glDrawElements(GL_TRIANGLE_FAN, 4, GL_UNSIGNED_BYTE, indices);

glDisableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture( GL_TEXTURE_2D,0);

glUseProgram(0);

So it draws the box at the correct position but it’s all white. Also, as you may have noticed, most of the code above is mumbo-jumbo and I don’t know what I need or what I don’t or the proper way to do it. All of the tutorials I see are of OpenGL 3.0, but my computer is limited to 2.1 so I want to learn how to use it with shaders so I don’t need to change much when I finally upgrade. Any help is appreciated. Thanks in advance!

Hi,
I think there are two reasons for this.

  1. Are you calling
glEnable(GL_TEXTURE_2D);

when you first bind the texture and specify the texture data using glTexImage2D function?
2) Are you specifying the texture minification filter? If not the default minification filter is mipmaps and if you don’t provide mipmaps, the texturing would not work. Make sure that when you are specifying the texture filters, you have atleast specified the texture minification filter as follows.

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)

So the whole sequence will be as follows,


GLuint texID;
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexImage2D(...);

See if this helps.

  1. I put it in and it does nothing. I was under the impression that when using shaders, enabling GL_TEXTURE_2D did nothing. Somehow though, the framerate goes higher for some reason…

  2. Doesn’t change anything. My texture gets created fine, I’ve tested it with immediate mode I said.

Thanks anyway.

Hi,
I just noticed, the sampler uniform is named tex in the shader while the name you give when u set the uniform is color_texture.
Change this to tex and and tell us if it still does not work.


int texture_location = glGetUniformLocation(mainProgram.program,"tex");

By the way, could you add this assertion at the first line in the render function just to make sure that everything is fine.


void Display() {
   assert(glGetError()==GL_NO_ERROR);
   ...rest of the display stuff
}

I just noticed I renamed it. I changed it and it still gives me a white rectangle, even with the suggestions you made before.

When I cout glGetError() at the end of my draw, I get 0 which means there is no error.

Could u try once again whether you get anything in immediate mode?

Yup, tried:

glClearColor(100.0f/256.0f,149.0f/256.0f,236.0f/256.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);

glEnable( GL_TEXTURE_2D );
glBindTexture (GL_TEXTURE_2D, newTexture);
glBegin(GL_QUADS);
    // Front Face
    glTexCoord2f(0.0f, 0.0f); glVertex3f(0.0f, 0.0f,  1.0f);  // Bottom Left Of The Texture and Quad
    glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 0.0f,  1.0f);  // Bottom Right Of The Texture and Quad
    glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f,  1.0f,  1.0f);  // Top Right Of The Texture and Quad
    glTexCoord2f(0.0f, 1.0f); glVertex3f(0.0f,  1.0f,  1.0f);  // Top Left Of The Texture and Quad
glEnd();

glDisable(GL_TEXTURE_2D);

And I see the texture on the screen. Man, looking at examples, OpenGL 3.0 looks a lot easier. Too bad I have to wait till I go to college till I get a new computer…
My texture is not the problem, it’s my drawing function that’s messed up, I don’t understand how to correctly set it up.

Before adding in buffer objects, try vertex arrays and see if you get anything on screen.

These functions don’t do what you think they do, remove them:


glEnableClientState( GL_INDEX_ARRAY );
glIndexPointer( GL_UNSIGNED_BYTE, 0, indices );

Try changing the code


glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture( GL_TEXTURE_2D, newTexture);
glTexCoordPointer(2,GL_FLOAT,0,newTexCoord);

to


glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER,newTexCoord[0]);
glTexCoordPointer(2,GL_FLOAT,0,0);

Thanks, it’s working now! This is what mainly helped me. I just put the newTexCoord in a vertex array and then binded that buffer.

One more question, what are indices? I could never find a definition on them. From my understanding, they allow you to reuse coordinates, useful for creating cubes and such. Is this correct?

Glad that worked.

As for your second question: Yes indices allow you to reuse coordinates. Try reading these references:

  • Take a look at the “Enter Index Buffers” section. The key to understanding indices is getting the picture straight – notice the figure has a bunch of P^n “points”. So to get say point 3 you could think in terms of C notation P[3]. Notice that P[3] is shared between four triangles in the drawing … that is exactly what glDrawElements does it only requires here 17 unique points and references the particular triangles by index number.

  • Or take a look at Section glDrawElements() which states “glDrawElements() draws a sequence of primitives by hopping around vertex arrays with the associated array indices.”

Important to note that - as mentioned above - GL_INDEX_ARRAY is not used for drawing with indices; it’s an unfortunate coincidence in terminology that confuses when first encountered, but you can get by if you just forget that you ever heard of GL_INDEX_ARRAY and glIndexPointer (these are actually used for an OpenGL context in colour index mode, as opposed to the more common RGBA mode, and are highly unlikely to be even supported on modern hardware).