好吧,我不能保证这会帮助您弄清楚发生了什么。您只是没有发布足够的信息以了解要追踪任何特定错误的操作。尽管我可以很快纠正您的一件事:
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X, textureObject, 0);
...
for (face = 1; face < 6; face++) {
drawSpheres();
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, textureObject, 0);
}
这只会调用drawSpheres
五次。我猜你想叫它6次。
但是我可以发布一个有效的答案。请注意,此代码旨在与我的教程系列一起运行,因此它引用了不存在的代码。但这主要是诸如创建网格之类的事情。没有什么真正重要的。
这是要点。主球体对象的着色器。
顶点着色器:
#version 330
layout(std140) uniform;
layout(location = 0) in vec4 position;
layout(location = 2) in vec3 normal;
out vec3 modelSpaceNormal;
uniform Projection
{
mat4 cameraToClipMatrix;
};
uniform mat4 modelToCameraMatrix;
void main()
{
gl_Position = cameraToClipMatrix * (modelToCameraMatrix * position);
modelSpaceNormal = normal;
}
片段着色器:
#version 330
in vec3 modelSpaceNormal;
uniform samplerCube cubeTexture;
out vec4 outputColor;
void main()
{
outputColor = texture(cubeTexture, modelSpaceNormal);
// outputColor = vec4(normalize(modelSpaceNormal), 1.0);
}
创建将用作渲染目标的立方体贴图纹理:
void CreateCubeTexture()
{
glGenTextures(1, &g_cubeTexture);
glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
std::vector<GLubyte> testData(CUBE_TEXTURE_SIZE * CUBE_TEXTURE_SIZE * 256, 128);
std::vector<GLubyte> xData(CUBE_TEXTURE_SIZE * CUBE_TEXTURE_SIZE * 256, 255);
for(int loop = 0; loop < 6; ++loop)
{
if(loop)
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + loop, 0, GL_RGBA8,
CUBE_TEXTURE_SIZE, CUBE_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &testData[0]);
}
else
{
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + loop, 0, GL_RGBA8,
CUBE_TEXTURE_SIZE, CUBE_TEXTURE_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, &xData[0]);
}
}
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
我实际上是用数据填充纹理(而不是将NULL传递给glTexImage2D)作为调试辅助。它可以确保在开始使用纹理作为渲染目标之前一切正常。
另外,请注意,我提供了BASE_LEVEL和MAX_LEVEL。创建后,我总是立即用我的纹理进行处理。这是一个好习惯,因为OpenGL有时可能对纹理完整性和mipmap金字塔有些挑剔。我没有记住规则,而是虔诚地将它们设置为正确的值。
这是主要的绘图功能:
void display()
{
//Draw the cubemap.
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, g_framebuffer);
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, g_depthbuffer);
for(int loop = 0; loop < 6; ++loop)
DrawFace(loop);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
//Draw the main scene.
//The projection matrix is in a uniform buffer.
ProjectionBlock projData;
projData.cameraToClipMatrix = glm::perspective(90.0f,
(g_viewportSize.x / (float)g_viewportSize.y), g_fzNear, g_fzFar);
glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glViewport(0, 0, (GLsizei)g_viewportSize.x, (GLsizei)g_viewportSize.y);
glClearColor(0.75f, 0.75f, 1.0f, 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glutil::MatrixStack modelMatrix;
modelMatrix.ApplyMatrix(g_viewPole.CalcMatrix());
if(g_pSphere)
{
glutil::PushStack push(modelMatrix);
glUseProgram(g_progMain.theProgram);
glUniformMatrix4fv(g_progMain.modelToCameraMatrixUnif, 1, GL_FALSE,
glm::value_ptr(modelMatrix.Top()));
glActiveTexture(GL_TEXTURE0 + g_cubeTexUnit);
glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);
g_pSphere->Render("lit");
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glUseProgram(0);
}
glutPostRedisplay();
glutSwapBuffers();
}
这参考了DrawFace
,它绘制了立方体贴图的给定面。实现如下:
void DrawFace(int iFace)
{
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_CUBE_MAP_POSITIVE_X + iFace, g_cubeTexture, 0);
GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
printf("Status error: %08x\n", status);
//The projection matrix is in a uniform buffer.
ProjectionBlock projData;
projData.cameraToClipMatrix = glm::perspective(90.0f, 1.0f, g_fzNear, g_fzFar);
glBindBuffer(GL_UNIFORM_BUFFER, g_projectionUniformBuffer);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(ProjectionBlock), &projData);
glBindBuffer(GL_UNIFORM_BUFFER, 0);
glViewport(0, 0, (GLsizei)CUBE_TEXTURE_SIZE, (GLsizei)CUBE_TEXTURE_SIZE);
const glm::vec4 &faceColor = g_faceColors[iFace];
glClearColor(faceColor.x, faceColor.y, faceColor.z, faceColor.w);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
if(g_pSphere)
{
glutil::MatrixStack modelMatrix;
modelMatrix.Translate(g_faceSphereLocs[iFace]);
glUseProgram(g_progUnlit.theProgram);
glUniformMatrix4fv(g_progUnlit.modelToCameraMatrixUnif, 1, GL_FALSE,
glm::value_ptr(modelMatrix.Top()));
const glm::vec4 &sphereColor = g_faceSphereColors[iFace];
glUniform4fv(g_progUnlit.objectColorUnif, 1, glm::value_ptr(sphereColor));
glActiveTexture(GL_TEXTURE0 + g_cubeTexUnit);
glBindTexture(GL_TEXTURE_CUBE_MAP, g_cubeTexture);
g_pSphere->Render("flat");
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
glUseProgram(0);
}
}
此函数引用了一组全局表,我使用这些全局表为每张脸赋予不同的背景色,不同的球体颜色,并为该脸部正确地放置球体(在摄影机空间中)。
这些的要点DrawFace
是这些。
通常,除非我对状态已设置有一定的了解,否则我将设置该状态。每次调用时,都会设置视口DrawFace
。我每次都设置投影矩阵。这些都是多余的;我可以将它们重新设置在display
调用循环之前DrawFace
,就像对当前FBO和深度渲染缓冲区所做的那样。
但是我还要清除缓冲区,每个缓冲区都不同(因为每个面都有不同的颜色)。
drawSpheres
函数实际上绘制了可见的东西?该函数是否实际绘制了东西?如果更改drawSpheres
为仅清除帧缓冲区会怎样?