【问题标题】:How to get camera movement when using openGL framebuffers使用openGL帧缓冲区时如何获得相机运动
【发布时间】:2020-07-29 00:14:05
【问题描述】:

我一直在编写一个程序来可视化分形点云,到目前为止一切正常,相机移动使用以原点为中心的弧球移动,并且正在渲染点。但是,我需要将场景输出到 UI 内的集成窗口中,所以我一直在尝试让帧缓冲区工作。

到目前为止,我已经成功地将纹理渲染到四边形上,然后我将其输出到屏幕上,出于测试目的,这与我不使用 fbo 时基本相同。我的问题出现在尝试让相机移动也使用渲染纹理显示时。我知道这绝对是可能的,因为有很多这样的例子,但我无法让任何人使用我的代码。我相当确定我的问题出在我的着色器上,但我搜索了很多网站、YouTube 教程、openGL 示例,但没有发现任何可行的方法。据我所知,我必须正常渲染场景,所以我一直在使用之前为我工作的相同着色器进行初始渲染步骤,但我使用的是我的 fbo 而不是默认的 fbo

为简单起见,我刚刚渲染了一个点立方体,因为它比每次生成分形都快。

这里是 fbo、纹理和 rbo 的主要设置:

GLuint fbo;
GLuint texturebuffer;
GLuint rbo;
void initFBO(){
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);

    glGenTextures(1, &texturebuffer);
    glBindTexture(GL_TEXTURE_2D, texturebuffer);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, WINDOW_WIDTH, WINDOW_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texturebuffer, 0);

    glGenRenderbuffers(1, &rbo);
    glBindRenderbuffer(GL_RENDERBUFFER, rbo);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, WINDOW_WIDTH, WINDOW_HEIGHT);
    glBindRenderbuffer(GL_RENDERBUFFER, 0); // once rbo memory allocated unbind
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
}

这里是主循环和绘制循环:

int main(){
    if(!setup())
        return -1;

    // // white background
    glClearColor(1.0f, 1.0f, 1.0f, 0.0f);

    GLuint VertexArrayID;
    glGenVertexArrays(1, &VertexArrayID);
    glBindVertexArray(VertexArrayID);

    // GLuint programID = LoadShaders( "new_vertex_shader", "new_fragment_shader" ); // custom shader
    GLuint programID = LoadShaders("new_vertex_shader", "new_fragment_shader");
    GLuint modelMatrixID = glGetUniformLocation(programID, "model");
    GLuint viewMatrixID = glGetUniformLocation(programID, "view");    
    GLuint matrixID = glGetUniformLocation(programID, "MVP");

    GLuint quad_programID = LoadShaders( "screen_vertex_shader", "screen_fragment_shader" );
    GLuint textureID = glGetUniformLocation(quad_programID, "screenTexture");

    // initialise mvp matrices
    glm::mat4 ProjectionMatrix = perspective(radians(45.0f), 4.0f / 3.0f, 0.1f, 100.0f);
    glm::mat4 ViewMatrix = translate(mat4(1.0f), vec3(0,0,-RADIUS));
    glm::mat4 ModelMatrix = mat4(1.0f);
    glm::mat4 MVP;

    GLuint vertexbuffer;
    glGenBuffers(1, &vertexbuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);

    GLfloat cube[24] = {
        0.5,0.5,0.5,
        0.5,-0.5,0.5,
        -0.5,0.5,0.5,
        -0.5,-0.5,0.5,
        0.5,0.5,-0.5,
        0.5,-0.5,-0.5,
        -0.5,-0.5,-0.5,
        -0.5,0.5,-0.5
    };
    glBufferData(GL_ARRAY_BUFFER, sizeof(cube),cube, GL_STATIC_DRAW);

    glfwSetMouseButtonCallback(window, mouseCallback);


    // ################# main draw loop #######################
    while( glfwGetKey(window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose(window) == 0 ){

        // render to fbo first
        glBindFramebuffer(GL_FRAMEBUFFER, fbo);
        glEnable(GL_DEPTH_TEST);
        glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        computeMatricesFromInputs();
        ProjectionMatrix = getProjectionMatrix();
        ViewMatrix = getViewMatrix();
        ModelMatrix = getModelMatrix();
        MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;

        // Use our shader
        glUseProgram(programID);

        // Send our transformation to the currently bound shader in the "MVP" uniform
        glUniformMatrix4fv(matrixID, 1, GL_FALSE, &MVP[0][0]);
        glUniformMatrix4fv(modelMatrixID, 1, GL_FALSE, &ModelMatrix[0][0]);
        glUniformMatrix4fv(viewMatrixID, 1, GL_FALSE, &ViewMatrix[0][0]);

        // render scene as normal
        glEnableVertexAttribArray(0);
        glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer); // index buffer
        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
        );

        glPointSize(POINT_SIZE);
        glDrawArrays(GL_POINTS, 0, sizeof(cube));
        glDisableVertexAttribArray(0);


        // bind back to default frame buffer to show on screen
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        glDisable(GL_DEPTH_TEST);
        glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glUseProgram(quad_programID);

        glEnableVertexAttribArray(0);
        glBindVertexArray(quad_vertex_buffer);

        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
        );
        glDrawArrays(GL_POINTS, 0, sizeof(cube));
        glDisableVertexAttribArray(0);

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

顶点着色器:

#version 330 core

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

// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 view;
uniform mat4 model;

void main(){

    // Output position of the vertex, in clip space : MVP * position
    gl_Position =  MVP * vec4(vertexPosition_modelspace,1.0);

}

片段着色器:

#version 330 core

// Output data
out vec3 color;

void main(){

    // Output color = black 
    color = vec3(0,0,0);

}

屏幕四边形顶点着色器:

#version 330 core
layout (location = 0) in vec2 aPos;
layout (location = 1) in vec2 aTexCoords;

out vec2 TexCoords;

void main()
{
    TexCoords = aTexCoords;
    gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
}

屏幕四边形片段着色器:

#version 330 core
out vec4 FragColour;

in vec2 TexCoords;

uniform sampler2D screenTexture;

void main()
{
    FragColour = texture(screenTexture, TexCoords);
}

对不起,如果这是一个相当大的代码块,我不完全确定错误在哪里,而且我对使用 openGL 有点陌生。非常感谢您的任何帮助。

【问题讨论】:

  • 你为什么只画GL_POINTS原语?第二遍必须渲染一个屏幕空间四边形(例如 2 GL_TRIANGLES primitives)。 quad_vertex_buffer 是什么?你为什么在glBindVertexArray之前glEnableVertexAttribArray?注意,glEnableVertexAttribArray 更改了Vertex Array Object 中的状态。
  • 我已经将第二遍更改为使用GL_TRIANGLESquad_vertex_buffer 保存屏幕四顶点数组,因此我将其重命名为quadvao,我认为这更合适。我现在在glBindVertexArray 之后移动了glEnableVertexAttribArray,但我仍然遇到屏幕四边形上没有显示纹理的问题。如果可能的话,我可以尝试提供更多信息,但就像我提到的那样,我对 openGL 大多是新手,所以不确定需要执行的顺序。

标签: c++ opengl opengl-3


【解决方案1】:

glEnableVertexAttribArray 更改Vertex Array Object 中的状态。必须在glBindVertexArray绑定VAO后完成。
我假设quad_vertex_buffer 是一个顶点数组对象,即使名称“vertex_buffer”具有误导性。

glBindVertexArray(quad_vertex_buffer);
glEnableVertexAttribArray(0);

当您绘制屏幕空间四边形(第二遍)时,您必须使用primitive 类型来生成(填充)多边形(可能是GL_TRIANGLESGL_TRIANGLE_STRIP),而不是点基本类型@ 987654331@:

glDrawArrays(GL_POINTS, 0, sizeof(cube));

glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(cube))

【讨论】:

  • 感谢您的回复,但是当我在第二次通过时使用 GL_TRIANGLES 或 GL_TRIANGLE_STRIP 时,而不是只获取渲染立方体的点,这正是我要寻找的,我当然会得到一个矩形。我仍然有未应用相机移动的问题。
  • @SuperSpudDude 摄像机运动应用于第一次传递中的点。但请注意MVP 永远不会改变,它是不变的。
猜你喜欢
  • 2014-06-26
  • 1970-01-01
  • 2013-12-19
  • 2012-04-12
  • 2013-01-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多