0
votes

I'm completely new to OpenGL and am having trouble sorting out how binding textures and shaders to VBOs works.

I'm using Cinder's texture and shader classes. Here's part of my draw method:

mShader.bind();

myImage.bind();
glPushMatrix();
glTranslated( scaledX, scaledY, scaledZ);
gl::draw(sphere.getVBO());
glPopMatrix();

glPushMatrix();
glTranslated( 0, 0, zshift - 200);
mDisc.draw();
glPopMatrix();

In the above code if I comment out the call to mShader.bind(), my sphere VBO will display the texture (myImage). My shader works fine for plain (untextured) shapes, but when I bind the shader before drawing any shapes with wrapped textures it blocks the textures from being displayed.

Is this a problem with the shader I'm using, or is it something else that I'm not understanding? (...there is still a lot I'm not understanding)

Thanks

edit:

here are the shaders I'm using:

(frag):

uniform sampler2DShadow     depthTexture;

varying vec3                N, V, L;
varying vec4                q;

void main(void)
{
    vec3 normal = normalize( N );
    vec3 R = -normalize( reflect( L, normal ) );

vec4 ambient = gl_FrontLightProduct[0].ambient;
vec4 diffuse = gl_FrontLightProduct[0].diffuse * max(dot( normal, L), 0.0);
vec4 specular = gl_FrontLightProduct[0].specular * pow(max(dot(R, V), 0.0), gl_FrontMaterial.shininess);

vec3 coord = 0.5 * (q.xyz / q.w + 1.0);
float shadow = shadow2D( depthTexture, coord ).r;
gl_FragColor = ((ambient + (0.2 + 0.8 * shadow) * diffuse) + specular * shadow);

}

(vert):

varying vec3        N, V, L;
varying vec4        q;
uniform mat4        shadowTransMatrix;

void main(void)
{
    vec4 eyeCoord = gl_ModelViewMatrix * gl_Vertex;

V = normalize( -eyeCoord.xyz );
L = normalize( gl_LightSource[0].position.xyz - eyeCoord.xyz );
N = gl_NormalMatrix * gl_Normal;

q = shadowTransMatrix * eyeCoord;

gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;

}

1
Show your shader code. Most of the time you will need a different shader for texturing. Also this code is mixing VBOs and shaders with deprecated functions.Bartek Banachewicz
"I'm using Cinder's texture and shader classes." If you want to understand how OpenGL works, you need to expose yourself to OpenGL, not classes that hide OpenGL.Nicol Bolas
I've added the shaders. I am woking on a project for a psyc class and am very time-limited. I will learn OpenGL properly soon enough, but for now I'm just trying to understand enough to cobble something decent together.jag

1 Answers

4
votes

You must implement the texture sampling yourself in your shader. I see that the shader already uses a shadow texture sampler, is that the texture that you want to use? If so, you have to do this:

  1. Set the active texture unit: glActiveTexture(GL_TEXTURE0);
  2. Activate the texture: probably myImage.bind();
  3. Get the location of the uniform variable 'depthTexture': GLint loc = glGetUniformLocation(program, "depthTexture");
  4. Bind the texture to you texture sampler in the shader: glUniform1i(loc, 0);

Notes: In step 3, you must pass the shader program ID as the first parameter to glGetUniformLocation. I don't know Cinder's texture and shader classes, but I suppose that there is either a way to query them directly for uniform variable locations (or even set the variable values directly), or at least they should allow you to get the program ID. In step 4, you are telling OpenGL to set the depthTexture sampler to the texture of the first texture unit (which has the index 0); you need to do this because you have previously selected this texture unit with glActiveTexture(GL_TEXTURE0);.

Please also see this for a more in-depth example of using textures in shaders.