gpt4 book ai didi

c - 使用 fbo 和纹理的离屏渲染得到黑屏

转载 作者:太空宇宙 更新时间:2023-11-04 08:01:37 24 4
gpt4 key购买 nike

我正在 mac os x (10.12) 上开发一个简单的离屏渲染应用程序,但总是黑屏。我确认shader编译链接没问题,把贴图改成单色也ok。然后我注释了有关深度信息相关的代码,但没有效果。单步调试时,没有发现glGetError返回错误。以下是代码,请问有什么问题?

GLuint program;
if (compile_link_shader(vertex_shader_source, fragment_shader_source, &program) < 0) {
base_error_log("call compile_link_shader failed\n");
return -1;
}
glViewport(0, 0, target->width, target->height);

GLuint vao, vbo, ibo, loc_attr;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ibo);

glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

glBufferData(GL_ARRAY_BUFFER, sizeof(pos_coord), pos_coord, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_index), element_index, GL_STATIC_DRAW);

loc_attr = _static_cast(GLuint) glGetAttribLocation(program, "vertexPosition");
glVertexAttribPointer(loc_attr, 2, GL_FLOAT, GL_FALSE,
4 * sizeof(GLfloat), _static_cast(GLvoid*) (0 * 2 * sizeof(GLfloat)));
glEnableVertexAttribArray(loc_attr);

loc_attr = (GLuint) glGetAttribLocation(program, "textureCoordinate");
glVertexAttribPointer(loc_attr, 2, GL_FLOAT, GL_FALSE,
4 * sizeof(GLfloat), (GLvoid*) (1 * 2 * sizeof(GLfloat)));
glEnableVertexAttribArray(loc_attr);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
GLuint texture;
glGenTextures(1, &texture);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // Removed from GL 3.1 and above */

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GLenum format = origin->channels == 3 ? GL_RGB : GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, format, origin->width, origin->height, 0,
format, GL_UNSIGNED_BYTE, origin->image);
glGenerateMipmap(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, 0);

GLuint fbo;
GLuint depthBufferName;
glGenRenderbuffers(1, &depthBufferName);
glBindRenderbuffer(GL_RENDERBUFFER, depthBufferName);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, origin->width, origin->height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);

glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBufferName);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
base_error_log("glCheckFramebufferStatus not GL_FRAMEBUFFER_COMPLETE\n");
return -1;
}

glUseProgram(program);

GLint loc_uniform = glGetUniformLocation(program, "texture");
glUniform1i(loc_uniform, texture);

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glCullFace(GL_BACK);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
glEnable(GL_DEPTH_TEST);

glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, 2 * 3, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

glReadBuffer(GL_COLOR_ATTACHMENT0);
target->image = malloc(_static_cast(size_t) (target->width * target->height * target->channels));
if (!target->image) {
base_error_log("malloc target->image failed\n");
return -1;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glReadPixels(0, 0, target->width, target->height, (target->channels == 3 ? GL_RGB : GL_RGBA),
GL_UNSIGNED_BYTE, target->image);
glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(GL_FRAMEBUFFER, 0);

另一部分是:

#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
#define GLEW_STATIC
#include <GL/glew.h>
#include <OpenGL/OpenGL.h>
#include <OpenGL/gl3.h>
#include <OpenGL/gl3ext.h>
static GLfloat pos_coord[] = {
// Vertex Positions // Texture Coordinates
-1.0f, 1.0f, 0.0f, 1.0f, // Left Top
1.0f, 1.0f, 1.0f, 1.0f, // Right Top
1.0f, -1.0f, 1.0f, 0.0f, // Right Bottom
-1.0f, -1.0f, 0.0f, 0.0f, // Left Bottom
};
static GLuint element_index[] = { // Note that we start from 0 with GL_CCW!
0, 3, 2, // First Triangle
0, 2, 1, // Second Triangle
};
static const char *vertex_shader_source = ""
"#version 330 core\n"
"precision mediump float;\n"
"in vec2 vertexPosition;\n"
"in vec2 textureCoordinate;\n"
"out vec2 varyingTextureCoordinate;\n"
"void main() {\n"
" gl_Position = vec4(vertexPosition, 0.0, 1.0);\n"
" varyingTextureCoordinate = textureCoordinate;\n"
"}";
static const char *default_fragment_shader_source = ""
"#version 330 core\n"
"precision mediump float;\n"
"in vec2 varyingTextureCoordinate;\n"
"out vec4 fragmentColor;\n"
"uniform sampler2D texture;\n"
"void main() {\n"
" fragmentColor = texture(texture, varyingTextureCoordinate);\n"
/* " fragmentColor = vec4(1.0, 1.0, 0.0, 1.0);\n" */ // this line work fine
"}";

以下代码具有相同的效果:黑屏。是同一个问题吗?

glViewport(0, 0, target->width, target->height);

GLuint vao, vbo, ibo, loc_attr;
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ibo);

glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

glBufferData(GL_ARRAY_BUFFER, sizeof(pos_coord), pos_coord, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(element_index), element_index, GL_STATIC_DRAW);

loc_attr = _static_cast(GLuint) glGetAttribLocation(program, "vertexPosition");
glVertexAttribPointer(loc_attr, 2, GL_FLOAT, GL_FALSE,
4 * sizeof(GLfloat), _static_cast(GLvoid*) (0 * 2 * sizeof(GLfloat)));
glEnableVertexAttribArray(loc_attr);

loc_attr = (GLuint) glGetAttribLocation(program, "textureCoordinate");
glVertexAttribPointer(loc_attr, 2, GL_FLOAT, GL_FALSE,
4 * sizeof(GLfloat), (GLvoid*) (1 * 2 * sizeof(GLfloat)));
glEnableVertexAttribArray(loc_attr);

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);

glActiveTexture(GL_TEXTURE0);
GLuint texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
/* glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); // Removed from GL 3.1 and above */

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
GLenum format = origin->channels == 3 ? GL_RGB : GL_RGBA;
glTexImage2D(GL_TEXTURE_2D, 0, format, origin->width, origin->height, 0,
format, GL_UNSIGNED_BYTE, origin->image);
glGenerateMipmap(GL_TEXTURE_2D);

glBindTexture(GL_TEXTURE_2D, 0);

GLuint fbo;
GLuint colorBufferName, depthBufferName;

glGenRenderbuffers(1, &colorBufferName);
glBindRenderbuffer(GL_RENDERBUFFER, colorBufferName);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA, origin->width, origin->height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);

glGenRenderbuffers(1, &depthBufferName);
glBindRenderbuffer(GL_RENDERBUFFER, depthBufferName);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT32, origin->width, origin->height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);

glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferName);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBufferName);

if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
base_error_log("glCheckFramebufferStatus not GL_FRAMEBUFFER_COMPLETE\n");
return -1;
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);

glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glUseProgram(program);

GLint loc_uniform = glGetUniformLocation(program, "texture");
glUniform1i(loc_uniform, texture);

glBindTexture(GL_TEXTURE_2D, texture);
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glDrawElements(GL_TRIANGLES, 2 * 3, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);

glDrawBuffer(GL_COLOR_ATTACHMENT0);
glReadBuffer(GL_COLOR_ATTACHMENT0);

target->image = malloc(_static_cast(size_t) (target->width * target->height * target->channels));
if (!target->image) {
base_error_log("malloc target->image failed\n");
return -1;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glReadPixels(0, 0, target->width, target->height, (target->channels == 3 ? GL_RGB : GL_RGBA),
GL_UNSIGNED_BYTE, target->image);

glBindFramebuffer(GL_FRAMEBUFFER, 0);

最佳答案

texture 是写入帧缓冲区的颜色附件,纹理绑定(bind)到从中读取的纹理采样器。这是未定义的行为。

Khronos OpenGL 文档 Framebuffer Object - Feedback Loops说:

It is possible to bind a texture to an FBO, bind that same texture to a shader, and then try to render with it at the same time.
It is perfectly valid to bind one image from a texture to an FBO and then render with that texture, as long as you prevent yourself from sampling from that image. If you do try to read and write to the same image, you get undefined results. Meaning it may do what you want, the sampler may get old data, the sampler may get half old and half new data, or it may get garbage data. Any of these are possible outcomes.
Do not do this. What you will get is undefined behavior.


由于 texture 是事件帧缓冲区的颜色附件,因此 glClear命令将清除纹理:

glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

.....

glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

如果要渲染到纹理,则必须创建第二个纹理,将其附加到帧缓冲区颜色平面并写入。

另见:


答案的扩展

您必须将纹理单元的索引设置为纹理采样器统一,而不是纹理对象本身。纹理单元由 glActiveTexture 设置和 glBindTexture将纹理绑定(bind)到目标(例如 GL_TEXTURE_2D)和事件纹理单元。
顺便说一句,你必须重命名统一texture的名称,因为它与GLSL函数texture的名称相同。在下面的代码中,我使用了 u_texture

GLint loc_uniform = glGetUniformLocation( program, "u_texture" );

.....

int textureUnitIndex = 0; // 0, 1, 2 ...
glActiveTexture( GL_TEXTURE0 + textureUnitIndex );
glBindTexture( GL_TEXTURE_2D, texture );

.....

glUseProgram( program );
glUniform1i( loc_uniform, textureUnitIndex ); // <-- index of the texture unit
// NOT the texture object

关于c - 使用 fbo 和纹理的离屏渲染得到黑屏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46291313/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com