游戏开发论坛

 找回密码
 立即注册
搜索
查看: 4161|回复: 2

POST_GodRay效果

[复制链接]

33

主题

159

帖子

272

积分

中级会员

Rank: 3Rank: 3

积分
272
QQ
发表于 2012-2-13 22:15:00 | 显示全部楼层 |阅读模式
[img][/img]
在FX sampler里看到GODRAY效果,很喜欢,就学了下。花了两天业余时间做了个效果测试程序,天气太冷,明天上班了吹着空调再来解释GodRay的原理

33

主题

159

帖子

272

积分

中级会员

Rank: 3Rank: 3

积分
272
QQ
 楼主| 发表于 2012-2-14 09:39:00 | 显示全部楼层

Re: POST_GodRay效果



用一个四方形表现效果不怎么好,换一个教堂玻璃

33

主题

159

帖子

272

积分

中级会员

Rank: 3Rank: 3

积分
272
QQ
 楼主| 发表于 2012-2-14 13:20:00 | 显示全部楼层

Re:POST_GodRay效果

在FX SAMPLER里面的GOD RAY有两种方法,一种是普通渲染模型,另一种就是这里使用的POST GOD RAY,由于普通的GOD RAY光照模型的效果实在让我不怎么感冒,所以只看了使用后处理的这个例子,这里把原理写出来供大家参考。
POST后处理是间接渲染技术,即:并不直接将模型渲染到屏幕上,而是将正常状态下渲染出来的SURFACE存在一个LPDIRECT3DTEXTURE9里,然后将这张图片作为一个四顶点正方形的纹理传入shader,最后POST到屏幕。DIRECT3D SDK里动态模糊的例子里面有POST技术用的一些常用函数,修改下就能用在自己的程序里。

本例中,
1.        正常渲染段要求渲染出一张背景alpha值为0.0的LPDIRECT3DTEXTURE9,可以在正常渲染段使用半透明纹理。
2.        Post段中,尽可能不要使用顶点着色器,如果顶点FVF设置为D3DFVF_XYZRHW(或Vertex Decl中设置为等效于_XYZRHW)的情况下,顶点着色器会被过滤掉

这样下来,在这个FX中真正有用的代码就这么一段
float4 PostGodRay_PS(GODRAY_V_OUT IN):COLOR0
{
        float4 c4OUT = 0;
        float4 c4Org = 0;
        float4 c4Blur = 0;
        float2 v2UVTransed = IN.v2UV - g_v2Center;//g_v2Center 是UV座标系中GOD RAY的发射中心点
        for(int i=0; i< g_iBlurTimes; i++)
        {
                float fScale = g_fBlurStart + g_fBlurWidth*(i/(float)(g_iBlurTimes-1));
                c4Blur += tex2D(spPost,v2UVTransed*fScale + g_v2Center);
        }//end for
        c4Blur /= g_iBlurTimes;
        c4Blur.rgb = pow(c4Blur.rgb,g_fGlowGamma)*g_fIntensity;
        c4Blur.rgb = saturate(c4Blur.rgb);
        c4Org = tex2D(spPost,v2UVTransed + g_v2Center);
        c4OUT.rgb = c4Org.rgb+(1.0-c4Org.a)*c4Blur.rgb;
        float fAlpha = max(c4Org.a,c4Blur.a);
        c4OUT.a = fAlpha;
       
        ///////////////////////////
        return c4OUT;
}//end func


解释:
float2 v2UVTransed = IN.v2UV - g_v2Center;
即UV座标系偏移至 g_v2Center为中心。
座标系偏移的好处是你在新的座标糸中进行的位移、拉伸等操作,都是以 g_v2Center为中心点进行的
而取样时只要: v2UV = v2UVTransed+g_v2Center就又回到正常的UV座标系了

for(int i=0; i< g_iBlurTimes; i++)
        {
                float fScale = g_fBlurStart + g_fBlurWidth*(i/(float)(g_iBlurTimes-1));
                c4Blur += tex2D(spPost,v2UVTransed*fScale + g_v2Center);
        }//end for
        c4Blur /= g_iBlurTimes;

由外及内,多重取样后求模糊效果在当前点的色彩平均值
        c4Blur.rgb = pow(c4Blur.rgb,g_fGlowGamma)*g_fIntensity;
乘上效果的强度值 g_fIntensity
这时候 c4Blur就成型了,但如果当前PEXEL点在正常渲染的物体上呢?
        c4Org = tex2D(spPost,v2UVTransed + g_v2Center);
取出当前像素点上原图应该显示的色值
好,整理一下,到这里,我们得到了一个 c4Blur 模糊色值  与一个 c4Org 原始图的色值
我们要的效果是:显示原始图,在其基础上显示一个光照投射的效果,所以当前点上如果原始图有色值,就应该使用原始图色值,而原始图没有色值的情况下,应显示光影模糊的色值
这里使用了一个alpha值来补差,当然,你要搞复杂点,效果搞好一点,也可以另外做lerp。
        c4OUT.rgb = c4Org.rgb+(1.0-c4Org.a)*c4Blur.rgb;
alpha补差如同上面的 座标系偏移,虽然简单,但却是一个好用又有用的小技术 ,以原始色值的alpha为阀值混合了两个色彩
到这里就OK了,但为什么还有最后两句
        float fAlpha = max(c4Org.a,c4Blur.a);
        c4OUT.a = fAlpha;

喵的,仔细想想吧,如果一个教堂的场景,可不光光是一块彩色玻璃,还有墙壁还有桌椅,渲染的时候怎么做,1先render除玻璃外的场景 2再以alpha 0.0为背景 Render玻璃,再做GodRay的POST,最后喵,3再把GodRay技术POST出来的图混合到总场景的图上 这个时候就要求 GodRay这个effect做出来的图片必须要带alpha值

原理解释完了,文采不怎么好,见谅咯
这个小程序的CODE不公布了,图方便用自己做的c#下的direct框架做的(喵喵,事实上不怎么实用 c++/clr架桥,主要函数全在 win32的C++工程,C#就一张皮 )WIN7下运行正常,XP滴能不能运行不知道,手头穷没机器测试
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-9 11:07

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表