一种软阴影的实现方法 收藏

上传人:工**** 文档编号:456807488 上传时间:2022-10-01 格式:DOCX 页数:19 大小:127.54KB
返回 下载 相关 举报
一种软阴影的实现方法 收藏_第1页
第1页 / 共19页
一种软阴影的实现方法 收藏_第2页
第2页 / 共19页
一种软阴影的实现方法 收藏_第3页
第3页 / 共19页
一种软阴影的实现方法 收藏_第4页
第4页 / 共19页
一种软阴影的实现方法 收藏_第5页
第5页 / 共19页
点击查看更多>>
资源描述

《一种软阴影的实现方法 收藏》由会员分享,可在线阅读,更多相关《一种软阴影的实现方法 收藏(19页珍藏版)》请在金锄头文库上搜索。

1、一种软阴影的实现方法收藏www.GameD 作者:Anirudh.S Shastryhttp:/www.gamedev .n et/refere nce/articles/article2193.asp译者:赟赟带图片的word文档在附件中介绍最初,动态阴影技术只有在有限的几种情况下才能实现。但是,随着强大的可编 程图形硬件的面世,动态阴影技术已经完全取代了以前的如light map这样的 静态阴影技术及像projected shadows这样的半动态阴影技术。目前两种流行 的动态阴影技术分另U是shadow volumes和shadow mapping。近况shadow volumes技术是

2、一种基于几何形体的技术,它需要几何体在一定方向 的灯光下的轮廓去产生一个封闭的容积,然后通过光线的投射就可以决定场景的 阴影部分(常常使用模板缓冲去模拟光线的投射)。这项技术是像素精确的,不 会产生任何的锯齿现象,但是与其他的技术一样,它也有缺点。最主要的两个问 题一是极度依赖几何形体,二是需要非常高的填充率。由于这些缺点,使得sh adow mapping技术渐渐地变得更为流行起来。阴影映射技术是一种图像空间的技术,它首先在以光源位置作为视点的情况下渲 染整个场景的深度信息,然后再使用这些深度信息去决定场景的哪一部分是处于 阴影之中。虽然这项技术有许多优点,但它有锯齿现象并且依赖z-缓冲技术

3、。 不过它的优点足以抵消它的这些缺点,因此本文选用了这项技术。软阴影硬阴影破坏了场景的真实性,因此,我们必须仿造软阴影来提升场景的可视效果。 许多狂热的学者都拿出了描述软阴影技术的论文。但实际上,这些技术大部分都 是很难在一个较为复杂的场景下实现实时效果。直到我们拥有了能克服这些技术 局限性的硬件后,我们才真正的采用了这些方法。本文采用了基于图像空间的方法,并利用shadow mapping技术来产生软阴 影。这个方法不能产生完美的阴影,因为没有真正的模拟出本影和半影,但它不 仅仅可以解决阴影映射技术的锯齿现象,还能以赏心悦目的软阴影来提升场景的 可视效果。那么它如何工作?首先,我们生成阴影映

4、射图(shadow map),具体方法是以光源位置为视点, 将场景的深度信息渲染到浮点格式的缓冲中去。然后我们不是像通常那样在阴影 下渲染场景,而是将阴影区域渲染到一幅屏幕大小的缓冲中去,这样就可以使用 bloom filter进行模糊并将它投射回屏幕空间中使其显示在屏幕上。是不是很简 单?本文只处理了聚光灯源这种情况,但可以很方便的推广到点光源上。下面是具体步骤:通过将深度信息写入浮点纹理的方法产生阴影映射图(shadow map)。深度比较后将场景的阴影部分渲染到定点纹理,此时不要任何的灯光。使用bloom filter模糊上一步的纹理,本文采用了 separable Gaussian f

5、ilter,也可用其他的方法。在所有的光源下将上一步模糊后的纹理投射到屏幕空间中,从而得到最终的效 果。步骤一:渲染阴影映射图(shadow map)首先,我们需要创建一个能保存屏幕深度信息的纹理。因为要把这幅纹理作为r ender target,所以我们还要创建一个表面(surface)来保存纹理的表面信息。 由于深度信息值的范围很大因此这幅纹理必须是浮点类型的。R32F的格式有足 够的精度可以满足我们的需要。下面是创建纹理的代码片断:/ Create the shadow mapif( FAILED( g_pd3dDevice-CreateTexture( SHADOW_MAP_SIZE,

6、 SHADOW_MAP_SIZE, 1, D3DUSAGE_RENDERTARGET, D3DFMT_R32F, D3DPOOL_DEFAULT, &g_pShadowMap,NULL )MessageBox( g_hW nd, Un able to create shadow map!,Error, MB_OK | MB_IC on ERROR );return E_FAIL;/ Grab the textures surfaceg_pShadowMap-GetSurfaceLevel( 0, &g_pShadowSurf );为了完成阴影映射图,我们要把场景的深度信息渲染到阴影映射图中。为

7、此在光源的世界-视点-投影变换矩阵(world-view-projectio n matrix)下渲染整个 场景。下面是构造这些矩阵的代码:/ Ordi nary view matrixD3DXMatrixLookAtLH( & matView, &vLightPos, &vLightAim, &g_vU p );/ Projectio n matrix for the lightD3DXMatrixPerspectiveFovLH( & matProj, D3DXToRadia n( 30.0f),1.0f, 1.0f, 1024.0f);/实际上作者在例程中使用的是D3DXMatrixOr

8、thoLH( &matProj, 45.0f, 45.0f, 1.0f, 1024.0f )。这个函数所构造的 project 矩阵与 D3DXMatrix PerspectiveFovLH ()构造的不同之处在于:它没有透视效果。即物体的大小 与视点和物体的距离没有关系。显然例程中模拟的是平行光源(direction ligh t),而这里模拟的是聚光灯源(spot light不知翻译得对不对?)/ Con cate nate the world matrix with the above/ two to get the required matrixmatLightViewProj = m

9、atWorld * matView * matProj;下面是渲染场景深度的顶点渲染和像素渲染的代码:/ Shadow gen erati on vertex shaderstruct VSOUTPUT_SHADOWfloat4 vPositi on : POSITION;float fDepth : TEXCOORDO;VSOUTPUT_SHADOW VS_Shadow( float4 in Positio n : POSITION )/ Output structVSOUTPUT_SHADOW OUT = (VSOUTPUT_SHADOW)0;/ Output the tra nsform

10、ed positi onOUT.vPosition = mul( inPosition, g_matLightViewProj );/ Output the sce ne depthOUT.fDepth = OUT.vPositi on.z;return OUT;这里我们将顶点的位置与变换矩阵相乘,并将变换后的z值作为深度。在像素渲 染中将深度值以颜色(color)的方式输出。float4 PS_Shadow( VSOUTPUT_SHADOW IN ) : COLOR0/ Output the sce ne depthreturn float4( IN.fDepth, IN.fDepth, I

11、N.fDepth, 1.0f );瞧,我们完成了阴影映射图,下面就是以颜色方式输出的阴影映射图,深蓝色部 分表明较小的深度值,浅蓝色部分表明较大的深度值。步骤二:将带阴影的场景渲染到缓冲中下面,我们要把场景的带阴影的部分渲染到并不立即显示的缓冲中,使我们可以 进行模糊处理,然后再将它投射回屏幕。首先把场景的阴影部分渲染到一幅屏幕 大小的定点纹理中。/ Create the scree n-sized buffer mapif( FAILED( g_pd3dDevice-CreateTexture( SCREEN_WIDTH, SCREEN_HEIGHT, 1, D3DUSAGE_RENDERT

12、ARGET, D3DFMT_A8R8G8B8, D3DP00L_DEFAULT,&g_pScree nMap, NULL )MessageBox( g_hW nd, Un able to create scree n map!,Error, MB_OK | MB_IC on ERROR );return E_FAIL;/ Grab the textures surfaceg_pScree nMap-GetSurfaceLevel( 0, & g_pScree nSurf );为了获得投影纹理坐标(projective texture coordinates),我们需要一个 纹理矩阵,作用是把投

13、影空间(projectio n space)中的位置变换到纹理空间(texture space)中去。/ Gen erate the texture matrixfloat fTexOffs = 0.5 + (0.5 / (float)SHADOW_MAP_SIZE);D3DXMATRIX matTexAdj( 0.5f,0.0f,0.0f,0.0f,0.0f,-0.5f,0.0f,0.0f,0.0f,0.0f,1.0f,0.0f,fTexOffs, fTexOffs, 0.0f, 1.0f );这个矩阵是把projection space中范围为-1, 1的x,y坐标值转换到纹理 空间中0,

14、 1的范围中去。注意y轴的方向改变了。那个(0.5 / (float)SHADOW_ MAP_SIZE)的值有什么作用我还不清楚,原文也没有说明。matTexture = matLightViewProj * matTexAdj;我们像往常那样通过深度的比较来获得阴影因数,但随后并不是像平常那样输出 整个照亮了的场景,我们只输出阴影因数。下面的顶点渲染和像素渲染完成这个 工作。/ Shadow mapp ing vertex shaderstruct VSOUTPUT_UNLITfloat4 vPositi on : POSITION;float4 vTexCoord : TEXCOORD0;

15、float fDepth : TEXCOORD1;VSOUTPUT_UNLIT VS_Unlit( float4 inPosition : POSITION )/ Output structVSOUTPUT_UNLIT OUT = (VSOUTPUT_UNLIT)0;/ Output the tra nsformed positi onOUT.vPositio n = mul( in Positi on, g_matWorldViewProj );/ Output the projective texture coordi natesOUT.vTexCoord = mul( in Positi on, g_matTexture );/ Output the sce ne depthOUT.fDepth = mul( in Positi on, g_matLightViewProj ).z;return OUT;我们采用percentage closer filtering (PCF)来平滑锯齿边缘。为了完成“PC F,我们简单的对周围8个纹理点进行采样,并取

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 机械/制造/汽车 > 电气技术

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号