• <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>

            永遠(yuǎn)也不完美的程序

            不斷學(xué)習(xí),不斷實踐,不斷的重構(gòu)……

            常用鏈接

            統(tǒng)計

            積分與排名

            好友鏈接

            最新評論

            一起學(xué)習(xí)Shadow mapping

            轉(zhuǎn)自:http://www.cnblogs.com/cxrs/archive/2009/10/17/1585038.html
            1、什么是Shadow Maping?
                  Shadow Mapping是由Lance Williams于1978年在一篇名為"Casting curved shadows on curved surfaces"的文章中提出的,這篇文章是ShadowMap技術(shù)之根源。其實原理很簡單,如果光源和目標(biāo)點之間的連線沒有任何物體阻擋的話,則目標(biāo)點沒有在陰影中;如果有物體遮擋,則目標(biāo)點處在陰影中。而ShadowMap,就是一張記錄了每個象素處用于比較遮擋關(guān)系信息的Texture. 
                  產(chǎn)生這個ShadowTexture的方法很簡單,以SpotLight為例,把3D Camera放到光源的位置,把DepthTest打開,渲染場景,在PixShader中把每個象素的深度信息或者光源和此象素的距離信息寫到RenderTarget上,由于DepthTest是打開的,保證了最終寫到RenderTarget上的均是物體上未處在陰影中的點的深度值,實質(zhì)完全可以等效為最終的DepthBuffer。
                 得到這個ShowMap之后,如何最終生成陰影呢?在PixShader對每個pixel進(jìn)行處理時,算出當(dāng)前象素與燈當(dāng)?shù)木嚯xDc,與存在ShdowMap中的引像素的值Dz進(jìn)行比較,如果Dc > Dz,則在陰影中,反之則被燈光照亮。
            2、Shadowmap之HLSL的實現(xiàn)
                在Direct SDk中有ShadowMap的Sample,下面的Shader和Sample里面空全一樣,只是加了一些注釋便于理解。
                (1)生成ShadowMap的VS和PS

            //-----------------------------------------------------------------------------
            // Vertex Shader: VertShadow
            void VertShadow( float4 Pos : POSITION,
                             float3 Normal : NORMAL,
                             out float4 oPos : POSITION,
                             out float2 Depth : TEXCOORD0 )
            {
                //從模型坐標(biāo)系變換到觀察坐標(biāo)系
                oPos = mul( Pos, g_mWorldView );
               //進(jìn)行投影變換
               oPos = mul( oPos, g_mProj );
               //把投影坐標(biāo)系的ZW值賦給Depth,作為PixelShader中的輸出,這里的Z還是齊次坐標(biāo),這里不直接輸出Z/W,我的理解是讓Z和W都在Rasterizer中進(jìn)行線性插
              //值,這樣可以增加最終生成的ShadowMap的精度。
                Depth.xy = oPos.zw;
            }
            //-----------------------------------------------------------------------------
            // Pixel Shader: PixShadow
            void PixShadow( float2 Depth : TEXCOORD0,
                            out float4 Color : COLOR )
            {
                // 把 z / w的值作為Color值輸出,寫到RenderTarget上,此時的RT formate是D3DFMT_R32F
               //把Z/W目的是把齊次坐標(biāo)Z變換到三維空間的非齊次坐標(biāo),范圍則是[-1,1]
                Color = Depth.x / Depth.y;
            }

            (2)用ShadowMap生成Shadow

            //-----------------------------------------------------------------------------
            // Vertex Shader: VertScene
            // Desc: Process vertex for scene
            //-----------------------------------------------------------------------------
            void VertScene( float4 iPos : POSITION,
                            float3 iNormal : NORMAL,
                            float2 iTex : TEXCOORD0,
                            out float4 oPos : POSITION,
                            out float2 Tex : TEXCOORD0,
                            out float4 vPos : TEXCOORD1,
                            out float3 vNormal : TEXCOORD2,
                            out float4 vPosLight : TEXCOORD3 )
            {
                vPos = mul( iPos, g_mWorldView );
                oPos = mul( vPos, g_mProj );
                vNormal = mul( iNormal, (float3x3)g_mWorldView );
                Tex = iTex;
                //把當(dāng)前頂點位置變換到以光源為Camera的投影空間,
                vPosLight = mul( vPos, g_mViewToLightProj );
            }

             


            //-----------------------------------------------------------------------------
            // Pixel Shader: PixScene
            // Desc: Process pixel (do per-pixel lighting) for enabled scene
            //-----------------------------------------------------------------------------
            float4 PixScene( float2 Tex : TEXCOORD0,
                             float4 vPos : TEXCOORD1,
                             float3 vNormal : TEXCOORD2,
                             float4 vPosLight : TEXCOORD3 ) : COLOR
            {
                float4 Diffuse;

                // 計算光源到當(dāng)前象素方向向量并單位化
                float3 vLight = normalize( float3( vPos - g_vLightPos ) );

                //  dot( vLight, g_vLightDir )為光源到當(dāng)前象素方向向量和光的方向向量之間的夾角余旋值,由于是spotlight,因此必須要在spotlight可照射的范圍內(nèi)。因為角
                //度越小余旋值越大,因此這里是大于
                if( dot( vLight, g_vLightDir ) > g_fCosTheta ) 
                {
                    // Pixel is in lit area. Find out if it's
                    // in shadow using 2x2 percentage closest filtering

                    //從投影空間坐標(biāo)轉(zhuǎn)化為紋理空間坐標(biāo),也就是找到投影空間中的點和紋理空間中的點的對應(yīng)關(guān)系
                   //除以w,xy坐標(biāo)便處在(-1,1)的范圍內(nèi),乘0.5加0.5,則變換到了(0,1)的范圍,因texture space的u,v坐標(biāo)是(0,1)的
                    float2 ShadowTexC = 0.5 * vPosLight.xy / vPosLight.w + float2( 0.5, 0.5 );
                   //在投影坐標(biāo)系中,Y軸是向上的,而在紋理空間中Y軸向下,因此要作以下處理
                    ShadowTexC.y = 1.0f - ShadowTexC.y;

                    // 在texel space中對應(yīng)的象素坐標(biāo)
                    float2 texelpos = SMAP_SIZE * ShadowTexC;
                   
                    // 取得小數(shù)部分         
                    float2 lerps = frac( texelpos );

                    //這里使用的是2x2 percentage closest filtering,因此是采的鄰近的四個點,判斷它們是否在陰影中,
                    float sourcevals[4];
                    sourcevals[0] = (tex2D( g_samShadow, ShadowTexC ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f; 
                    sourcevals[1] = (tex2D( g_samShadow, ShadowTexC + float2(1.0/SMAP_SIZE, 0) ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f; 
                    sourcevals[2] = (tex2D( g_samShadow, ShadowTexC + float2(0, 1.0/SMAP_SIZE) ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f; 
                    sourcevals[3] = (tex2D( g_samShadow, ShadowTexC + float2(1.0/SMAP_SIZE, 1.0/SMAP_SIZE) ) + SHADOW_EPSILON < vPosLight.z / vPosLight.w)? 0.0f: 1.0f; 
                   
                    // 用lerps 
                    float LightAmount = lerp( lerp( sourcevals[0], sourcevals[1], lerps.x ),
                                              lerp( sourcevals[2], sourcevals[3], lerps.x ),
                                              lerps.y );
                    // 計算光照,如果完全在陰影中,則LightAmount為0,這里只計算了Diffuse color,沒有高光
                    Diffuse = ( saturate( dot( -vLight, normalize( vNormal ) ) ) * LightAmount * ( 1 - g_vLightAmbient ) + g_vLightAmbient )
                              * g_vMaterial;
                } else
                {
                    Diffuse = g_vLightAmbient * g_vMaterial;
                }

                return tex2D( g_samScene, Tex ) * Diffuse;
            }


            3、ShdowMap的優(yōu)缺點
                優(yōu)點:簡單,不需要知道場景中Object的Geometry,不需要Stencil Buffer,每個燈光只需多渲染一個Pass。
                缺點:當(dāng)ShadowMap分辨率不夠高時,或燈光與物體隔得很近時,在邊緣處會產(chǎn)生Aliasing,鋸齒,因此,很多改進(jìn)shadowMap的算法都圍繞著如何消除鋸齒作文章。
            4、ShadowMap的改進(jìn)
                關(guān)于ShadowMap的改進(jìn),又出了很多的paper和技術(shù),比如:Percentage Shadow map,  使用bloom filter對ShadowMap進(jìn)行模糊處理.以及siggraph 2002 中Marc Stamminger和 George Drettakis提出的Perspective Shadow map.以及Adaptive Shadow Map等等。

            posted on 2010-03-21 20:15 狂爛球 閱讀(2018) 評論(0)  編輯 收藏 引用 所屬分類: 圖形編程

            最新久久免费视频| 99999久久久久久亚洲| 久久中文字幕精品| 久久丫精品国产亚洲av| 国内精品久久久久国产盗摄| 久久午夜免费视频| 亚洲一本综合久久| 日韩AV无码久久一区二区| 91久久成人免费| 久久久久亚洲AV无码永不| 久久精品无码一区二区三区免费 | 伊人久久精品无码二区麻豆| 99精品久久久久中文字幕| 伊人久久亚洲综合影院| 国产精品久久一区二区三区| 2021最新久久久视精品爱| 久久99精品久久久久久不卡| 色综合久久无码中文字幕| 久久无码国产| 国内精品久久久久久久coent| 欧美牲交A欧牲交aⅴ久久| 99久久国产亚洲综合精品| 国产亚洲成人久久| 99久久婷婷国产一区二区| 国产人久久人人人人爽| 亚洲精品乱码久久久久久中文字幕| 久久久久这里只有精品| 久久久久九九精品影院| 久久久久成人精品无码 | 91精品婷婷国产综合久久| 99国产欧美久久久精品蜜芽 | 国产欧美久久久精品| 久久久噜噜噜久久中文福利| 久久精品青青草原伊人| 国产亚洲精品久久久久秋霞| 久久婷婷五月综合国产尤物app| 亚洲精品99久久久久中文字幕| 亚洲国产成人精品无码久久久久久综合 | 久久综合88熟人妻| 久久99国产精品久久99果冻传媒| 91精品国产乱码久久久久久|