3) 定义并生成Shadow Map纹理

 texture2D Lamp0ShadowMapColor : RENDERCOLORTARGET
<
float2 ViewPortRatio = {1.0,1.0};
int MipLevels = ;
string Format = "A8R8G8B8" ;
>; sampler2D Lamp0ShadowMapSampler = sampler_state {
Texture = <Lamp0ShadowMapColor>;
FILTER = MIN_MAG_MIP_LINEAR;
AddressU = Clamp;
AddressV = Clamp;
};

第3行的作用是使生成的Shadaow Map纹理大小与渲染窗口自动保持一致,这样可以很方便地观察到Shadow Map纹理大小改变时,对最终生成的阴影效果的影响。

 float4x4 matWorld : World;
float4x4 matView : View;
float4x4 matProject : Projection; struct SourceData
{
float3 pos3 : POSITION;
float4 n : NORMAL;
}; struct VertexOutput
{
float4 pos4 : POSITION; float4 rpos4 : TEXCOORD3;
float4 n : NORMAL; float4 lpos4 : TEXCOORD2;
float4 ldirt4 : TEXCOORD6;
float4 uvd : TEXCOORD5;
}; static float4x4 matLightView = LightViewMat(Lamp0Point, Lamp0LookAt);
static float4x4 matLightProj = LightProjcetMat(); VertexOutput makeShadowVS(SourceData vData)
{
VertexOutput vOut = (VertexOutput); float4x4 matTmp = mul(matWorld, matLightView);
matTmp = mul(matTmp, matLightProj); float4 coordCVV = mul(float4(vData.pos3.xyz, 1.0f), matTmp); float4 m = /coordCVV.w; vOut.pos4.xyz = m*coordCVV.xyz;
vOut.pos4.w = 1.0f; vOut.lpos4 = vOut.pos4;
vOut.lpos4.z *= fat; return vOut;
} float4 makeShadowPS(VertexOutput In) : COLOR
{
return float4(In.lpos4.z, , , );
}

在生成纹理时,将Z-Buffer Test 设为Enable状态,这样就可以保证纹理中保存的深度值始终是离光源最近的那个点的。另外,可以修改上段代码第5行的纹理像素格式,就能方便地得到更精确的深度值。

4) 使用Shadow Map纹理生成阴影

以图一为例,直观来看,生成阴影前应该先将相应观察平面S上的像素对应的空间点(如b'对应的b)的位置计算出来,再用之前生成的Light Space的matLightView和matLightProj把点b投射到平面H上。这样就需要进行从b'到b的变换,很显然观察窗口S的透视矩阵的逆矩阵是存在的。但实际上还有更简易的做法:

 VertexOutput useShadowVS(SourceData vData)
{
VertexOutput v = (VertexOutput);
v.pos4 = mul(float4(vData.pos3, 1.0f), matWorldViewProj); v.n = mul(float4(vData.n.xyz, 0.0f), matWorld);
v.n = normalize(v.n);
v.rpos4 = mul(float4(vData.pos3, 1.0f), matWorld); float3 vLightDirect = Lamp0Point - v.rpos4.xyz;
vLightDirect = normalize(vLightDirect);
v.ldirt4 = float4(vLightDirect, 0.0f); float4x4 matTmp = mul(matWorld, matLightView);
matTmp = mul(matTmp, matLightProj); float4 lightCVV = mul(float4(vData.pos3, 1.0f), matTmp);
lightCVV.z -= 0.1f; float m = /lightCVV.w;
lightCVV.xyz = m*lightCVV.xyz;
lightCVV.w = 1.0f; v.lpos4 = lightCVV; float2 uv = (float2);
uv.x = (1.0f+v.lpos4.x)/2.0f;
uv.y = (1.0f-v.lpos4.y)/2.0f;
v.uvd.xy = uv;
v.uvd.z = v.lpos4.z; return v;
} float4 useShadowPS(VertexOutput v) : COLOR
{ float2 uv = v.uvd.xy;
float dep = v.uvd.z; float3 samplerCol = (float3);
float c = -;
float tmpLm = 0.0f; float3 sdp = tex2D(Lamp0ShadowMapSampler, uv).rgb;
if( dep < sdp.x )
{
tmpLm = 1.0f;
}
float fall = 1.0/dot(v.ldirt4.xyz, v.ldirt4.xyz); float3 ld = v.ldirt4.xyz;
float3 n = v.n;
float diffuse = dot(ld, n);
float3 col = float3(,,);
float linf = 0.8f;
//col = diffuse * col; tmpLm = (tmpLm)*diffuse*fall*linf;
col = tmpLm * col; return float4(col, );
}

第15到第32行,直接计算出每一个顶点在Light Space投影平面上的点的x、y、 z坐标值;在进入到观察者投影变换时,可见像素的x、y、z坐标就可以据此通过插值得到。这样做好处是,避免计算透视变换的逆运算,能使代码更简洁,不足之处是增加了大量多余的运算。

第19行,对lightCVV的z值做了一个偏移运算,作用是校正浮点运算可能出现的误差。以图一中的点b为例,由于基于浮点数的空间变换运算会出现计算误差,因此位于W表面上的b点经投影变换后,本应等于Z-Buffer中相应像素的深度值,有可能变得大于此值,从而导致其后的逻辑判断出错(第49行),所以需要对运算结果做一个误差校正。更一般的做法是将lightCVV乘以一个事先设置好的误差校正矩阵。

第53行,计算光照强度衰减因子(与距离的平方成反比)。初始光照强度在第59行设定。

Shadow Mapping 的原理与实践(二)的更多相关文章

  1. Shadow Mapping 的原理与实践(一)

    早在上世纪七十年代末,Williams在他的“Casting Curved Shadows on Curved Surface”一文中提出了名为Shadow Map的阴影生成技术.之后,他人在此基础上 ...

  2. Shadow Mapping 的原理与实践 【转】

    早在上世纪七十年代末,Williams在他的“Casting Curved Shadows on Curved Surface”一文中提出了名为Shadow Map的阴影生成技术.之后,他人在此基础上 ...

  3. WebSocket原理与实践(二)---WebSocket协议

    WebSocket原理与实践(二)---WebSocket协议 WebSocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通信问题而设计的.协议定义ws和wss协议,分别为普通请求和基 ...

  4. [从Paxos到ZooKeeper][分布式一致性原理与实践]<二>一致性协议[Paxos算法]

    Overview 在<一>有介绍到,一个分布式系统的架构设计,往往会在系统的可用性和数据一致性之间进行反复的权衡,于是产生了一系列的一致性协议. 为解决分布式一致性问题,在长期的探索过程中 ...

  5. RPC原理与实践(二)----Thrift分层模型

    这一节我们从一下几个方面来讲一下Thrift的分层架构,按照官方的定义这是Thrift的网络栈,其中网络栈中分为一下几个部分,(由栈顶到栈底)server,processor,protocol,tra ...

  6. shadow mapping实现动态shadow实现记录 【转】

    http://blog.csdn.net/iaccepted/article/details/45826539 前段时间一直在弄一个室内场景,首先完成了render,效果还可以.然后给其加上shado ...

  7. kafka原理和实践(二)spring-kafka简单实践

    系列目录 kafka原理和实践(一)原理:10分钟入门 kafka原理和实践(二)spring-kafka简单实践 kafka原理和实践(三)spring-kafka生产者源码 kafka原理和实践( ...

  8. 2017.2.9 深入浅出MyBatis技术原理与实践-第八章 MyBatis-Spring(二)-----配置文件详解

    深入浅出MyBatis技术原理与实践-第八章 MyBatis-Spring(二) ------配置文件详解 8.2 MyBatis-Spring应用 8.2.1 概述 本文主要讲述通过注解配置MyBa ...

  9. Spring Boot自动配置原理与实践(二)

    前言 在之前的博文(Spring Boot自动配置原理与实践(一))中,已经介绍了Spring boot的自动配置的相关原理与概念,本篇主要是对自动配置的实践,即自定义Starter,对原理与概念加深 ...

随机推荐

  1. 开源堡垒机GateOne的安装、配置笔记

    因为内部临时需要这么一套系统,所以搜搜查查,搞定了系统部署,使用pam认证的配置. 系统初始化是使用CentOS 6.5 Mini x64版本.   首先exports http_proxy和http ...

  2. MVC同一个视图多个submit对应不同action

    Vi ew中代码 <input type="submit" value="yes" name="action"> <inp ...

  3. 轻松学习Linux之AWK使用初步

    AWK最初是Unix平台上一种可以对文本进行逐行处理的编程语言,它来源于3个创作者的名字:Aho.(Peter)Weinberg和(Brain)Kernighan. 现在广泛应用于Linux,他与se ...

  4. 第三百五十九天 how can I 坚持

    在家待了一天,鼓捣了下linux,总算能连上网了,懂得还是少啊. 晚上去华北电力大学跑了会步,十圈,还挺有成就感呢,就是没带手环,哎. 以后学习一定要记笔记,上了这么多年学,都 没学会怎么记笔记,也是 ...

  5. 第三百三十八天 how can I 坚持

    下午去奥体森林公园跑了个步,好累. 晚上和徐斌同学一起吃了个饭,接触了下杨辉三角,还没整明白,明天看下. 突然想起java 编译,ant脚本. 要精通门技术,还要赶上潮流. 睡觉.

  6. 如何使cron任务出错时发邮件

    如果设置了 MAILTO,cron就会将任务的标准输出和标准错误输出重定向到邮箱(即发送邮件).但如果只想接到错误报警邮件 -- 即任务正常执行时不发送,只在出错时发送 -- 应该怎么实现呢? 方法很 ...

  7. JQuery实现的动态Table(转)

    这个例子做的不错,转载备份. 原文:http://www.cnblogs.com/linjiqin/archive/2013/06/21/3148181.html $("#mytable t ...

  8. Ubuntu下Android编译环境的配置

    从安装操作系统到编译程序结束,过程大致如下. 1. Ubuntu Linux操作系统安装软件包.使用 Ubuntu 14.04 Desktop系统.安装Linux系统到VMWare虚拟机上. 2. 完 ...

  9. SQLCONNECTION使用HTTP通信协议和中间件连接

    SQLCONNECTION支持TCP/IP和HTTP两种通信协议和中间件连接.一般地,默认情况下使用TCP/IP协议. HTTP 协议的一个非常重要的优势在于穿越防火墙. SQLCONNECTION使 ...

  10. Arduino 模拟信号的读入并转化为0-5V电压

    int ledIn = A0; void setup(){ Serial.begin(9600); } void loop(){ int sensorValue = analogRead(ledIn) ...