Store world normals in gbuffer

This commit is contained in:
Robert Beckebans 2024-07-31 17:04:42 +02:00
parent 449f56ab9f
commit ea78cf42e3
7 changed files with 203 additions and 69 deletions

View file

@ -443,13 +443,30 @@ float idConsoleLocal::DrawFPS( float y )
aaMode = aaValues[ r_antiAliasing.GetInteger() ];
}
idStr resolutionText;
resolutionScale.GetConsoleText( resolutionText );
static const int rrNumValues = 8;
static const char* rrValues[rrNumValues] =
{
"None",
"C64",
"C64 Hi",
"CPC",
"CPC Hi",
"Sega",
"Sega Hi",
"Sony PSX",
};
compile_time_assert( rrNumValues == ( RENDERMODE_PSX + 1 ) );
const char* retroRenderMode = rrValues[ r_renderMode.GetInteger() ];
//idStr resolutionText;
//resolutionScale.GetConsoleText( resolutionText );
int width = renderSystem->GetWidth();
int height = renderSystem->GetHeight();
ImGui::TextColored( colorCyan, "API: %s, AA[%i, %i]: %s, %s", API, width, height, aaMode, resolutionText.c_str() );
ImGui::TextColored( colorCyan, "API: %s, AA[%i, %i]: %s, R: %s", API, width, height, aaMode, retroRenderMode );
ImGui::TextColored( colorGold, "Device: %s", deviceManager->GetRendererString() );
ImGui::TextColored( colorPastelMagenta, "VRAM Usage: %llu MB", commonLocal.GetRendererGpuMemoryMB() );

View file

@ -271,7 +271,11 @@ void SsaoPass::Render(
// 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 );
// TODO would be nicer and faster to have idRenderMatrix::Copy
idRenderMatrix tmp;
idRenderMatrix::Transpose( *( idRenderMatrix* ) viewDef->worldSpace.modelViewMatrix, tmp );
idRenderMatrix::Transpose( tmp, ssaoConstants.matWorldToView );
ssaoConstants.clipToView = idVec2(
viewDef->projectionMatrix[2 * 4 + 3] / viewDef->projectionMatrix[0 * 4 + 0],

View file

@ -5116,6 +5116,11 @@ void idRenderBackend::DrawScreenSpaceAmbientOcclusion( const viewDef_t* _viewDef
SetVertexParms( RENDERPARM_MODELMATRIX_X, viewDef->unprojectionToCameraRenderMatrix[0], 4 );
// RB: we need to rotate the normals of the gbuffer from world space to view space
idRenderMatrix viewMatrix;
idRenderMatrix::Transpose( *( idRenderMatrix* ) viewDef->worldSpace.modelViewMatrix, viewMatrix );
SetVertexParms( RENDERPARM_MODELVIEWMATRIX_X, viewMatrix[0], 4 );
const float jitterSampleScale = 1.0f;
float jitterTexScale[4];
@ -6251,11 +6256,79 @@ void idRenderBackend::PostProcess( const void* data )
blitParms.targetViewport = nvrhi::Viewport( renderSystem->GetWidth(), renderSystem->GetHeight() );
commonPasses.BlitTexture( commandList, blitParms, &bindingCache );
globalFramebuffers.smaaBlendFBO->Bind();
//GL_Viewport( 0, 0, screenWidth, screenHeight );
//GL_Scissor( 0, 0, screenWidth, screenHeight );
if( r_renderMode.GetInteger() == RENDERMODE_CPC || r_renderMode.GetInteger() == RENDERMODE_CPC_HIGHRES )
{
// clear the alpha buffer and draw only the hands + weapon into it so
// we can avoid blurring them
renderLog.OpenBlock( "Render_HandsAlpha" );
GL_State( GLS_COLORMASK | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED );
GL_Color( 0, 0, 0, 1 );
renderProgManager.BindShader_Color();
currentSpace = NULL;
// draw shader over entire screen
RB_SetMVP( renderMatrix_identity );
DrawElementsWithCounters( &unitSquareSurface );
// draw the hands + weapon with alpha 0
GL_Color( 0, 0, 0, 0 );
drawSurf_t** drawSurfs = ( drawSurf_t** )&viewDef->drawSurfs[0];
for( int surfNum = 0; surfNum < viewDef->numDrawSurfs; surfNum++ )
{
const drawSurf_t* surf = drawSurfs[ surfNum ];
if( !surf->space->weaponDepthHack && !surf->space->skipMotionBlur && !surf->material->HasSubview() )
{
// Apply motion blur to this object
continue;
}
const idMaterial* shader = surf->material;
if( shader->Coverage() == MC_TRANSLUCENT )
{
// muzzle flash, etc
continue;
}
// set mvp matrix
if( surf->space != currentSpace )
{
RB_SetMVP( surf->space->mvp );
currentSpace = surf->space;
}
// this could just be a color, but we don't have a skinned color-only prog
if( surf->jointCache )
{
renderProgManager.BindShader_TextureVertexColorSkinned();
}
else
{
renderProgManager.BindShader_TextureVertexColor();
}
// draw it solid
DrawElementsWithCounters( surf );
}
renderLog.CloseBlock();
}
GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ZERO | GLS_DEPTHMASK | GLS_DEPTHFUNC_ALWAYS | GLS_CULL_TWOSIDED );
GL_SelectTexture( 0 );
globalImages->smaaBlendImage->Bind();
globalFramebuffers.ldrFBO->Bind();
GL_SelectTexture( 1 );
globalImages->blueNoiseImage256->Bind();
@ -6265,11 +6338,11 @@ void idRenderBackend::PostProcess( const void* data )
GL_SelectTexture( 3 );
if( r_useHierarchicalDepthBuffer.GetBool() )
{
commandList->clearTextureFloat( globalImages->hierarchicalZbufferImage->GetTextureHandle(), nvrhi::AllSubresources, nvrhi::Color( 1.f ) );
// build hierarchical depth buffer
renderLog.OpenBlock( "Render_HiZ" );
commandList->clearTextureFloat( globalImages->hierarchicalZbufferImage->GetTextureHandle(), nvrhi::AllSubresources, nvrhi::Color( 1.f ) );
commonPasses.BlitTexture(
commandList,
globalFramebuffers.csDepthFBO[0]->GetApiObject(),
@ -6287,6 +6360,8 @@ void idRenderBackend::PostProcess( const void* data )
globalImages->currentDepthImage->Bind();
}
globalFramebuffers.ldrFBO->Bind();
float jitterTexScale[4] = {};
if( r_renderMode.GetInteger() == RENDERMODE_C64 || r_renderMode.GetInteger() == RENDERMODE_C64_HIGHRES )

View file

@ -361,7 +361,15 @@ void main( PS_IN fragment, out PS_OUT result )
visibility = 0.0;
#if 1
float3 n_C = sampleNormal( t_NormalRoughness, ssP, 0 );
float3 n_W = sampleNormal( t_NormalRoughness, ssP, 0 );
// rotate n_W from world space into view space
float3 n_C;
n_C.x = dot3( rpModelViewMatrixX, n_W );
n_C.y = dot3( rpModelViewMatrixY, n_W );
n_C.z = dot3( rpModelViewMatrixZ, n_W );
n_C = normalize( n_C );
if( length( n_C ) < 0.01 )
{

View file

@ -221,9 +221,9 @@ void main( uint3 globalId : SV_DispatchThreadID )
float3 pixelNormal = t_Normals[pixelPos].xyz;
#endif
// RB: pixelNormal is already in view space but it has to be negated to look correct which is weird
// RB: pixelNormal has to be negated to look correct which is weird
pixelNormal = -normalize( pixelNormal * 2.0 - 1.0 );
//pixelNormal = normalize( mul( float4( pixelNormal, 0 ), g_Ssao.matWorldToView ).xyz );
pixelNormal = normalize( mul( float4( pixelNormal, 0 ), g_Ssao.matWorldToView ).xyz );
float2 pixelClipPos = WindowToClip( pixelPos );
float3 pixelViewPos = ViewDepthToViewPos( pixelClipPos.xy, pixelViewDepth );

View file

@ -34,8 +34,8 @@ If you have questions concerning this license or the applicable additional terms
Texture2D t_BaseColor : register( t0 VK_DESCRIPTOR_SET( 0 ) );
Texture2D t_BlueNoise : register( t1 VK_DESCRIPTOR_SET( 0 ) );
SamplerState samp0 : register(s0 VK_DESCRIPTOR_SET( 1 ) );
SamplerState samp1 : register(s1 VK_DESCRIPTOR_SET( 1 ) ); // blue noise 256
SamplerState s_LinearClamp : register(s0 VK_DESCRIPTOR_SET( 1 ) );
SamplerState s_LinearWrap : register(s1 VK_DESCRIPTOR_SET( 1 ) ); // blue noise 256
struct PS_IN
{
@ -226,9 +226,10 @@ void main( PS_IN fragment, out PS_OUT result )
float2 uvPixelated = floor( fragment.position.xy / RESOLUTION_DIVISOR ) * RESOLUTION_DIVISOR;
float3 quantizationPeriod = _float3( 1.0 / NUM_COLORS );
float3 quantDeviation = Deviation( palette );
// get pixellated base color
float3 color = t_BaseColor.Sample( samp0, uvPixelated * rpWindowCoord.xy ).rgb;
float3 color = t_BaseColor.Sample( s_LinearClamp, uvPixelated * rpWindowCoord.xy ).rgb;
float2 uvDither = uvPixelated;
//if( rpJitterTexScale.x > 1.0 )
@ -259,7 +260,7 @@ void main( PS_IN fragment, out PS_OUT result )
// dithered quantized
color = HSVToRGB( float3( uv.x, 1.0, ( uv.y - 0.125 ) * 16.0 ) );
color.rgb += float3( dither, dither, dither ) * quantizationPeriod;
color.rgb += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
color = LinearSearch( color, palette );
result.color = float4( color, 1.0 );
@ -269,11 +270,16 @@ void main( PS_IN fragment, out PS_OUT result )
{
color = _float3( uv.x );
color = floor( color * NUM_COLORS ) * ( 1.0 / ( NUM_COLORS - 1.0 ) );
color += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
color = LinearSearch( color.rgb, palette );
result.color = float4( color, 1.0 );
return;
}
#endif
//color.rgb += float3( dither, dither, dither ) * quantizationPeriod;
color.rgb += float3( dither, dither, dither ) * Deviation( palette ) * rpJitterTexScale.y;
color.rgb += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
// find closest color match from C64 color palette
color = LinearSearch( color.rgb, palette );

View file

@ -315,28 +315,6 @@ float3 ditherRGB( float2 fragPos, float3 quantDeviation )
return float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
}
float2 cubeProject( float3 p )
{
float2 x = p.zy;
float2 y = p.xz;
float2 z = p.xy;
//select face
p = abs( p );
if( p.x > p.y && p.x > p.z )
{
return x;
}
else if( p.y > p.x && p.y > p.z )
{
return y;
}
else
{
return z;
}
}
void main( PS_IN fragment, out PS_OUT result )
{
#if 0
@ -646,6 +624,18 @@ void main( PS_IN fragment, out PS_OUT result )
RGB( 154, 158, 63 ),
};
#elif 0
// Hollow
// https://lospec.com/palette-list/hollow
const float3 palette[NUM_COLORS] = // 4
{
RGB( 15, 15, 27 ),
RGB( 86, 90, 117 ),
RGB( 198, 183, 190 ),
RGB( 250, 251, 246 ),
};
#else
// https://lospec.com/palette-list/2bit-demichrome
@ -666,7 +656,7 @@ void main( PS_IN fragment, out PS_OUT result )
float3 quantDeviation = Deviation( palette );
// get pixellated base color
float3 color = t_BaseColor.Sample( s_LinearClamp, uvPixelated * rpWindowCoord.xy ).rgb;
float4 color = t_BaseColor.Sample( s_LinearClamp, uvPixelated * rpWindowCoord.xy );
float2 uvDither = uvPixelated;
//if( rpJitterTexScale.x > 1.0 )
@ -678,40 +668,40 @@ void main( PS_IN fragment, out PS_OUT result )
#if 0
if( uv.y < 0.0625 )
{
color = HSVToRGB( float3( uv.x, 1.0, uv.y * 16.0 ) );
color.rgb = HSVToRGB( float3( uv.x, 1.0, uv.y * 16.0 ) );
result.color = float4( color, 1.0 );
result.color = float4( color.rgb, 1.0 );
return;
}
else if( uv.y < 0.125 )
{
// quantized
color = HSVToRGB( float3( uv.x, 1.0, ( uv.y - 0.0625 ) * 16.0 ) );
color = LinearSearch( color, palette );
color.rgb = HSVToRGB( float3( uv.x, 1.0, ( uv.y - 0.0625 ) * 16.0 ) );
color.rgb = LinearSearch( color.rgb, palette );
result.color = float4( color, 1.0 );
result.color = float4( color.rgb, 1.0 );
return;
}
else if( uv.y < 0.1875 )
{
// dithered quantized
color = HSVToRGB( float3( uv.x, 1.0, ( uv.y - 0.125 ) * 16.0 ) );
color.rgb = HSVToRGB( float3( uv.x, 1.0, ( uv.y - 0.125 ) * 16.0 ) );
color.rgb += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
color = LinearSearch( color, palette );
color.rgb = LinearSearch( color.rgb, palette );
result.color = float4( color, 1.0 );
result.color = float4( color.rgb, 1.0 );
return;
}
else if( uv.y < 0.25 )
{
color = _float3( uv.x );
color = floor( color * NUM_COLORS ) * ( 1.0 / ( NUM_COLORS - 1.0 ) );
color.rgb = _float3( uv.x );
color.rgb = floor( color.rgb * NUM_COLORS ) * ( 1.0 / ( NUM_COLORS - 1.0 ) );
color.rgb += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
color = LinearSearch( color, palette );
color.rgb = LinearSearch( color.rgb, palette );
result.color = float4( color, 1.0 );
result.color = float4( color.rgb, 1.0 );
return;
}
#endif
@ -720,10 +710,21 @@ void main( PS_IN fragment, out PS_OUT result )
color.rgb += float3( dither, dither, dither ) * quantDeviation * rpJitterTexScale.y;
// find closest color match from CPC color palette
color = LinearSearch( color.rgb, palette );
color.rgb = LinearSearch( color.rgb, palette );
#if 1
#if 0
//
// similar to Obra Dinn
//
// don't post process the hands, which were drawn with alpha = 0
if( color.a == 0.0 )
{
result.color = float4( color.rgb, 1.0 );
return;
}
// triplanar mapping based on reconstructed depth buffer
@ -765,13 +766,13 @@ void main( PS_IN fragment, out PS_OUT result )
float2 uvY = worldPos.xz; // y facing plane
float2 uvZ = worldPos.xy; // z facing plane
#if 0
uvX = abs( uvX );
uvY = abs( uvY );
uvZ = abs( uvZ );
#if 1
uvX = abs( uvX );// + 1.0;
uvY = abs( uvY );// + 1.0;
uvZ = abs( uvZ );// + 1.0;
#endif
#if 0
#if 1
uvX *= 4.0;
uvY *= 4.0;
uvZ *= 4.0;
@ -793,6 +794,24 @@ void main( PS_IN fragment, out PS_OUT result )
float3 triblend = saturate( pow( worldNormal, 4.0 ) );
triblend /= max( dot( triblend, float3( 1, 1, 1 ) ), 0.0001 );
#if 1
// change from simple triplanar blending to cubic projection
// which handles diagonal geometry way better
if( ( abs( worldNormal.x ) > abs( worldNormal.y ) ) && ( abs( worldNormal.x ) > abs( worldNormal.z ) ) )
{
triblend = float3( 1, 0, 0 ); // X axis
}
else if( ( abs( worldNormal.z ) > abs( worldNormal.x ) ) && ( abs( worldNormal.z ) > abs( worldNormal.y ) ) )
{
triblend = float3( 0, 0, 1 ); // Z axis
}
else
{
triblend = float3( 0, 1, 0 ); // Y axis
}
#endif
#if 0
// preview blend
result.color = float4( triblend.xyz, 1.0 );
@ -807,29 +826,34 @@ void main( PS_IN fragment, out PS_OUT result )
uvZ.x *= -axisSign.z;
#endif
//result.color = float4( suv.xy, 0.0, 1.0 );
//return;
// FIXME get pixellated base color or not
//float2 pixelatedUVX = floor( uvX / RESOLUTION_DIVISOR ) * RESOLUTION_DIVISOR;
//float2 pixelatedUVY = floor( uvY / RESOLUTION_DIVISOR ) * RESOLUTION_DIVISOR;
//float2 pixelatedUVZ = floor( uvZ / RESOLUTION_DIVISOR ) * RESOLUTION_DIVISOR;
// FIXME get pixellated base color
//color = t_BaseColor.Sample( s_LinearClamp, uvPixelated * rpWindowCoord.xy ).rgb;
color = t_BaseColor.Sample( s_LinearClamp, uv ).rgb;
//float3 pixelatedColor = colX * triblend.x + colY * triblend.y + colZ * triblend.z;
//
//float2 uvPixelated = floor( fragment.position.xy / RESOLUTION_DIVISOR ) * RESOLUTION_DIVISOR;
float3 colX = ditherRGB( uvX, quantDeviation ) * 2.0;
float3 colY = ditherRGB( uvY, quantDeviation ) * 2.0;
float3 colZ = ditherRGB( uvZ, quantDeviation ) * 2.0;
color.rgb = t_BaseColor.Sample( s_LinearClamp, uvPixelated * rpWindowCoord.xy ).rgb;
//color = t_BaseColor.Sample( s_LinearClamp, uv ).rgb;
float3 colX = ditherRGB( uvX, quantDeviation ) * 1.0;
float3 colY = ditherRGB( uvY, quantDeviation ) * 1.0;
float3 colZ = ditherRGB( uvZ, quantDeviation ) * 1.0;
float3 dither3D = colX * triblend.x + colY * triblend.y + colZ * triblend.z;
color.rgb += dither3D;
// find closest color match from CPC color palette
color = LinearSearch( color.rgb, palette );
color.rgb = LinearSearch( color.rgb, palette );
#if 0
float2 uvC = cubeProject( abs( worldPos ) );
color.rgb = _float3( DitherArray8x8( uvC ) - 0.5 );
#endif
#if 1
#if 0
colX = _float3( DitherArray8x8( uvX ) - 0.5 );
colY = _float3( DitherArray8x8( uvY ) - 0.5 );
colZ = _float3( DitherArray8x8( uvZ ) - 0.5 );
@ -859,5 +883,5 @@ void main( PS_IN fragment, out PS_OUT result )
#endif // cubic mapping
//color.rgb = float3( suv.xy * 0.5 + 0.5, 1.0 );
result.color = float4( color, 1.0 );
result.color = float4( color.rgb, 1.0 );
}