我正在处理我的 ssr 演示,因此我需要将一些渲染数据存储到纹理中以进行后期处理。但是当我使用这些纹理时,似乎在paintGL 中只能激活一个纹理单元:
//I did a small test
//enable texture unit
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gPosition);
//bind gColor to TEXTURE0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gColor);
之后我可以确保渲染数据是正确的。但我无法在我的着色器中正确使用它,我测试了 gNormal、gColor、gPosition。但它们都显示与 gPosition 相同的图片。有人能帮我吗?
void fboTest::initShaders()
{
//render to framebuffer
QString vFrameBuffer ("#version 330 core\n"
"layout (location = 0) in vec3 aPos;\n"
"layout (location = 1) in vec3 aNormal;\n"
"out float PosY;\n"
"out vec3 FragPos;\n"
"out vec3 Normal;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"void main()\n"
"{\n"
" PosY = aPos.y + 0.3;\n"
" FragPos = aPos.xyz;\n"
" Normal = aNormal;\n"
" gl_Position = projection * view * model * vec4(aPos, 1.0);\n"
"}\n");
QString fFrameBuffer("#version 330 core\n"
"layout (location = 0) out vec3 gPosition;\n"
"layout (location = 1) out vec3 gNormal;\n"
"layout (location = 2) out vec3 gColor;\n"
"in float PosY;\n"
"in vec3 FragPos;\n"
"in vec3 Normal;\n"
"void main()\n"
"{\n"
" gPosition = FragPos;\n"
" gNormal = normalize(Normal);\n"
" gColor = vec3(PosY, PosY + 0.2, PosY + 0.5);\n"
" //gPosition = gColor;\n"
"}\n");
shaderGeoPass.create();
shaderGeoPass.addShaderFromSourceCode(QOpenGLShader::Vertex, vFrameBuffer);
shaderGeoPass.addShaderFromSourceCode(QOpenGLShader::Fragment, fFrameBuffer);
shaderGeoPass.link();
//render to quad
QString vQuad("#version 330 core\n"
"layout (location = 0) in vec2 aPos;\n"
"layout (location = 1) in vec2 aTexCoords;\n"
"out vec2 TexCoords;\n"
"void main()\n"
"{\n"
" TexCoords = aTexCoords;\n"
" gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0); \n"
"}\n");
QString fQuad("#version 330 core\n"
"out vec4 FragColor;\n"
"in vec2 TexCoords;\n"
"uniform sampler2D gPosition;\n"
"uniform sampler2D gNormal;\n"
"uniform sampler2D gColor;\n"
"void main()\n"
"{\n"
//gPosition, gColor, gNormal get the same value???
" vec3 col = texture(gPosition, TexCoords).rgb;\n"
" FragColor = vec4(col, 1.0f);\n"
"} ");
shaderReflectPass.create();
shaderReflectPass.addShaderFromSourceCode(QOpenGLShader::Vertex, vQuad);
shaderReflectPass.addShaderFromSourceCode(QOpenGLShader::Fragment, fQuad);
shaderReflectPass.link();
shaderReflectPass.setUniformValue(shaderReflectPass.uniformLocation("gPosition"), 0);
shaderReflectPass.setUniformValue(shaderReflectPass.uniformLocation("gNormal"), 1);
shaderReflectPass.setUniformValue(shaderReflectPass.uniformLocation("gColor"), 2);
}
油漆GL:
void fboTest::paintGL()
{
glDisable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//enable texture unit
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, gColor);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, gNormal);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, gColor);
shaderReflectPass.bind();
glBindVertexArray(quadVAO);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
初始化GL:
initializeOpenGLFunctions();
initShaders();
initVAOs();
initFrameBuffer();
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glEnable(GL_DEPTH_TEST);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, SCR_WIDTH, SCR_HEIGHT);
shaderGeoPass.bind();
QMatrix4x4 model;
QMatrix4x4 view;
QMatrix4x4 projection;
view.lookAt({0, 0, 3}, {0, 0, 0}, {0, 1, 0});
projection.perspective(45.0f,static_cast<float>(SCR_WIDTH)/static_cast<float>(SCR_HEIGHT),0.1f,100.0f);
//render two cube
glBindVertexArray(cubeVAO);
model.translate(QVector3D(-1.0f, 0.0f, -1.0f));
shaderGeoPass.setUniformValue(shaderGeoPass.uniformLocation("model"), model);
shaderGeoPass.setUniformValue(shaderGeoPass.uniformLocation("view"), view);
shaderGeoPass.setUniformValue(shaderGeoPass.uniformLocation("projection"), projection);
glDrawArrays(GL_TRIANGLES, 0, 36);
model.setToIdentity();
model.translate(QVector3D(2.0f, 0.0f, 0.0f));
shaderGeoPass.setUniformValue(shaderGeoPass.uniformLocation("model"), model);
glDrawArrays(GL_TRIANGLES, 0, 36);
//render floor
glBindVertexArray(planeVAO);
model.setToIdentity();
shaderGeoPass.setUniformValue(shaderGeoPass.uniformLocation("model"), model);
glDrawArrays(GL_TRIANGLES, 0, 6);
初始化帧缓冲区:
void fboTest::initFrameBuffer()
{
//first generate framebuffer object
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
//set up G-Buffer
//1.positions
//2.color
//3.normal
//1.positions
glGenTextures(1, &gPosition);
glBindTexture(GL_TEXTURE_2D, gPosition);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, gPosition, 0);
//2.normal
glGenTextures(1, &gNormal);
glBindTexture(GL_TEXTURE_2D, gNormal);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, gNormal, 0);
//3.color
glGenTextures(1, &gColor);
glBindTexture(GL_TEXTURE_2D, gColor);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2, GL_TEXTURE_2D, gColor, 0);
//4.tell opengl which color attachment we'll use for rendering
unsigned int attachments[3] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2 };
glDrawBuffers(3, attachments);
//5.we also need a depth buffer(renderbuffer)
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, SCR_WIDTH, SCR_HEIGHT);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo);
//finally check if framebuffer complete
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
qDebug() << "Framebuffer not complete!" << endl;
}