opengl 为什么该纹理显示为全黑?

ifsvaxew  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(436)

这是我调用所有绘制操作的函数。我还在函数中编译着色器。当我只为每个顶点使用颜色,但纹理根本不想工作时,它会正确显示四边形。
下面是代码:

void doGL2() {

    glTranslatef(0.f, 0.f, 0.f);

    const GLchar* vertShader[] = { R"glsl(
            #version 330 core
            layout (location = 0) in vec3 aPos;
            layout (location = 1) in vec3 aColor;
            layout (location = 2) in vec2 aTexPos;

            out vec3 col;
            out vec2 texturePos;

            void main()
            {
                gl_Position = vec4(aPos, 1.0);
                col = aColor;
                texturePos = aTexPos;
            }
        )glsl" };

    const GLchar* fragShader[] = { R"glsl(
            #version 330 core
            out vec4 FragColor;

            in vec3 col;
            in vec2 texturePos;

            uniform sampler2D t;

            uniform vec2 iResolution;

            void main()
            {
                vec2 uv = gl_FragCoord.xy / iResolution;
                //FragColor = vec4(iResolution, 1., 1.);
                FragColor = mix(vec4(col, 1.0f), texture(t, gl_FragCoord.xy / vec2(1200., 675.)), 1.);
            }
        )glsl" };

    vShader2 = glCreateShader(GL_VERTEX_SHADER);
    fShader2 = glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(vShader2, 1, vertShader, NULL);
    glCompileShader(vShader2);

    GLint success;
    GLchar infoLog[1024];
    glGetShaderiv(vShader2, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(vShader2, 1024, NULL, infoLog);
        throw std::runtime_error("\noh no vert\n");
    }

    glShaderSource(fShader2, 1, fragShader, NULL);
    glCompileShader(fShader2);

    glGetShaderiv(fShader2, GL_COMPILE_STATUS, &success);
    if (!success)
    {
        glGetShaderInfoLog(fShader2, 1024, NULL, infoLog);
        throw std::runtime_error("\noh no frag\n");
    }

    shaderProgram2 = glCreateProgram();

    glAttachShader(shaderProgram2, vShader2);
    glAttachShader(shaderProgram2, fShader2);

    glLinkProgram(shaderProgram2);

    GLfloat screen[2] = { 1200.0f, 675.0f };
    glUseProgram(shaderProgram2);

    glUniform2fv(glGetUniformLocation(shaderProgram2, "iResolution"), 2, screen);
    glUniform1i(glGetUniformLocation(shaderProgram2, "t"), 10);

    //not sure if I should do this on cleanup or now
    glDeleteShader(vShader2);
    glDeleteShader(fShader2);

    //lets make a temporary test texture
    int width, height, channels;
    unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 0);

    GLuint tempT = 1;

    glActiveTexture(GL_TEXTURE10);
    glEnable(GL_TEXTURE_2D);

    glGenTextures(1, &tempT);
    glBindTexture(GL_TEXTURE_2D, tempT);
    // set texture options

    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    //glPixelStorei(GL_UNPACK_ALIGNMENT, 2);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

    stbi_image_free(data);

    GLfloat vertices[] = {
        // positions         // colors          // texture positions
         0.0f,  0.0f, 1.0f,  1.0f, 0.0f, 0.0f,  0.0f, 0.0f,         // bottom left
         1.0f,  0.0f, 1.0f,  0.0f, 1.0f, 0.0f,  1.0f, 0.0f,         // bottom right
         1.0f,  1.0f, 1.0f,  0.0f, 0.0f, 1.0f,  1.0f, 1.0f          // top right
         ,
         0.0f,  0.0f, 1.0f,  1.0f, 0.0f, 0.0f,  0.0f, 0.0f,         // bottom left
         0.0f,  1.0f, 1.0f,  0.0f, 1.0f, 0.0f,  0.0f, 1.0f,         // top left
         1.0f,  1.0f, 1.0f,  0.0f, 0.0f, 1.0f,  1.0f, 1.0f          // top right
    };

    glGenVertexArrays(1, &VAO2);
    glGenBuffers(1, &VBO2);

    glBindVertexArray(VAO2);

    glBindBuffer(GL_ARRAY_BUFFER, VBO2);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    //positions
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);

    //colors
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
    glEnableVertexAttribArray(1);

    //texture positions
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);

    float initTime = glutGet(GLUT_ELAPSED_TIME);
    float prevTime = initTime;
    float dt = 0.0f;
    while (prevTime - initTime < 1000.0f) {

        dt = (glutGet(GLUT_ELAPSED_TIME) - prevTime) / 1000.0f;
        prevTime = glutGet(GLUT_ELAPSED_TIME);

        glClearColor(1.f, 1.f, 1.f, 1.f);
        glClear(GL_COLOR_BUFFER_BIT);

        glBindVertexArray(VAO2);

        glBindTexture(GL_TEXTURE_2D, tempT);

        glDrawArrays(GL_TRIANGLES, 0, 6);

        SwapBuffers(GetDC(w));
        glFlush();
    }

}

由于某种原因,当我把纹理绑定到GL_TEXTURE0时,它会显示纹理。
编辑:我正在做进一步的修改,因为我原来问题的内容没有正确解决这个问题。看起来我无法将任何纹理绑定到GL_TEXTURE0以外的任何纹理。我看过其他论坛上的这个问题,但是这些问题的答案都解决了这里没有的其他问题。正如你所看到的,我正在尝试将这个纹理绑定到GL_TEXTURE10,然而输出是全黑的。当我绑定到GL_TEXTURE0时,纹理显示的很好。我已经修改了代码来反映Rabbid的答案,因为这些确实是错误,但不是影响这个问题的错误;该代码是反映当前问题的最新代码。
此外,我打印了tempT,它总是返回1,这意味着它每次都绑定到GL_TEXTURE0,而不管我在glActiveTexture()中调用了什么。

hwazgwia

hwazgwia1#

如果您不生成mipmaps(使用glGenerateMipmap),则设置GL_TEXTURE_MIN_FILTER非常重要。由于默认过滤器为GL_NEAREST_MIPMAP_LINEAR,因此如果您不将最小化函数更改为GL_NEARESTGL_LINEAR,纹理将为“Mipmap Incomplete”。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

此外,必须指定图像的大小(withheight),而不是(1,1):
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

不能保证stbi_load生成一个有4个颜色通道的纹理。通过显式传递4到最后一个参数,强制stbi_load生成一个有4个颜色通道的图像:
unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 0);

unsigned char* data = stbi_load("tex2.jpg", &width, &height, &channels, 4);

如果使用着色器程序,则不需要启用纹理。是否使用纹理由着色器程序决定。glEnable(GL_TEXTURE_2D);是传统OpenGL,请删除它。
除了你的代码运行良好,我测试了它。但是,纹理单元的数量是有限的。请确保你使用的纹理单元在你的系统范围内。你可以用GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS来格尔纹理单元的数量。例如:

int max_units;
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_units);
std::cout << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS " << max_units << std::endl;

此外,我打印了tempT,它总是返回1,这意味着无论我在glActiveTexture()中调用什么,它每次都绑定到GL_TEXTURE0。
纹理单元与纹理对象ID无关。tempT的值不指示纹理将绑定到的纹理单元。在将纹理与glBindTexture绑定之前,必须设置纹理单元,但它对glGenTextures没有影响。您可以将纹理绑定到多个纹理单元,或者在不同的时间分配给不同的纹理单元,纹理单元是纹理对象和纹理采样器均匀体之间的绑定点。
如果要在着色器程序中使用纹理,则需要确保该纹理绑定到纹理单元,并且该单元设置为纹理采样器均匀。
我建议在绑定纹理并使用它来绘制对象之前设置纹理单元:
第一个

相关问题