Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #define ScreenSize float4(BUFFER_WIDTH, BUFFER_RCP_WIDTH, float(BUFFER_WIDTH) / float(BUFFER_HEIGHT), float(BUFFER_HEIGHT) / float(BUFFER_WIDTH)) //x=Width, y=1/Width, z=ScreenScaleY, w=1/ScreenScaleY
- //textures
- texture2D texColor : COLOR;
- texture2D texDepth : DEPTH;
- texture texNoise < string source = "mcnoise.png"; >
- {
- Width = 1920;
- Height = 1080;
- MipLevels = 1;
- Format = RGBA8;
- };
- sampler2D SamplerColor
- {
- Texture = texColor;
- MinFilter = LINEAR;
- MagFilter = LINEAR;
- MipFilter = LINEAR;
- AddressU = Clamp;
- AddressV = Clamp;
- SRGBTexture=FALSE;
- MaxMipLevel=1;
- MipMapLodBias=0;
- };
- sampler2D SamplerDepth
- {
- Texture = texDepth;
- MinFilter = POINT;
- MagFilter = POINT;
- MipFilter = NONE;
- AddressU = Clamp;
- AddressV = Clamp;
- SRGBTexture=FALSE;
- MaxMipLevel=1;
- MipMapLodBias=0;
- };
- sampler2D SamplerNoise
- {
- Texture = texNoise;
- MinFilter = POINT;
- MagFilter = POINT;
- MipFilter = NONE;
- AddressU = Clamp;
- AddressV = Clamp;
- SRGBTexture=FALSE;
- MaxMipLevel=0;
- MipMapLodBias=0;
- };
- struct VS_OUTPUT_POST
- {
- float4 vpos : SV_Position;
- float2 txcoord : TEXCOORD0;
- };
- struct VS_INPUT_POST
- {
- uint id : SV_VertexID;
- };;
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- //
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- VS_OUTPUT_POST VS_PostProcess(VS_INPUT_POST IN)
- {
- VS_OUTPUT_POST OUT;
- OUT.txcoord.x = (IN.id == 2) ? 2.0 : 0.0;
- OUT.txcoord.y = (IN.id == 1) ? 2.0 : 0.0;
- OUT.vpos = float4(OUT.txcoord * float2(2.0, -2.0) + float2(-1.0, 1.0), 0.0, 1.0);
- return OUT;
- }
- static float nearZ = 0.1;
- static float farZ = 100.0;
- #define FAR_PLANE_Z (460.0)
- static float g_Strength = 1.0f; // 0.0..3.0
- static float g_IntensityMul = 1.0f; // 1.0..3.0
- static float g_NumSteps = 3; // 0..32
- static float g_NumDir = 5; // 0..25
- static float m_RadiusMultiplier = 0.5; // 0.0..2.0
- static float m_AngleBias = 0.0; // 0.0..60.0
- #define SAMPLE_FIRST_STEP 1
- #define M_PI 3.14159265f
- #define g_R (m_RadiusMultiplier * 1.0f )
- #define g_Radius2 (g_R * g_R)
- #define g_NegInvRadius2 (-1.0f / g_Radius2 )
- #define g_AngleBias ( m_AngleBias * M_PI / 180)
- #define g_TanAngleBias (tan(g_AngleBias))
- #define g_MaxRadiusPixels (0.1f * min(BUFFER_WIDTH, BUFFER_HEIGHT))
- #define fovY 70
- #define g_FocalLen float2(1.0f / tan(fovY * 0.5 * 0.01745) * BUFFER_WIDTH / BUFFER_HEIGHT, 1.0f / tan(fovY * 0.5 * 0.01745)) //needs PI/180 otherwise image is plain white
- #define SCREEN_SIZE float2(BUFFER_WIDTH, BUFFER_HEIGHT)
- #define PIXEL_SIZE float2(BUFFER_RCP_WIDTH, BUFFER_RCP_HEIGHT)
- /** Negative, "linear" values in world-space units */
- float LinearizeDepth(float depth)
- {
- //return (2.0f * nearZ) / (nearZ + farZ - depth * (farZ - nearZ));
- return 1 / ((depth * ((farZ - nearZ) / (-farZ * nearZ)) + farZ / (farZ * nearZ)));
- }
- //----------------------------------------------------------------------------------
- float3 fetchEyePos(in float2 v)
- {
- float z = tex2Dlod(SamplerDepth, float4(v, 0, 0)).x;
- v = v * 2 - 1;
- float3 result = float3(v * 1.0, 1) * z;
- return result;
- }
- //----------------------------------------------------------------------------------
- float length2(float3 v)
- {
- return dot(v, v);
- }
- //----------------------------------------------------------------------------------
- float invLength(float2 v)
- {
- return rsqrt(dot(v,v));
- }
- //----------------------------------------------------------------------------------
- float3 minDiff(float3 P, float3 Pr, float3 Pl)
- {
- float3 V1 = Pr - P;
- float3 V2 = P - Pl;
- return (length2(V1) < length2(V2)) ? V1 : V2;
- }
- //----------------------------------------------------------------------------------
- float2 rotateDirections(float2 Dir, float2 CosSin)
- {
- return float2(Dir.x*CosSin.x - Dir.y*CosSin.y, Dir.x*CosSin.y + Dir.y*CosSin.x);
- }
- //----------------------------------------------------------------------------------
- float falloff(float d2)
- {
- return d2 * g_NegInvRadius2 + 1.0f;
- }
- //----------------------------------------------------------------------------------
- float2 snapUVOffset(float2 uv)
- {
- return round(uv * SCREEN_SIZE) * PIXEL_SIZE;
- }
- //----------------------------------------------------------------------------------
- float tangent(float3 T)
- {
- return -T.z * invLength(T.xy);
- }
- //----------------------------------------------------------------------------------
- float tangent(float3 P, float3 S)
- {
- return (P.z - S.z) * invLength(S.xy - P.xy);
- }
- //----------------------------------------------------------------------------------
- float biasedtangent(float3 T)
- {
- return tangent(T) + g_TanAngleBias;
- }
- //----------------------------------------------------------------------------------
- float3 tangentVector(float2 deltaUV, float3 dPdu, float3 dPdv)
- {
- return deltaUV.x * dPdu + deltaUV.y * dPdv;
- }
- //----------------------------------------------------------------------------------
- float tanToSin(float x)
- {
- return x * rsqrt(x*x + 1.0f);
- }
- //----------------------------------------------------------------------------------
- void computeSteps(inout float2 step_size_uv, inout float numSteps, float ray_radius_pix, float rand)
- {
- // Avoid oversampling if g_NumSteps is greater than the kernel radius in pixels
- numSteps = min(g_NumSteps, ray_radius_pix);
- // Divide by Ns+1 so that the farthest samples are not fully attenuated
- float step_size_pix = ray_radius_pix / (numSteps + 1);
- // Clamp numSteps if it is greater than the max kernel footprint
- float maxNumSteps = g_MaxRadiusPixels / step_size_pix;
- [branch]
- if (maxNumSteps < numSteps)
- {
- // Use dithering to avoid AO discontinuities
- numSteps = floor(maxNumSteps + rand);
- numSteps = max(numSteps, 1);
- step_size_pix = g_MaxRadiusPixels / numSteps;
- }
- // Step size in uv space
- step_size_uv = step_size_pix * PIXEL_SIZE;
- }
- //----------------------------------------------------------------------------------
- float integerateOcclusion(float2 uv0, float2 snapped_duv, float3 P, float3 dPdu, float3 dPdv, inout float tanH)
- {
- float ao = 0;
- // Compute a tangent vector for snapped_duv
- float3 T1 = tangentVector(snapped_duv, dPdu, dPdv);
- float tanT = biasedtangent(T1);
- float sinT = tanToSin(tanT);
- float3 S = fetchEyePos(uv0 + snapped_duv);
- float tanS = tangent(P, S);
- float sinS = tanToSin(tanS);
- float d2 = length2(S - P);
- [branch]
- if ((d2 < g_Radius2) && (tanS > tanT))
- {
- // Compute AO between the tangent plane and the sample
- ao = falloff(d2) * (sinS - sinT);
- // Update the horizon angle
- tanH = max(tanH, tanS);
- }
- return ao;
- }
- //----------------------------------------------------------------------------------
- float horizon_occlusion(float2 deltaUV, float2 texelDeltaUV, float2 uv0, float3 P, float numSteps, float randstep, float3 dPdu, float3 dPdv )
- {
- float ao = 0;
- // Randomize starting point within the first sample distance
- float2 uv = uv0 + snapUVOffset( randstep * deltaUV );
- // Snap increments to pixels to avoid disparities between xy
- // and z sample locations and sample along a line
- deltaUV = snapUVOffset( deltaUV );
- // Compute tangent vector using the tangent plane
- float3 T = deltaUV.x * dPdu + deltaUV.y * dPdv;
- float tanH = biasedtangent(T);
- #if SAMPLE_FIRST_STEP
- // Take a first sample between uv0 and uv0 + deltaUV
- float2 snapped_duv = snapUVOffset( randstep * deltaUV + texelDeltaUV );
- ao = integerateOcclusion(uv0, snapped_duv, P, dPdu, dPdv, tanH);
- --numSteps;
- #endif
- float sinH = tanH / sqrt(1.0f + tanH*tanH);
- [loop]
- for (float j = 1; j <= numSteps; ++j)
- {
- uv += deltaUV;
- float3 S = fetchEyePos(uv);
- float tanS = tangent(P, S);
- float d2 = length2(S - P);
- // Use a merged dynamic branch
- [branch]
- if ((d2 < g_Radius2) && (tanS > tanH))
- {
- // Accumulate AO between the horizon and the sample
- float sinS = tanS / sqrt(1.0f + tanS*tanS);
- ao += falloff(d2) * (sinS - sinH);
- // Update the current horizon angle
- tanH = tanS;
- sinH = sinS;
- }
- }
- return ao;
- }
- /** Used for packing Z into the GB channels */
- float CSZToKey(float z)
- {
- return clamp(z * (1.0 / FAR_PLANE_Z), 0.0, 1.0);
- }
- /** Used for packing Z into the GB channels */
- void packKey(float key, out float2 p)
- {
- // Round to the nearest 1/256.0
- float temp = floor(key * 256.0);
- // Integer part
- p.x = temp * (1.0 / 256.0);
- // Fractional part
- p.y = key * 256.0 - temp;
- }
- float unpackKey(float2 p)
- {
- return p.x * (256.0 / 257.0) + p.y * (1.0 / 257.0);
- }
- float4 PS_HBAOCalculate(VS_OUTPUT_POST IN) : COLOR
- {
- float4 output = float4(1,1,1,1);
- float3 P = fetchEyePos(IN.txcoord.xy);
- float3 rand = tex2Dlod(SamplerNoise, float4(IN.txcoord.xy * 64.0, 0, 0)).rgb*2-1;
- float2 ray_radius_uv = 0.5 * g_R * g_FocalLen / P.z;
- float ray_radius_pix = ray_radius_uv.x * SCREEN_SIZE.x;
- if (ray_radius_pix < 10)
- {
- return 1.0;
- }
- float numSteps;
- float2 step_size;
- computeSteps(step_size, numSteps, ray_radius_pix, rand.z);
- packKey(CSZToKey(P.z), output.gb);
- float3 Pr, Pl, Pt, Pb;
- Pr = fetchEyePos(IN.txcoord.xy + float2(PIXEL_SIZE.x, 0));
- Pl = fetchEyePos(IN.txcoord.xy + float2(-PIXEL_SIZE.x, 0));
- Pt = fetchEyePos(IN.txcoord.xy + float2(0, PIXEL_SIZE.y));
- Pb = fetchEyePos(IN.txcoord.xy + float2(0, -PIXEL_SIZE.y));
- float3 dPdu = minDiff(P, Pr, Pl) * (SCREEN_SIZE.x * PIXEL_SIZE.y);
- float3 dPdv = minDiff(P, Pt, Pb) * (SCREEN_SIZE.y * PIXEL_SIZE.x);
- float ao = 0;
- float d;
- float alpha = 2.0f * M_PI / g_NumDir;
- [loop]
- for (d = 0; d < g_NumDir; ++d)
- {
- float angle = alpha * d;
- float2 dir = rotateDirections(float2(cos(angle), sin(angle)), rand.xy);
- float2 deltaUV = dir * step_size.xy;
- float2 texelDeltaUV = dir * PIXEL_SIZE;
- ao += horizon_occlusion(deltaUV, texelDeltaUV, IN.txcoord.xy, P, numSteps, rand.z, dPdu, dPdv);
- }
- output.r = 1.0 - ao / g_NumDir * g_Strength * g_IntensityMul;
- return float4(output.r, output.r, output.r, 1.0);
- //return tex2D(SamplerColor, IN.txcoord.xy)*1.5;
- }
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- //
- //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- technique MasterEffect < bool enabled = 1; toggle = 0x20; >
- {
- pass s1
- {
- VertexShader = VS_PostProcess;
- PixelShader = PS_HBAOCalculate;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement