Hi all,
I'm interested working on screen space reflection because it's the future.
Here the actual code I have, learned from a book :
struct PS_INPUT
{
float4 Position : SV_POSITION;
float3 Normal : NORMAL;
float4 Tangent : TANGENT;
float2 TexCoord : TEXCOORD0;
float4 PosVS : TEXCOORD1;
};
cbuffer PROJECTION_CBUFFER : register( b0 )
{
float4x4 Projection;
float4 PerspectiveValues;
};
cbuffer SSR_CBUFFER : register( b1 )
{
float ViewAngleThreshold;
float EdgeDistThreshold;
float DepthBias;
float ReflectionScale;
};
Texture2D DiffuseMap : register( t0 );
Texture2D DepthMap : register( t1 );
SamplerState LinearSampler : register( s0 );
SamplerState PointSampler : register( s1 );
float ConvertZToLinearDepth( in float DepthValue )
{
return PerspectiveValues.z / (DepthValue - PerspectiveValues.w);
}
float3 PosFromDepth( in float2 uv, in float LinearDepth )
{
return float3( PerspectiveValues.xy * uv * LinearDepth, LinearDepth );
}
static const float PixelSize = 2.0f / 720.0f;
static const int NumSteps = 1280;
float4 main( in PS_INPUT Input ) : SV_TARGET
{
// Normalize the normal.
float3 NormalVS = normalize( Input.Normal );
// Compute the camera to pixel direction.
float3 EyeToPixel = normalize( Input.PosVS.xyz );
// Compute the reflected view direction.
float3 ReflectVS = reflect( EyeToPixel, NormalVS );
// The initial reflection color for the pixel.
float4 ReflectColor = float4( 0.0f, 0.0f, 0.0f, 0.0f );
// Check the angle using threshold.
if( ReflectVS.z >= ViewAngleThreshold )
{
// Fade the reflection as the view angles gets close to the threshold.
float ViewAngleThresholdInv = 1.0f - ViewAngleThreshold;
float ViewAngleFade = clamp( 3.0f * (ReflectVS.z - ViewAngleThreshold) / ViewAngleThresholdInv, 0.0f, 1.0f );
// Transform the View Space Reflection to clip-space.
float3 PosReflectVS = Input.PosVS.xyz + ReflectVS;
float3 PosReflectCS = mul( float4( PosReflectVS, 1.0f ), Projection ).xyz / PosReflectVS.z;
float3 ReflectCS = PosReflectCS - Input.Position.xyz;
// Resize Screen Space Reflection to an appropriate length.
float ReflectScale = PixelSize / length( ReflectCS.xy );
ReflectCS *= ReflectScale;
// Compute the first sampling position in screen-space.
float2 SampPos = float2( 0.5f, -0.5f ) * (Input.Position.xy + ReflectCS.xy) + 0.5f;
// Find each iteration step in screen-space.
float2 Step = ReflectCS.xy * float2( 0.5f, -0.5f );
// Build a plane laying on the reflection vector.
float4 RayPlane;
float3 Right = cross( EyeToPixel, ReflectVS );
RayPlane.xyz = normalize( cross( ReflectVS, Right ) );
RayPlane.w = dot( RayPlane.xyz, Input.PosVS.xyz );
// Iterate over the texture searching for intersection.
for( int CurStep = 0; CurStep < NumSteps; ++CurStep )
{
// Get the current depth.
float CurDepth = DepthMap.SampleLevel( PointSampler, SampPos, 0.0f ).x;
// Reconstruct the position from depth.
float CurDepthLin = ConvertZToLinearDepth( CurDepth );
float3 CurPos = PosFromDepth( Input.Position.xy + ReflectCS.xy * ((float)CurStep + 1.0f), CurDepthLin );
// The intersection happens between two positions on the oposite sides of the plane.
if( RayPlane.w >= dot( RayPlane.xyz, CurPos ) + DepthBias )
{
// Compute the actual position on the ray for the given depth value.
float3 FinalPosVS = Input.PosVS.xyz + (ReflectVS / abs(ReflectVS.z)) * abs(CurDepthLin - Input.PosVS.z + DepthBias);
float2 FinalPosCS = FinalPosVS.xy / PerspectiveValues.xy / FinalPosVS.z;
SampPos = float2( 0.5f, -0.5f ) * FinalPosCS.xy + 0.5f;
// Get the value at the current screen space location.
ReflectColor.rgb = DiffuseMap.SampleLevel( LinearSampler, SampPos, 0.0f ).rgb;
// Fade out samples as they get close to the texture edges.
float EdgeFade = clamp( distance( SampPos, float2( 0.5f, 0.5f ) ) * 2.0f - EdgeDistThreshold, 0.0f, 1.0f );
// Compute the fade value.
ReflectColor.a = min( ViewAngleFade, 1.0f - EdgeFade * EdgeFade );
// Apply the reflection scale.
ReflectColor.a *= ReflectionScale;
// Advance past the final iteration to break the loop.
CurStep = NumSteps;
}
// Advance to the next sample.
SampPos += Step;
}
}
// Return the reflect color.
return ReflectColor;
}
This part is because it's fixed-size for test :
static const float PixelSize = 2.0f / 720.0f;
static const int NumSteps = 1280;
The problem is that cost very a lot.
Does a way exists to have a quality value ?
Thanks