为什么这种质地显示全黑?

发布于 2025-01-26 15:08:08 字数 5599 浏览 2 评论 0原文

这是我调用所有抽奖操作的功能。我还会在功能中编译着阴暗器内联。当我只为每个顶点使用颜色时,它正确显示了四边形,但纹理根本不想工作。

这是代码:

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时,纹理显示正常。我已经更改了代码以反映拉比德的回答,因为这些确实是错误,而不是影响这个问题的错误。代码是最新的,反映了当前问题。

另外,我打印了诱惑,它始终返回为1,这意味着它每次都绑定到gl_texture0,尽管我在glactiveTexture()中都称为。

Here is the function where I am calling all of my draw operations. I also compile the shaders inline in the function. It displays the quad correctly when I just use colors for each vertex but textures don't want to work at all.

Here is the code:

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

}

For some reason, when I instead put the texture bound to GL_TEXTURE0 it displays the texture.

Edit:
I am making a further edit, as the content of my original question did not properly address the problem. It seems that I am unable to Bind any texture to any texture other than GL_TEXTURE0. I have seen other forums with this problem but the answers in those problems all address other issues that are not present here. As you can see I am trying to bind this texture to GL_TEXTURE10, however the output is all black. When I bind to GL_TEXTURE0 however, the texture shows up fine. I have changed the code to reflect Rabbid's answer as those were indeed errors but not errors that affected this problem; the code is up to date reflecting the current problem.

Also, I printed tempT and it always returns as 1, meaning it is binding to GL_TEXTURE0 every time despite what I call in glActiveTexture().

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

沐歌 2025-02-02 15:08:08

如果您不生成 mipmaps (with glgeneratemipmap )很重要的是设置gl_texture_min_min_min_min_filter 。由于默认过滤器为gl_nearest_mipmap_linear,因此,如果您不将最小功能更改为gl_nearestgl_linearear,则纹理将是“ mipmap contote”。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

此外,必须指定图像的大小(,, height ),而不是(1,1):

glteximage2d(gl_texture_2d,0,0,0,0,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个颜色通道的纹理。强迫stbi_load通过明确将4传递到最后一个参数:

unsigned char* data = stbi_load(“ tex2.jpg”,&amp; width, ,&amp; height,&amp; channels,0);

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

如果使用着色器程序,则无需启用纹理。是否使用纹理是在着色器程序中确定的。 glenable(gl_texture_2d);是旧版OpenGL,将其删除。


除了您的代码正常工作外,我还对其进行了测试。但是,纹理单元的数量受到限制。确保在系统范围内使用纹理单元。您可以使用 /代码> 。例如:

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

另外,我打印诱惑,它总是返回为1,这意味着它每次都绑定到gl_texture0,尽管我在glactiveTexture()中所说的东西()

纹理单元与纹理对象ID无关。 诱惑的值不会覆盖纹理将被弹跳的纹理单元。您必须在用glbindTexture将纹理绑定之前设置纹理单元,但对glgentextures没有影响。您可以将纹理绑定到多个纹理单元,或在不同时间与不同的纹理单元。纹理单元是纹理对象和纹理采样器均匀的绑定点。
如果要在着色器程序中使用纹理,则需要确保纹理绑定到纹理单元,并且该单元设置为纹理采样器均匀。

我建议在绑定纹理之前设置纹理单元并使用它来绘制对象:

GLint t_location = glGetUniformLocation(shaderProgram2, "t")
glUseProgram(shaderProgram2);
glUniform1i(t_location, 10);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, tempT);
glDrawArrays(GL_TRIANGLES, 0, 6);

If you are not generating mipmaps (with glGenerateMipmap) it is important to set GL_TEXTURE_MIN_FILTER. Since the default filter is GL_NEAREST_MIPMAP_LINEAR, the texture would be "Mipmap Incomplete" if you do not change the minimize function to GL_NEAREST or GL_LINEAR.

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

In addition, the size of the image (with, height) must be specified instead of (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);

It is not guaranteed that stbi_load generates a texture with 4 color channels. Force the stbi_load to generate an image with 4 color channels, by explicitly pass 4 to the last parameter:

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

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

If you use a shader program, you don't need to enable texturing. Whether the texture is used or not is decided in the shader program. glEnable(GL_TEXTURE_2D); is legacy OpenGL, remove it.


Aside from your code working fine, I tested it. However, the number of texture units is limited. Make sure you use a texture unit within range of your system. You can ger the number of texture units with GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS. e.g.:

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

Also, I printed tempT and it always returns as 1, meaning it is binding to GL_TEXTURE0 every time despite what I call in glActiveTexture().

The texture unit has nothing to do with the texture object ID. The value of tempT does not inidcate the texture unit in which the texture will be bouned. You must set the texture unit before binding the texture with glBindTexture, but it has no effect on glGenTextures. You can bind the texture to multiple texture units, or to different texture units at different times. The texture unit is the binding point between the texture object and the texture sampler uniform.
If you want to use a texture in a shader program, you need to make sure that the texture is bound to a texture unit and that unit is set to texture sampler uniform.

I suggest setting the texture unit before binding the texture and using it to draw the object:

GLint t_location = glGetUniformLocation(shaderProgram2, "t")
glUseProgram(shaderProgram2);
glUniform1i(t_location, 10);
glActiveTexture(GL_TEXTURE10);
glBindTexture(GL_TEXTURE_2D, tempT);
glDrawArrays(GL_TRIANGLES, 0, 6);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文