diff --git a/neo/renderer/GLMatrix.cpp b/neo/renderer/GLMatrix.cpp index 33e5f149..4d567344 100644 --- a/neo/renderer/GLMatrix.cpp +++ b/neo/renderer/GLMatrix.cpp @@ -535,7 +535,7 @@ void R_SetupProjectionMatrix( viewDef_t* viewDef, bool doJitter ) projectionMatrix[2 * 4 + 2] = -0.999f; // adjust value to prevent imprecision issues // RB: was -2.0f * zNear - // the transformation into window space has changed from [-1 .. -1] to [0 .. -1] + // the transformation into window space has changed from [-1 .. 1] to [0 .. 1] projectionMatrix[3 * 4 + 2] = -1.0f * zNear; projectionMatrix[0 * 4 + 3] = 0.0f; @@ -545,7 +545,8 @@ void R_SetupProjectionMatrix( viewDef_t* viewDef, bool doJitter ) #else - // alternative Z for better precision in the distance + // alternative far plane at infinity Z for better precision in the distance but still no reversed depth buffer + // see Foundations of Game Engine Development 2, chapter 6.3 float aspect = viewDef->renderView.fov_x / viewDef->renderView.fov_y; @@ -570,7 +571,11 @@ void R_SetupProjectionMatrix( viewDef_t* viewDef, bool doJitter ) projectionMatrix[0 * 4 + 2] = 0.0f; projectionMatrix[1 * 4 + 2] = 0.0f; + + // adjust value to prevent imprecision issues projectionMatrix[2 * 4 + 2] = -k; + + // the clip space Z range has changed from [-1 .. 1] to [0 .. 1] for DX12 & Vulkan projectionMatrix[3 * 4 + 2] = -k * zNear; projectionMatrix[0 * 4 + 3] = 0.0f; @@ -665,10 +670,12 @@ create a matrix with similar functionality like gluUnproject, project from windo */ void R_SetupUnprojection( viewDef_t* viewDef ) { + // RB: I don't like that this doesn't work + //idRenderMatrix::Inverse( *( idRenderMatrix* ) viewDef->projectionMatrix, viewDef->unprojectionToCameraRenderMatrix ); + R_MatrixFullInverse( viewDef->projectionMatrix, viewDef->unprojectionToCameraMatrix ); idRenderMatrix::Transpose( *( idRenderMatrix* )viewDef->unprojectionToCameraMatrix, viewDef->unprojectionToCameraRenderMatrix ); - R_MatrixMultiply( viewDef->worldSpace.modelViewMatrix, viewDef->projectionMatrix, viewDef->unprojectionToWorldMatrix ); R_MatrixFullInverse( viewDef->unprojectionToWorldMatrix, viewDef->unprojectionToWorldMatrix ); diff --git a/neo/renderer/Passes/SsaoPass.cpp b/neo/renderer/Passes/SsaoPass.cpp index 24526ef5..613882de 100644 --- a/neo/renderer/Passes/SsaoPass.cpp +++ b/neo/renderer/Passes/SsaoPass.cpp @@ -1,5 +1,8 @@ /* * Copyright (c) 2014-2021, NVIDIA CORPORATION. All rights reserved. +* Copyright (C) 2022 Stephen Pridham (id Tech 4x integration) +* Copyright (C) 2023 Stephen Saunders (id Tech 4x integration) +* Copyright (C) 2023 Robert Beckebans (id Tech 4x integration) * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -27,12 +30,12 @@ #include "SsaoPass.h" -static idCVar r_ssaoBackgroundViewDepth( "r_ssaoBackgroundViewDepth", "100", CVAR_RENDERER | CVAR_FLOAT, "" ); -static idCVar r_ssaoRadiusWorld( "r_ssaoRadiusWorld", "0.5", CVAR_RENDERER | CVAR_FLOAT, "" ); -static idCVar r_ssaoSurfaceBias( "r_ssaoSurfaceBias", "0.1", CVAR_RENDERER | CVAR_FLOAT, "" ); +static idCVar r_ssaoBackgroundViewDepth( "r_ssaoBackgroundViewDepth", "100", CVAR_RENDERER | CVAR_FLOAT, "specified in meters" ); +static idCVar r_ssaoRadiusWorld( "r_ssaoRadiusWorld", "1.0", CVAR_RENDERER | CVAR_FLOAT, "specified in meters" ); +static idCVar r_ssaoSurfaceBias( "r_ssaoSurfaceBias", "0.05", CVAR_RENDERER | CVAR_FLOAT, "specified in meters" ); static idCVar r_ssaoPowerExponent( "r_ssaoPowerExponent", "2", CVAR_RENDERER | CVAR_FLOAT, "" ); static idCVar r_ssaoBlurSharpness( "r_ssaoBlurSharpness", "16", CVAR_RENDERER | CVAR_FLOAT, "" ); -static idCVar r_ssaoAmount( "r_ssaoAmount", "2", CVAR_RENDERER | CVAR_FLOAT, "" ); +static idCVar r_ssaoAmount( "r_ssaoAmount", "4", CVAR_RENDERER | CVAR_FLOAT, "" ); struct SsaoConstants { @@ -40,8 +43,8 @@ struct SsaoConstants idVec2 viewportSize; idRenderMatrix matClipToView; - idRenderMatrix matWorldToView; - idRenderMatrix matViewToWorld; + idRenderMatrix matWorldToView; // unused + idRenderMatrix matViewToWorld; // unused idVec2 clipToView; idVec2 invQuantizedGbufferSize; @@ -240,42 +243,44 @@ void SsaoPass::Render( assert( m_Blur.BindingSets[bindingSetIndex] ); { - nvrhi::Rect viewExtent( viewDef->viewport.x1, viewDef->viewport.x2, viewDef->viewport.y1, viewDef->viewport.y2 ); + // RB HACK: add one 1 extra pixel to width and height + nvrhi::Rect viewExtent( viewDef->viewport.x1, viewDef->viewport.x2 + 1, viewDef->viewport.y1, viewDef->viewport.y2 + 1 ); nvrhi::Rect quarterResExtent = viewExtent; quarterResExtent.minX /= 4; quarterResExtent.minY /= 4; quarterResExtent.maxX = ( quarterResExtent.maxX + 3 ) / 4; quarterResExtent.maxY = ( quarterResExtent.maxY + 3 ) / 4; + // TODO required and remove this by fixing the shaders + renderProgManager.BindShader_TextureVertexColor(); + renderProgManager.CommitConstantBuffer( commandList, true ); + SsaoConstants ssaoConstants = {}; ssaoConstants.viewportOrigin = idVec2( viewDef->viewport.x1, viewDef->viewport.y1 ); ssaoConstants.viewportSize = idVec2( viewDef->viewport.GetWidth(), viewDef->viewport.GetHeight() ); - ssaoConstants.matClipToView = viewDef->unprojectionToCameraRenderMatrix; + // RB: this actually should work but it only works with the old SSAO method ... + //ssaoConstants.matClipToView = viewDef->unprojectionToCameraRenderMatrix; - // SRS - FIXME: These transformations need to be verified + idRenderMatrix::Inverse( *( idRenderMatrix* ) viewDef->projectionMatrix, ssaoConstants.matClipToView ); // RB: TODO: only need for DIRECTIONAL_OCCLUSION + // we don't store the view matrix separatly yet //ssaoConstants.matViewToWorld = viewDef->worldSpace; //idRenderMatrix::Inverse( ssaoConstants.matViewToWorld, ssaoConstants.matWorldToView ); - // SRS end - - float projectionMatrix[16]; - - //R_MatrixTranspose( viewDef->projectionMatrix, projectionMatrix ); - memcpy( projectionMatrix, viewDef->projectionMatrix, 16 * 4 ); ssaoConstants.clipToView = idVec2( - projectionMatrix[2 * 4 + 3] / projectionMatrix[0 * 4 + 0], - projectionMatrix[2 * 4 + 3] / projectionMatrix[1 * 4 + 1] ); - ssaoConstants.invQuantizedGbufferSize = 1.f / m_QuantizedGbufferTextureSize; + viewDef->projectionMatrix[2 * 4 + 3] / viewDef->projectionMatrix[0 * 4 + 0], + viewDef->projectionMatrix[2 * 4 + 3] / viewDef->projectionMatrix[1 * 4 + 1] ); + + ssaoConstants.invQuantizedGbufferSize = idVec2( 1.0f, 1.0f ) / m_QuantizedGbufferTextureSize; ssaoConstants.quantizedViewportOrigin = idVec2i( quarterResExtent.minX, quarterResExtent.minY ) * 4; ssaoConstants.amount = r_ssaoAmount.GetFloat(); ssaoConstants.invBackgroundViewDepth = ( r_ssaoBackgroundViewDepth.GetFloat() > 0.f ) ? 1.f / r_ssaoBackgroundViewDepth.GetFloat() : 0.f; ssaoConstants.radiusWorld = r_ssaoRadiusWorld.GetFloat(); ssaoConstants.surfaceBias = r_ssaoSurfaceBias.GetFloat(); ssaoConstants.powerExponent = r_ssaoPowerExponent.GetFloat(); - ssaoConstants.radiusToScreen = 0.5f * viewDef->viewport.GetHeight() * abs( projectionMatrix[1 * 4 + 1] ); + ssaoConstants.radiusToScreen = 0.5f * viewDef->viewport.GetHeight() * abs( viewDef->projectionMatrix[1 * 4 + 1] ); commandList->writeBuffer( m_ConstantBuffer, &ssaoConstants, sizeof( ssaoConstants ) ); uint32_t dispatchWidth = ( quarterResExtent.width() + 7 ) / 8; diff --git a/neo/renderer/RenderBackend.cpp b/neo/renderer/RenderBackend.cpp index 00790856..372f03ad 100644 --- a/neo/renderer/RenderBackend.cpp +++ b/neo/renderer/RenderBackend.cpp @@ -44,7 +44,7 @@ If you have questions concerning this license or the applicable additional terms #include #include - idCVar r_useNewSsaoPass( "r_useNewSSAOPass", "0", CVAR_RENDERER | CVAR_BOOL, "use the new ssao pass from donut" ); + idCVar r_useNewSsaoPass( "r_useNewSSAOPass", "1", CVAR_RENDERER | CVAR_BOOL, "use the new SSAO pass from Donut" ); extern DeviceManager* deviceManager; #endif diff --git a/neo/shaders/builtin/SSAO/AmbientOcclusion_AO.ps.hlsl b/neo/shaders/builtin/SSAO/AmbientOcclusion_AO.ps.hlsl index 0617fb8f..8408cf07 100644 --- a/neo/shaders/builtin/SSAO/AmbientOcclusion_AO.ps.hlsl +++ b/neo/shaders/builtin/SSAO/AmbientOcclusion_AO.ps.hlsl @@ -163,8 +163,8 @@ float3 reconstructNonUnitCSFaceNormal( float3 C ) float3 reconstructCSPosition( float2 S, float z ) { float4 P; - P.z = z * 2.0 - 1.0; - P.xy = ( S * rpWindowCoord.xy ) * 2.0 - 1.0; + P.z = z;// * 2.0 - 1.0; + P.xy = ( S * rpWindowCoord.xy );// * 2.0 - 1.0; P.w = 1.0; float4 csP; diff --git a/neo/shaders/builtin/SSAO/ssao_compute.cs.hlsl b/neo/shaders/builtin/SSAO/ssao_compute.cs.hlsl index 12a1bdc7..5595d112 100644 --- a/neo/shaders/builtin/SSAO/ssao_compute.cs.hlsl +++ b/neo/shaders/builtin/SSAO/ssao_compute.cs.hlsl @@ -176,13 +176,14 @@ float ComputeAO( float3 V, float3 N, float InvR2 ) float2 WindowToClip( float2 windowPos ) { - float2 clipToWindowScale = float2( 0.5f * g_Ssao.viewportSize.x, -0.5f * g_Ssao.viewportSize.y ); - float2 clipToWindowBias = g_Ssao.viewportOrigin.xy + g_Ssao.viewportSize.xy * 0.5f; + float2 clipToWindowScale = float2( 0.5 * g_Ssao.viewportSize.x, -0.5 * g_Ssao.viewportSize.y ); + float2 clipToWindowBias = g_Ssao.viewportOrigin.xy + g_Ssao.viewportSize.xy * 0.5; - float2 windowToClipScale = 1.f / clipToWindowScale; + float2 windowToClipScale = 1.0 / clipToWindowScale; float2 windowToClipBias = -clipToWindowBias * windowToClipScale; // TODO add pixelOffset for TAA + //windowPos = windowPos * 2.0 - 1.0; return windowPos.xy * windowToClipScale + windowToClipBias; } @@ -207,7 +208,9 @@ void main( uint3 globalId : SV_DispatchThreadID ) float3 pixelNormal = t_Normals[pixelPos].xyz; #endif - // RB: pixelNormal is already in view space + // RB: pixelNormal is already in view space but it has to be negated to look correct which is weird + pixelNormal = -normalize( pixelNormal ); + //pixelNormal = normalize( float3( pixelNormal.x, 1.0 - pixelNormal.y, -pixelNormal.z ) ); //pixelNormal = normalize( mul( float4( pixelNormal, 0 ), g_Ssao.matWorldToView ).xyz ); float2 pixelClipPos = WindowToClip( pixelPos ); diff --git a/neo/shaders/builtin/SSAO/ssao_deinterleave.cs.hlsl b/neo/shaders/builtin/SSAO/ssao_deinterleave.cs.hlsl index 7951a392..2ac93728 100644 --- a/neo/shaders/builtin/SSAO/ssao_deinterleave.cs.hlsl +++ b/neo/shaders/builtin/SSAO/ssao_deinterleave.cs.hlsl @@ -74,22 +74,12 @@ void main( uint3 globalId : SV_DispatchThreadID ) #if LINEAR_DEPTH float linearDepth = depth; #else - //float4 clipPos = float4( 0, 0, depth, 1 ); - //float4 clipPos = float4( 0, 0, depth * 2.0 - 1.0, 1 ); - - // adjust depth - depth = ( depth * 2.0 - 1.0 ); float4 clipPos = float4( 0, 0, depth, 1 ); - float4 viewPos = mul( clipPos, g_Ssao.matClipToView ); float linearDepth = viewPos.z / viewPos.w; - // HACK: adjust linear depth to fit into [0 .. 16000] range - //linearDepth += 0.35; - //linearDepth = saturate( linearDepth ); - //linearDepth = 1.0 - linearDepth; // reverse depth - //linearDepth *= 4000; // zFar - //linearDepth *= DOOM_TO_METERS; + linearDepth *= -1.0f; // now we have something similar to Doom units = inches + linearDepth *= DOOM_TO_METERS; #endif depths[y * 4 + x] = linearDepth; diff --git a/neo/shaders/builtin/gbuffer.ps.hlsl b/neo/shaders/builtin/gbuffer.ps.hlsl index efdd4dc1..38194b57 100644 --- a/neo/shaders/builtin/gbuffer.ps.hlsl +++ b/neo/shaders/builtin/gbuffer.ps.hlsl @@ -66,7 +66,9 @@ void main( PS_IN fragment, out PS_OUT result ) localNormal.z = sqrt( 1.0f - dot3( localNormal, localNormal ) ); float3 globalNormal; -#if 0 + +#if 1 + // rotate normal into view space globalNormal.x = dot3( localNormal, fragment.texcoord2 ); globalNormal.y = dot3( localNormal, fragment.texcoord3 ); globalNormal.z = dot3( localNormal, fragment.texcoord4 ); @@ -81,6 +83,5 @@ void main( PS_IN fragment, out PS_OUT result ) // RB: rpColor is white and only used to generate the _fa_ uniform array result.color.rgb = ( globalNormal.xyz * 0.5 + 0.5 ) * fragment.color.rgb;// * rpColor; - //result.color.rgb = ( globalNormal.xyz );// * fragment.color.rgb;// * rpColor; result.color.a = 1.0; }