Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- buffer CameraUniforms : register(b0) { float4x4 u_view; float4x4 u_proj; float4x4 u_viewProj; float4x4 u_prevView; float4x4 u_prevViewProj; float4x4 u_prevViewProjInvView; float4 u_projInfo; float4 u_uvProjInfo; float4x4 u_viewToWorld; float4x4 u_worldmapToView; float3 u_clipInfo; float u_time; float3 u_viewUp; float u_gameTime; float2 u_screenSize; float2 u_invScreenSize; float3 u_cameraPosition; int u_frameNum; float3 u_gameCameraPosition; float u_prevGameTime; }
- Texture2D u_color : register(t0); Texture2D u_normal : register(t1); Texture2D u_depth : register(t2); Texture2D u_motionVectors : register(t3);
- Texture2D u_texture0 : register(t4);
- SamplerState pointClamp : register(s0);
- // {
- // Filter = MIN_MAG_MIP_POINT;
- //
- // AddressU = CLAMP;
- // AddressV = CLAMP;
- // };
- SamplerState samLinear : register(s1);
- // {
- // Filter = MIN_MAG_LINEAR_MIP_POINT;
- //
- // AddressU = BORDER;
- // AddressV = BORDER;
- // BorderColor = (0.65, 0.65, 0.65, 0.65);
- // MaxLOD = 0;
- // };
- /** The height in pixels of a 1m object if viewed from 1m away.
- You can compute it from your projection matrix. The actual value is just
- a scale factor on radius; you can simply hardcode this to a constant (~500)
- and make your radius value unitless (...but resolution dependent.) */
- //float u_projScale;
- ////////////////////////////////////////////////////////
- // Total number of direct samples to take at each pixel
- #define NUM_SAMPLES (16)
- #define radius 2.6
- static const float intensity = 1.85 / NUM_SAMPLES;
- // This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent
- // taps from lining up. This particular choice was tuned for NUM_SAMPLES == 10
- #define NUM_SPIRAL_TURNS (7)
- /** Bias to avoid AO in smooth corners, e.g., 0.01m */
- #define BIAS 0.01
- // If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower
- // miplevel to maintain reasonable spatial locality in the cache
- // If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing.
- // If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively
- #define invMaxOffset 0.34
- //////////////////////////////////////////////////
- /** vec4 u_projInfo (-2.0f / (width*P[0][0]),
- 2.0f / (height*P[1][1]),
- ( 1.0f - P[0][2]) / P[0][0],
- ( -1.0f - P[1][2]) / P[1][1])
- where P is the projection matrix that maps camera space points
- to [-1, 1] x [-1, 1]. That is, GCamera::getProjectUnit(). */
- /** Reconstruct camera-space P.xyz from screen-space S = (x, y) in
- pixels and camera-space z < 0. Assumes that the upper-left pixel center
- is at (0.5, 0.5) [but that need not be the location at which the sample tap
- was placed!]
- */
- float3 reconstructCSPositionUV(float2 S, float z) {
- return float3((S.xy * u_uvProjInfo.xy + u_uvProjInfo.zw) * z, z);
- }
- float getAO(float2 uv, float3 viewPos, float3 normal, float mipLevel, float epsilon)
- {
- float3 Q = reconstructCSPositionUV(uv, u_depth.SampleLevel(pointClamp, uv, mipLevel).r);
- float3 v = Q - viewPos;
- float vv = dot(v, v) + epsilon;
- float vn = max(dot(v, normal) - BIAS, 0.0);
- return vn / vv;
- }
- float sampleAO(in float2 uv, in float3 viewPos, in float3 normal, in float ssDiskRadius, in float tapIndex, in float randomAngle, in float logOffset, float epsilon)
- {
- // Offset on the unit disk, spun for this pixel
- float ssR = (tapIndex+0.5) / NUM_SAMPLES * ssDiskRadius;
- // Derivation:
- // mipLevel = floor(log(ssR / MAX_OFFSET));
- float mipLevel = log2(ssR * logOffset);
- float angle = tapIndex * (NUM_SPIRAL_TURNS * 6.28 / NUM_SAMPLES) + randomAngle;
- float2 offset = float2(cos(angle), sin(angle)) * ssR;
- return getAO(uv + offset, viewPos, normal, mipLevel, epsilon);
- }
- struct PS_INPUT
- {
- float4 position : SV_Position;
- float2 uv : TEXCOORD0;
- };
- float4 main (PS_INPUT input) : SV_Target
- {
- int3 ssC = int3(input.position.xy, 0);
- float z = u_depth.Load(ssC).r;
- float2 motionVectors = u_motionVectors.Load(ssC).rg;
- float2 prevUv = input.uv + motionVectors;
- float3 viewPos = reconstructCSPositionUV( input.uv, z);
- // Choose the screen-space sample radius
- // proportional to the projected area of the sphere
- float ssDiskRadius = 0.5 * radius / viewPos.z;
- float epsilon = 0.0025 - 0.0002 * viewPos.z;
- float randomPatternRotationAngle = (61.111231231 * u_time + (9.2735171213125 * ssC.x + -7.235171213125 * ssC.y + 1.53713171123412415411 * (ssC.x ^ ssC.y)));
- float logOffset = invMaxOffset / u_projInfo.x;
- float4 normalTex = u_normal.Load(ssC);
- float3 normal = normalTex.xyz;
- //float validity = normalTex.a >= 0.0 ? 0.825 : 0.0; // is previous frame data valid is stored at normalTex.a sign
- //validity *= saturate(2.0 - length(motionVectors) * 200.0);
- float sum = 0.0;
- [unroll]
- for (int i = 0; i < NUM_SAMPLES; ++i)
- {
- sum += sampleAO(input.uv, viewPos, normal, ssDiskRadius, i, randomPatternRotationAngle, logOffset, epsilon);
- }
- float ao = saturate(sum * intensity);
- return ao;
- //float prevValue = u_texture0.SampleLevel(samLinear, prevUv, 0).r;
- //validity = saturate(validity - 4.0 * saturate(-0.8 + abs(ao - prevValue))); // avoid ghosting if samples are too different.
- //return lerp(ao, prevValue, validity);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement