Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 游戏天堂 > 游戏开发 > Shaderey――非真实渲染
【标  题】:Shaderey――非真实渲染
【关键字】:Shaderey
【来  源】:http://blog.csdn.net/soilwork/archive/2007/01/11/1480538.aspx

Shaderey――非真实渲染

Your Ad Here

Shaderey――非真实渲染

本文版权归原作者所有,仅供个人学习使用,请勿转载,勿用于任何商业用途。
由于本人水平有限,难免出错,不清楚的地方请大家以原著为准。欢迎大家和我多多交流。
作者:Aras Pranckevicius
翻译:clayman
Blog:
http://blog.csdn.net/soilwork
clayman_joe@yahoo.com.cn 

     本文描述了以非真实渲染(none-photorealistic rendering)风格,对户外场景进行着色的技术。在2003年秋天的Beyond3D/ATI shader compititon中,Shaderey程序最先使用了这些技术来进行渲染。在Shaderey的户外场景中,包含了地形,云,树木,房屋,天空顶,以及湖水,如图所示:

    确切的说,这里使用的NPR技术都是在图片空间(image space)进行的操作,它依赖于场景中两张重要的图片:一张包含了颜色信息,一张包含法线和深度信息。处理过程分为两部分:

渲染: 把场景渲染到颜色和法线/深度目标中。

后期处理: 在图片空间进行一系列过滤操作,获得最终的非真实效果。

         后期处理包括:HSV空间下的颜色扭曲,屏幕空间中简单“阴影线(hatching)”的渲染,以及在法线/深度不连续处的轮廓线绘制。我们将在后面详细讨论这些过滤操作。首先,先来看看Shaderey的场景渲染方式。

 

场景渲染

         场景中所有的树木和房屋都经过了可视体裁剪(frustumculled)。地形是一张512 x 512的高度图,但分为若干尺寸固定的(32 x 32)小块(chunk)。所有通过视见体裁剪的地形小块都没有进行任何形式的LOD。整个场景使用了一张1024 x 1024的阴影帖图。房屋和树木都将产生阴影,并且投影到地面上。场景中的树木和木屋投射阴影,而地形接收这些影子。我们使用pick-nearest采样器,对阴影贴图进行四次有偏移的采样,然后再shader中对这些值进行均值采样,以提高影子边界上的质量。阴影贴图并不需要覆盖整个地形的大小,在我们的实现中,它将随观察者的位置移动,以保证观察者前方总是有正确的阴影。

         为了模拟湖面的简单反射效果,可以把摄像机反转到水面之下,把场景渲染为一张较小的平面反射贴图。我们把这张阴影贴图投影到水面上,另外使用两张卷动的EMBM风格的凹凸贴图来模拟波纹。为了减少几何数据,渲染到反射贴图中的地形将使用较低的LOD层次。对所有物体来说,大气光照散射效果都是在顶点级别计算的。

         除了把颜色渲染到后备缓冲之外,还需要把场景中物体的法线和深度渲染到一张和屏幕大小相同的A8R8B8G8纹理中。世界坐标下的法线信息保存在RGB通道中,深度值的导数保存在alpha通道中。

         下面是在vertex shader中,使用HLSL正确计算法线和深度值倒数的代码:

         //output normal in RGB, sort-of-depth in A, p – final ( clip space) position,  n—world space normal

         static inline float4 gNormalZ( float4 p, float3 n)

         {

                   float4 o;

                   o.xyz = n * 0.5 + 0.5;  // in to 0….1 range

              o.w = 100.0 / ( p.w + 100 );  // kind-of-depth

         }

         如果支持DirectX 9中的Multiple Render TargetMRT),可以在渲染场景颜色的同时,渲染法线和深度。如果不支持MRT,则需要分两次渲染(译注:从demo来看,使用MRT将会严重影响渲染质量,应该是由于MRT不支持多重采样造成的)。当把地形渲染到法线/深度纹理中时,需要使用<< Non-Photorealistic Rendering with Pixel and Vertex Shader>>中所描述的方法,在pixel shader中对阴影贴图进行采样,对阴影中的像素来说,需要对插值之后深度值取反(译注:Non-Photo原文中是对法线值取反)。这样做的原因在后面描述后期处理的部分会讲解。

 

图片后期处理

         目前已经把场景渲染为颜色和法线/深度图片了,接下来就可以对这些图片进行一系列处理了,包括把颜色转到HSV颜色空间下进行风格化处理,绘制边缘轮廓线,实现阴影线。

 

颜色失真

图片处理的第一步是进行颜色失真,获得风格化的样式。

1.降低采样率,把图片缩为一张521x512的纹理。

2.把颜色从RGB空间转换到HSV空间,并且量化(quantize)颜色值。颜色空间的转换将通过对一张体积材质的查找来实现。把原像素的RGB值作为立方纹理坐标。立方纹理中的像素为HSV颜色空间。这里我们将使用一张32x32x32的纹理,并且不进行任何过滤,所以颜色转换的同时将会量化颜色值。

3.使用2D偏移纹理,对同一纹理中当前像素的两个偏移位置进行采样。用来访问偏移纹理的纹理坐标由程序控制,它们将和观察者的位置有关(观察点的yaw值将在水平方向影响偏移,pitch值在垂直方向影响)。这些额外的采样颜色也必须转换到HSV空间。

4.替换图片中的颜色。目前我们有2个额外的偏移采样。首先,我们检察两个偏移值之间差分的差值,如果小于某个限制,就什么也不做。如果它们之间的差别足够大,则输出SV通道的均值,保留中心原像素的H值。这个方法能高效的在颜色区域边缘替换原像素的饱和度。

5.再使用一张立方纹理把颜色转换回HSV空间。

         2~5步的pixel shader代码如下,需要pixel shader 2.0的支持。

struct PS_INPUT

{

         float2 uv[2] : TEXCOORD0; //base uv,displace uv

};

 

float4 psMain( PS_INTPUT i) : COLOR

{

         //sample rgb,convert into hsv

         half base = tex2D( smpBase, i.uv[0] ).rgb;

         base = tex3D( smpRGB2HSV, base ).rgb;

        

         //get 2 displaced sample locations

         half2 bleedB = tex2D ( smpBleedB, i.uv[1] ).rg * 2 -1;

         half2 bleedC = tex2D ( smpBleedC, i.uv[1] ).rg * 2 -1;

         float2 uvB = i.uv[0] + bleedB * (8.0/512);

         float2 uvC = i.uv[0] + bleedC * (-7.0/512);

        

         //sample base at displaced locations ,convert to hsv

         half3 baseB = tex2D( smpBase,uvB).rgb;

         baseB = tex3D( smpRGB2HSV,baseB);

         half3 baseC = tex2D( smpBase, uvC).rgb;

         baseC = tex3D( smpRGB2HSV,baseC);

         half3 bleed = baseB * 0.5 + baseC * 0.5;

        

         //final color is base if differences in hsv values are smller than tresholds

         //else average of displace values

         half3 diff = abs(base - baseC) - half( 1/8.0,1/3.0,1/3.0)

         half3 final = all( diff < float3 ( 0,0,0) ? base : bleed;

        

         //leave original hue channel

         final.r = base.r;

         //convert back to rgb

         return tex3D ( smpHSV2RGB),final);

}

 

边缘检测和轮廓线

         为了获得NPR风格的样式,必须在图片上渲染出深色的轮廓线和阴影线,表现出场景的着色效果。在Shaderey中,我们将同时绘制边缘轮廓线和阴影线。这里需要使用之前计算的法线/深度图来计算边缘,用光线和法线的点积来计算那些区域需要绘制阴影线。阴影线是一张简单的纹理。在这一步处理中,边缘和轮廓线都是白色。最终合成时,进行反色处理,轮廓线变为纯黑色,轮廓线颜色根据场景的着色进行衰减。

         以下是绘制轮廓线和阴影线的pixel shader代码:

half4 psMain ( float2 uv[3]:TEXCOORD): COLOR

{

         //sample center and 2 neightbours

         half4 cbase = tex2D( smpBase, i.uv[0]);

         half4 cb1 = tex2D(smpBase, i.uv[1]);

         half4 cb3 = tex2D(smpBase, i.uv[2]);

        

         //normal into -1..1 range

         half3 nbase = cbase.xyz * 2 -1;

         half3 nb1 = cb1.xyz * 2 - 1;

         half3 nb3 = cb3.xyz * 2 - 1;

        

         //edges from normals

         half2 ndiff;

         ndiff.x = dot( nbase,nb1);

         ndiff.y = dot( nbase,nb3);

         ndiff -= 0.6;

         ndiff = ndiff > half2(0,0) ? half2(0,0):half2(1,1);

         half ndiff1 = ndiff.x + ndiff.y;

        

         //edges from z

         float2 zdiff;

         zdiff.x = cbase.a - cd1.a;

         zdiff.y = cbase.a - cb3.a;

         adiff = abs(zdiff) - 0.02;

         zdiff = zdiff > half2(0,0) ? half2(1,1) : half2(0,0);

        

         //sampler hatch

         half4 chatch = tex2D( smpHatch, i.uv[0]);

         //dot normal with light

         half dotNL = dot( nbase, vLightDir);

         //hatch blend factor

         half factor = saturate( (1.0 - 0.9 - dotNL) * 2);

         chatch *= factor;

        

         return chatch + ndiff1 + dot(zdiff,half2(1,1));

}

 

最终合成

         在处理完了两张图片之后,把失真之后的颜色与反转之后的边缘/轮廓线进行调制,合成出最终图像。

 

 点击这里下载完成程序和代码。

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    这是《ShaderX3》里的一篇文章,第一次看到这个demo时很是惊奇,嗯嗯,不是所有游戏都要做的像DOOM那样才能吸引人,非真实渲染也是很有意思的风格。文章倒是老早就写完了,最近有朋友正在研究NPR,所以整理出来,希望能有帮助。

 ps:造物弄人啊,这是扭曲的一周! 明天终于要回家了,怀念昆明的太阳^o^~~~~~~~~

你在评论的同时也暴露出你的无能!:【上一篇】
何苦做游戏:【下一篇】
【相关文章】
没有相关文章
【随机文章】
  • 關於AS編譯代碼的次序
  • 用Fireworks轻松制作网页交互按钮
  • 策略管理之访问控制
  • WEB服务器配置全攻略(三)
  • UDP服务器的设计
  • [链接]Sony新的CD防拷贝软件问题多多
  • 封QQ最新方法(2006-9-7已实践)
  • AppUpdater 的一个问题
  • More on connection pooling in a web application
  • 专家访谈:铺设天地间的通信高速公路
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.