• <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 狂爛球 閱讀(832) 評論(0)  編輯 收藏 引用 所屬分類: 圖形編程

            国产精品熟女福利久久AV| 久久夜色精品国产www| 久久久久一本毛久久久| 九九99精品久久久久久| 久久精品水蜜桃av综合天堂| 欧美日韩精品久久久久| 成人午夜精品无码区久久| 97久久婷婷五月综合色d啪蜜芽 | 久久久久AV综合网成人| 亚洲欧美日韩久久精品第一区| 色综合久久夜色精品国产| 欧美成人免费观看久久| 四虎国产精品成人免费久久| 久久精品一本到99热免费| 狠狠色丁香久久婷婷综合_中| 久久人妻少妇嫩草AV蜜桃| 久久亚洲精品无码VA大香大香| 精品多毛少妇人妻AV免费久久| 综合人妻久久一区二区精品| 亚洲国产另类久久久精品黑人 | 久久午夜无码鲁丝片秋霞 | 国产精品永久久久久久久久久| 色综合久久综精品| 久久久中文字幕日本| 中文字幕日本人妻久久久免费| 久久久无码精品亚洲日韩按摩| 欧美久久精品一级c片片| 蜜桃麻豆www久久国产精品| 亚洲欧美国产精品专区久久 | 久久久久久久尹人综合网亚洲 | 久久电影网2021| 亚洲人成无码久久电影网站| 日韩精品久久无码中文字幕| 国产精品久久久久久久久| 欧美午夜A∨大片久久| 精品久久久久久久无码| 久久本道久久综合伊人| 亚洲va久久久噜噜噜久久狠狠 | 久久精品嫩草影院| 久久精品成人欧美大片| 91精品国产91久久久久久蜜臀|