OpenGL C++,工作几天后纹理突然变黑

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

打开 GL 3.3

工作了很多天,我的纹理突然变黑了 几乎所有有类似问题的帖子都是关于 不正确或没有使用 glTexParameteri 不正确的纹理加载 但我似乎在这方面做的一切都是正确的, 包含数据的向量是 1024 字节(16 像素 x 16 像素 x 4 字节)所以很好, 问题出现后,我做了一个测试纹理,只是为了确保一切都是正确的。 还看到许多帖子问题是不完整的纹理,但这里我使用glTexImage2D传递数据,因此纹理必须完整,而且不创建mipmaps,我禁用了它们进行测试。虽然他们在这个错误之前就已经开始工作了。

我也经常调用 glGetError 并且没有错误

这里是纹理创建代码:

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();

这里是我设置 制服:

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);

还有片段着色器

#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);
}

如果我使用这条线 color = vec4(tex_coord.x,tex_coord.y,0.0f,1.0f) * tex_color;

代替这一行color = texture(texAtlas,tex_coord) * tex_color;

要显示来自 的坐标,它将从纹理中获取其颜色,结果就是您所期望的:(Currenlty 仅使用顶面对其进行测试)

Image Link Cause I Cant Do Images But Please Click

证明顶点着色器工作正常 (sampler2D是在fragment shader处从uniform得到的)

主循环渲染代码

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();

这里还有 OpenGL 初始化代码

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);

您错误地将纹理对象设置为纹理采样器统一。这是错误的:

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

纹理对象和纹理采样器统一之间的绑定点是纹理单元。当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。默认纹理单位是 GL_TEXTURE0.

由于您的纹理绑定到纹理单元 0 (GL_TEXTURE0),您已将值 0 设置为纹理采样器统一:

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

请注意,您的代码之前是偶然工作的。您只有 1 个纹理对象或 testTexture 是创建的第一个纹理名称。因此 testTexture 的值是 0。现在 testTexture 的值不再是 0,导致您的代码失败。