我被迫使用遗留的OpenGL和没有着色器的学术项目(是的..)。我正在渲染一个有山有水的3D世界。我的目标(和问题)是画天空圆顶反映在水面上。天空穹顶本身有2个纹理(夜晚和白天),它们是基于alpha值混合绘制的,如下所示:
void Renderer::drawSkydome()
{
// Enable blending
glEnable(GL_BLEND);
// Disable depth testing
glDisable(GL_DEPTH_TEST);
glCullFace(GL_FRONT);
// Bind the vertex array object for the skydome
glBindVertexArray(instance->objects[SKYDOME].vao);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
// Day texture
glBindTexture(GL_TEXTURE_2D, instance->objects[SKYDOME].texture);
glDrawElements(GL_TRIANGLES, instance->objects[SKYDOME].indices.size(), GL_UNSIGNED_INT, 0);
glColor4f(1.0, 1.0, 1.0, alpha);
// Night texture
glBindTexture(GL_TEXTURE_2D, instance->objects[SKYDOME].blend_texture);
glDrawElements(GL_TRIANGLES, instance->objects[SKYDOME].indices.size(), GL_UNSIGNED_INT, 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glColor4f(1.0, 1.0, 1.0, 1.0);
// Unbind the vertex array object and texture
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
// Re-enable depth testing
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
}
这只是工作正常。然后,我设法画物体的倒影,在水中使用模板测试;具体而言:
void Renderer::drawWater()
{
glEnable(GL_BLEND);
// Bind the water VAO
glBindVertexArray(instance->objects[WATER].vao);
// Enable two vertex arrays: co-ordinates and color.
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnable(GL_STENCIL_TEST); // Enable stencil testing
glClearStencil(0); // Set clearing value for stencil buffer.
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
glDepthMask(GL_FALSE);
glDisable(GL_DEPTH_TEST);
glStencilFunc(GL_ALWAYS, 1, 1);
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); // In all cases replace the stencil tag
glEnable(GL_PRIMITIVE_RESTART);
glDrawElements(GL_TRIANGLE_STRIP, instance->objects[WATER].indices.size(), GL_UNSIGNED_INT, 0);
glDisable(GL_PRIMITIVE_RESTART);
// Enable writing of the frame and depth buffers - actually drawing now begins.
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glStencilFunc(GL_EQUAL, 1, 1);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); // The stencil buffer itself is not updated.
glPushMatrix();
glScalef(1.0, -1.0, 1.0);
// Bind the vertex array object for the skydome
glBindVertexArray(instance->objects[SKYDOME].vao);
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindTexture(GL_TEXTURE_2D, instance->objects[SKYDOME].texture);
glDrawElements(GL_TRIANGLES, instance->objects[SKYDOME].indices.size(), GL_UNSIGNED_INT, 0);
glColor4f(1.0, 1.0, 1.0, alpha);
glBindTexture(GL_TEXTURE_2D, instance->objects[SKYDOME].blend_texture);
glDrawElements(GL_TRIANGLES, instance->objects[SKYDOME].indices.size(), GL_UNSIGNED_INT, 0);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClie**ntState(GL_TEXTURE_COORD_ARRAY);
// Unbind the vertex array object and texture
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glPopMatrix();
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glDisable(GL_STENCIL_TEST); // Disable the stencil test
// Bind the water texture
glBindTexture(GL_TEXTURE_2D, instance->objects[WATER].texture);
// Bind the water VAO
glBindVertexArray(instance->objects[WATER].vao);
glEnable(GL_PRIMITIVE_RESTART);
glDrawElements(GL_TRIANGLE_STRIP, instance->objects[WATER].indices.size(), GL_UNSIGNED_INT, 0);
glDisable(GL_PRIMITIVE_RESTART);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
// Unbind the vertex array object and texture
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_BLEND);
}
问题是,同样的代码(在push和pop之间的代码)用于渲染天空圆顶,在实际的天空圆顶上产生精细的混合,在绘制天空圆顶在水面上的反射时不起作用;具体来说,它只渲染夜间纹理,而不管Alpha值如何。换句话说,我不能设法绘制混合的白天/夜晚纹理作为水面上的反射(水纹理本身有0.5阿尔法,所以我能够看到水纹理如何与天空混合)。这是由于一些奇怪的行为与模具测试我不知道?
提前感谢你的帮助。
1条答案
按热度按时间vqlkdk9b1#
显然,解决方案是在渲染反射的圆顶时禁用GL_LIGHTING,如下所示:
不知道照明是如何干扰混合,但添加简单的禁用调用解决了我最初的答案!。请提供更准确的解释。