zoukankan      html  css  js  c++  java
  • Introduction to my galaxy engine 7: Volumetric Light Scattering

    花了一天时间,给引擎中添加了Volumetric Light Scattering模块.

    视频地址:https://vimeo.com/43232452

    截屏图如下:

    Volumetric Light Scattering又名god light,Crepuscular Rays 等等, 也是一个游戏中比较常见的效果,主要是用post process来实现的。

    具体实现步骤如下:

    1.渲染发光体和场景,场景不添加材质,只显示成黑色,将结果渲染到render target 1上。

    2. 只渲染场景,添加材质和光照,将结果渲染到render target 2上。

    3. 对render target 1 做采样处理,计算光照。原理见如下图:

    在屏幕上每一点到光源中心点做射线,对射线上点做采样。如果采样点被物体遮住,自然光照亮会减少。具体计算公式见GPU GERM 3相关那一张。最近处理结果如下图所示:

    4. 最后一步,将render target 2的贴图附在上图上,就是最后的结果了。

    完整代码如下:

      1 SamplerState g_samWrap
      2 {
      3     Filter = MIN_MAG_MIP_LINEAR;
      4     AddressU = Wrap;
      5     AddressV = Wrap;
      6 };
      7 
      8 SamplerState g_samClamp
      9 {
     10     Filter = MIN_MAG_MIP_LINEAR;
     11     AddressU = Clamp;
     12     AddressV = Clamp;
     13 };
     14 
     15 DepthStencilState DisableDepth
     16 {
     17     DepthEnable = FALSE;
     18     DepthWriteMask = ZERO;
     19 };
     20 
     21 DepthStencilState EnableDepth
     22 {
     23     DepthEnable = TRUE;
     24     DepthWriteMask = ALL;
     25     DepthFunc = Less_Equal;//set to less equal since texture background is ini as 1.0
     26 };
     27 
     28 BlendState NoBlending
     29 {
     30     AlphaToCoverageEnable = FALSE;
     31     BlendEnable[0] = FALSE;
     32 };
     33 
     34 BlendState AdditiveBlending
     35 {
     36     AlphaToCoverageEnable = FALSE;
     37     BlendEnable[0] = TRUE;
     38     SrcBlend = ONE;
     39     DestBlend = ONE;
     40     BlendOp = ADD;
     41     SrcBlendAlpha = SRC_ALPHA;
     42     DestBlendAlpha = INV_SRC_ALPHA;
     43     RenderTargetWriteMask[0] = 0x0F;
     44 };
     45 
     46 Texture2D  g_ModelTexture;
     47 
     48 Texture2D  g_BlackSceneTexture;
     49 Texture2D  g_NormalSceneTexture;
     50 
     51 matrix g_World;
     52 matrix g_View;
     53 matrix g_Projection;
     54 
     55 //float4 g_AmbientColor = float4(0.1f, 0.1f, 0.1f, 1.0f);
     56 float4 g_DirLightColor = float4(0.3f, 0.3f, 0.3f, 1.0f);
     57 float3 g_DirLightDir = float3(0.0f, 1.0f, -1.0f);
     58 
     59 float4 g_LightPos = float4(0.0f, 1.0f, 0.0f, 1.0f);
     60 uint NUM_SAMPLES = 200;
     61 float g_Density = 1.0f;
     62 float g_Weight = 1.0f;
     63 float g_Decay = 0.98f;
     64 float g_Exposure = 0.05f;
     65 
     66 bool g_bLight;
     67 
     68 struct VS_MODEL_INPUT
     69 {
     70     float4 Pos            : POSITION;         
     71     float2 Tex            : TEXCOORD0;     
     72     float3 Norm        : NORMAL;       
     73 };
     74 
     75 struct PS_MODEL_INPUT
     76 {
     77     float4 Pos            : SV_POSITION;   
     78     float2 Tex            : TEXCOORD0;     
     79     float3 Norm        : NORMAL;    
     80 };
     81 
     82 struct PS_MODEL_OUTPUT
     83 {
     84     float4 blackScene        : SV_Target0;
     85     float4 normalScene        : SV_Target1;
     86 };
     87 //----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
     88 struct VS_QUAD_INPUT
     89 {
     90     float4 Pos            : POSITION;           
     91     float2 Tex            : TEXCOORD0;       
     92 };
     93 
     94 struct PS_SCENE_INPUT
     95 {
     96     float4 Pos                        : SV_POSITION;   
     97     float2 Tex                        : TEXCOORD0;     
     98     float2 ScreenLightPos        : TEXCOORD1;  
     99 };
    100 //---------------------------------------------------------------------------------------render black scene--------------------------------------------------------------------------------------------------------
    101 PS_MODEL_INPUT VS_SCENE(VS_MODEL_INPUT input)
    102 {
    103     PS_MODEL_INPUT output = (PS_MODEL_INPUT)0;
    104     output.Pos = input.Pos;
    105     output.Pos.w = 1;
    106 
    107     output.Pos = mul( output.Pos, g_World );
    108     output.Pos = mul( output.Pos, g_View );
    109     output.Pos = mul( output.Pos, g_Projection );
    110     output.Pos = output.Pos / output.Pos.w;
    111 
    112     output.Norm = input.Norm;
    113     output.Tex = input.Tex;
    114     return output;
    115 }
    116 
    117 PS_MODEL_OUTPUT PS_BLACK_SCENE(PS_MODEL_INPUT input)
    118 {
    119     PS_MODEL_OUTPUT output = (PS_MODEL_OUTPUT)0;
    120 
    121     if(g_bLight)
    122     {
    123         output.blackScene = float4(1.0f, 1.0f, 1.0f, 1.0f);
    124         output.normalScene = float4(0.0f, 0.0f, 0.0f, 0.0f);
    125     }
    126     else
    127     {
    128         output.blackScene = float4(0.0f, 0.0f, 0.0f, 1.0f);
    129         output.normalScene = dot(normalize(g_DirLightDir), input.Norm) * g_DirLightColor * g_ModelTexture.Sample( g_samWrap, input.Tex );
    130         output.normalScene.a = 1;
    131     }
    132 
    133     return output;
    134 }
    135 
    136 PS_SCENE_INPUT VS_VLS(VS_QUAD_INPUT input)
    137 {
    138     PS_SCENE_INPUT output = (PS_SCENE_INPUT)0;
    139 
    140     float2 Pos = input.Pos.xy;
    141     output.Pos = float4(Pos.xy, 0, 1);
    142     
    143     output.Tex =  0.5 * (1 + Pos);
    144 
    145     float4 ScreenLightPos = g_LightPos;
    146     ScreenLightPos = mul( ScreenLightPos, g_World );
    147     ScreenLightPos = mul( ScreenLightPos, g_View );
    148     ScreenLightPos = mul( ScreenLightPos, g_Projection );
    149     ScreenLightPos = ScreenLightPos / ScreenLightPos.w;
    150     ScreenLightPos = (ScreenLightPos + 1.0f) / 2.0f;
    151     output.ScreenLightPos = ScreenLightPos;
    152 
    153     return output;
    154 }
    155 
    156 float4 PS_VLS(PS_SCENE_INPUT input) : SV_Target
    157 {
    158     float2 texCoord = input.Tex;
    159 
    160     float2 deltaTexCoord = (texCoord - input.ScreenLightPos); 
    161     deltaTexCoord *= 1.0f / NUM_SAMPLES * g_Density;
    162 
    163     float4 color = g_BlackSceneTexture.Sample(g_samClamp, float2(texCoord.x, 1 - texCoord.y));
    164 
    165     float illuminationDecay = 1.0f;
    166 
    167     for (uint i = 0; i < NUM_SAMPLES; i++)
    168     {
    169         texCoord -= deltaTexCoord;
    170         float4 sampleColor = g_BlackSceneTexture.Sample(g_samClamp, float2(texCoord.x, 1 - texCoord.y));//shift y after operation
    171         sampleColor *= illuminationDecay * g_Weight;
    172         color += sampleColor;
    173         illuminationDecay *= g_Decay;
    174     }
    175 
    176     color *= g_Exposure;
    177     color.a = 1;
    178     return color;
    179 }
    180 
    181 float4 PS_Blend(PS_SCENE_INPUT input) : SV_Target
    182 {
    183     float2 texCoord = input.Tex;
    184     return g_NormalSceneTexture.Sample(g_samClamp, float2(texCoord.x, 1 - texCoord.y));
    185 }
    186 
    187 technique10 RenderBlackScene
    188 {
    189     pass p0
    190     {
    191         SetVertexShader( CompileShader( vs_4_0, VS_SCENE() ) );
    192         SetGeometryShader( NULL );
    193         SetPixelShader( CompileShader( ps_4_0, PS_BLACK_SCENE() ) );
    194 
    195         SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    196     }  
    197 }
    198 //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    199 technique10 VLS
    200 {
    201     pass p0
    202     {
    203         SetVertexShader( CompileShader( vs_4_0, VS_VLS() ) );
    204         SetGeometryShader( NULL );
    205         SetPixelShader( CompileShader( ps_4_0, PS_VLS() ) );
    206 
    207         SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    208     }  
    209 }
    210 
    211 technique10 BlendScene
    212 {
    213     pass p0
    214     {
    215         SetVertexShader( CompileShader( vs_4_0, VS_VLS() ) );
    216         SetGeometryShader( NULL );
    217         SetPixelShader( CompileShader( ps_4_0, PS_Blend() ) );
    218 
    219         SetBlendState( AdditiveBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
    220         SetDepthStencilState( EnableDepth, 0 );//set depth test to less_equal
    221     }  
    222 }

    References:

    [1] http://www.unrealcreations.com/groups/kb/wiki/7d174/Volumetric_Light_Scattering_Implementation.html

    [2] http://developer.nvidia.com/node/170

    [3] http://fabiensanglard.net/lightScattering/index.php

  • 相关阅读:
    3.2 机器学习基本算法
    《TensorFlow深度学习应用实践》
    基于element动态调整table高度
    关于小程序表单验证解决方案
    LHS与RHS
    小程序---获取地理位置及获取用户userinfo信息
    element----修改element中table里面的右侧滚动条样式
    关于微信里wx.getUserInfo获取用户信息都是拼音的转成中文方法
    element中upload单图片转base64后添加进数组,请求接口
    vue的生命周期
  • 原文地址:https://www.cnblogs.com/RobinG/p/2530527.html
Copyright © 2011-2022 走看看