|
主要是使用OpenGL模板缓冲区实现平面阴影,关键代码:
GLvoid OpenGL::RenderPlanarShadow() const
{
// 临时变量,保存球体原来的材质颜色
Vector3 vec3MaterialColor;
// 平面阴影矩阵
GLfloat fShadowMatrixArray[16] = {0.0f};
// 得到光源的坐标位置
const GLfloat fLightPosition[4] = {g_Light.GetPosition().x, g_Light.GetPosition().y,
g_Light.GetPosition().z, g_Light.GetPolarCoordinatesPostion() };
glClear(GL_STENCIL_BUFFER_BIT); // 清除模板缓冲区
glEnable(GL_STENCIL_TEST); // 启动模板测试
glDisable(GL_DEPTH_TEST); // 之所以关闭深度测试是因为想要在达到这样的
// 一个判断结果:如果被绘制的物体能通过模板测
// 试则其必然能通过深度测试,不存在通过了模板
// 测试但不通过深度测试的情形,当然在我们能绘
// 制上阴影的地方一般都可以通过正常的深度测试,
// 但显示的关闭深度测试可以减少工作量
glDisable(GL_LIGHTING); // 之所以关闭光照是因为绘制模板和阴影都不需要启动光照
// 在各墙面上绘制球体阴影
for (GLint i = 0; i < g_iWallNumber; ++i) //
{
glStencilFunc(GL_ALWAYS, 1, 1); // 设置模板测试函数
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); // 设置模板操作
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // 设置颜色缓冲区为不可写
glDepthMask(GL_FALSE); // 使深度缓冲区为只读
g_WallArray.Render(); // 绘制墙模板
glDepthMask(GL_TRUE); // 使深度缓冲区为可读写
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // 设置颜色缓冲区为可读写
glStencilFunc(GL_EQUAL, 1, 1); // 设置模板测试函数
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // 设置绘制上阴影的模板值加1(导致其模板值大于1)
// 生成平面阴影矩阵
GenerateShadowMatrix(fShadowMatrixArray, g_WallArray.GetCornerVertex(), g_WallArray.GetNormal(), fLightPosition);
glEnable(GL_BLEND); // 启动混合
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // 设置混合函数
glPushMatrix(); // 保存模型视图矩阵
// 将平面阴影矩阵设置进模型视图矩阵中
glMultMatrixf(fShadowMatrixArray);
// 绘制球体在此墙上的阴影
for (GLint j = 0; j < 1; ++j) // g_iBallNumber
{
vec3MaterialColor = g_BallArray[j].GetMaterialColor();
g_BallArray[j].SetMaterialColor( Vector3(0.3f, 0.3f, 0.3f) ); // 设置阴影颜色
g_BallArray[j].Render(); // 绘制球体阴影
g_BallArray[j].SetMaterialColor(vec3MaterialColor); // 设置回球体原来的材质颜色
}
glPopMatrix(); // 恢复模型视图矩阵
glDisable(GL_BLEND); // 关闭混合
}
glEnable(GL_LIGHTING); // 启动光照
glEnable(GL_DEPTH_TEST); // 启动深度测试
glDisable(GL_STENCIL_TEST); // 关闭模板测试
}
反复检查了下,实在一时半会找不出哪出错了.希望哪位高手指点下.
这是只绘制一个球体阴影时的Bug截图(居然出现了两个阴影,一个是正确的另一个是错误的,晕)
|
-
|