问题描述
我想为我的游戏引擎实现阴影映射,因此必须将深度视图渲染为fbo。我已经绘制了深度纹理并缩放了值,以使纹理看起来不完全是白色,并且结果看起来正确。但是,场景中的某些对象每隔一帧就会消失一次,这是以前从未发生过的事情。我简化了代码,现在看起来类似于以下内容;
- 更新统一缓冲区对象
- 绑定fbo
- 渲染为fbo
- 绑定默认fbo
- 照常渲染场景
在以下情况下,物体的闪烁消失:
渲染到fbo时使用的着色器中的统一块已删除,即使从未访问过。
我们从不绑定fbo(我们从简化的伪代码中删除了步骤(2))
我们在步骤(5)中交换一些渲染调用的顺序
我们在渲染到fbo之后更新统一缓冲区对象,即将步骤(1)移动到步骤(3)之后的某个位置。我们仅在步骤(1)内更新ubo的某些元素,但是无论更新了哪些元素,在移动该步骤时问题都会消失。请注意,完全删除步骤并不能消除错误。
我们从不渲染fbo(我们删除了步骤(3))
请注意,在步骤(5)的绘制调用的着色器内部访问了统一块。我创建了一个相同的统一缓冲区对象,并在渲染到fbo时使用的着色器内部访问了该对象,而闪烁消失了,所以看起来问题是我在渲染到fbo时正在访问同一ubo就像我渲染到默认帧缓冲区时一样。但是,据我所知这不是问题。我正在使用统一块内的所有变量,因此似乎已正确初始化。
编辑: 我已尽力简化了代码。在简化了一个着色器之后,渲染的对象将完全消失而不是闪烁,但这并不能使问题变得更好。不可见的渲染调用是“渲染调用B”。以上所有观察仍然成立。在下面的代码中已经进行了一些新的观察,并对此进行了注释。
完整的源代码:
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <assert.h>
static void AttachShader(unsigned int program,GLenum type,const std::string& source)
{
unsigned int shader = glCreateShader(type);
const char* cString = source.c_str();
glShaderSource(shader,1,&cString,NULL);
glCompileShader(shader);
int status;
glGetShaderiv(shader,GL_COMPILE_STATUS,&status);
assert(status);
glAttachShader(program,shader);
}
int main(void)
{
GLFWwindow* window;
/* Initialize the library */
if (!glfwInit())
return -1;
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640,480,"Hello World",NULL,NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
GLenum err = glewInit();
assert(GLEW_OK == err);
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
static bool first = true;
static unsigned int vao;
static unsigned int framebuffer;
static unsigned int shadowMapTexture;
static unsigned int uniformBuffer;
static unsigned int programA;
static unsigned int programB;
static float identity[16] =
{ 1.0f,0.0f,1.0f,1.0f };
if (first)
{
first = false;
//Creating program A
{
programA = glCreateProgram();
AttachShader(programA,GL_VERTEX_SHADER,"#version 450 core\n\
\n\
//If the data block gets commented the issue goes away\n\
layout(std140,binding = 0) uniform DataBlock\n\
{\n\
mat4 identity;\n\
}dataBlock;\n\
\n\
\n\
void main()\n\
{\n\
vec3 positions[3] = { vec3(-0.5,-0.25,-0.2),vec3(0.0,vec3(-0.25,0.25,-0.2) };\n\
gl_Position = vec4(positions[gl_VertexID],1.0);\n\
}");
AttachShader(programA,GL_FRAGMENT_SHADER,"#version 450 core\n\
out vec4 colour;\n\
\n\
void main()\n\
{\n\
colour = vec4(1.0,1.0,0.0,1.0);\n\
}");
glLinkProgram(programA);
int status;
glGetProgramiv(programA,GL_LINK_STATUS,&status);
assert(status);
}
//Creating program B
{
programB = glCreateProgram();
AttachShader(programB,"#version 450 core\n\
\n\
layout(location = 0) in int index;\n\
layout(location = 1) uniform mat4[2] matrices;\n\
\n\
layout(std140,binding = 0) uniform DataBlock\n\
{\n\
mat4 identity;\n\
}dataBlock;\n\
\n\
void main()\n\
{\n\
\n\
vec3 positions[3] = { vec3(-0.25,vec3(0.25,-0.2) };\n\
\n\
vec4 pos = vec4(positions[gl_VertexID],1.0);\n\
\n\
//If \"index\" is substituted by \"0\" the problem goes away\n\
vec4 secondPos = matrices[index] * pos;\n\
\n\
//If \"secondPos\" is substituted by \"pos\" the problem remains\n\
//If we remove \"dataBlock.identity *\" the problem goes away\n\
gl_Position = dataBlock.identity*secondPos;\n\
}");
AttachShader(programB,"#version 450 core\n\
\n\
out vec4 colour;\n\
\n\
void main()\n\
{\n\
colour = vec4(0.0,1.0);\n\
}");
glLinkProgram(programB);
int status;
glGetProgramiv(programB,&status);
assert(status);
}
//Creating the vao used inside shader "B"
{
glCreateVertexArrays(1,&vao);
unsigned int vertexBuffer;
glCreateBuffers(1,&vertexBuffer);
int vertexData[3] = { 0,0 };
glNamedBufferData(vertexBuffer,sizeof(int) * 3,vertexData,GL_STATIC_DRAW);
glVertexArrayVertexBuffer(vao,vertexBuffer,sizeof(int));
glVertexArrayAttribBinding(vao,0);
glVertexArrayAttribIFormat(vao,GL_INT,0);
glEnableVertexArrayAttrib(vao,0);
}
//Creating the framebuffer
{
glCreateFramebuffers(1,&framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER,framebuffer);
glGenTextures(1,&shadowMapTexture);
glBindTexture(GL_TEXTURE_2D,shadowMapTexture);
glTexStorage2D(GL_TEXTURE_2D,GL_DEPTH_COMPONENT32F,512,512);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glFramebufferTexture(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,shadowMapTexture,0);
unsigned int drawBuffers[] = { GL_NONE };
glDrawBuffers(1,drawBuffers);
assert(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
}
//Creating the uniform buffer object
{
glCreateBuffers(1,&uniformBuffer);
glNamedBufferStorage(uniformBuffer,sizeof(float)*16,GL_DYNAMIC_STORAGE_BIT);
glBindBufferBase(GL_UNIFORM_BUFFER,uniformBuffer);
glNamedBufferSubData(uniformBuffer,sizeof(float) * 16,identity);
}
//Creating and binding a vao for compatability with the core profile
static unsigned int emptyVao;
glCreateVertexArrays(1,&emptyVao);
glBindVertexArray(emptyVao);
}
//Step 2,binding the fbo
glBindFramebuffer(GL_FRAMEBUFFER,framebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
//End of step 2
//Step 3,rendering to fbo
{
glUseProgram(programA);
glDrawArrays(GL_TRIANGLES,3);
}
//If we update the uniform buffer here the issue disappears,i.e. if the following line gets uncommented
{
//glNamedBufferSubData(uniformBuffer,identity);
}
//Step 4,binding the default fbo
glBindFramebuffer(GL_FRAMEBUFFER,0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//If the following line gets uncommented the issue goes away
//glUseProgram(programB);
//Render call A
glUseProgram(programA);
glDrawArrays(GL_TRIANGLES,3);
//Render call B
glBindVertexArray(vao);
glUseProgram(programB);
float* matrices = new float[sizeof(float) * 16 * 2];
for (size_t i = 0; i < 2; ++i)
{
memcpy((char*)matrices + i * sizeof(float) * 16,(char*)identity,sizeof(float) * 16);
}
glUniformMatrix4fv(1,2,GL_FALSE,matrices);
glDrawArrays(GL_TRIANGLES,3);
assert(glGetError() == 0);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
程序A:
顶点着色器:
#version 450 core
//If the data block gets commented the issue goes away
layout(std140,binding = 0) uniform DataBlock
{
mat4 identity;
}dataBlock;
void main()
{
vec3 positions[3] = { vec3(-0.5,-0.2) };
gl_Position = vec4(positions[gl_VertexID],1.0);
}
片段着色器:
#version 450 core
out vec4 colour;
void main()
{
colour = vec4(1.0,1.0);
}
程序B:
顶点着色器:
#version 450 core
layout(location = 0) in int index;
layout(location = 1) uniform mat4[2] matrices;
layout(std140,binding = 0) uniform DataBlock
{
mat4 identity;
}dataBlock;
void main()
{
vec3 positions[3] = { vec3(-0.25,-0.2) };
vec4 pos = vec4(positions[gl_VertexID],1.0);
//If "index" is substituted by "0" the problem goes away
vec4 secondPos = matrices[index] * pos;
//If "secondPos" is substituted by "pos" the problem remains
//If we remove "dataBlock.identity *" the problem goes away
gl_Position = dataBlock.identity*secondPos;
}
片段着色器:
#version 450 core
out vec4 colour;
void main()
{
colour = vec4(0.0,1.0);
}
glGetError()仅返回零。我完全迷路了,不知道如何进行。非常感谢您的帮助。
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)