CGBeginner 发表于 2012-12-30 11:52:00

Introduction to my galaxy engine 2: Depth of field

Introduction to my galaxy engine 2: Depth of field

<div id="cnblogs_post_body">参考shaderx2 中DOF via Simulation of Circle of Confusion 算法,引擎中增加了depth of field 功能模块。基本原理就是根据物体与聚焦平面的距离还设定模糊kernel的大小,对原理聚焦平面的物体做模糊处理。
视频地址:http://my.ku6.com/watch?v=c-wjiz_TdM2S7MkC_MNwpw..#

1.首先将场景中物体的颜色渲染到一个render target上,颜色计算公式可以自己定,以下是我用的方法:
output.Color = saturate( dot(input.Norm, normalize(SunLightDir)) * vLightColor + diffuse + vAmbiantColor );
2.再将场景深度,模糊值blur分别存到另一个render target的R值和G值
深度模糊值计算方法如下:
float blur = saturate(abs(input.Depth - focalDist) / focalRange);
input.Depth为物体深度,focalDist为聚焦平面的值,focalRange为聚焦范围,blue这样计算的话就在0-1范围内。
output.Depth = float4(depth, blur, 0, 1);

下面的话就是按照以上两个信息做模糊处理
首先建立一个屏幕大小的平面,有四个顶点,作为画布传入vertex shader
从第一个贴图中去除颜色值
float4 colorSum = g_SceneTexture.Sample( g_samClamp, input.Tex );
然后从另一张贴图去除深度值和模糊值
float2 centerDepthBlur = g_DepthTexture.Sample( g_samClamp,input.Tex );
依据模糊值确定kernel大小
float sizeCoC = centerDepthBlur.y * g_MaxCoC;
下面是关键:
for (int i = 0; i < 12; i++)//kernel中原先有的12个采样点
{
// Compute tap coordinates
float2 tapCoord = input.Tex + g_FilterTaps * sizeCoC;计算采样点的纹理坐标

// Fetch tap sample
float4 tapColor = g_SceneTexture.Sample(g_samClamp, tapCoord); 采样点所在位置的颜色值
float2 tapDepthBlur = g_DepthTexture.Sample(g_samClamp, tapCoord);采样点所在位置的深度和模糊因素
// Compute tap contribution
//for obj in front, use tapDepthBlur.y, and if obj is in focus, tapDepthBlur.y is 0, so no leak of front obj color; for back obj, use 1.0f
float tapContribution = (tapDepthBlur.x > centerDepthBlur.x) ? 1.0f : tapDepthBlur.y;防止聚焦平面后面的物体采样到聚焦平面的物体的颜色值
// Accumulate color and contribution
colorSum += tapColor * tapContribution;
totalContribution += tapContribution;
}
// Normalize to get proper luminance
finalColor = colorSum / totalContribution;
以下是截图,分别是没有DOF效果图,深度图,模糊因素图和有DOF的效果图
http://pic002.cnblogs.com/images/2012/411346/2012052310575782.png
http://pic002.cnblogs.com/images/2012/411346/2012052804414737.jpg
http://pic002.cnblogs.com/images/2012/411346/2012052804420293.jpg
http://pic002.cnblogs.com/images/2012/411346/2012052311001364.png
以下是所有shader代码
<div class="cnblogs_code">1 SamplerState g_samWrap2 {3   Filter = MIN_MAG_MIP_LINEAR;4   AddressU = Wrap;5   AddressV = Wrap;6 };7 8 SamplerState g_samClamp9 { 10   Filter = MIN_MAG_MIP_LINEAR; 11   AddressU = Clamp; 12   AddressV = Clamp; 13 }; 14 15 BlendState NoBlending 16 { 17   AlphaToCoverageEnable = FALSE; 18   BlendEnable[0] = FALSE; 19 }; 20 21 BlendState AlphaBlendingOn 22 { 23   BlendEnable[0] = TRUE; 24   SrcBlend = SRC_ALPHA; 25   DestBlend = INV_SRC_ALPHA; 26 }; 27 28 matrix World; 29 matrix View; 30 matrix Projection; 31 matrix LightView; 32 float3SunLightDir; 33 34 float4 vLightColor = float4(0.3f, 0.3f, 0.3f, 1.0f); 35 float4 vAmbiantColor = float4(0.1f, 0.1f, 0.1f, 1.0f); 36 37 float focalDist = 1.0; 38 float focalRange = 1.0; 39 40 Texture2D g_SceneTexture; 41 Texture2D g_DepthTexture; 42 Texture2D g_ModelTexture; 43 44 float2 g_FilterTaps[12]; 45 46 float g_MaxCoC = 3; 47 48 struct VS_MODEL_INPUT 49 { 50     float4 Pos            : POSITION;          51     float2 Tex            : TEXCOORD0;    52     float3 Norm      : NORMAL;       53 }; 54 55 struct PS_MODEL_INPUT 56 { 57     float4 Pos            :SV_POSITION;    58     float2 Tex            : TEXCOORD0;    59     float3 Norm      : TEXCOORD1;    60   float   Depth      : TEXCOORD2;    61 }; 62 63 struct PS_MODEL_OUTPUT 64 { 65     float4 Color    : SV_Target1; 66     float4 Depth    : SV_Target0; 67 }; 68 69 struct VS_DOF_INPUT 70 { 71     float4 Pos            : POSITION;          72     float2 Tex            : TEXCOORD0;       73 }; 74 75 struct PS_DOF_INPUT 76 { 77     float4 Pos            :SV_POSITION;    78     float2 Tex            : TEXCOORD0;    79 }; 80 81 PS_MODEL_INPUT VS_SCENE(VS_MODEL_INPUT input) 82 { 83   PS_MODEL_INPUT output = (PS_MODEL_INPUT)0; 84   output.Pos = input.Pos; 85   output.Pos.w = 1; 86 87   output.Pos = mul( output.Pos, World ); 88   output.Pos = mul( output.Pos, View ); 89   output.Pos = mul( output.Pos, Projection ); 90   output.Depth = output.Pos.z; 91   output.Pos = output.Pos / output.Pos.w; 92 93   output.Norm = mul( input.Norm, World ); 94   output.Norm = normalize( output.Norm ); 95 96   output.Tex = input.Tex; 97 98   return output; 99 }100 101 PS_MODEL_OUTPUT PS_SCENE( PS_MODEL_INPUT input ) : SV_Target102 {103   PS_MODEL_OUTPUT output = (PS_MODEL_OUTPUT)0;104 105   float4 diffuse = g_ModelTexture.Sample( g_samClamp, input.Tex );106   output.Color = saturate( dot(input.Norm, normalize(SunLightDir)) * vLightColor + diffuse + vAmbiantColor );107 108   float blur = saturate(abs(input.Depth - focalDist) / focalRange);109   float depth = input.Pos.z;110   output.Depth = float4(depth, blur, 0, 1);111 112   return output;113 }114 115 PS_DOF_INPUT VS_DOF(VS_DOF_INPUT input)116 {117   PS_DOF_INPUT output = (PS_DOF_INPUT)0;118   output.Pos = input.Pos;119 120   output.Tex = float2( input.Tex.x,1 - input.Tex.y );121 122   return output;123 }124 125 float4 PS_DOF(PS_DOF_INPUT input) : SV_Target126 {127   float4 finalColor = 0;128 129      float4 colorSum = g_SceneTexture.Sample( g_samClamp, input.Tex );130 131   float2 centerDepthBlur = g_DepthTexture.Sample( g_samClamp,input.Tex );132 133   //return centerDepthBlur.y;134 135   float sizeCoC = centerDepthBlur.y * g_MaxCoC;//blur * maxCoC136 137   //return sizeCoC;138   float totalContribution = 1.0f;139 140   for (int i = 0; i < 12; i++)141     {142         // Compute tap coordinates143         float2 tapCoord = input.Tex + g_FilterTaps * sizeCoC;144         145         // Fetch tap sample146         float4 tapColor = g_SceneTexture.Sample(g_samClamp, tapCoord); 147         float2 tapDepthBlur = g_DepthTexture.Sample(g_samClamp, tapCoord);148 149         // Compute tap contribution150         //for obj in front, use tapDepthBlur.y, and if obj is in focus, tapDepthBlur.y is 0, so no leak of front obj color; for back obj, use 1.0f151         float tapContribution = (tapDepthBlur.x > centerDepthBlur.x) ? 1.0f : tapDepthBlur.y;152 153         // Accumulate color and contribution154         colorSum += tapColor * tapContribution;155         totalContribution += tapContribution;156     }157 158   // Normalize to get proper luminance159   finalColor = colorSum / totalContribution;160 161   return finalColor;162 }163 164 technique10 DoF165 {166     pass p0167     {168       SetVertexShader( CompileShader( vs_4_0, VS_SCENE() ) );169       SetGeometryShader( NULL );170       SetPixelShader( CompileShader( ps_4_0, PS_SCENE() ) );171 172         SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );173     }174 175    pass p1176     {177       SetVertexShader( CompileShader( vs_4_0, VS_DOF() ) );178       SetGeometryShader( NULL );179       SetPixelShader( CompileShader( ps_4_0, PS_DOF() ) );180 181         SetBlendState( NoBlending, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );182     }183 }
页: [1]
查看完整版本: Introduction to my galaxy engine 2: Depth of field