【发布时间】:2014-06-04 20:13:20
【问题描述】:
我目前正在开发一个带有(尚未实现)后期效果的应用程序。因此 3D 场景在缓冲区中渲染,然后另一个着色器在屏幕上渲染缓冲区。
我的问题是程序在第二遍中使用我的基本着色器来处理 3d 场景而不是后期效果着色器。你有什么想法,可以这样做吗?
我的方法:我有一个有两个主要功能的类: - bindBuffer() 将渲染目标设置为缓冲区 - renderSSAO() 将缓冲区渲染到屏幕上,并且有朝一日会添加环境光遮蔽效果。 :)
绑定缓冲区功能
void SSAOShader::bindBuffer() {
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glViewport(0,0,windowWidth,windowHeight);
}
渲染函数
void SSAOShader::renderSSAO(GLuint currentShader) {
// set shader
glUseProgram(shader);
//draw on Screen
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glViewport(0,0,windowWidth,windowHeight);
// clear screen
glClearColor(0.4, 0.4, 0.4, 1.0);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
// bind texture, pass to shader
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, renderTexture);
glUniform1i(textureID, 0);
glBindVertexArray(vertexarray);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
glBindVertexArray(0);
glUseProgram(currentShader);
}
渲染循环(函数来自ssaoShader-object)
while (!glfwWindowShouldClose(mainWindow)) {
ssaoShader->bindBuffer();
// clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// draw cool stuff
ssaoShader->renderSSAO(programID);
// Swap buffers
glfwSwapBuffers(mainWindow);
glUseProgram(programID);
}
所以基本上,渲染目标通过bindBuffer(); 设置到我的缓冲区,然后我用我的基本(phong 等)着色器绘制对象,renderSSAO 函数将目标更改为我的屏幕。此函数还将着色器更改为我的后期效果着色器,并将其更改回之前的状态。 programID 是着色器 GLuint。
我知道问题出在使用的着色器上,因为结果是我在世界原点只有一个带有四边形的黑屏。我也可以像往常一样四处走动。
构造者
SSAOShader::SSAOShader(float windowWidth, float windowHeight, GLuint currentShader) {
this->windowWidth = windowWidth;
this->windowHeight = windowHeight;
//shader
shader = LoadShaders("Passthrough.vertexshader", "SSAO.fragmentshader");
glUseProgram(shader);
textureID = glGetUniformLocation(shader, "renderTexture");
int status;
glGetProgramiv(shader, GL_COMPILE_STATUS, &status);
std::cout << (status == GL_TRUE) << std::endl;
GLfloat planeVertices[] = {
-1, -1,
1, -1,
-1, 1,
1, 1
};
// create vertex array
glGenVertexArrays(1, &vertexarray);
glBindVertexArray(vertexarray);
// create "uv" (vertex) buffer
glGenBuffers(1, &vertexbuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(planeVertices), planeVertices, GL_STATIC_DRAW);
// add vertecies to as attributes
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);
glBindVertexArray(0);
// ---- set up framebuffer ----
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glGenTextures(1, &renderTexture);
glBindTexture(GL_TEXTURE_2D, renderTexture);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, windowWidth, windowHeight, 0,GL_RGB, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glGenRenderbuffers(1, &depthrenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthrenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, windowWidth, windowHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthrenderbuffer);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderTexture, 0);
DrawBuffers[1] = GL_COLOR_ATTACHMENT0;
glDrawBuffers(1, DrawBuffers);
if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE){
exit(0); // bad luck
}
glBindFramebuffer(GL_FRAMEBUFFER, 0);
//glUseProgram(currentShader);
}
VS2012 项目 https://studi.f4.htw-berlin.de/~s0539750/SSAOTest.zip
对于那些疯狂到看我的代码的人。 ;)
【问题讨论】:
-
你程序的着色器编译正确并且链接很好?顺便说一句,您应该使用与程序相关的名称而不是着色器来调用着色器程序。这有点令人困惑。一开始我以为你是在着色器上调用
glUseProgram。 -
我对 openGL 很陌生,所以我必须习惯这样的东西。 ;) 应用程序告诉我没有编译错误。但是,我只是使用了这个函数,它在
GL_TRUE == status上返回 0:glGetShaderiv(shader, GL_COMPILE_STATUS, &status);我仍然使用一个为我编译程序的小函数,来自这个页面:opengl-tutorial.org 但是编译时它不会返回任何错误。这可能是什么原因? -
如果在
glUseProgram(shader)之前和之后调用glGetError(),返回值分别是多少? -
等等等等,所以着色器是一个着色器,而不是一个程序。之后你需要将着色器链接到一个程序,然后你使用这个程序与
glUseProgram -
不,“shader”是一个程序。 (对不起)glGetError 的两个调用都返回 GL_NO_ERROR
标签: opengl shader framebuffer