Search code examples
c++opengltexturesglfwglew

OpenGL C++, Textures Suddenly Black After Being Working For Days


Open GL 3.3

My textures suddenly became black after working for many days Pretty much all the posts that had a similiar issue were about incorrect or absent use of glTexParameteri or incorrect texture loading but i seem to be doing everything correctly regarding that, the vector containing the data is 1024 bytes (16 pixels x 16 pixels x 4 bytes) so that's good, after the issue arose i made a test texture just to make shure everything about that was right. also saw that many posts issues were incomplete texture but here im using glTexImage2D passing the data so the texture has to be complete, also am not creating mipmaps, i disabled them for testing. Altough they were on and working before this bug.

Also im calling glGetError quite frequently and there are no errors

Here is the texture creation code:

unsigned int testTexture;
unsigned long w, h;
std::vector<byte> data;
std::vector<byte> img;
loadFile(data, "./assets/textures/blocks/brick.png");
decodePNG(img, w, h, &data[0], data.size());
glGenTextures(1, &testTexture);
glBindTexture(GL_TEXTURE_2D, testTexture);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,w,h,0,GL_RGBA, GL_UNSIGNED_BYTE,&img[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
data.clear();
img.clear();

And here is where i setup my Uniforms:

glUseProgram(worldShaderProgram);
glUniform1f(glGetUniformLocation(worldShaderProgram, "time"), gameTime);
glUniformMatrix4fv(glGetUniformLocation(worldShaderProgram, "MVP"), 1, GL_FALSE, &TheMatrix[0][0]);
glUniform1i(glGetUniformLocation(worldShaderProgram, "texAtlas"), testTexture);
glUniform1f(glGetUniformLocation(worldShaderProgram, "texMult"), 16.0f / 256.0f);
glUniform4f(glGetUniformLocation(worldShaderProgram, "fogColor"), fogColor.r, fogColor.g, fogColor.b, fogColor.a);

Also Here Is The Fragment Shader

#version 330

in vec4 tex_color;
in vec2 tex_coord;

layout(location = 0) out vec4 color;

uniform sampler2D texAtlas;
uniform mat4 MVP;
uniform vec4 fogColor;

const float fogStart = 0.999f;
const float fogEnd = 0.9991f;
const float fogMult = 1.0f / (fogEnd - fogStart);

void main() {
    if (gl_FragCoord.z >= fogEnd)
        discard;

    //color = vec4(tex_coord.x,tex_coord.y,0.0f,1.0f) * tex_color; // This Line Does What Its Supposed To
    color = texture(texAtlas,tex_coord) * tex_color; // This One Does Not

    if (gl_FragCoord.z >= fogStart)
        color = mix(color,fogColor,(gl_FragCoord.z - fogStart) * fogMult);
}

If i use this line color = vec4(tex_coord.x,tex_coord.y,0.0f,1.0f) * tex_color;

Instead of this line color = texture(texAtlas,tex_coord) * tex_color;

To show the coord from witch it would be getting its color from the texture, the result is what you would expect: (Currenlty only testing it with the top faces)

Image Link Cause I Cant Do Images But Please Click

That Proves That The Vertex Shader Is Working Corretly (The sampler2D is obtained from a uniform at the fragment shader)

Main Loop Rendering Code

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glBindTexture(GL_TEXTURE_2D, textures.textureId);
glUseProgram(worldShaderProgram);
wm.render();
// wm.render() calls lots of meshes to render themselves
// just wanted to point out each one of them has their own
// vertex arry buffer, vertex buffer, and index buffer
// to render i bind the vertex array buffer with glBindVertexArray(vertexArrayBuffer);
// then i call glDrawElements();

Also here is the OpenGL Initialization Code

if (!glfwInit()) // Initialize the library
    return -1;

window = glfwCreateWindow(wndSize.width, wndSize.height, "Minecraft", NULL, NULL);

if (!window)
{
    glfwTerminate();
    return -1;
}

glfwMakeContextCurrent(window); // Make the window's context current
glfwSetWindowSizeCallback(window,resiseEvent);

glfwSwapInterval(1);

if (glewInit() != GLEW_OK)
    return -1;

glClearColor(fogColor.r, fogColor.g, fogColor.b, fogColor.a);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST); // Enable depth testing for z-culling
glEnable(GL_CULL_FACE); // Orientation Culling
glDepthFunc(GL_LEQUAL);    // Set the type of depth-test (<=)
glShadeModel(GL_SMOOTH);   // Enable smooth shading
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  // Nice perspective corrections
glLineWidth(2.0f);

Solution

  • You wrongly set the texture object to the texture sampler uniform. This is wrong:

    glUniform1i(glGetUniformLocation(worldShaderProgram, "texAtlas"), testTexture);
    

    The binding point between the texture object and the texture sampler uniform is the texture unit. When glBindTexture is invoked, then the texture object is bound to the specified target and the current texture unit. The texture unit can be chosen by glActivTexture. The default texture unit is GL_TEXTURE0.

    Since your texture is bound to texture unit 0 (GL_TEXTURE0), you have set the value 0 to the texture sampler uniform:

    glUniform1i(glGetUniformLocation(worldShaderProgram, "texAtlas"), 0);
    

    Note that your code worked before by chance. You just had 1 texture object or testTexture was the first texture name created. Hence the value of testTexture was 0. Now the value of testTexture is no longer 0, causing your code to fail.