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