• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            永遠也不完美的程序

            不斷學習,不斷實踐,不斷的重構……

            常用鏈接

            統計

            積分與排名

            好友鏈接

            最新評論

            [轉]HLSL實現Layer Fog

            What’s Layer Fog

            這個問題通過圖片來解答再合適不過了,下面是本文利用layerFog做的一個結果。

            所謂layer fog,顧名思義就是被限制在某一層的霧,本文的目的就是描述如何實現了被限制在一定高度范圍內的霧效。

            1         Thanks to Programmable Pipeline

            霧效增強場景真實感也不是一天半天了,但無論opengl還是d3d,無論linear(線性衰減)、exp(指數衰減)還是exp2(指數平方衰減),以往實現的霧效都是全局的,要么就都加霧效,要么都不加。在固定渲染流水線的統治時代,想做到“山谷煙霧彌漫,峰頂明月清風是相當復雜而啰嗦的事。

            感謝那些大牛公司和它們的圖形精英,他們在享受創造的樂趣之余,想到了我們,給了我們參與創作的機會。可編程流水線的出現,讓我們在做類似layer fog這類事情的時候可以直奔主題。

            閑話少說,本文不介紹Programmable Pipeline,也不介紹vspsHLSLeffect,相關知識可以參考Directx9 SDK,下面來開始介紹Layer fog

            1         Theory

            我們知道霧效最終體現在一個顏色的融合因子上,根據這個融合因子的大小,可以確定霧化程度,如果融合因子為factor,霧的顏色為fogColor,場景點本身的顏色為sceneColor則最終霧化后的顏色finalColor應為:

                   finalColor = sceneColor+factor*(fogColor-sceneColor)                (0<=factor<=1)

                該融合因子體現了顏色混合中霧的權重,假設霧的濃度函數為fuction(x,y,z), 以視線進入霧層為起點fStart,實現離開霧層(或到達場景物體表面)為結束點fEnd,factor實際上是function(x,y,z)在從fStartfEnd這段路徑上的積分,如下:

            本文的重點是描述layer fog的實現思想,所以采用了最簡單的霧效方程,認為在霧層范圍內,霧的濃度保持常數不變。則公式變為:

            distance(fStart,fEnd)是求兩點之間距離的函數,在實際計算中,霧層定義在Y方向,此式往往可用以下公式表示

            其中abs函數是取絕對值函數,θ角是射線與XOZ平面的夾角。

            下面針對具體情況進行說明。

               

            如圖所示,layerFog有霧頂(y坐標為fFogTop),霧底(fFogEnd,霧在fFogEndfFogTop之間存在,需要保證fFogTop>fFogEnd

            由于layerfog的照相機位置存在三種情況

            l         Camera.y>fFogTop

            l         fFogEnd<Camera.y<fFogTop

            l         fFogEnd<Camera.y

            場景點ScenePoint位置也存在三種情況

            l         ScenePoint.y>fFogTop

            l         fFogEnd< ScenePoint.y<fFogTop

            l         fFogEnd< ScenePoint.y

            所以,實際上共有9種組合情況,每種的處理方法有所不同,實際上說白了就一句話“合法范圍內積分,超出霧層范圍之外不進行積分“,本著這個原則針對每種情況的不同確定積分上下限。

            1 Code

            本文采用Effect實現該算法,其主要代碼如下:

             

            texture g_MeshTexture;              // 紋理

             

            float4x4 g_matWorld;                  // 物體的世界變換矩陣,由應用程序輸入

            float4x4 g_matWorldViewProj;    // World * View * Projection matrix,由應用程序輸入

            float4   g_FogParameter;//.x=fogHeight   .y = fogEnd  .z = fogRange,由應用程序輸入

            float4   g_vCamera;      //攝像機位置,由應用程序輸入

            float4   g_FogColor;     //霧顏色,由應用程序輸入

             

            //--------------------------------------------------------------------------------------

            // 紋理采樣器

            //--------------------------------------------------------------------------------------

            sampler MeshTextureSampler =

            sampler_state

            {

                Texture = <g_MeshTexture>;

                MipFilter = LINEAR;

                MinFilter = LINEAR;

                MagFilter = LINEAR;

            };

             

             

            //--------------------------------------------------------------------------------------

            // 頂點著色器輸入結構體

            //--------------------------------------------------------------------------------------

             

            struct VS_INPUT

            {

                float4 Position   : POSITION;   // 頂點位置

                float4 Diffuse    : COLOR0;     // 頂點顏色

                float2 TextureUV  : TEXCOORD0;  // 紋理坐標

            };

            //--------------------------------------------------------------------------------------

            // 頂點著色器輸出結構體

            //--------------------------------------------------------------------------------------

             

            struct VS_OUTPUT

            {

                float4 Position   : POSITION;   // 頂點位置

                float2 TextureUV  : TEXCOORD0;  // 紋理坐標

                 float4 FogVal     : COLOR0;      //霧化因子,僅使用x分量

            };

             

            //--------------------------------------------------------------------------------------

            // 頂點著色器處理程序

            //--------------------------------------------------------------------------------------

            VS_OUTPUT RenderSceneVS( const VS_INPUT Input)

            {

                     float4 clpPos, camPos, worldPos;

                     float fDistance;

                    

                     // 初始化輸出

                     VS_OUTPUT ut = (VS_OUTPUT) 0;

                    

                     // 計算頂點剪切空間的坐標

                     clpPos = mul(Input.Position, g_matWorldViewProj);

                     Out.Position = clpPos;

                    

                     // 輸出紋理坐標

                     Out.TextureUV.xy = Input.TextureUV.xy;

                    

                     // 獲得霧化參數

                     float fFogTop   = g_FogParameter.x;

                     float fFogEnd   = g_FogParameter.y;

                     float fFogRange = g_FogParameter.z;

                    

                    

                     // 計算頂點在世界坐標系中的位置

                     worldPos = mul(Input.Position, g_matWorld);

                    

                     // 計算頂點和觀測者之間的位置

                     fDistance = distance(worldPos, g_vCamera);

                    

                     // factor = 1/sinθ * fDensityFog ,其中fDensityFog = 1/fFogRange;

                     // 該值就是最后與deltaY相乘的系數,在一起計算,可以節省一次除法運算。

                    

                     float factor =fDistance/(fFogRange*(worldPos.y - g_vCamera.y));

                  

                     //fDeltaY 是經過霧層的線段在Y方向的距離,下面是分情況卻定fDeltaY的代碼 

                     float fDeltaY ;

                     if(g_vCamera.y > fFogTop)

                          {

                                        if (worldPos.y > fFogTop) //

                                        {

                                             fDeltaY = 0.0f;

                                        }

                                        else

                                        {

                                             if( worldPos.y > fFogEnd)//fFogEnd< worldPos.y <fFogTop

                                             {

                                                 fDeltaY = fFogTop - worldPos.y;

                                             }

                                             else                      //worldPos.y< fFogEnd

                                             {

                                                 fDeltaY = fFogTop - fFogEnd;

                                             }

                                        }

                          }

                          else

                          {

                                   if( g_vCamera.y > fFogEnd)

                                   {

                                                 if (worldPos.y > fFogTop)

                                                 {

                                                     

                                                      fDeltaY =fFogTop - g_vCamera.y;

                                                 }

                                                 else

                                                 {

                                                      if( worldPos.y > fFogEnd)//fFogEnd< worldPos.y <fFogTop

                                                      {

                                                           fDeltaY = worldPos.y - g_vCamera.y;

                                                      }

                                                      else                        //worldPos.y< fFogEnd

                                                      {

                                                           fDeltaY = fFogEnd -g_vCamera.y;

                                                      }

                                                 }

                                   }

                                   else//g_vCamera.y < fFogEnd

                                   {

                                             if (worldPos.y > fFogTop)

                                                 {

                                                      fDeltaY = fFogTop - fFogEnd;

                                                 }

                                                 else

                                                 {

                                                      if( worldPos.y > fFogEnd) //fFogEnd< worldPos.y <fFogTop

                                                      {

                                                           fDeltaY =  worldPos.y - fFogEnd;

             

                                                      }

                                                      else                     //worldPos.y< fFogEnd

                                                      {

                                                           fDeltaY = 0.0f;

                                                      }

                                                 }

                                   }

                          }

                     Out.FogVal.x = abs(factor*fDeltaY);

                     return Out;

            }

             

             

            //--------------------------------------------------------------------------------------

            // 象素著色器輸出結構體

            //--------------------------------------------------------------------------------------

            struct PS_OUTPUT

            {

                float4 RGBColor : COLOR0;  // 象素顏色 

            };

            struct PS_IUTPUT

            {

                float2 TextureUV  : TEXCOORD0;  // 頂點紋理坐標

                float4  FogVal    : COLOR0;      //霧化系數

            };

            //--------------------------------------------------------------------------------------

            // This shader outputs the pixel's color by modulating the texture's

            //       color with diffuse material color

            //--------------------------------------------------------------------------------------

            PS_OUTPUT RenderScenePS( const PS_IUTPUT In)

            {

              PS_OUTPUT Output;

             

              //獲得紋理顏色

              Output.RGBColor = tex2D(MeshTextureSampler, In.TextureUV);

             

              //顏色混合

              float f = In.FogVal.x;

              Output.RGBColor = lerp(Output.RGBColor,g_FogColor,f);

              return Output;

            }

            posted on 2008-08-27 17:18 狂爛球 閱讀(828) 評論(0)  編輯 收藏 引用 所屬分類: 圖形編程

            久久综合亚洲色HEZYO国产| 午夜精品久久久久久毛片| 久久www免费人成精品香蕉| 久久精品视频91| 久久精品国产亚洲AV电影| 亚洲国产精品久久久久久| 欧美黑人激情性久久| 久久精品9988| 无码AV中文字幕久久专区| 久久久久这里只有精品| 久久午夜无码鲁丝片| 久久综合久久性久99毛片| 久久久亚洲欧洲日产国码aⅴ| 久久天天躁狠狠躁夜夜2020| 久久最新精品国产| 少妇精品久久久一区二区三区| 久久久久亚洲av成人无码电影 | 久久亚洲中文字幕精品一区| 久久精品国产亚洲AV电影| 久久久久亚洲av成人网人人软件| 亚洲成色999久久网站| 99久久精品毛片免费播放| 久久久久久久久久久| 色综合久久天天综线观看| 94久久国产乱子伦精品免费| 久久精品国产69国产精品亚洲| 久久99精品久久久久久动态图| 人妻无码久久一区二区三区免费| 一本色道久久88综合日韩精品 | 奇米影视7777久久精品| 热99RE久久精品这里都是精品免费 | 蜜桃麻豆www久久国产精品| 狠狠精品干练久久久无码中文字幕| 热99re久久国超精品首页| 久久国产精品成人免费| 色综合合久久天天综合绕视看| 热久久这里只有精品| 久久成人18免费网站| 日韩AV毛片精品久久久| 久久久黄色大片| 久久久亚洲欧洲日产国码aⅴ |