`
absolute
  • 浏览: 190223 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Shadow Map

    博客分类:
  • CG
阅读更多

有光则有影,即时渲染的阴影可以使场景看上去更加真实。

算法描述: 

ShadowMap是一种基于阴影图的阴影生成方法,阴影图是一张2D贴图。阴影图中的每个像素都记录了从光源到遮挡物(遮挡物就是阴影生成物体)的每个“可见”像素的距离。这里的“可见”像素是指,以光源为观察点,光的方向为观察方向,设置观察矩阵并渲染所有遮挡物,最终出现在渲染表面上的像素。使用ShadowMap渲染阴影主要分两个过程:生成阴影图和使用阴影图渲染。下面的代码取自生成阴影图的PS代码

float distance=distance(lightpos,input.PWorld);    ①
distance*=distancescale;                                      ②
distance-=depthbais;                                            ③
return distance;                                                     ④

①     distance是HLSL的内置函数用于计算两点距离,这里获得了光源到当前像素的距离。

②     disancescaler用于对距离值进行缩放,这个值可以通过应用程序设置,使用它就可以对阴影进行即时可见的调整。

③     depthbais同样用于阴影图调整。

④     返回距离值,实际上此时的渲染目标已经被设置成阴影图,阴影图的设置方法和上节的立方体环境贴图类似,不过这里只需要将遮挡物渲染一次。

下图显示了一个场景和其使用到的阴影图。

需要在阴影图中保存从光源到“可见”点的距离是因为:利用这个距离就可以直接判

断一个像素是否在阴影中。如果一个世界空间的“点”到光源的距离大于阴影图中对

应像素的值,那么这个点肯定已经被另一个离光源更近的点遮挡住了,所以它肯定在

阴影中。基于这个原理就可以很容易的编写渲染阴影的代码了。

下面的代码取自渲染阴影的PS代码

 

float CurrentPixelDistance=distance(lightpos,input.PWorld)*distancescale+depthbais;①

Shadow = (CurrentPixelDistance > tex2Dproj(shadowmap,input.ShadowMapCord))②

Shadow*=ShadowDensity;③

Return Shadow;

  

①     这里获得当前像素到光源的距离。

②     首先对阴影图采样,再用当前像素的值和采样所得的值进行比较。大于则当前像素在阴影中,Shadow=1;否则Shadow=0;

③     这里ShadowDensity同样由应用程序调整,用于设置阴影浓度。

该PS返回了阴影值,该数值越大表示阴影越浓。但是直接将其输出是不行的,因为这里只有阴影,而场景必须将场景本身的颜色和阴影“混合”输出。这里的解决方案是AlphaBlend,简单的说就是首先按照指定的方式渲染场景,这里可以使用前面说的任何渲染方式;接着渲染阴影,在渲染阴影的时候启用AlphaBlend,这样前后两次渲染的结果就可以通过AlphaBlend“混合”在一起了。

另外,由于阴影图是一种基于贴图采样的技术。渲染效果和阴影图的分辨率有着极大的关系,当提高分辨率无法满足渲染效果的需要时,有必要采用一些图象处理的方法。例如,对阴影图进行多次采样使得阴影的边缘更加平滑。下面的Shader使用2×2PCF(Percentage Closer Filter)方法对阴影图进行过滤。

float ShadowDepth=tex2Dproj(shadowmap,input.ShadowMapCord);①

float ShadowDepth1=tex2Dproj(shadowmap,input.ShadowMapCord+float4(-SampleOffset,0,0,0));

float ShadowDepth2=tex2Dproj(shadowmap,input.ShadowMapCord+float4(0,-SampleOffset,0,0));

float ShadowDepth3=tex2Dproj(shadowmap,input.ShadowMapCord+float4(-SampleOffset,0,0,0));

float Shadow = (CurrentPixelDistance > ShadowDepth);②

float Shadow1=CurrentPixelDistance> ShadowDepth1;

float Shadow2=CurrentPixelDistance> ShadowDepth2;

float Shadow3=CurrentPixelDistance> ShadowDepth3;

……………………………………….

finalshadow=(Shadow+Shadow1+Shadow2+Shadow3)/4;③

①     这四行代码对阴影图执行了4次采样,每次采样以Sample Offset为偏移量,获得阴影图中对应像素周围4个像素所保存的光源距离。

②     这四行代码用每一个距离值和当前像素距离值比较得到4个阴影值。

③     平均四个阴影值,得到最终的阴影值。

很显然,当一个像素处于阴影边缘的时候,4次采样中可能会有部分结果为0,部分为1。平均以后就可以得到一个

0,1之间的值,这个值将会表现在阴影的浓度上,这样就可以形成平滑的阴影边缘。但是,提升效果的代价也是明

显的,使用多次采样会明显的降低速度。由于PS2.0最多可用64条指令,编写3×3PCF刚好够用,效果更好,但也

更慢。

下图对各种采样方式做了一个比较。从左到右逐渐提高了PCF(百分比渐进过滤)的采样次数:

结论,本文给出了一个ShadowMap的实现方式。需要注意的是,文中所提到的PCF实现方式并不是最佳的,因为现在的很多图形硬件已经从硬件上支持多次采样的PCF技术,这种技术能够获得更好的执行效率并且能够免除ps指令条数的限制。

分享到:
评论

相关推荐

    shadowmap阴影实现

    5. **MainFrame.cpp, BaseDraw.cpp, MyGLSL.cpp, shadowmap.cpp, Camera.cpp, StdAfx.cpp, shadowmap.dsp, shadowmap.dsw**: 这些文件是项目的主要组成部分,它们分别包含了项目框架、基本绘制操作、GLSL相关的...

    opengl shadowmap阴影实现

    OpenGL Shadow Map阴影实现 在3D图形编程中,阴影效果是增强场景真实感的重要手段。...在提供的文件列表中,`shadowmap.cpp`很可能是实现Shadow Map的核心部分,而其他文件则提供了支持性的框架和功能。

    D3D11_ShadowMap1

    《D3D11_ShadowMap1:深度阴影贴图技术在Direct3D11中的应用》 在3D图形编程领域,为了实现更逼真的光照效果,阴影的模拟是必不可少的一部分。本项目“D3D11_ShadowMap1”专注于在Direct3D11环境下,利用深度阴影...

    shadow map 纹理阴影

    "Shadow Map"技术就是一种常用的实现实时阴影的方法,特别是在3D游戏和虚拟现实应用中。本话题将深入探讨如何利用OpenGL和GLSL(OpenGL着色语言)来创建基本的纹理阴影。 一、阴影贴图(Shadow Map)原理 阴影贴图...

    ShadowMap + Phong

    在3D图形渲染领域,"ShadowMap + Phong"是一个重要的技术组合,它结合了阴影映射(ShadowMap)和菲涅尔(Pong)光照模型,以提高场景的真实感和视觉质量。这两种技术都是现代实时渲染中的核心组件,主要用于创建更逼真的...

    改进后的GLSL+Shadowmap

    Shadowmap是实现软阴影和硬阴影的一种常见技术,而Phong光照模型则为物体提供了真实感的反射和高光效果。在"改进后的GLSL+Shadowmap"项目中,我们将会探讨如何利用这些技术来提升场景的真实感。 首先,让我们深入...

    Shadow Map在DirectX9_0 SDK Sample 的实现方法

    《深度阴影贴图(Shadow Map)在DirectX9.0 SDK Sample中的实现解析》 深度阴影贴图(Shadow Map),也称为Shadow Mapping,是计算机图形学中一种常用的实时光照技术,用于模拟真实世界中物体投射的阴影效果。在...

    OpenGL影子 ShadowMap 源码

    - Shadow Map是一个从光源视角看场景的深度纹理,记录了场景中每个点到光源的距离。 - 这个深度纹理在渲染时被用来判断物体表面是否在光源的阴影中。 2. **光源和摄像机视角**: - 在OpenGL中,我们需要两个不同...

    shadow map范例

    在提供的"ShadowMap"压缩包中,可能包含有Unity项目文件,用于展示如何创建和配置Shadow Map,以及相关的脚本示例。你可以通过导入这些文件到Unity编辑器中,实际操作并观察效果,加深理解。 通过查阅链接的博客...

    shadow map PCF

    "Shadow Map" 技术是一种常用的实时光照计算方法,它通过将光源视角下的场景深度信息编码到一张纹理中,然后在接收光照的物体上进行采样,判断物体是否处于阴影中。而"Percentage-Closer Filtering (PCF)"则是一种...

    简单ShadowMap2.rar

    unity shader实现自定义shadowmap,shadowmask原理学习用

    shadow map

    5. **硬件加速**:现代GPU提供了硬件支持的阴影映射功能,如OpenGL的Shadow Volumes和Direct3D的Shadow Map纹理采样,大大提升了阴影映射的效率。 6. **高级阴影技术**:除了基本的阴影映射,还有许多高级技术,如...

    osg实现shadowmap

    在OpenSceneGraph (osg) 中实现ShadowMap是一种增强3D场景真实感的重要技术。ShadowMap是将光源的位置作为观察者,记录下场景中物体在光源视角下的投影,然后在渲染时使用这些投影来确定哪些区域应该被遮蔽,从而...

    阴影渲染 shadowmap

    ### 阴影渲染 Shadowmap 知识点详解 #### 一、阴影渲染与 Shadow Mapping 概述 阴影渲染在计算机图形学中是一项至关重要的技术,它能够显著提高三维场景的真实感。随着计算机图形学的发展,多种阴影生成算法...

    ShadowMap 动态阴影

    Shadow Map,也称为深度贴图,是一种计算和投射阴影的技术,它广泛应用于游戏开发和实时渲染领域。本篇文章将深入探讨Shadow Map的概念、工作原理以及如何在Unity引擎中实现动态阴影。 一、Shadow Map简介 Shadow ...

    GL_ShadowMap phong

    《GL_ShadowMap与Phong光照在图形渲染中的应用》 在计算机图形学领域,真实感渲染是追求的目标之一,而阴影是增加场景真实感的关键因素。GL_ShadowMap技术结合Phong光照模型,能够有效地在3D场景中实现高质量的阴影...

    shadow map pdf

    # Shadow Map 技术在三维图形中的应用及发展 ## 摘要 在现代三维图形渲染技术中,阴影效果是提升场景真实感的关键因素之一。本文主要探讨了阴影映射(Shadow Maps)这一技术的基本原理及其在当前图形渲染领域的...

    最初级的Shadow Map

    【标题】:“最初级的Shadow Map” 在3D图形编程中,阴影映射(Shadow Mapping)是一种常用的技术,用于在场景中实现逼真的光照效果,尤其是动态光源产生的影子。这个话题涉及到Direct3D,一个由微软开发的API,...

    perspective shadow map

    透视阴影贴图(Perspective Shadow Map,PSM)是计算机图形学中用于渲染真实感阴影的一种高级技术。在3D游戏中或复杂的可视化应用中,阴影的逼真度对整体视觉效果有着重大影响。传统的阴影贴图方法,如正交阴影贴图...

    variance shadow map

    **Variance Shadow Map的工作原理** 1. **存储阴影信息:**在传统Shadow Mapping中,我们直接存储每个像素是否被遮挡(1或0)。而在VSM中,我们存储两个值——阴影像素的平均深度(Mean)和深度方差(Variance)。...

Global site tag (gtag.js) - Google Analytics