zoukankan      html  css  js  c++  java
  • 体积雾(dx9)

    1.什么是体积雾?

             这个问题通过图片来解答再合适不过了,下面是本文利用体积雾做的一个结果

            

            
             所谓体积雾:顾名思义就是被限制了形状的雾,本文表述如何通过ImageProcess(图象处理)的方式实现体积雾。
       2.常规雾原理
           雾效最终体现在雾颜色与场景色的混合上。决定雾的浓度的关键就在这个混合因子上。下面我们给出公式.
           float4   finalColor = factor * fogColor + ( 1 - factor) * sceneColor; ( !提取公因式,减少计算量)
                                       = factor(  fogColor - sceneColor) + sceneColor;   ( factor>=0 && factor<=1)
           (雾化公式)  finalColor   :混合后颜色
                              sceneColor:场景象素色
                               factor         :混合因子
      3.体积雾原理
         雾效关键在于如何求得每个场景可见象素点的混合因子!
         float  factor = fogDepth / ( fogEnd - fogStart);
        也就是视点与目标象素点的距离上雾所占的距离 fogDepth。根据Z Buffer,我们可以获取每帧每个象素到视点的距离。
         于是,我们同样可以通过渲染FogVolume的正面与反面的深度到两张贴图上。这样我们就可以根据当前场景深度信息以及前面的两张贴图,获得FogDepth,
     4.实现步骤
        1.首先渲染所有场景物体, 此处我们需要FrameBuffer, 与  Z Buffer信息
        2.渲染所有物模型的背面的深度到一张纹理上
        3.渲染所有雾模型的正面的尝试到一张纹理上
        4.利用场景的ZBuffer信息, 雾的两张深度纹理, 雾参数  处理 场景的FrameBuffer
    5.具体步骤
      1.获取场景的ZBuffer, 与 FrameBuffer
      因为dx9无法直接获取场景的ZBuffer信息,所以我们要采用别的方式,
              1.把所有的场景多渲染一次,把深度信息渲染到一张纹理上;
              2.使用MultiRenderTarget 渲染场景的同时把深度信息保存到一张纹理上
     下面我们只介绍MultiRenderTarget的方式。
     MultiRenderTarget 是 Ps 2.0 即支持的渲染方式。其实现方法比较简单,只需更改PS( pixel shader)的返回值
    例(这里使用使用两个RenderTarget):
       struct PS_OUTPUT
       {
            float4   Target0  : COLOR0;
            float4   Target1  : COLOR1;
        };
      硬件支持的RenderTarget数可以通过 D3DCaps.NumSimultaneousRTs 查看, 一般显卡:4
      代码部分:
      // 设置多RenderTarget
      g_pDevice->SetRenderTarget( 0, m_pMainRenderTarget);
      g_pDevice->SetRenderTarget( 1, m_pDepthTexture->GetSurface());
     
      //  渲染调用代码  
     
      g_pDevice->SetRenderTarget( 0, m_pMainRenderTarget);
      g_pDevice->SetRenderTarget( 1, NULL);
     
     注意:使用MultiRenderTarget 不能开启反锯齿
     
     // 拷贝FrameBuffer到一张动态纹理上
      IDirect3DSurface9* pSurface = NULL;
      g_pDevice->GetRenderTarget( 0, &pSurface);
     
      // copy back buffer into refraction map texture
      g_pDevice->StretchRect( pSurface, 0, m_pTextureSrc->GetSurface(), 0, D3DTEXF_NONE);
      SAFE_RELEASE( pSurface);
     
        2.渲染所有物模型的背面的深度到一张纹理上 
        3.渲染所有雾模型的正面的尝试到一张纹理上
       
     
      4最后利用所有的数据更改FrameBuffer
      Shader 代码:
     
    uniform float2  g_fogParam;   // x: fogStart  y: fogEnd
    uniform float3  g_fogColor;   // FogColor

    // vertexInput
    struct VS_INPUT
    {
     float3 Position : POSITION0;
     float2 Texcoord : TEXCOORD0;
    };
    // Vertex OutPut
    struct VS_OUTPUT
    {
     float4 Position : POSITION;
     float2 Texcoord : TEXCOORD1;
    };
    // Vertex Shader
    VS_OUTPUT VS(VS_INPUT In)
    {
     VS_OUTPUT Out;
     
     Out.Position = float4(In.Position, 1.0f);
     Out.Texcoord = In.Texcoord;
     return Out;
    }
    texture  texSrc;
    texture  texSceneDepth;
    texture  texFogFront;
    texture  texFogBack;
    // 纹理采样
    sampler2D RGBSampler = sampler_state
    {
        texture   = <texSrc>;
    };
    sampler2D DepthSampler = sampler_state
    {
     texture   = <texSceneDepth>;
    };
    sampler2D FogFrontSampler = sampler_state
    {
     texture   = <texFogFront>;
    };
    sampler2D FogBackSampler = sampler_state
    {
     texture   = <texFogBack>;
    };
    // Pixel Shader
    float4 PS(VS_OUTPUT In) : COLOR
    {
     float depth    = tex2D( DepthSampler,    In.Texcoord).r;
     float fogFront = tex2D( FogFrontSampler, In.Texcoord).r;
     float fogBack  = tex2D( FogBackSampler,  In.Texcoord).r;
     float dis = 0.f;

     if( depth > fogBack)
      dis = fogBack - fogFront;
     else if( depth > fogFront)
      dis = depth - fogFront;
     
     float factor = max(( dis - g_fogParam.x), 0.f) / ( g_fogParam.y - g_fogParam.x);

     
     float3 rgb   = tex2D(RGBSampler, In.Texcoord);
     float3 color = rgb + factor * ( g_fogColor - rgb);
     return float4( color, 1.f);
    }
    technique technique0
    {
     pass p0
     {    
      VertexShader = compile vs_3_0 VS();
      PixelShader  = compile ps_3_0 PS();
     }
    }
     
    另:为了减少判断量, 需把所有的图片 Clear为黑色
    Please help to write shaders for volumetric fog. I have an error. But I do not know where.

    float4x4 g_wvp;
    //depth.vsh  m_pFogShaderDepth
    void vs_depth( inout float4 pos   : POSITION  ,
                     
    out float  depth : TEXCOORD0 )
    {
        pos 
    = mul( pos, g_wvp );
        depth 
    = pos.z;
    }

    //depth.psh  m_pFogShaderDepth
    float4 ps_depth( in float depth : TEXCOORD0 ) : COLOR
    {
        
    return float4( depth, 0.f, 0.f, 0.f );
    }

        sampler2D s_fog_back;
        sampler2D s_fog_front;
        sampler2D s_scene_depth;

    //fog.ps  m_pPixShader
    float4 Main_ps( in float2 tex : TEXCOORD0 ) : COLOR
    {

        
    float fog_back    = tex2D( s_fog_back    , tex ).r;
        
    float fog_front   = tex2D( s_fog_front   , tex ).r;
        
    float scene_depth = tex2D( s_scene_depth , tex ).r;
        
        
    float k = fog_back - fog_front;
        k 
    -= fog_back - clamp( scene_depth, 0, fog_back );

        
    return float4(0.5f,0.5f,0.5f, k*0.5f );
    }

    Code C
    ++

    p_d3d_Device
    ->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);

        p_d3d_Device
    ->SetTexture(0,m_pEndFogTexture);
    //********************************
        D3DXMATRIX V;
        TheCamera.getViewMatrix(
    &V);

        D3DXMATRIX matRes;
        
    //matRes=mxWorld*mxView*mxProj;
        matRes=mxWorld*V*mxProj;

        VertShaderConstTable
    ->SetMatrix(p_d3d_Device, MatrixHandle, &matRes);
        
    //------------------------------
        p_d3d_Device->SetPixelShader( NULL );
        
    //reverse the culling order to get the back side
        
        
        p_d3d_Device
    ->SetRenderState( D3DRS_ZFUNC , D3DCMP_GREATER  );

        p_d3d_Device
    ->Clear(NULL, NULL, D3DCLEAR_TARGET| D3DCLEAR_ZBUFFER , D3DCOLOR_ARGB(0000), 0.00);

        p_d3d_Device
    ->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);

        p_d3d_Device
    ->SetTexture(0,m_pEndFogTexture);

        p_d3d_Device
    ->SetVertexShader( m_pFogShaderDepth );


        

        
    for( DWORD i=0; i<g_dwNumMaterials; i++ )
         {
         m_pMeshFloor
    ->DrawSubset( i );
         }

        p_d3d_Device
    ->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW);

        p_d3d_Device
    ->SetTexture(1,m_pStartFogTexture);
        

        p_d3d_Device
    ->SetVertexShader( m_pFogShaderDepth );


        
    for( DWORD i=0; i<g_dwNumMaterials; i++ )
         {
         m_pMeshFloor
    ->DrawSubset( i );
         }
        p_d3d_Device
    ->SetRenderState( D3DRS_CULLMODE,         D3DCULL_NONE );


        p_d3d_Device
    ->SetVertexShader( NULL);
        p_d3d_Device
    ->SetPixelShader( m_pPixShader );

        

        
    for( DWORD i=0; i<g_dwNumMaterials; i++ )
         {
         m_pMeshFloor
    ->DrawSubset( i );
         }

        
        

        
    //---------------------------------
        p_d3d_Device->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE); 
       
    //**********************************

        p_d3d_Device
    ->EndScene ();
        p_d3d_Device
    ->Present (NULL, NULL, NULL, NULL);

    as a result I have displayed a blue cube, textured very wrong, on a gray background. Read the article Russian programmer http://timai-ru.blogspot.com/ 

  • 相关阅读:
    dalvik浅析二:jni、so
    android apk壳
    prism4 StockTrader RI 项目分析一些体会
    PRISM ‘VS100COMNTOOLS’ not set. Cannot set the build environment
    安卓移动应用代码安全加固系统设计及实现
    手机游戏外挂技术研究与运用
    移动终端安全威胁与应对措施
    游戏软件反外挂技术方案的设计和安全解决方案
    网络安全等级保护 2.0 下的安全体系建设
    APP加密,ios代码混淆工具,虚拟化技术 适用于移动应用程序的虚拟化加密软件
  • 原文地址:https://www.cnblogs.com/lancidie/p/1962538.html
Copyright © 2011-2022 走看看