http://www.cnblogs.com/cxrs/archive/2009/10/17/1585038.html

1、什么是Shadow Maping?
      Shadow Mapping是由Lance Williams于1978年在一篇名为"Casting curved shadows on curved surfaces"的文章中提出的,这篇文章是ShadowMap技术之根源。其实原理很简单,如果光源和目标点之间的连线没有任何物体阻挡的话,则目标点没有在阴影中;如果有物体遮挡,则目标点处在阴影中。而ShadowMap,就是一张记录了每个象素处用于比较遮挡关系信息的Texture. 
      产生这个ShadowTexture的方法很简单,以SpotLight为例,把3D Camera放到光源的位置,把DepthTest打开,渲染场景,在PixShader中把每个象素的深度信息或者光源和此象素的距离信息写到RenderTarget上,由于DepthTest是打开的,保证了最终写到RenderTarget上的均是物体上未处在阴影中的点的深度值,实质完全可以等效为最终的DepthBuffer。
     得到这个ShowMap之后,如何最终生成阴影呢?在PixShader对每个pixel进行处理时,算出当前象素与灯当的距离Dc,与存在ShdowMap中的引像素的值Dz进行比较,如果Dc > Dz,则在阴影中,反之则被灯光照亮。
2、Shadowmap之HLSL的实现
    在Direct SDk中有ShadowMap的Sample,下面的Shader和Sample里面空全一样,只是加了一些注释便于理解。
    (1)生成ShadowMap的VS和PS

//-----------------------------------------------------------------------------
// Vertex Shader: VertShadow
void VertShadow( float4 Pos : POSITION,
                 float3 Normal : NORMAL,
                 out float4 oPos : POSITION,
                 out float2 Depth : TEXCOORD0 )
{
    //从模型坐标系变换到观察坐标系
    oPos = mul( Pos, g_mWorldView );
   //进行投影变换
   oPos = mul( oPos, g_mProj );
   //把投影坐标系的ZW值赋给Depth,作为PixelShader中的输出,这里的Z还是齐次坐标,这里不直接输出Z/W,我的理解是让Z和W都在Rasterizer中进行线性插
  //值,这样可以增加最终生成的ShadowMap的精度。
    Depth.xy = oPos.zw;
}
//-----------------------------------------------------------------------------
// Pixel Shader: PixShadow
void PixShadow( float2 Depth : TEXCOORD0,
                out float4 Color : COLOR )
{
    // 把 z / w的值作为Color值输出,写到RenderTarget上,此时的RT formate是D3DFMT_R32F
   //把Z/W目的是把齐次坐标Z变换到三维空间的非齐次坐标,范围则是[-1,1]
    Color = Depth.x / Depth.y;
}

(2)用ShadowMap生成Shadow

//-----------------------------------------------------------------------------
// Vertex Shader: VertScene
// Desc: Process vertex for scene
//-----------------------------------------------------------------------------
void VertScene( float4 iPos : POSITION,
                float3 iNormal : NORMAL,
                float2 iTex : TEXCOORD0,
                out float4 oPos : POSITION,
                out float2 Tex : TEXCOORD0,
                out float4 vPos : TEXCOORD1,
                out float3 vNormal : TEXCOORD2,
                out float4 vPosLight : TEXCOORD3 )
{
    vPos = mul( iPos, g_mWorldView );
    oPos = mul( vPos, g_mProj );
    vNormal = mul( iNormal, (float3x3)g_mWorldView );
    Tex = iTex;
    //把当前顶点位置变换到以光源为Camera的投影空间,
    vPosLight = mul( vPos, g_mViewToLightProj );
}

//-----------------------------------------------------------------------------
// Pixel Shader: PixScene
// Desc: Process pixel (do per-pixel lighting) for enabled scene
//-----------------------------------------------------------------------------
float4 PixScene( float2 Tex : TEXCOORD0,
                 float4 vPos : TEXCOORD1,
                 float3 vNormal : TEXCOORD2,
                 float4 vPosLight : TEXCOORD3 ) : COLOR
{
    float4 Diffuse;

// 计算光源到当前象素方向向量并单位化
    float3 vLight = normalize( float3( vPos - g_vLightPos ) );

//  dot( vLight, g_vLightDir )为光源到当前象素方向向量和光的方向向量之间的夹角余旋值,由于是spotlight,因此必须要在spotlight可照射的范围内。因为角 
    //度越小余旋值越大,因此这里是大于
    if( dot( vLight, g_vLightDir ) > g_fCosTheta ) 
    {
        // Pixel is in lit area. Find out if it's
        // in shadow using 2x2 percentage closest filtering

//从投影空间坐标转化为纹理空间坐标,也就是找到投影空间中的点和纹理空间中的点的对应关系
       //除以w,xy坐标便处在(-1,1)的范围内,乘0.5加0.5,则变换到了(0,1)的范围,因texture space的u,v坐标是(0,1)的
        float2 ShadowTexC = 0.5 * vPosLight.xy / vPosLight.w + float2( 0.5, 0.5 );
       //在投影坐标系中,Y轴是向上的,而在纹理空间中Y轴向下,因此要作以下处理
        ShadowTexC.y = 1.0f - ShadowTexC.y;

// 在texel space中对应的象素坐标
        float2 texelpos = SMAP_SIZE * ShadowTexC;
        
        // 取得小数部分         
        float2 lerps = frac( texelpos );

//这里使用的是2x2 percentage closest filtering,因此是采的邻近的四个点,判断它们是否在阴影中,
        float sourcevals[4];
        sourcevals[0] = (tex2D( g_samShadow, ShadowTexC ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f;  
        sourcevals[1] = (tex2D( g_samShadow, ShadowTexC + float2(1.0/SMAP_SIZE, 0) ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f;  
        sourcevals[2] = (tex2D( g_samShadow, ShadowTexC + float2(0, 1.0/SMAP_SIZE) ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f;  
        sourcevals[3] = (tex2D( g_samShadow, ShadowTexC + float2(1.0/SMAP_SIZE, 1.0/SMAP_SIZE) ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f;  
        
        // 用lerps 
        float LightAmount = lerp( lerp( sourcevals[0], sourcevals[1], lerps.x ),
                                  lerp( sourcevals[2], sourcevals[3], lerps.x ),
                                  lerps.y );
        // 计算光照,如果完全在阴影中,则LightAmount为0,这里只计算了Diffuse color,没有高光
        Diffuse = ( saturate( dot( -vLight, normalize( vNormal ) ) ) * LightAmount * ( 1 - g_vLightAmbient ) + g_vLightAmbient )
                  * g_vMaterial;
    } else
    {
        Diffuse = g_vLightAmbient * g_vMaterial;
    }

return tex2D( g_samScene, Tex ) * Diffuse;
}

3、ShdowMap的优缺点
    优点:简单,不需要知道场景中Object的Geometry,不需要Stencil Buffer,每个灯光只需多渲染一个Pass。
    缺点:当ShadowMap分辨率不够高时,或灯光与物体隔得很近时,在边缘处会产生Aliasing,锯齿,因此,很多改进shadowMap的算法都围绕着如何消除锯齿作文章。
4、ShadowMap的改进
    关于ShadowMap的改进,又出了很多的paper和技术,比如:Percentage Shadow map,  使用bloom filter对ShadowMap进行模糊处理.以及siggraph 2002 中Marc Stamminger和 George Drettakis提出的Perspective Shadow map.以及Adaptive Shadow Map等等。

Shadow mapping相关推荐

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

    Shadow Mapping 的原理与实践 [转] Shadow Mapping 的原理与实践 [转] posted on 2018-08-16 23:37 时空观察者9号 阅读(...) 评论(.. ...

  2. OpenGL shadow mapping 阴影贴图的实例

    OpenGL shadow mapping 阴影贴图 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <glad/glad.h> #i ...

  3. OpenGL Shadow Mapping阴影贴图的实例

    OpenGL Shadow Mapping阴影贴图 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include "vapp.h" #inc ...

  4. [转载] [OpenGL] shadow mapping(实时阴影映射)

    参考链接: Java中静态函数的阴影(方法隐藏) 转载原创:ZJU_fish1996   http://blog.csdn.net/zju_fish1996/article/details/51932 ...

  5. 3DShader之阴影贴图(Shadow Mapping)

    好久没写shader了,一直被实验室要求作java开发,中间准备了一个月雅思,最近又被老师拉到东莞做Hadoop开发.马上面临毕业的问题了,突然人生苦短,趁有生之年多做点自己喜欢的事情吧,所以最近又开 ...

  6. 【GAMES-202实时渲染】1、软阴影01(Shadow Mapping、Peter Panning、PCSS原理超详细)

    Lecture3 Real-Time shadows1 1 Shadow Mapping回顾 2 Shadow Mapping缺点及解决方案 2.1 自遮挡现象 解决方案1 定义一个bias 解决方案 ...

  7. 【Shading】Shadow Mapping 阴影映射

    课程来源:GAMES101-现代计算机图形学入门-闫令琪 Lecture12 GAMES101 现代计算机图形学入门 主讲老师:闫令琪,UCSB 课程主页:https://sites.cs.ucsb. ...

  8. [OpenGL] shadow mapping(实时阴影映射)

    source:原文地址 code:点击可以直接下载源代码 1978年,Lance Williams在其发表的论文<Casting curved shadows on curved surface ...

  9. 阴影(shadow mapping)(硬阴影)

            着色是一种局部现象,只考虑着色点自己.光源.摄像机,如果我要算出它的着色,完全不考虑其它物体,甚至自己的其它部分对这个着色点的影响.而事实上如果有其它物体挡在 shading poin ...

最新文章

  1. 赵本山:我的时代还没有结束 | Python告诉你
  2. 802.1x------2
  3. 第三章——jXLS Excel标记
  4. 一步一步学NUnit
  5. 2021教师资格证中学科目二简答汇总分享
  6. ssh 免密_大数据时代:SSH如何免密码登录?
  7. 数据库与hadoop_OLTP,MPP和Hadoop
  8. 教大家防止Jar包被反编译
  9. vue 中引入使用其他字体
  10. 【资料总结】html开发小实例
  11. 羊车门问题。有三扇关闭的门,一扇门背后面停着汽车,其余门后面是山羊,只有主持人知道每扇门后面是什么。参赛者可以选择一扇门,在开启它之前,主持人会开启另一扇门,露出门后的山羊,然后允许参赛者更换自己的选
  12. 以下关于c语言程序中函数的说法正确的是( ),以下关于C语言程序中函数的说法正确的是:(  )...
  13. ips细胞技术治疗尿毒症最新进展
  14. 这个行情,币圈小白该如何生存?
  15. uniapp项目中引用iconfont图标,实现信号强度图标展示(离线使用)
  16. java大写md5_java 字符按字母排序-拼接-md5加密-大写
  17. redis 内存分析工具 `rma4go`
  18. Flexsim Database Connectors连接数据库
  19. BUUCTF Reverse/Ultimate Minesweeper
  20. python打印类的内容_python-打印类的所有实例

热门文章

  1. 10.1 国庆 考试
  2. java 泛型 窜讲
  3. php实现input输入框失去焦点自动保存输入框的数据
  4. 嵌入式VxWorks系统开发与应用
  5. IOS 滑动指示导航栏 渐变
  6. linux 文件的打包和解压
  7. ORA-16629: database reports a different protection
  8. 使用Lucene2.3构建搜索引擎
  9. Retrofit2.0
  10. IIS服务器五大安全要素