I am just starting out with OpenGL and shaders. My last look at OpenGL was around 2001, so it’s been a while! I will try to be succinct. My actual program is quite lengthy, so I have only copied the section of code I think is relevant to the issue at hand, and I have simplified it considerably during testing to eliminate as many variables as possible. I am now left with just the code below, which does not work.
GLint texture_sampler_id = 0;
guchar data[786432] = {255}; /* Fake texture -- should be all white and 512 x 512 pixels */
GLuint texid;
glEnableVertexAttribArray(0);
if(bm_glerror("Unable to enable vertex attribute array 0")) {
goto fail;
}
glBindBuffer(GL_ARRAY_BUFFER, widget->vb_id);
if(bm_glerror("Unable to bind vertex buffer to attribute array 0")) {
goto fail;
}
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
if(bm_glerror("Unable to setup attribute pointer for attribute array 0")) {
goto fail;
}
/* Use the widget's shader program when rendering */
if (glIsProgram(rd->shader_program_id) != GL_TRUE) {
bm_alert(BM_FATAL, "Invalid shader program for widget [%s].", bm_str_nil(widget->utf8_name));
bm_shutdown();
goto fail;
}
texture_sampler_id = glGetUniformLocation(rd->shader_program_id, "texture_sampler");
if(bm_glerror("Unable to locate texture sampler in widget shader program")) {
goto fail;
}
glUseProgram(rd->shader_program_id);
if(bm_glerror("Unable to use shader program")) {
goto fail;
}
glUniform1i(texture_sampler_id, 0);
if(bm_glerror("Invalid uniform variable specified")) {
goto fail;
}
glActiveTexture(GL_TEXTURE0 + 0);
if(bm_glerror("Unable to activate GL_TEXTURE0")) {
goto fail;
}
glGenTextures(1, &texid);
glBindTexture(GL_TEXTURE_2D, texid);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glEnableVertexAttribArray(1);
if(bm_glerror("Unable to enable vertex attribute array 1")) {
goto fail;
}
glBindBuffer(GL_ARRAY_BUFFER, widget->uv_id);
if(bm_glerror("Unable to bind UV buffer to vertex attribute array 1")) {
goto fail;
}
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, NULL);
if(bm_glerror("Unable to specifiy vertex attribute pointer parameters")) {
goto fail;
}
/* Draw the triangles */
glDrawArrays(GL_TRIANGLES, 0, 6); /* Starting from vertex 0; 3 vertices total -> 1 triangle */
if(bm_glerror("Unable to draw widget")) {
goto fail;
}
glDisableVertexAttribArray(0);
if(bm_glerror("Unable to disable vertex attribute array 0")) {
goto fail;
}
glDisableVertexAttribArray(1);
if(bm_glerror("Unable to disable vertex attribute array 1")) {
goto fail;
}
All this C code is supposed to do is make a fake white texture in memory and apply it to my two triangles which make up the surface of my widget. Obviously, I want to eventually use a DDS file for the texture, but since that was not working, I eliminated that code and moved to an in-memory all-white texture to simplify things.
Vertex Shader:
#version 330 core
// Input vertex data, different for all executions of this shader
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;
// Output data; will be interpolated for each fragment.
out vec2 UV;
// Values that stay constant for the whole mesh.
uniform mat4 MVP;
void main()
{
// Output position of the vertex, in clip space : MVP * position
//gl_Position = MVP * vec4(vertexPosition_modelspace, 1);
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
// UV of the vertex. No special space for this one.
UV = vertexUV;
}
Fragment Shader:
#version 330 core
// Interpolated values from the vertex shaders
in vec2 UV;
// Values that stay constant for the whole mesh.
uniform sampler2D texture_sampler;
void main()
{
// Output color = color of the texture at the specified UV
gl_FragColor = vec4(texture(texture_sampler, UV).rgb, 1.0);
/*if (gl_FragColor.r == 0.0f) {
gl_FragColor.r = UV.x;
}
if (gl_FragColor.g == 0.0f) {
gl_FragColor.g = UV.y;
}
if (gl_FragColor.b == 0.0f) {
gl_FragColor.b = 0.5f;
}*/
}
So, if I try to render the fake white texture to the triangles, no triangles show up – the screen is simply blank. If I uncomment the set of “if” statements in the fragment shader which set the output color based on the UV coordinates for each texel, then I get both triangles showing up in a very nice rainbow of color (as expected). If I remove the “texture(texture_sampler, UV).rgb” and replace it with a vec3() color, it shows up in that color.
So, I have figured out that my sampler is not sampling the fake white texture. I have no idea why. I am sure I am missing something stupid and simple, but I have been pouring over this for probably 12 hours over the past 4 days and I have not been able to figure out what I’m missing.
Debugging output from my program:
Vendor: ATI Technologies Inc.
Renderer: AMD Radeon HD 5700 Series
Version: 3.3.12618 Core Profile Context 13.251.0.0
Shader version: 4.30
Unknown GLerror in glewInit() at bm_display.c:bm_display_thread:72: Invalid ENUM
This is the only GLerror that shows up in my program, and I have no idea what causes it, but I doubt it has any impact on the texture sampler.
Thanks in advance for any assistance on this.