Quantcast
Channel: GameDev.net
Viewing all articles
Browse latest Browse all 17825

Screen Space Reflections and 1 year long headache

$
0
0
Hi, I'm developing a mod for Dirt 3, I'm using 3DMigoto as a shader injector. I've modified 100s of shaders, but I'm completely stuck at implementing Screen Space reflections for water shaders. I've got it almost working, but the reflection is floating whenever I change the camera elevation and there is a lot of misaligned elements floating around. It's been my number one headache trigger for the last year. I've tried everything. but no luck so far. If there is anyone that could spare some time, take a look at the shader code and point me in the right direction I would be really grateful. Here is a video showing my problem: and the vertex and pixel shaders: // water deep not moving VS cbuffer _Globals : register(b0) { float HDRRange : packoffset(c29); float4x4 model : packoffset(c30); float4x4 modelViewProj : packoffset(c34); float2 AmbientLightMapScale : packoffset(c38); float4x4 modelView : packoffset(c39); float4x4 prevViewProj : packoffset(c43); float4x4 prevModel : packoffset(c47); float4 normalParams1 : packoffset(c51); float4 normalParams2 : packoffset(c52); float4 normalParams3 : packoffset(c53); float4 normalParams4 : packoffset(c54); float timer : packoffset(c55); float blendValue : packoffset(c55.y); float4 specularParams : packoffset(c56); float4 waveParams : packoffset(c57); float4 interactiveParams2 : packoffset(c58); float4 interactiveParams3 : packoffset(c59); float4 interactiveParams4 : packoffset(c60); } cbuffer CameraParamsConstantBuffer : register(b3) { float4x4 projection : packoffset(c0); float4x4 viewProjection : packoffset(c4); row_major float3x4 view : packoffset(c8); row_major float3x4 viewI : packoffset(c11); float3 eyePositionWS : packoffset(c14); float4x4 inverseProj : packoffset(c15); bool leftEye : packoffset(c19); bool padding3[3] : packoffset(c20); } cbuffer PerFrameConstantBuffer : register(b1) { float4 colorBufferEncodingParams : packoffset(c0); float4 envMapEncodingParams : packoffset(c1); float4 velocityEncodingParams : packoffset(c2); float4 snowEffectsParam2 : packoffset(c3); float4 sunDirectionAndTime : packoffset(c4); float4 sunColour : packoffset(c5); float4 skylightColour : packoffset(c6); float4 ambientOcclusionScales : packoffset(c7); float4 backlightColour : packoffset(c8); float4 specularScales : packoffset(c9); float3 specularDirection : packoffset(c10); float4 specularColourAndMultiplier : packoffset(c11); float4 fogColour : packoffset(c12); float4 fogParams : packoffset(c13); float4 hazeParams : packoffset(c14); float4 hazeParams2 : packoffset(c15); float4 nightLightmapParam1 : packoffset(c16); float4 nightLightmapParam2 : packoffset(c17); float4 wetLightingParam : packoffset(c18); float4 snowEffectsParam : packoffset(c19); float4 ambientColour : packoffset(c20); float4 shadowBlend : packoffset(c21); float4 maskParams : packoffset(c22); float4 deferredSpecularParams : packoffset(c23); } // 3Dmigoto declarations #define cmp - Texture1D<float4> IniParams : register(t120); Texture2D<float4> StereoParams : register(t125); void main( float4 v0 : POSITION0, float3 v1 : NORMAL0, float3 v2 : TANGENT0, float3 v3 : BINORMAL0, float4 v4 : COLOR0, out float4 o0 : SV_Position0, out float4 o1 : COLOR1, out float4 o2 : TEXCOORD0, out float4 o3 : TEXCOORD1, out float4 o4 : TEXCOORD2, out float4 o5 : TEXCOORD3, out float4 o6 : TEXCOORD4, out float4 o7 : TEXCOORD5, out float4 o8 : TEXCOORD6, out float4 o9 : TEXCOORD7, out float4 o10 : TEXCOORD8, //viewPosition out float3 o11 : TEXCOORD9, //viewNormal out float3 o12 : TEXCOORD10) //csPos { float4 r0,r1,r2,r3,r4,r5; uint4 bitmask, uiDest; float4 fDest; //-- original game shader code r0.xyzw = modelViewProj._m01_m11_m21_m31 * v0.yyyy; r0.xyzw = modelViewProj._m00_m10_m20_m30 * v0.xxxx + r0.xyzw; r0.xyzw = modelViewProj._m02_m12_m22_m32 * v0.zzzz + r0.xyzw; r0.xyzw = modelViewProj._m03_m13_m23_m33 * v0.wwww + r0.xyzw; o0.xyzw = r0.xyzw; r1.xyz = model._m01_m11_m21 * v0.yyy; r1.xyz = model._m00_m10_m20 * v0.xxx + r1.xyz; r1.xyz = model._m02_m12_m22 * v0.zzz + r1.xyz; r1.xyz = model._m03_m13_m23 * v0.www + r1.xyz; r2.xyz = -eyePositionWS.xyz + r1.xyz; r1.w = dot(r2.xyz, r2.xyz); r1.w = sqrt(r1.w); r2.xyz = r2.xyz / r1.www; r2.x = saturate(dot(r2.xyz, sunDirectionAndTime.xyz)); r2.x = log2(r2.x); r2.x = hazeParams2.w * r2.x; r2.x = exp2(r2.x); r2.yzw = hazeParams2.xyz + -hazeParams.xyz; r2.xyz = r2.xxx * r2.yzw + hazeParams.xyz; r3.x = 1 / fogParams.z; r3.x = -r3.x + r1.w; r1.w = -30 + r1.w; r1.w = saturate(fogParams.z * r1.w); r4.w = fogParams.w * r1.w; r1.w = max(0, r3.x); r1.w = hazeParams.w * r1.w; r1.w = 1.44269502 * r1.w; r1.w = exp2(r1.w); r2.w = 1 + -r1.w; r4.xyz = fogColour.xyz; r3.xyzw = -r4.xyzw + r2.xyzw; r2.xyzw = r2.wwww * r3.xyzw + r4.xyzw; o1.xyz = r2.xyz * r2.www; o1.w = 1 + -r2.w; r2.xyz = model._m01_m11_m21 * v1.yyy; r2.xyz = model._m00_m10_m20 * v1.xxx + r2.xyz; r2.xyz = model._m02_m12_m22 * v1.zzz + r2.xyz; r1.w = dot(r2.xyz, r2.xyz); r1.w = rsqrt(r1.w); r2.xyz = r2.xyz * r1.www; o2.xyz = r2.xyz; r3.xy = interactiveParams2.wz * float2(1,-1); r3.xy = interactiveParams4.xx * r3.xy; r1.w = timer + 0.5; r3.xy = r1.ww * r3.xy; r3.zw = float2(0.0500000007,0.0500000007) * r1.xz; r3.xy = r3.zw * interactiveParams4.xx + r3.xy; o2.w = r3.x; o3.w = r3.y; r4.xyz = model._m01_m11_m21 * v2.yyy; r4.xyz = model._m00_m10_m20 * v2.xxx + r4.xyz; r4.xyz = model._m02_m12_m22 * v2.zzz + r4.xyz; r1.w = dot(r4.xyz, r4.xyz); r1.w = rsqrt(r1.w); r4.xyz = r4.xyz * r1.www; o3.xyz = r4.xyz; r5.xyz = r4.yzx * r2.zxy; r2.xyz = r2.yzx * r4.zxy + -r5.xyz; r1.w = dot(r2.xyz, r2.xyz); r1.w = rsqrt(r1.w); o4.xyz = r2.xyz * r1.www; o4.w = 0; r2.xyzw = normalParams4.xyzw + r1.xzxz; o7.xyz = r1.xyz; o7.w = 0; r1.xyzw = normalParams2.xxyy * r2.xyzw; r1.xyzw = specularParams.wwww * r1.xyzw; o5.xyzw = float4(0.0500000007,0.0500000007,0.0500000007,0.0500000007) * r1.xyzw; r1.xy = specularParams.ww * r3.zw; r1.zw = waveParams.xy * timer; r1.zw = normalParams1.zz * r1.zw; o6.xy = r1.xy * normalParams2.zz + r1.zw; r1.xy = interactiveParams3.ww * interactiveParams2.zw; r1.xy = timer * r1.xy; o6.zw = r3.zw * interactiveParams3.ww + r1.xy; o8.x = dot(float2(0.5,0.5), r0.xw); o8.y = dot(float2(0.5,0.5), r0.yw); o8.zw = r0.zw; r0.x = modelView._m21 * v0.y; r0.x = modelView._m20 * v0.x + r0.x; r0.x = modelView._m22 * v0.z + r0.x; o9.z = modelView._m23 + r0.x; o9.xyw = float3(0,0,1); //-- output values for SSR o10 = mul(modelView, v0.xyzw); //viewPosition o11 = mul((float3x3)modelView, v1.xyz); //viewNormal float4 position = mul(modelViewProj, float4(v0.xyzw)); o12 = position.xyz / position.w; //csPosition return; } // water deep not moving PS cbuffer _Globals : register(b0) { float HDRRange : packoffset(c29); float2 AmbientLightMapScale : packoffset(c29.y); float4 normalParams1 : packoffset(c30); float4 normalParams2 : packoffset(c31); float4 normalParams3 : packoffset(c32); float4 normalParams4 : packoffset(c33); float timer : packoffset(c34); float4 screenProj : packoffset(c35); float4 fresnelParams : packoffset(c36); float4 horizonColour : packoffset(c37); float4 nadirColour : packoffset(c38); float4 interactiveParams1 : packoffset(c39); float4 interactiveParams5 : packoffset(c40); float4 waterShadowBlend : packoffset(c41); float4 decodeParam : packoffset(c42); float4 sparkleParams : packoffset(c43); float4 sparkleParams2 : packoffset(c44); float blendValue : packoffset(c45); float4 specularParams : packoffset(c46); float4 waveParams : packoffset(c47); float4 interactiveParams2 : packoffset(c48); float4 interactiveParams3 : packoffset(c49); float4 interactiveParams4 : packoffset(c50); } cbuffer RenderTargetConstantBuffer : register(b2) { float4 viewportDimensions : packoffset(c0); } cbuffer CameraParamsConstantBuffer : register(b3) { float4x4 projection : packoffset(c0); float4x4 viewProjection : packoffset(c4); row_major float3x4 view : packoffset(c8); row_major float3x4 viewI : packoffset(c11); float3 eyePositionWS : packoffset(c14); float4x4 inverseProj : packoffset(c15); bool leftEye : packoffset(c19); bool padding3[3] : packoffset(c20); } cbuffer PerFrameConstantBuffer : register(b1) { float4 colorBufferEncodingParams : packoffset(c0); float4 envMapEncodingParams : packoffset(c1); float4 velocityEncodingParams : packoffset(c2); float4 snowEffectsParam2 : packoffset(c3); float4 sunDirectionAndTime : packoffset(c4); float4 sunColour : packoffset(c5); float4 skylightColour : packoffset(c6); float4 ambientOcclusionScales : packoffset(c7); float4 backlightColour : packoffset(c8); float4 specularScales : packoffset(c9); float3 specularDirection : packoffset(c10); float4 specularColourAndMultiplier : packoffset(c11); float4 fogColour : packoffset(c12); float4 fogParams : packoffset(c13); float4 hazeParams : packoffset(c14); float4 hazeParams2 : packoffset(c15); float4 nightLightmapParam1 : packoffset(c16); float4 nightLightmapParam2 : packoffset(c17); float4 wetLightingParam : packoffset(c18); float4 snowEffectsParam : packoffset(c19); float4 ambientColour : packoffset(c20); float4 shadowBlend : packoffset(c21); float4 maskParams : packoffset(c22); float4 deferredSpecularParams : packoffset(c23); } SamplerState TNormalMap_s : register(s0); SamplerState DepthMap_s : register(s1); SamplerState ReflectionMap_s : register(s2); SamplerState ReflectionMap2_s : register(s3); SamplerState TMaskMap_s : register(s4); SamplerState TShadowMask_s : register(s10); Texture2D<float4> DepthMap : register(t0); Texture2D<float4> TNormalMap : register(t1); Texture2D<float4> ReflectionMap : register(t2); Texture2D<float4> ReflectionMap2 : register(t3); Texture2D<float4> TShadowMask : register(t4); Texture2D<float4> TMaskMap : register(t5); //-- SSR buffers Texture2D<float> DepthBuffer : register(t100); SamplerState DepthBuffer_s : register(s11); Texture2D<float4> HDRTex : register(t101); SamplerState HDRTex_s : register(s12); //-- 3Dmigoto declarations #define cmp - Texture1D<float4> IniParams : register(t120); Texture2D<float4> StereoParams : register(t125); //-- SSR Constants static float2 cb_depthBufferSize; // dimensions of the z-buffer static const float cb_zThickness = 1; // thickness to ascribe to each pixel in the depth buffer //static const float cb_nearPlaneZ = 0.6; // the camera's near z plane static const float cb_stride = 1; // Step in horizontal or vertical pixels between samples. This is a float // because integer math is slow on GPUs, but should be set to an integer >= 1. static float cb_maxSteps; // Maximum number of iterations. Higher gives better images but may be slow. //static const float cb_maxDistance = 10000; // Maximum camera-space distance to trace before returning a miss. static const float cb_strideZCutoff = 0; // More distant pixels are smaller in screen space. This value tells at what point to // start relaxing the stride to give higher quality reflections for objects far from // the camera. static const float cb_numMips = 1; // the number of mip levels in the convolved color buffer static const float cb_fadeStart = 0; // determines where to start screen edge fading of effect static const float cb_fadeEnd = 0; // determines where to end screen edge fading of effect static const float cb_sslr_padding0 = 0; // padding for alignment //--SSR Functions float linearizeDepth(float depth) { float4 tmp = mul(inverseProj, float4(0, 0, depth, 1)); return mul(projection, tmp / tmp.w).w; //float n = cb_nearPlaneZ; // camera z near //float f = cb_maxDistance; // camera z far //float z = depth; //return (2.0 * n) / (f + n - z * (f - n)); } float distanceSquared(float2 a, float2 b) { a -= b; return dot(a, a); } bool intersectsDepthBuffer(float z, float minZ, float maxZ) { /* * Based on how far away from the camera the depth is, * adding a bit of extra thickness can help improve some * artifacts. Driving this value up too high can cause * artifacts of its own. */ float depthScale = min(1.0f, z * cb_strideZCutoff); z += cb_zThickness + lerp(0.0f, 2.0f, depthScale); return (maxZ >= z) && (minZ - cb_zThickness <= z); } void swap(inout float a, inout float b) { float t = a; a = b; b = t; } float linearDepthTexelFetch(int2 hitPixel) { // Load returns 0 for any value accessed out of bounds return linearizeDepth(DepthBuffer.Load(int3(hitPixel, 0)).r); } bool traceScreenSpaceRay( // Camera-space ray origin, which must be within the view volume float3 csOrig, // Unit length camera-space ray direction float3 csDir, // Number between 0 and 1 for how far to bump the ray in stride units // to conceal banding artifacts. Not needed if stride == 1. float jitter, // Pixel coordinates of the first intersection with the scene out float2 hitPixel, // Camera space location of the ray hit out float3 hitPoint) { float near = linearizeDepth(0); float far = linearizeDepth(1); // Clip to the near plane float rayLength = ((csOrig.z + csDir.z * far) > -near) ? (-near - csOrig.z) / csDir.z : far; float3 csEndPoint = csOrig + csDir * rayLength; // Project into homogeneous clip space float4 H0 = mul(projection, float4(csOrig, 1.0f)); float4 H1 = mul(projection, float4(csEndPoint, 1.0f)); float k0 = 1.0f / H0.w; float k1 = 1.0f / H1.w; // The interpolated homogeneous version of the camera-space points float3 Q0 = csOrig * k0; float3 Q1 = csEndPoint * k1; // Screen-space endpoints float2 P0 = H0.xy * k0; float2 P1 = H1.xy * k1; // Scale to pixels: P0 = (P0 * float2(0.5, -0.5) + 0.5) * cb_depthBufferSize; P1 = (P1 * float2(0.5, -0.5) + 0.5) * cb_depthBufferSize; // If the line is degenerate, make it cover at least one pixel // to avoid handling zero-pixel extent as a special case later P1 += (distanceSquared(P0, P1) < 0.0001f) ? float2(0.01f, 0.01f) : 0.0f; float2 delta = P1 - P0; // Permute so that the primary iteration is in x to collapse // all quadrant-specific DDA cases later bool permute = false; if(abs(delta.x) < abs(delta.y)) { // This is a more-vertical line permute = true; delta = delta.yx; P0 = P0.yx; P1 = P1.yx; } float stepDir = sign(delta.x); float invdx = stepDir / delta.x; // Track the derivatives of Q and k float3 dQ = (Q1 - Q0) * invdx; float dk = (k1 - k0) * invdx; float2 dP = float2(stepDir, delta.y * invdx); // Scale derivatives by the desired pixel stride and then // offset the starting values by the jitter fraction float strideScale = 1.0f - min(1.0f, csOrig.z * cb_strideZCutoff); float stride = 1.0f + strideScale * cb_stride; dP *= stride; dQ *= stride; dk *= stride; P0 += dP * jitter; Q0 += dQ * jitter; k0 += dk * jitter; // Slide P from P0 to P1, (now-homogeneous) Q from Q0 to Q1, k from k0 to k1 float4 PQk = float4(P0, Q0.z, k0); float4 dPQk = float4(dP, dQ.z, dk); float3 Q = Q0; float end = P1.x * stepDir; float stepCount = 0.0f; float prevZMaxEstimate = csOrig.z; float rayZMin = prevZMaxEstimate; float rayZMax = prevZMaxEstimate; float sceneZMax = rayZMax + 100.0f; for(; ((PQk.x * stepDir) <= end) && (stepCount < cb_maxSteps) && !intersectsDepthBuffer(sceneZMax, rayZMin, rayZMax) && (sceneZMax != 0.0f); ++stepCount) { rayZMin = prevZMaxEstimate; rayZMax = (dPQk.z * 0.5f + PQk.z) / (dPQk.w * 0.5f + PQk.w); prevZMaxEstimate = rayZMax; if(rayZMin > rayZMax) { swap(rayZMin, rayZMax); } hitPixel = permute ? PQk.yx : PQk.xy; // You may need hitPixel.y = depthBufferSize.y - hitPixel.y; here if your vertical axis // is different than ours in screen space sceneZMax = linearDepthTexelFetch(int2(hitPixel)); PQk += dPQk; } // Advance Q based on the number of steps Q.xy += dQ.xy * stepCount; hitPoint = Q * (1.0f / PQk.w); return intersectsDepthBuffer(sceneZMax, rayZMin, rayZMax); } //-- Main stripped from all code, only planar reflection is displayed void main( float4 v0 : SV_Position0, float4 v1 : COLOR1, float4 v2 : TEXCOORD0, float4 v3 : TEXCOORD1, float4 v4 : TEXCOORD2, linear centroid float4 v5 : TEXCOORD3, linear centroid float4 v6 : TEXCOORD4, linear centroid float4 v7 : TEXCOORD5, float4 v8 : TEXCOORD6, linear centroid float4 v9 : TEXCOORD7, out float4 o0 : SV_Target0, float4 viewPosition : TEXCOORD8, float3 normalVS : TEXCOORD9, float3 csPosition : TEXCOORD10) { float4 stereo = StereoParams.Load(0); float separation = stereo.x * (leftEye ? -1 : 1); float convergence = stereo.y; viewPosition.x += separation * convergence * inverseProj._m00; DepthBuffer.GetDimensions(cb_depthBufferSize.x, cb_depthBufferSize.y); cb_maxSteps = cb_depthBufferSize.y; float2 hitPixel = float2(0.0f, 0.0f); float3 hitPoint = float3(0.0f, 0.0f, 0.0f); int3 loadIndices = int3(v0.xy, 0); float depth = DepthBuffer.Load(loadIndices); float3 rayOriginVS = viewPosition * linearizeDepth(depth); float3 toPositionVS = normalize(rayOriginVS); float3 rayDirectionVS = normalize(reflect(-toPositionVS, normalVS)); // output rDotV to the alpha channel for use in determining how much to fade the ray float rDotV = dot(rayDirectionVS, toPositionVS); float jitter = cb_stride > 1.0f ? float(int(v0.x + v0.y) & 1) * 0.5f : 0.0f; bool intersection = traceScreenSpaceRay(-rayOriginVS, -rayDirectionVS, jitter, hitPixel, hitPoint); if (intersection != false) o0.xyz = HDRTex.Load(float3(hitPixel, 0)); else o0.xyz = float3(0,0,0); o0.w=1; return; }

Viewing all articles
Browse latest Browse all 17825

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>