OpenGL光照阴影算法的实现
来源:互联网 发布:北大青鸟java课程详解 编辑:程序博客网 时间:2024/05/29 04:33
阴影
影(又称影子、背影),光线被不透明物体阻档而产生的黑暗范围,与光源的方向相反。影的横切面是二维轮廓、阻档光线物体的倒转投影。影的大小、形状随光线的入射角而改变。(维基百科)在场景中添加阴影可以使得场景更加逼真。下面两幅图是有无阴影效果的对比:
如何制造阴影?
简单地做法,我们可以通过把源物体压平在物体表面所处的平面上,来制造阴影效果。然后被压平的物体用黑色或深色进行绘制。通过操作高级矩阵的方式,来把物体压平到其他表面上。
被压平的效果
我们需要压平的模型视图投影矩阵,以使得所有被绘制的物体都会被压平到阴影所处的二维平面上。无论物体朝哪个方向,都会被投影到阴影所在的平面上。在此需要考虑两种情况,光源离物体的距离以及光源的照射方向。光源的方向决定了阴影的形状和大小。就像在一天中的不同时段,人站在太阳底下,影子会随着太阳的位置而变化。
在math3d库中,有一个函数m3dMakePlanarShadowMatrix,它接受的参数包括一个阴影所处平面的平面方程(3个点不能位于一条直线上),光源的位置,返回的是一个变换矩阵。用当前的模型视图矩阵乘以这个矩阵,随后的所有被绘制的物体都会被压平到这个投影平面上。
void m3dMakePlanarShadowMatrix(M3DMatrix44f proj, const M3DVector4f planeEq, const M3DVector3f vLightPos){// These just make the code below easier to read. They will be // removed by the optimizer. float a = planeEq[0];float b = planeEq[1];float c = planeEq[2];float d = planeEq[3];float dx = -vLightPos[0];float dy = -vLightPos[1];float dz = -vLightPos[2];// Now build the projection matrixproj[0] = b * dy + c * dz;proj[1] = -a * dy;proj[2] = -a * dz;proj[3] = 0.0;proj[4] = -b * dx;proj[5] = a * dx + c * dz;proj[6] = -b * dz;proj[7] = 0.0;proj[8] = -c * dx;proj[9] = -c * dy;proj[10] = a * dx + b * dy;proj[11] = 0.0;proj[12] = -d * dx;proj[13] = -d * dy;proj[14] = -d * dz;proj[15] = a * dx + b * dy + c * dz;// Shadow matrix ready}
阴影例子
为了演示阴影的效果,我们把喷气式飞机悬空,然后在其上面放置一个光源,制造一个飞机投影到地面的阴影效果。
下面的例子,我们在SetupRC中创建一个阴影矩阵,并用全局变量保存它。在RenderScene中使用。
GLfloat lightPos = {-75.0f, 150.0f, -50.0f, 0.0f};
...
//阴影矩阵
M3DMatrix44f shadowMat;
...
void SetupRC()
{
//投影平面上的三个不处于同一直线上的点
M3DVector3f points[3] = {{-30.0f, -149.0f, -20.0f},
{-30.0f, -149.0f, 20.0f},
{40.0f, -149.0f, 20.0f}};
glEnable(GL_DEPTH_TEST);
glFrontFace(GL_CCW);
glEnable(GL_CULL_FACE);
//Enable lighting
glEnable(GL_LIGHTING);
....
//构造投影平面
M3DVector4f vPlaneEquation;
m3dGetPlaneEquation(vPlaneEquation, points[0], points[1], points[2]);
//计算投影矩阵
m3dMakePlanarShadowMatrix(shadowMat, vPlaneEquation, lightPos);
...
}
在RenderScene中,我们先绘制地面,然后画喷气式飞机。然后恢复模型视图矩阵乘以阴影矩阵,然后我们再次绘制喷气式飞机(此过程要关掉深度测试)。飞机的投影和地面处于同一个位置,在一般情况下后面画的那个物体会叠在之前的物体上面被显示。但有的时候,会导致z-figinting,从而产生混乱。
代码如下:
void RenderScene(void){glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);//绘制地板glBegin(GL_QUADS);glColor3ub(0, 32, 0);glVertex3f(400.0f, -150.0f, -200.0f);glVertex3f(-400.0f, -150.0f, -200.0f);glColor3ub(0, 235, 0);glVertex3f(-400.0f, -150.0f, 200.0f);glVertex3f(400.0f, -150.0f, 200.0f);glEnd();//画悬空的喷气式飞机glPushMatrix();//开启光照glEnable(GL_LIGHTING);glLightfv(GL_LIGHT0, GL_POSITION, lightPos);//旋转glRotatef(xRot, 1.0f, 0.0f, 0.0f);glRotatef(yRot, 0.0f, 1.0f, 0.0f);DrawJet(0);//关闭光照glDisable(GL_DEPTH_TEST);glDisable(GL_LIGHTING);glPopMatrix();//画阴影glPushMatrix();//乘以压平的阴影矩阵glMultMatrixf((GLfloat*)shadowMat);//旋转glRotatef(xRot, 1.0f, 0.0f, 0.0f);glRotatef(yRot, 0.0f, 1.0f, 0.0f);DrawJet(1);glPopMatrix();//画光源位置,用小黄球模拟glPushMatrix();glTranslatef(lightPos[0], lightPos[1], lightPos[2]);glColor3ub(255, 255, 0);glutSolidSphere(3.0, 15, 15);glPopMatrix();glEnable(GL_DEPTH_TEST);// Display the resultsglutSwapBuffers();}运行的效果
- OpenGL光照阴影算法的实现
- 3DGAMES中WIN32+OpenGL游戏中实现光照阴影算法主要代码实现
- Win32+OpenGL计算机图形学光照阴影算法 可控制光源、光照物等位置的移动以及漫游等
- 斜坡光照阴影算法
- Win32+OpenGL计算机图形学光照阴影算法(参照超级宝典4改编)
- OpenGL: 阴影算法
- openGL 光照的学习
- 光照阴影镜面反射综合算法
- 光照和阴影算法该如何优化?
- 探究OpenGL光照模型的着色器实现
- OpenGL(十一) 可编程管线 基础光照 的实现
- 模拟实时光照下的阴影
- OpenGL中光照的设置
- OpenGL光照的计算模型
- OpenGL 光照方程的计算
- OpenGL光照的一点理解
- OpenGL中光照的设置
- OpenGL光照的计算模型
- 引用与指针
- hdu2037 今年暑假不AC (贪心求最长事件长度)
- 百度地图
- 《大富翁手机游戏开发实战--基于Cocos2d-x 3.2引擎》现已登陆各大网络销售平台发售
- CV学习重要资源
- OpenGL光照阴影算法的实现
- 更改Jenkins的主目录
- LeetCode 14 Longest Common Prefix(最长公共前缀)(String)
- java,android中网络数据获取和json解析
- 定量/高光谱遥感之——概述
- org.json.JSONException:End of input at character 0 of
- android裁剪相册图片
- 杨辉三角
- 整理iOS9适配中出现的坑(图文)