OpenGL纹理显示为黑色

0md85ypi  于 2022-11-04  发布在  其他
关注(0)|答案(2)|浏览(297)

我是第一次使用OpenGL与GLFW,GLEW和GLM。我已经或多或少遵循教程,但也转移,以集中在我感兴趣的方面的时刻。
目前,我正在尝试将像素绘制到纹理上,然后在屏幕上显示为全屏四边形。但是,纹理总是显示为黑色,我不确定哪里出错了。
在此处初始化纹理(以及全屏四元菜单):

int InitializeRenderTarget(GameManager* gameManager)
{
    // Vertex Array Object
    GLuint vertexArrayID;
    glGenVertexArrays(1, &vertexArrayID);
    glBindVertexArray(vertexArrayID);

    programID = LoadShaders("Source/Graphics/SimpleVertexShader.vert", "Source/Graphics/RenderTextureFragmentShader.frag");

    // The texture we're going to render to
    glGenTextures(1, &renderedTexture);
    glBindTexture(GL_TEXTURE_2D, renderedTexture);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
        gameManager->GRID_SIZE, gameManager->GRID_SIZE,
        0, GL_RGB, GL_UNSIGNED_BYTE, 0);
    glGenerateMipmap(GL_TEXTURE_2D);

    // The fullscreen quad's FBO
    static const GLfloat g_quad_vertex_buffer_data[] = {
        -1.0f, -1.0f, 0.0f, //0.0f, 0.0f,
         1.0f, -1.0f, 0.0f, //1.0f, 0.0f,
        -1.0f,  1.0f, 0.0f, //0.0f, 1.0f,
        -1.0f,  1.0f, 0.0f, //0.0f, 1.0f,
         1.0f, -1.0f, 0.0f, //1.0f, 0.0f,
         1.0f,  1.0f, 0.0f, //1.0f, 1.0f
    };

    glGenBuffers(1, &quad_vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC_DRAW);

    texID = glGetUniformLocation(programID, "renderedTexture");

    glEnable(GL_TEXTURE_2D);

    return 0;
}

在此处绘制纹理:

void RenderToTexture(GameManager* gameManager)
{
    glBindTexture(GL_TEXTURE_2D, renderedTexture);

    float* particleColors = gameManager->getParticleColors();
    glTexSubImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
        gameManager->GRID_SIZE, gameManager->GRID_SIZE,
        0, GL_RGB, GL_FLOAT, (GLvoid*)particleColors);
    glGenerateMipmap(GL_TEXTURE_2D);

    // Poor filtering
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}

在此处绘制到屏幕:

void RenderToScreen()
{
    // Render to the screen
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    // Render on the whole framebuffer, complete from the lower left corner to the upper right
    glViewport(100, 100, screenWidth-200, screenHeight-200);

    // Clear the screen
    glClearColor(0.0f, 0.0f, 0.4f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // Use our shader
    glUseProgram(programID);

    // Bind our texture in Texture Unit 0
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, renderedTexture);
    // Set our "renderedTexture" sampler to use Texture Unit 0
    glUniform1i(texID, 0);

    // 1rst attribute buffer : vertices
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
    glVertexAttribPointer(
        0,                  // attribute 0. No particular reason for 0, but must match the layout in the shader.
        3,                  // size
        GL_FLOAT,           // type
        GL_FALSE,           // normalized?
        0,  // stride
        (void*)0            // array buffer offset
    );

    // Draw the triangles !
    glDrawArrays(GL_TRIANGLES, 0, 6); // 2*3 indices starting at 0 -> 2 triangles

    glDisableVertexAttribArray(0);

    // Swap buffers
    glfwSwapBuffers(window);
    glfwPollEvents();
}

主循环:

int main(void)
{
    if (InitializeWindow() != 0) {
        fprintf(stderr, "Failed to open GLFW window.\n");
        getchar();
        glfwTerminate();
        return -1;
    }

    GameManager* gameManager = gameManager->getInstance();

    if (InitializeRenderTarget(gameManager) != 0) {
        fprintf(stderr, "Failed to initialize render target.\n");
        getchar();
        glfwTerminate();
        return -1;
    }

    do {
        gameManager->Update();
        RenderToTexture(gameManager);
        RenderToScreen();
    } // Check if the ESC key was pressed or the window was closed
    while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS &&
        glfwWindowShouldClose(window) == 0);

    CleanUp();

    return 0;
}

顶点着色器:


# version 460 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;

// Output data ; will be interpolated for each fragment.
out vec2 UV;

void main(){
    gl_Position =  vec4(vertexPosition_modelspace, 1);
    UV = (vertexPosition_modelspace.xy+vec2(1,1))/2.0;
}

最后是片段着色器:


# version 460 core

in vec2 UV;

out vec4 color;

uniform sampler2D renderedTexture;

void main(){
    color = texture(renderedTexture, UV);
    //color = vec4(UV.x, UV.y, 0, 1);
}

我很确定我把四边形正确地绘制到了屏幕上,因为我在片段着色器中使用了注解掉的行来制作一个漂亮的彩色渐变效果。但是,我可能没有正确地绑定纹理。
我确认了particleColors数组确实包含正确的浮点值。我尝试将所有红色设置为1.0f,将所有值设置为1.0f,并将所有值设置为255.0f(以防万一)。
我试着添加这样的行:

glEnable(GL_TEXTURE_2D);

glGenerateMipmap(GL_TEXTURE_2D);

// Poor filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

基于我看到的其他一些帖子,但我还没有看到任何明显的效果。
我还尝试改变顶点和片段着色器的计算和使用UV的方式,但这只会让事情变得更糟,因为渐变效果甚至不会出现在这一点上。
希望你能找出我错过了什么。谢谢你的帮助。

sd2nnvve

sd2nnvve1#

你完全用错了glTexSubImage2D,第二个和第三个参数是偏移量,第四个和第五个参数是大小:
glTexSubImage2D(GL_TEXTURE_2D, 0, GL_RGBA, gameManager->GRID_SIZE, gameManager->GRID_SIZE, 0, GL_RGB, GL_FLOAT, (GLvoid*)particleColors);

glTexSubImage2D(
    GL_TEXTURE_2D, 0, 
    0, 0, gameManager->GRID_SIZE, gameManager->GRID_SIZE,
    GL_RGB, GL_FLOAT, (GLvoid*)particleColors);

glEnable(GL_TEXTURE_2D);仅在使用固定函数管道且没有着色器程序时才有意义。

fjnneemd

fjnneemd2#

我已经想通了,Rabbid76的修正,是很大的第一步。
之后我用我的像素数组玩了一些,在把它变小之后,我发现在我的纹理底部确实有一小行像素。再仔细检查一下,我发现我实际上填充了错误的像素数据。在我的循环中修复了错误的逻辑,正确地填充了纹理。

相关问题