赞
踩
转载请声明出处:http://blog.csdn.net/xiaoge132/article/details/51458489
像素与以纹理形式保存的光照深度缓冲区或者深度图像比较,通过这种方式计算像素是否处于光源照射范围之内,从而生成阴影。(引自维基百科)
上图很好的解释了Shadow Mapping的原理
一 首先将摄像机设置到光源所在的位置(观察方向面对场景,此时叫摄像机观察矩阵为观察矩阵1”,同时设置合理的投影矩阵(这里称此矩阵为投影矩阵1)。
二 然后对与景进行第二次绘制.此次绘制将每个可以看见的片元(可以观察到指的是片元到光源间无遮挡)到光源的距离记录到一幅纹理图中的对应像素中,供后面的步骤使用。
三 接着将摄像机恢复到实际摄像机所处的位置,绘制场景。此次绘制时将前面步骤产生的纹理采用投影贴图的方式应用到场景中,进行投影贴图时采用的投影矩阵为投影矩阵1、观察矩阵为观察矩阵1.
四 绘制每个片元时,根据投影贴图纹理采样的结果换算出光源与此片元连线中距光源最近的片元距离(ZA),再计算出此片元距光源的实际距离(ZB)。若ZB〉ZA,则需要绘制的片元处于阴影中,采用阴影的颜色着色,否则此片兀不在阴影中,进行既定的光照着色。
- precision mediump float;
- varying vec4 vPosition; //接收从顶点着色器过来的参数
- uniform highp vec3 uLightLocation; //光源位置
- void main()
- {
- float dis=distance(vPosition.xyz,uLightLocation);//计算距离
- float zsbf=floor(dis);//取整数
- float xsbf=fract(dis);//取小数
- xsbf=floor(xsbf*1024.0);//将小数放大1024倍取整
-
- float hzsbf=floor(zsbf/256.0);
- float lzsbf=mod(zsbf,256.0);
- float hxsbf=floor(xsbf/32.0);
- float lxsbf=mod(xsbf,32.0);
-
- float r=hzsbf/256.0;
- float g=lzsbf/256.0;
- float b=hxsbf/32.0;
- float a=lxsbf/32.0;
-
- gl_FragColor=vec4(r,g,b,a);
- }

- precision mediump float; //给出默认浮点精度
- uniform sampler2D sTexture; //纹理内容数据
- uniform highp vec3 uLightLocation; //光源位置
- uniform highp mat4 uMVPMatrixGY; //总变换矩阵(光源)
- varying vec4 ambient; //接收从顶点着色器传来的环境光最终强度
- varying vec4 diffuse; //接收从顶点着色器传来的散射光最终强度
- varying vec4 specular; //接收从顶点着色器传来的镜面光最终强度
- varying vec4 vPosition; //接收从顶点着色器传来的变换后顶点位置
- void main(){
- //将片元的位置投影到光源处虚拟摄像机的近平面上
- vec4 gytyPosition=uMVPMatrixGY * vec4(vPosition.xyz,1);
- gytyPosition=gytyPosition/gytyPosition.w; //进行透视除法
- float s=(gytyPosition.s+1.0)/2.0; //将投影后的坐标换算为纹理坐标
- float t=(gytyPosition.t+1.0)/2.0;
- vec4 depth4=texture2D(sTexture, vec2(s,t)); //对投影纹理(距离纹理)图进行采样
- //将采样出的颜色值换算成最小距离值ZA
- float minDis=depth4.r*256.0*256.0+depth4.g*256.0+depth4.b+depth4.a/32.0;
- float currDis=distance(vPosition.xyz,uLightLocation); //计算光源到此片元的距离ZB
- vec4 finalColor=vec4(0.95,0.95,0.95,1.0); //物体的颜色
- if(s>=0.0&&s<=1.0&&t>=0.0&&t<=1.0) { //若纹理坐标在合法范围内则考虑投影贴图
- if(minDis<=currDis-3.0) { //若实际距离大于最小距离则在阴影中
- gl_FragColor= finalColor*ambient*1.2; //仅用环境光着色
- } else{//不在阴影中用三个通道光照着色
- gl_FragColor = finalColor*ambient+finalColor*specular+finalColor*diffuse;
- }
- } else{ //不在阴影中用三个通道光照着色
- gl_FragColor = finalColor*ambient+finalColor*specular+finalColor*diffuse;
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。