mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2025-03-13 22:22:05 +00:00
Started to port SSR code by Mara & McGuire
This commit is contained in:
parent
dc378ec4bf
commit
192742a81b
6 changed files with 278 additions and 12 deletions
|
@ -415,6 +415,10 @@ void idRenderBackend::PrepareStageTexturing( const shaderStage_t* pStage, const
|
|||
SetVertexParm( RENDERPARM_WOBBLESKY_Y, probeMaxs.ToFloatPtr() );
|
||||
SetVertexParm( RENDERPARM_WOBBLESKY_Z, probeCenter.ToFloatPtr() );
|
||||
|
||||
SetVertexParm( RENDERPARM_TEXGEN_0_S, viewDef->probePositions[0].ToFloatPtr() );
|
||||
SetVertexParm( RENDERPARM_TEXGEN_0_T, viewDef->probePositions[1].ToFloatPtr() );
|
||||
SetVertexParm( RENDERPARM_TEXGEN_0_Q, viewDef->probePositions[2].ToFloatPtr() );
|
||||
|
||||
// specular cubemap blend weights
|
||||
renderProgManager.SetUniformValue( RENDERPARM_LOCALLIGHTORIGIN, viewDef->radianceImageBlends.ToFloatPtr() );
|
||||
|
||||
|
@ -5656,6 +5660,19 @@ void idRenderBackend::DrawViewInternal( const viewDef_t* _viewDef, const int ste
|
|||
}
|
||||
|
||||
SetVertexParm( RENDERPARM_PSX_DISTORTIONS, parm );
|
||||
|
||||
// make sure rpWindowCoord is set even without post processing surfaces in the view
|
||||
int x = viewDef->viewport.x1;
|
||||
int y = viewDef->viewport.y1;
|
||||
int w = viewDef->viewport.x2 - viewDef->viewport.x1 + 1;
|
||||
int h = viewDef->viewport.y2 - viewDef->viewport.y1 + 1;
|
||||
|
||||
float windowCoordParm[4];
|
||||
windowCoordParm[0] = 1.0f / w;
|
||||
windowCoordParm[1] = 1.0f / h;
|
||||
windowCoordParm[2] = w;
|
||||
windowCoordParm[3] = h;
|
||||
SetFragmentParm( RENDERPARM_WINDOWCOORD, windowCoordParm ); // rpWindowCoord
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
|
|
|
@ -623,12 +623,13 @@ struct viewDef_t
|
|||
// RB: collect environment probes like lights
|
||||
viewEnvprobe_t* viewEnvprobes;
|
||||
|
||||
// RB: nearest probe for now
|
||||
// RB: nearest 3 probes for now
|
||||
idBounds globalProbeBounds;
|
||||
idRenderMatrix inverseBaseEnvProbeProject; // the matrix for deforming the 'zeroOneCubeModel' to exactly cover the environent probe volume in world space
|
||||
idImage* irradianceImage; // cubemap image used for diffuse IBL by backend
|
||||
idImage* radianceImages[3]; // cubemap image used for specular IBL by backend
|
||||
idVec4 radianceImageBlends; // blending weights
|
||||
idVec4 probePositions[3]; // only used by parallax correction
|
||||
|
||||
Framebuffer* targetRender; // SP: The framebuffer to render to
|
||||
|
||||
|
|
|
@ -551,6 +551,10 @@ static void R_FindClosestEnvironmentProbes()
|
|||
verts[i] = vProbe->parms.origin;
|
||||
}
|
||||
|
||||
tr.viewDef->probePositions->Set( verts[0].x, verts[0].y, verts[0].z, 1 );
|
||||
tr.viewDef->probePositions->Set( verts[1].x, verts[1].y, verts[1].z, 1 );
|
||||
tr.viewDef->probePositions->Set( verts[2].x, verts[2].y, verts[2].z, 1 );
|
||||
|
||||
idVec3 closest = R_ClosestPointPointTriangle( testOrigin, verts[0], verts[1], verts[2] );
|
||||
idVec3 bary;
|
||||
|
||||
|
@ -663,6 +667,10 @@ static void R_FindClosestEnvironmentProbes2()
|
|||
triIndexes[i] = vProbe->index;
|
||||
}
|
||||
|
||||
tr.viewDef->probePositions->Set( verts[0].x, verts[0].y, verts[0].z, 1 );
|
||||
tr.viewDef->probePositions->Set( verts[1].x, verts[1].y, verts[1].z, 1 );
|
||||
tr.viewDef->probePositions->Set( verts[2].x, verts[2].y, verts[2].z, 1 );
|
||||
|
||||
// don't assume tri changed if we just moved inside a triangle and only the indixes switched
|
||||
// because one vertex is closer than before
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2013 Robert Beckebans
|
||||
Copyright (C) 2024 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
@ -35,6 +35,7 @@ Texture2D t_NormalMap : register( t0 VK_DESCRIPTOR_SET( 1 ) );
|
|||
Texture2D t_RadianceCubeMap1 : register( t1 VK_DESCRIPTOR_SET( 1 ) );
|
||||
Texture2D t_RadianceCubeMap2 : register( t2 VK_DESCRIPTOR_SET( 1 ) );
|
||||
Texture2D t_RadianceCubeMap3 : register( t3 VK_DESCRIPTOR_SET( 1 ) );
|
||||
Texture2D t_Depth : register( t4 VK_DESCRIPTOR_SET( 1 ) );
|
||||
|
||||
SamplerState s_Material : register( s0 VK_DESCRIPTOR_SET( 2 ) );
|
||||
SamplerState s_LinearClamp : register( s1 VK_DESCRIPTOR_SET( 2 ) );
|
||||
|
@ -58,6 +59,231 @@ struct PS_OUT
|
|||
// *INDENT-ON*
|
||||
|
||||
|
||||
#if 0
|
||||
float linearDepthTexelFetch( int2 hitPixel )
|
||||
{
|
||||
// Load returns 0 for any value accessed out of bounds
|
||||
return linearizeDepth( t_Depth.Load( int3( hitPixel, 0 ) ).r );
|
||||
}
|
||||
|
||||
// can be either view space or world space depending on rpModelMatrix
|
||||
float3 ReconstructPosition( float2 S, float depth )
|
||||
{
|
||||
// derive clip space from the depth buffer and screen position
|
||||
float2 uv = S * rpWindowCoord.xy;
|
||||
float3 ndc = float3( uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0, depth );
|
||||
float clipW = -rpProjectionMatrixZ.w / ( -rpProjectionMatrixZ.z - ndc.z );
|
||||
|
||||
float4 clip = float4( ndc * clipW, clipW );
|
||||
|
||||
// camera space position
|
||||
float4 csP;
|
||||
csP.x = dot4( rpModelMatrixX, clip );
|
||||
csP.y = dot4( rpModelMatrixY, clip );
|
||||
csP.z = dot4( rpModelMatrixZ, clip );
|
||||
csP.w = dot4( rpModelMatrixW, clip );
|
||||
|
||||
csP.xyz /= csP.w;
|
||||
|
||||
return csP.xyz;
|
||||
}
|
||||
|
||||
/*
|
||||
float3 GetPosition( int2 ssP )
|
||||
{
|
||||
float depth = texelFetch( t_Depth, ssP, 0 ).r;
|
||||
|
||||
// offset to pixel center
|
||||
float3 P = ReconstructPosition( float2( ssP ) + _float2( 0.5 ), depth );
|
||||
|
||||
return P;
|
||||
}
|
||||
*/
|
||||
|
||||
float distanceSquared( float2 a, float2 b )
|
||||
{
|
||||
a -= b;
|
||||
return dot( a, a );
|
||||
}
|
||||
|
||||
void swap( inout float a, inout float b )
|
||||
{
|
||||
float t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
|
||||
#if 0
|
||||
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 );
|
||||
}
|
||||
#endif
|
||||
|
||||
// By Morgan McGuire and Michael Mara at Williams College 2014
|
||||
// Released as open source under the BSD 2-Clause License
|
||||
// http://opensource.org/licenses/BSD-2-Clause
|
||||
|
||||
// Returns true if the ray hit something
|
||||
bool TraceScreenSpaceRay(
|
||||
// Camera-space ray origin, which must be within the view volume
|
||||
float3 csOrig,
|
||||
|
||||
// Unit length camera-space ray direction
|
||||
float3 csDir,
|
||||
|
||||
// Camera space thickness to ascribe to each pixel in the depth buffer
|
||||
float zThickness,
|
||||
|
||||
// Stride samples trades quality for performance
|
||||
float stride,
|
||||
|
||||
// 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,
|
||||
|
||||
// Maximum number of iterations. Higher gives better images but may be slow
|
||||
const float maxSteps,
|
||||
|
||||
// Pixel coordinates of the first intersection with the scene
|
||||
out float2 hitPixel,
|
||||
|
||||
// Camera space location of the ray hit
|
||||
out float3 hitPoint )
|
||||
{
|
||||
// Clip to the near plane
|
||||
//float rayLength = ( ( csOrig.z + csDir.z * cb_maxDistance ) < cb_nearPlaneZ ) ?
|
||||
// ( cb_nearPlaneZ - csOrig.z ) / csDir.z : cb_maxDistance;
|
||||
|
||||
float rayLength = 10000;
|
||||
float3 csEndPoint = csOrig + csDir * rayLength;
|
||||
|
||||
// Project into homogeneous clip space
|
||||
//float4 H0 = mul( float4( csOrig, 1.0f ), viewToTextureSpaceMatrix );
|
||||
|
||||
float4 csPos = float4( csOrig, 1.0 );
|
||||
float4 H0;
|
||||
H0.x = dot4( csPos, rpProjectionMatrixX );
|
||||
H0.y = dot4( csPos, rpProjectionMatrixY );
|
||||
H0.z = dot4( csPos, rpProjectionMatrixZ );
|
||||
H0.w = dot4( csPos, rpProjectionMatrixW );
|
||||
H0.xy *= rpWindowCoord.zw;
|
||||
|
||||
//float4 H1 = mul( float4( csEndPoint, 1.0f ), viewToTextureSpaceMatrix );
|
||||
float4 H1;
|
||||
H1.x = dot4( csPos, rpProjectionMatrixX );
|
||||
H1.y = dot4( csPos, rpProjectionMatrixY );
|
||||
H1.z = dot4( csPos, rpProjectionMatrixZ );
|
||||
H1.w = dot4( csPos, rpProjectionMatrixW );
|
||||
H1.xy *= rpWindowCoord.zw;
|
||||
|
||||
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;
|
||||
|
||||
// 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;
|
||||
|
||||
// Adjust end condition for iteration direction
|
||||
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 < maxSteps ) &&
|
||||
//!intersectsDepthBuffer( sceneZMax, rayZMin, rayZMax ) &&
|
||||
( ( rayZMax < sceneZMax - zThickness ) || ( rayZMin > sceneZMax ) ) &&
|
||||
( 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 );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
float2 GetSampleVector( float3 reflectionVector )
|
||||
{
|
||||
float2 normalizedOctCoord = octEncode( reflectionVector );
|
||||
float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + _float2( 1.0 ) ) * 0.5;
|
||||
|
||||
return normalizedOctCoordZeroOne;
|
||||
}
|
||||
|
||||
void main( PS_IN fragment, out PS_OUT result )
|
||||
{
|
||||
|
@ -84,6 +310,10 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
|
||||
float3 reflectionVector = reflect( globalView, globalNormal );
|
||||
|
||||
float2 octCoord0 = GetSampleVector( reflectionVector );
|
||||
float2 octCoord1 = octCoord0;
|
||||
float2 octCoord2 = octCoord0;
|
||||
|
||||
#if 1
|
||||
// parallax box correction using portal area bounds
|
||||
float hitScale = 0.0;
|
||||
|
@ -108,19 +338,28 @@ void main( PS_IN fragment, out PS_OUT result )
|
|||
float3 hitPoint = rayStart - reflectionVector * hitScale;
|
||||
|
||||
// rpWobbleSkyZ is cubemap center
|
||||
#if 1
|
||||
reflectionVector = hitPoint - rpWobbleSkyZ.xyz;
|
||||
octCoord0 = octCoord1 = octCoord2 = GetSampleVector( reflectionVector );
|
||||
#else
|
||||
// this should look better but only works in the case all 3 probes are in this area bbox
|
||||
octCoord0 = GetSampleVector( hitPoint - rpTexGen0S.xyz );
|
||||
octCoord1 = GetSampleVector( hitPoint - rpTexGen0T.xyz );
|
||||
octCoord2 = GetSampleVector( hitPoint - rpTexGen0Q.xyz );
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
//float4 envMap = t_CubeMap.Sample( samp0, reflectionVector );
|
||||
|
||||
float2 normalizedOctCoord = octEncode( reflectionVector );
|
||||
float2 normalizedOctCoordZeroOne = ( normalizedOctCoord + _float2( 1.0 ) ) * 0.5;
|
||||
|
||||
const float mip = 0;
|
||||
float3 radiance = t_RadianceCubeMap1.SampleLevel( s_LinearClamp, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.x;
|
||||
radiance += t_RadianceCubeMap2.SampleLevel( s_LinearClamp, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.y;
|
||||
radiance += t_RadianceCubeMap3.SampleLevel( s_LinearClamp, normalizedOctCoordZeroOne, mip ).rgb * rpLocalLightOrigin.z;
|
||||
float3 radiance = t_RadianceCubeMap1.SampleLevel( s_LinearClamp, octCoord0, mip ).rgb * rpLocalLightOrigin.x;
|
||||
radiance += t_RadianceCubeMap2.SampleLevel( s_LinearClamp, octCoord1, mip ).rgb * rpLocalLightOrigin.y;
|
||||
radiance += t_RadianceCubeMap3.SampleLevel( s_LinearClamp, octCoord2, mip ).rgb * rpLocalLightOrigin.z;
|
||||
|
||||
result.color = float4( sRGBToLinearRGB( radiance.xyz ), 1.0f ) * fragment.color;
|
||||
// give it a red blood tint
|
||||
//radiance *= float3( 0.5, 0.25, 0.25 );
|
||||
|
||||
// make this really dark although it is already in linear RGB
|
||||
radiance = sRGBToLinearRGB( radiance.xyz );
|
||||
|
||||
result.color = float4( radiance, 1.0f ) * fragment.color;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2024 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
Doom 3 BFG Edition GPL Source Code
|
||||
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
||||
Copyright (C) 2013-2020 Robert Beckebans
|
||||
Copyright (C) 2013-2024 Robert Beckebans
|
||||
|
||||
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
||||
|
||||
|
|
Loading…
Reference in a new issue