You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#lockdown nick.penwarden ========================== MAJOR FEATURES + CHANGES ========================== Change 2967522 on 2016/05/05 by Martin.Mittring fixed UE-30208 Ensure taking high resolution screenshot renamed cvar from r.SaveUncompressedEXRFrame to r.SaveEXR.CompressionQuality and change meaning Change 2967541 on 2016/05/05 by Martin.Mittring added cvar help entry to the editor menu Change 2967544 on 2016/05/05 by Martin.Mittring * added ensures to track down UE-22073 [CrashReport] Crash when changing Editor Window Size - FDeferredShadingSceneRenderer::ClearTranslucentVolumeLighting() * fixed typo * improved r.DisplayInternals Change 2967685 on 2016/05/05 by Rolando.Caloca DR - Fix 2013 compile #jira UE-30369 Change 2967883 on 2016/05/05 by Olaf.Piesche Making inherit rotation work for mesh particles #jira UE-30153 Change 2967948 on 2016/05/05 by Daniel.Wright MaterialParameterCollections now create default resources (uniform buffers) which are used when no valid FScene is present (eg DrawTile while exporting materials to lightmass) Change 2967954 on 2016/05/05 by Daniel.Wright New refraction mode 'Pixel Normal Offset', which uses the difference between the per-pixel normal and the per-vertex normal to compute the refraction offset. This is useful for refraction from large water surfaces without reading outside of screen bounds as much. Change 2967970 on 2016/05/05 by Olaf.Piesche Improvement for depth buffer collision; reduce tunneling by sampling midpoint instead of predicted position. #jira UE-27297 Change 2968125 on 2016/05/05 by Daniel.Wright Hopeful fix for mac compile error with enum Change 2968126 on 2016/05/05 by Daniel.Wright Forward declare to fix compile error Change 2969070 on 2016/05/06 by Martin.Mittring fixed Clang Compile error Change 2969224 on 2016/05/06 by Martin.Mittring fixed Clang Change 2969275 on 2016/05/06 by Rolando.Caloca DR - Fix for simulation time from BP not matching material editor expression time #jira UE-26431 Change 2969413 on 2016/05/06 by Daniel.Wright Simple forward shading path * Support for a directional light in the base pass, which can be shadowed either by distance field shadowmaps or a single shadow factor from the Indirect Lighting Cache * Binding and outputting to GBuffers is disabled when using simple forward shading, along with dependencies of the GBuffers * Specular, normal maps and the 3rd SH band of skylighting are all hardcoded off. Materials are forced fully rough. * Enabled with 'r.SimpleForwardShading 1', which can be changed at runtime * Added r.SupportSimpleForwardShading, which determines if the necessary shaders are compiled * Removed r.SimpleDynamicLighting, whose functionality (unshadowed directional light in the base pass) is a subset of simple forward shading, and was unused Change 2969414 on 2016/05/06 by Daniel.Wright Added cvar 'r.Fog' for scalability Change 2969415 on 2016/05/06 by Daniel.Wright Low end scalability setup for Paragon Change 2969583 on 2016/05/06 by Daniel.Wright Effectively disabled the WRITES_PRECSHADOWFACTOR_TO_GBUFFER optimization, as all combinations use the GBuffer target * This fixes bSingleSampleShadowFromStationaryLights which was broken in cl 2863775 when selective GBuffer outputs was enabled Change 2969597 on 2016/05/06 by Olaf.Piesche Adding emitter tick times to Cascade viewport overlays #jira UE-25172 Change 2969599 on 2016/05/06 by Daniel.Wright Added r.Shadow.ForceSingleSampleShadowingFromStationary for scalability Change 2969795 on 2016/05/06 by Daniel.Wright Made r.SimpleForwardShading a scalability cvar Change 2969796 on 2016/05/06 by Daniel.Wright Enabled simple forward shading for the lowest shadow quality in Paragon * Moved Orion.Character.NonLocalHeroPreshadows to be under shadow quality * Enabling r.Shadow.ForceSingleSampleShadowingFromStationary when shadows are disabled through r.ShadowQuality Change 2972338 on 2016/05/10 by Martin.Mittring Added ImageValidator V0.11 to Perforce (for automated screenshot comparison) Change 2972450 on 2016/05/10 by Martin.Mittring fixed sorting issues, added column sort Change 2972564 on 2016/05/10 by Martin.Mittring fixed PixelCountToFail Change 2972572 on 2016/05/10 by Martin.Mittring added color Change 2972667 on 2016/05/10 by Daniel.Wright Capsule shadows support an off-center projection - fixes stereo rendering Indirect lighting cache is updated for primitives with a visible indirect capsule shadow - fixes indirect shadows disappearing when the caster is off-screen in the Static skylight case Change 2972687 on 2016/05/10 by Martin.Mittring split data from view Change 2972713 on 2016/05/10 by Martin.Mittring background validation Change 2972742 on 2016/05/10 by Martin.Mittring do not lock files in folder Change 2972837 on 2016/05/10 by Daniel.Wright Comment for tiled reflection culling edge failure case Change 2972891 on 2016/05/10 by Daniel.Wright Simple forward shading only supported on PC now Change 2972927 on 2016/05/10 by Martin.Mittring fixed comparison, added directory watcher Change 2972952 on 2016/05/10 by Martin.Mittring tooltips Change 2972965 on 2016/05/10 by Martin.Mittring readme Change 2972986 on 2016/05/10 by Martin.Mittring polish Change 2973015 on 2016/05/10 by Zabir.Hoque Clamp max cubemap resolutions for reflection capture component. Change 2973067 on 2016/05/10 by Uriel.Doyon Removed temporary streaming data from ULevel. Now the data goes directly in FStreamingManagerTexture. Removed deprecated classes and structures associated with old data. Uniformized dynamic primitives and static primitives streaming logic. Static primitive instances are now bound to level component and have visibility information. MeshTexCoordSize Debug now shows live update when tweaking "StreamingDistanceMultiplier" Change 2973129 on 2016/05/10 by Martin.Mittring fixed crash (uninit var) Change 2973167 on 2016/05/10 by Olaf.Piesche Fixing mac compiler warnings; removed beam tangent from particle source and target, as it's treated separately anyway. Change 2973654 on 2016/05/11 by Gil.Gribb FIxed bad resolve from main merge Change 2973787 on 2016/05/11 by Simon.Tovey PR #2080: Added 7 additional blueprint nodes and assoicated functions to Particle System Compoenent (Contributed by alwintom) #2080 Change 2973794 on 2016/05/11 by Simon.Tovey GitHub 1646 : Increase Wireframe Linear Color Value for Particles in Cascade Preview viewport #1646 Change 2973814 on 2016/05/11 by Chris.Bunner Fixed D3D warning. Change 2973868 on 2016/05/11 by Martin.Mittring fixed compiler warning Change 2974104 on 2016/05/11 by Uriel.Doyon Optimized TextureStreaming ASync task by improving cache efficency. Removed ForcedFullyLoad texture sets and merged them with the other entries (to prevent checking in two data structures). Change 2974163 on 2016/05/11 by Uriel.Doyon Fixed Editor Build Change 2974263 on 2016/05/11 by Olaf.Piesche Fix for particle beam source/target selection Change 2974313 on 2016/05/11 by Martin.Mittring nicer icon Change 2974632 on 2016/05/11 by Martin.Mittring zoom (mouse wheel) and pan support Change 2974651 on 2016/05/11 by Martin.Mittring UE-30565 Blend Radius does not override Priority for blendable post process material array #test:PC Change 2974994 on 2016/05/12 by Uriel.Doyon Fixed uninitialized members in texture streaming when updating dynamic primitives. #jira UE-30632 Change 2975514 on 2016/05/12 by Olaf.Piesche Getting mesh particle transform down to pixel shader, making available in TransformVector/TransformPosition nodes #udn 288158, and requests from several artists Change 2975970 on 2016/05/12 by Zabir.Hoque Enable setting high precision normals/tangets as a part of static mesh import. Change 2976134 on 2016/05/12 by Daniel.Wright Moved RHI prefix out of command list macros so you can find callers in a Find in Files for RHIBlendState, etc Change 2976135 on 2016/05/12 by Daniel.Wright Added material property bAllowNegativeEmissiveColor which is useful when rendering to an offscreen render target Change 2976139 on 2016/05/12 by Daniel.Wright Blueprint can now be used to draw to a TextureRenderTarget2D with DrawMaterialToRenderTarget Canvas can now draw to a TextureRenderTarget2D in a Blueprint with BeginDrawCanvasToRenderTarget / EndDrawCanvasToRenderTarget Change 2976199 on 2016/05/12 by Brian.Karis Improved screen space ray cast intersection heuristic. Change 2976203 on 2016/05/12 by Brian.Karis Fixed hair NaNs Change 2976214 on 2016/05/12 by Zabir.Hoque Fix compiler error on Clang Change 2976239 on 2016/05/12 by Brian.Karis Improved hair shadows Change 2976240 on 2016/05/12 by Brian.Karis Made recompileshaders specific file work again. Kind of hacky but better than nothing Change 2976290 on 2016/05/12 by Zabir.Hoque Few more clang compiler fixes. #jira UE-30713 Change 2976517 on 2016/05/13 by Zabir.Hoque Final set of fixes for compile breaks. Change 2976535 on 2016/05/13 by Zabir.Hoque Fix mono builds Change 2977270 on 2016/05/13 by Zabir.Hoque Incorrectly used 7 as max texcoords. Corrected to #define MAX_TEX_COORDS #lockdown gil.gribb Change 2980140 on 2016/05/17 by Gil.Gribb Merging //UE4/Dev-Main@2980127 to Dev-Rendering (//UE4/Dev-Rendering) #lockdown nick.penwarden Change 2980211 on 2016/05/17 by Ben.Marsh EC: Build DDC in Dev-Rendering every 3 hours. #lockdown Gil.Gribb Change 2980876 on 2016/05/17 by Michael.Trepka Metal shader compile fix #lockdown gil.gribb [CL 2981788 by Gil Gribb in Main branch]
539 lines
19 KiB
Plaintext
539 lines
19 KiB
Plaintext
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "Common.usf"
|
|
|
|
// 0:reference (slower, potentially higher quality) 1:use mips of the HZB depth (better performance)
|
|
#define USE_HZB 1
|
|
|
|
#define SCALAR_BRANCHLESS 0
|
|
#define VECTORIZED_BRANCHLESS 0
|
|
#define VECTORIZED_EARLY_OUT 1
|
|
|
|
#if USE_HZB
|
|
#define HZB_LEVEL_OFFSET 1.0
|
|
#else
|
|
#define HZB_LEVEL_OFFSET 0.0
|
|
#endif
|
|
|
|
float4 HZBUvFactorAndInvFactor;
|
|
|
|
float4 SampleDepthTexture( Texture2D Texture, SamplerState Sampler, float Level, float4 SampleUV0, float4 SampleUV1 )
|
|
{
|
|
float4 SampleDepth;
|
|
#if USE_HZB
|
|
// SampleUV{0,1}.{xy,zw} should already be in the HZB UV frame using HZBUvFactorAndInvFactor.xy
|
|
SampleDepth.x = Texture2DSampleLevel( Texture, Sampler, SampleUV0.xy, Level ).r;
|
|
SampleDepth.y = Texture2DSampleLevel( Texture, Sampler, SampleUV0.zw, Level ).r;
|
|
SampleDepth.z = Texture2DSampleLevel( Texture, Sampler, SampleUV1.xy, Level ).r;
|
|
SampleDepth.w = Texture2DSampleLevel( Texture, Sampler, SampleUV1.zw, Level ).r;
|
|
#else
|
|
SampleDepth.x = Texture2DSampleLevel( SceneDepthTexture, SceneDepthTextureSampler, SampleUV0.xy, 0 ).r;
|
|
SampleDepth.y = Texture2DSampleLevel( SceneDepthTexture, SceneDepthTextureSampler, SampleUV0.zw, 0 ).r;
|
|
SampleDepth.z = Texture2DSampleLevel( SceneDepthTexture, SceneDepthTextureSampler, SampleUV1.xy, 0 ).r;
|
|
SampleDepth.w = Texture2DSampleLevel( SceneDepthTexture, SceneDepthTextureSampler, SampleUV1.zw, 0 ).r;
|
|
#endif
|
|
return SampleDepth;
|
|
}
|
|
|
|
void RayCast(
|
|
Texture2D Texture, SamplerState Sampler, float2 TextureSize,
|
|
float3 RayOriginTranslatedWorld, float3 RayDirection,
|
|
float Roughness, float ConeAngleWorld, float SceneDepth,
|
|
int NumSteps, float StepOffset,
|
|
out float4 OutHitUVzTime,
|
|
out float OutLevelHCB
|
|
)
|
|
{
|
|
// TODO provide RayStartUVz
|
|
const float4 RayStartV = mul( float4( RayOriginTranslatedWorld, 1 ), View.TranslatedWorldToView );
|
|
const float4 RayDirV = mul(float4(RayDirection * SceneDepth, 0), View.TranslatedWorldToView);
|
|
const float4 RayEndV = RayStartV + RayDirV;
|
|
|
|
const float RayEndRadiusV = length(RayDirV.xyz) * tan(ConeAngleWorld * 0.4);
|
|
const float2 RayEndBorderV = RayEndV.xy + RayEndRadiusV / sqrt(2.0);
|
|
|
|
const float4 RayStartClip = mul( RayStartV, View.ViewToClip );
|
|
const float4 RayEndClip = mul( RayEndV, View.ViewToClip );
|
|
const float2 RayEndBorderClip = mul(float4(RayEndBorderV, RayEndV.zw), View.ViewToClip).xy;
|
|
|
|
const float3 RayStartScreen = RayStartClip.xyz / RayStartClip.w;
|
|
const float3 RayEndScreen = RayEndClip.xyz / RayEndClip.w;
|
|
const float2 RayEndBorderScreen = RayEndBorderClip.xy / RayEndClip.w;
|
|
|
|
float4 RayDepthClip = RayStartClip + mul( float4( 0, 0, SceneDepth, 0 ), View.ViewToClip );
|
|
float3 RayDepthScreen = RayDepthClip.xyz / RayDepthClip.w;
|
|
|
|
float3 RayStepScreen = RayEndScreen - RayStartScreen;
|
|
float2 RayStepRadiusScreen = RayEndBorderScreen - RayEndScreen.xy;
|
|
|
|
{
|
|
// Computes the scale down factor for RayStepScreen required to fit on the X and Y axis in order to clip it in the viewport
|
|
const float RayStepScreenInvFactor = 0.5 * length( RayStepScreen.xy );
|
|
const float2 AbsRayStepScreen = abs(RayStepScreen.xy);
|
|
const float2 S = (AbsRayStepScreen - max(abs(RayStepScreen.xy + RayStartScreen.xy * RayStepScreenInvFactor) - RayStepScreenInvFactor, 0.0f)) / AbsRayStepScreen;
|
|
|
|
// Rescales RayStepScreen accordingly
|
|
const float RayStepFactor = min(S.x, S.y) / RayStepScreenInvFactor;
|
|
|
|
RayStepScreen *= RayStepFactor;
|
|
RayStepRadiusScreen *= RayStepFactor;
|
|
}
|
|
|
|
const float2 HzbSize = float2(1024, 512);
|
|
#if USE_HZB
|
|
float3 RayStartUVz = float3( (RayStartScreen.xy * float2( 0.5, -0.5 ) + 0.5) * HZBUvFactorAndInvFactor.xy, RayStartScreen.z );
|
|
float3 RayStepUVz = float3( RayStepScreen.xy * float2( 0.5, -0.5 ) * HZBUvFactorAndInvFactor.xy, RayStepScreen.z );
|
|
float2 RayStepRadiusUV = RayStepRadiusScreen.xy * float2( 0.5, -0.5 ) * HZBUvFactorAndInvFactor.xy;
|
|
#else
|
|
float3 RayStartUVz = float3( (RayStartScreen.xy * float2( 0.5, -0.5 ) + 0.5), RayStartScreen.z );
|
|
float3 RayStepUVz = float3( RayStepScreen.xy * float2( 0.5, -0.5 ), RayStepScreen.z );
|
|
float2 RayStepRadiusUV = RayStepRadiusScreen.xy * float2( 0.5, -0.5 );
|
|
#endif
|
|
const float RayStepRadiusFactor = length(RayStepRadiusUV * TextureSize);
|
|
|
|
const float Step = 1.0 / NumSteps;
|
|
|
|
const float CompareTolerance = abs( RayDepthScreen.z - RayStartScreen.z ) * Step * 4;
|
|
|
|
// avoid bugs with early returns inside of loops on certain platform compilers.
|
|
float4 Result = float4( 0, 0, 0, 1 );
|
|
|
|
#if SCALAR_BRANCHLESS
|
|
|
|
float MinHitTime = 1;
|
|
float LastDiff = 0;
|
|
|
|
float SampleTime = StepOffset * Step + Step;
|
|
|
|
UNROLL
|
|
for( int i = 0; i < NumSteps; i++ )
|
|
{
|
|
float3 SampleUVz = RayStartUVz + RayStepUVz * SampleTime;
|
|
|
|
// Use lower res for farther samples
|
|
float Level = Roughness * (i * 4.0 / NumSteps) + HZB_LEVEL_OFFSET;
|
|
float SampleDepth = Texture.SampleLevel( Sampler, SampleUVz.xy, Level ).r;
|
|
|
|
float DepthDiff = SampleUVz.z - SampleDepth;
|
|
bool Hit = abs( DepthDiff + CompareTolerance ) < CompareTolerance;
|
|
|
|
// Find more accurate hit using line segment intersection
|
|
float TimeLerp = saturate( LastDiff / (LastDiff - DepthDiff) );
|
|
float IntersectTime = SampleTime + TimeLerp * Step - Step;
|
|
float HitTime = Hit ? IntersectTime : 1;
|
|
MinHitTime = min( MinHitTime, HitTime );
|
|
|
|
LastDiff = DepthDiff;
|
|
|
|
SampleTime += Step;
|
|
}
|
|
|
|
float3 HitUVz = RayStartUVz + RayStepUVz * MinHitTime;
|
|
|
|
Result = float4( HitUVz, MinHitTime );
|
|
|
|
#elif VECTORIZED_BRANCHLESS
|
|
|
|
float MinHitTime = 1;
|
|
float LastDiff = 0;
|
|
float Level = HZB_LEVEL_OFFSET;
|
|
|
|
// Vectorized to group fetches
|
|
float4 SampleTime = ( StepOffset + float4( 1, 2, 3, 4 ) ) * Step;
|
|
float4 SampleUV0 = RayStartUVz.xyxy + RayStepUVz.xyxy * SampleTime.xxyy;
|
|
float4 SampleUV1 = RayStartUVz.xyxy + RayStepUVz.xyxy * SampleTime.zzww;
|
|
float4 SampleZ = RayStartUVz.zzzz + RayStepUVz.zzzz * SampleTime;
|
|
|
|
LOOP
|
|
for( int i = 0; i < NumSteps; i += 4 )
|
|
{
|
|
// Use lower res for farther samples
|
|
float4 SampleDepth = SampleDepthTexture( Texture, Sampler, Level, SampleUV0, SampleUV1 );
|
|
|
|
#if 1
|
|
float4 DepthDiff = SampleZ - SampleDepth;
|
|
float4 IntersectTime = ( SampleDepth - RayStartUVz.zzzz ) / RayStepUVz.zzzz;
|
|
|
|
bool4 Hit = abs( DepthDiff + CompareTolerance ) < CompareTolerance;
|
|
|
|
// If hit set to intersect time. If missed set to 1, beyond end of ray
|
|
float4 HitTime = Hit ? IntersectTime : 1;
|
|
|
|
// Take closest hit
|
|
HitTime.xy = min( HitTime.xy, HitTime.zw );
|
|
MinHitTime = min( HitTime.x, HitTime.y );
|
|
#else
|
|
// Line segment intersection
|
|
float4 DepthDiff1 = SampleZ - SampleDepth;
|
|
float4 DepthDiff0 = float4( LastDiff, DepthDiff1.xyz );
|
|
float4 TimeLerp = saturate( DepthDiff0 / (DepthDiff0 - DepthDiff1) );
|
|
float4 IntersectTime = SampleTime + (TimeLerp - 1) / (NumSteps + 1);
|
|
|
|
bool4 Hit = abs( DepthDiff1 + CompareTolerance ) < CompareTolerance;
|
|
|
|
// If hit set to intersect time. If missed set to 1, beyond end of ray
|
|
float4 HitTime = Hit ? IntersectTime : 1;
|
|
|
|
// Take closest hit
|
|
HitTime.xy = min( HitTime.xy, HitTime.zw );
|
|
MinHitTime = min( MinHitTime, min( HitTime.x, HitTime.y ) );
|
|
|
|
LastDiff = DepthDiff1.w;
|
|
#endif
|
|
Level += Roughness * (16.0 / NumSteps);
|
|
|
|
SampleTime += 4.0 / (NumSteps + 1);
|
|
SampleUV0 += RayStepUVz.xyxy * 4.0 / (NumSteps + 1);
|
|
SampleUV1 += RayStepUVz.xyxy * 4.0 / (NumSteps + 1);
|
|
SampleZ += RayStepUVz.zzzz * 4.0 / (NumSteps + 1);
|
|
}
|
|
|
|
float3 HitUVz = RayStartUVz + RayStepUVz * MinHitTime;
|
|
|
|
Result = float4( HitUVz, MinHitTime );
|
|
|
|
#elif 1
|
|
|
|
float LastDiff = 0;
|
|
float Level = HZB_LEVEL_OFFSET;
|
|
|
|
RayStepUVz *= Step;
|
|
float3 RayUVz = RayStartUVz + RayStepUVz * StepOffset;
|
|
|
|
LOOP
|
|
for( int i = 0; i < NumSteps; i += 4 )
|
|
{
|
|
// Vectorized to group fetches
|
|
float4 SampleUV0 = RayUVz.xyxy + RayStepUVz.xyxy * float4( 1, 1, 2, 2 );
|
|
float4 SampleUV1 = RayUVz.xyxy + RayStepUVz.xyxy * float4( 3, 3, 4, 4 );
|
|
float4 SampleZ = RayUVz.zzzz + RayStepUVz.zzzz * float4( 1, 2, 3, 4 );
|
|
|
|
// Use lower res for farther samples
|
|
float4 SampleDepth = SampleDepthTexture( Texture, Sampler, Level, SampleUV0, SampleUV1 );
|
|
|
|
float4 DepthDiff = SampleZ - SampleDepth;
|
|
bool4 Hit = abs( -DepthDiff - CompareTolerance ) < CompareTolerance;
|
|
|
|
BRANCH if( any( Hit ) )
|
|
{
|
|
float DepthDiff0 = DepthDiff[2];
|
|
float DepthDiff1 = DepthDiff[3];
|
|
float MinTime = 3;
|
|
|
|
FLATTEN if( Hit[2] )
|
|
{
|
|
DepthDiff0 = DepthDiff[1];
|
|
DepthDiff1 = DepthDiff[2];
|
|
MinTime = 2;
|
|
}
|
|
FLATTEN if( Hit[1] )
|
|
{
|
|
DepthDiff0 = DepthDiff[0];
|
|
DepthDiff1 = DepthDiff[1];
|
|
MinTime = 1;
|
|
}
|
|
FLATTEN if( Hit[0] )
|
|
{
|
|
DepthDiff0 = LastDiff;
|
|
DepthDiff1 = DepthDiff[0];
|
|
MinTime = 0;
|
|
}
|
|
|
|
// Find more accurate hit using line segment intersection
|
|
float TimeLerp = saturate( DepthDiff0 / (DepthDiff0 - DepthDiff1) );
|
|
float IntersectTime = MinTime + TimeLerp;
|
|
float3 HitUVz = RayUVz + RayStepUVz * IntersectTime;
|
|
|
|
Result = float4( HitUVz, 0.5 );
|
|
break;
|
|
}
|
|
|
|
LastDiff = DepthDiff.w;
|
|
Level += Roughness * (16.0 / NumSteps);
|
|
|
|
RayUVz += 4 * RayStepUVz;
|
|
}
|
|
|
|
#elif 1
|
|
|
|
float Level = HZB_LEVEL_OFFSET;
|
|
|
|
RayStepUVz *= Step;
|
|
float3 RayUVz = RayStartUVz + RayStepUVz * StepOffset;
|
|
|
|
LOOP
|
|
for( uint i = 0; i < NumSteps; i += 4 )
|
|
{
|
|
// Vectorized to group fetches
|
|
float4 SampleUV0 = RayUVz.xyxy + RayStepUVz.xyxy * float4( 1, 1, 2, 2 );
|
|
float4 SampleUV1 = RayUVz.xyxy + RayStepUVz.xyxy * float4( 3, 3, 4, 4 );
|
|
float4 SampleZ = RayUVz.zzzz + RayStepUVz.zzzz * float4( 1, 2, 3, 4 );
|
|
|
|
// Use lower res for farther samples
|
|
float4 SampleDepth = SampleDepthTexture( Texture, Sampler, Level, SampleUV0, SampleUV1 );
|
|
|
|
float4 DepthDiff = SampleZ - SampleDepth;
|
|
bool4 Hit = abs( -DepthDiff - CompareTolerance ) < CompareTolerance;
|
|
|
|
BRANCH if( any( Hit ) )
|
|
{
|
|
float MinTime = 3;
|
|
MinTime = Hit[2] ? 2 : MinTime;
|
|
MinTime = Hit[1] ? 1 : MinTime;
|
|
MinTime = Hit[0] ? 0 : MinTime;
|
|
|
|
float3 HitUVz = RayUVz + RayStepUVz * MinTime;
|
|
|
|
Result = float4( HitUVz, 0.5 );
|
|
break;
|
|
}
|
|
|
|
Level += Roughness * (16.0 / NumSteps);
|
|
RayUVz += 4 * RayStepUVz;
|
|
}
|
|
|
|
#else // VECTORIZED_EARLY_OUT
|
|
|
|
float LastDiff = 0;
|
|
float Level = HZB_LEVEL_OFFSET;
|
|
|
|
float4 SampleTime = ( StepOffset + float4( 1, 2, 3, 4 ) ) * Step;
|
|
|
|
LOOP
|
|
for( int i = 0; i < NumSteps; i += 4 )
|
|
{
|
|
// Vectorized to group fetches
|
|
float4 SampleUV0 = RayStartUVz.xyxy + RayStepUVz.xyxy * SampleTime.xxyy;
|
|
float4 SampleUV1 = RayStartUVz.xyxy + RayStepUVz.xyxy * SampleTime.zzww;
|
|
float4 SampleZ = RayStartUVz.zzzz + RayStepUVz.zzzz * SampleTime;
|
|
|
|
// Use lower res for farther samples
|
|
float4 SampleDepth = SampleDepthTexture( Texture, Sampler, Level, SampleUV0, SampleUV1 );
|
|
|
|
float4 DepthDiff1 = SampleZ - SampleDepth;
|
|
bool4 Hit = abs( -DepthDiff1 - CompareTolerance ) < CompareTolerance;
|
|
|
|
BRANCH if( any( Hit ) )
|
|
{
|
|
// Find more accurate hit using line segment intersection
|
|
float4 DepthDiff0 = float4( LastDiff, DepthDiff1.xyz );
|
|
float4 TimeLerp = saturate( DepthDiff0 / (DepthDiff0 - DepthDiff1) );
|
|
float4 IntersectTime = SampleTime + (TimeLerp - 1) / (NumSteps + 1);
|
|
float4 HitTime = Hit ? IntersectTime : 1;
|
|
|
|
// Take closest hit
|
|
HitTime.xy = min( HitTime.xy, HitTime.zw );
|
|
float MinHitTime = min( HitTime.x, HitTime.y );
|
|
|
|
float3 HitUVz = RayStartUVz + RayStepUVz * MinHitTime;
|
|
|
|
Result = float4( HitUVz, MinHitTime );
|
|
break;
|
|
}
|
|
|
|
LastDiff = DepthDiff1.w;
|
|
Level += Roughness * (16.0 / NumSteps);
|
|
|
|
SampleTime += 4.0 / (NumSteps + 1);
|
|
}
|
|
|
|
#endif
|
|
|
|
#if USE_HZB
|
|
Result.xy *= HZBUvFactorAndInvFactor.zw;
|
|
Result.xy = Result.xy * float2( 2, -2 ) + float2( -1, 1 );
|
|
Result.xy = Result.xy * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz;
|
|
#endif
|
|
|
|
OutHitUVzTime = Result;
|
|
OutLevelHCB = log2(OutHitUVzTime.w * RayStepRadiusFactor) + 1;
|
|
}
|
|
|
|
float4 RayCastCheap( Texture2D Texture, SamplerState Sampler, float3 R, float SceneDepth, float3 PositionTranslatedWorld, float StepOffset )
|
|
{
|
|
// TODO provide RayStartUVz
|
|
|
|
// NOTE could clip ray against frustum planes
|
|
|
|
// TODO use screen position and skip matrix mul
|
|
float4 RayStartClip = mul( float4( PositionTranslatedWorld, 1 ), View.TranslatedWorldToClip );
|
|
float4 RayEndClip = mul( float4( PositionTranslatedWorld + R * SceneDepth, 1 ), View.TranslatedWorldToClip );
|
|
|
|
float3 RayStartScreen = RayStartClip.xyz / RayStartClip.w;
|
|
float3 RayEndScreen = RayEndClip.xyz / RayEndClip.w;
|
|
|
|
// Normalize 2D length
|
|
float3 RayStepScreen = ( RayEndScreen - RayStartScreen ) / length( RayEndScreen.xy - RayStartScreen.xy );
|
|
RayStepScreen *= 0.75;
|
|
|
|
#if USE_HZB
|
|
float3 RayStartUVz = float3( RayStartScreen.xy * float2( 0.5, -0.5 ) + 0.5, RayStartScreen.z );
|
|
float3 RayStepUVz = float3( RayStepScreen.xy * float2( 0.5, -0.5 ), RayStepScreen.z );
|
|
#else
|
|
float3 RayStartUVz = float3( RayStartScreen.xy * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz, RayStartScreen.z );
|
|
float3 RayStepUVz = float3( RayStepScreen.xy * View.ScreenPositionScaleBias.xy, RayStepScreen.z );
|
|
#endif
|
|
|
|
const float Step = 1.0 / (4 + 1);
|
|
|
|
// *2 to get less morie pattern in extreme cases, larger values make object appear not grounded in reflections
|
|
const float CompareTolerance = abs( RayStepUVz.z ) * Step * 2;
|
|
|
|
// Vectorized to group fetches
|
|
float4 SampleTime = ( StepOffset + float4( 1, 2, 3, 4 ) ) * Step;
|
|
float4 SampleUV0 = RayStartUVz.xyxy + RayStepUVz.xyxy * SampleTime.xxyy;
|
|
float4 SampleUV1 = RayStartUVz.xyxy + RayStepUVz.xyxy * SampleTime.zzww;
|
|
float4 SampleZ = RayStartUVz.zzzz + RayStepUVz.zzzz * SampleTime;
|
|
|
|
float4 SampleDepth;
|
|
#if USE_HZB
|
|
SampleDepth.x = Texture2DSampleLevel( Texture, Sampler, SampleUV0.xy, 0 ).r;
|
|
SampleDepth.y = Texture2DSampleLevel( Texture, Sampler, SampleUV0.zw, 0 ).r;
|
|
SampleDepth.z = Texture2DSampleLevel( Texture, Sampler, SampleUV1.xy, 1 ).r;
|
|
SampleDepth.w = Texture2DSampleLevel( Texture, Sampler, SampleUV1.zw, 1 ).r;
|
|
#else
|
|
SampleDepth.x = Texture2DSampleLevel( SceneDepthTexture, SceneDepthTextureSampler, SampleUV0.xy, 0 ).r;
|
|
SampleDepth.y = Texture2DSampleLevel( SceneDepthTexture, SceneDepthTextureSampler, SampleUV0.zw, 0 ).r;
|
|
SampleDepth.z = Texture2DSampleLevel( SceneDepthTexture, SceneDepthTextureSampler, SampleUV1.xy, 0 ).r;
|
|
SampleDepth.w = Texture2DSampleLevel( SceneDepthTexture, SceneDepthTextureSampler, SampleUV1.zw, 0 ).r;
|
|
#endif
|
|
|
|
#if 1
|
|
float4 DepthDiff = SampleZ - SampleDepth;
|
|
float4 IntersectTime = ( SampleDepth - RayStartUVz.zzzz ) / RayStepUVz.zzzz;
|
|
|
|
bool4 Hit = abs( DepthDiff + CompareTolerance ) < CompareTolerance;
|
|
|
|
// If hit set to intersect time. If missed set to 1, beyond end of ray
|
|
float4 HitTime = Hit ? IntersectTime : 1;
|
|
|
|
// Take closest hit
|
|
HitTime.xy = min( HitTime.xy, HitTime.zw );
|
|
float MinHitTime = min( HitTime.x, HitTime.y );
|
|
#else
|
|
// Line segment intersection
|
|
float4 DepthDiff1 = SampleZ - SampleDepth;
|
|
float4 DepthDiff0 = float4( 0, DepthDiff1.xyz );
|
|
float4 TimeLerp = saturate( DepthDiff0 / (DepthDiff0 - DepthDiff1) );
|
|
float4 IntersectTime = SampleTime + (TimeLerp - 1) * Step;
|
|
|
|
bool4 Hit = abs( DepthDiff1 + CompareTolerance ) < CompareTolerance;
|
|
|
|
// If hit set to intersect time. If missed set to 1, beyond end of ray
|
|
float4 HitTime = Hit ? IntersectTime : 1;
|
|
|
|
// Take closest hit
|
|
HitTime.xy = min( HitTime.xy, HitTime.zw );
|
|
float MinHitTime = min( HitTime.x, HitTime.y );
|
|
#endif
|
|
|
|
float3 HitUVz = RayStartUVz + RayStepUVz * MinHitTime;
|
|
|
|
BRANCH
|
|
if( MinHitTime == 1 && RayStepUVz.z < 0 )
|
|
{
|
|
float4 RayInfClip = mul( float4( PositionTranslatedWorld + R * 2000000, 1 ), View.TranslatedWorldToClip );
|
|
float3 RayInfScreen = RayInfClip.xyz / RayInfClip.w;
|
|
float3 RayInfUVz = float3( RayInfScreen.xy * float2( 0.5, -0.5 ) + 0.5, RayInfScreen.z );
|
|
|
|
HitUVz = RayInfUVz;
|
|
MinHitTime = 0.5;
|
|
}
|
|
|
|
#if USE_HZB
|
|
HitUVz.xy = HitUVz.xy = HitUVz.xy * float2( 2, -2 ) + float2( -1, 1 );
|
|
HitUVz.xy = HitUVz.xy * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz;
|
|
#endif
|
|
return float4( HitUVz, MinHitTime );
|
|
}
|
|
|
|
float4 SampleScreenColor( Texture2D Texture, SamplerState Sampler, float3 HitUVz )
|
|
{
|
|
float4 OutColor;
|
|
|
|
#if PREV_FRAME_COLOR
|
|
|
|
#if 0
|
|
// Find previous screen position for hit since color buffer is from last frame
|
|
// TODO combine to single matrix
|
|
float4 HitClip = float4( (HitUVz.xy - View.ScreenPositionScaleBias.wz) / View.ScreenPositionScaleBias.xy, HitUVz.z, 1 );
|
|
float4 HitTranslatedWorld = mul( HitClip, View.ClipToTranslatedWorld );
|
|
|
|
float4 PrevTranslatedWorld = float4( HitTranslatedWorld.xyz + HitTranslatedWorld.w * (View.PrevPreViewTranslation - View.PreViewTranslation), HitTranslatedWorld.w );
|
|
float4 PrevClip = mul( PrevTranslatedWorld, View.PrevTranslatedWorldToClip );
|
|
float2 PrevScreen = PrevClip.xy / PrevClip.w;
|
|
float2 PrevUV = PrevScreen.xy * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz;
|
|
#else
|
|
// Camera motion for pixel (in ScreenPos space).
|
|
float4 ThisClip = float4( (HitUVz.xy - View.ScreenPositionScaleBias.wz) / View.ScreenPositionScaleBias.xy, HitUVz.z, 1 );
|
|
float4 PrevClip = mul( ThisClip, View.ClipToPrevClip );
|
|
float2 PrevScreen = PrevClip.xy / PrevClip.w;
|
|
float2 PrevUV = PrevScreen.xy * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz;
|
|
#endif
|
|
|
|
OutColor.rgb = Texture.SampleLevel( Sampler, PrevUV, 0 ).rgb;
|
|
OutColor.a = 1;
|
|
|
|
// Off screen masking
|
|
float2 Vignette = saturate( abs( PrevScreen ) * 5 - 4 );
|
|
#else
|
|
OutColor.rgb = Texture.SampleLevel( Sampler, HitUVz.xy, 0 ).rgb;
|
|
OutColor.a = 1;
|
|
|
|
// Off screen masking
|
|
float2 HitScreenPos = ( HitUVz.xy - View.ScreenPositionScaleBias.wz ) / View.ScreenPositionScaleBias.xy;
|
|
float2 Vignette = saturate( abs( HitScreenPos ) * 5 - 4 );
|
|
#endif
|
|
|
|
//PrevScreen sometimes has NaNs or Infs. DX11 is protected because saturate turns NaNs -> 0.
|
|
//Do a SafeSaturate so other platforms get the same protection.
|
|
OutColor *= SafeSaturate( 1.0 - dot( Vignette, Vignette ) );
|
|
|
|
// Transform NaNs to black, transform negative colors to black.
|
|
OutColor.rgb = -min(-OutColor.rgb, 0.0);
|
|
|
|
return OutColor;
|
|
}
|
|
|
|
float4 SampleHCBLevel( Texture2D Texture, SamplerState Sampler, float3 HitUVz, float Level )
|
|
{
|
|
float4 OutColor;
|
|
|
|
#if PREV_FRAME_COLOR
|
|
// Find previous screen position for hit since color buffer is from last frame
|
|
// TODO combine to single matrix
|
|
float4 HitClip = float4( (HitUVz.xy - View.ScreenPositionScaleBias.wz) / View.ScreenPositionScaleBias.xy, HitUVz.z, 1 );
|
|
float4 HitTranslatedWorld = mul( HitClip, View.ClipToTranslatedWorld );
|
|
HitTranslatedWorld /= HitTranslatedWorld.w;
|
|
|
|
float3 PrevTranslatedWorld = HitTranslatedWorld.xyz + (View.PrevPreViewTranslation - View.PreViewTranslation);
|
|
float4 PrevClip = mul( float4( PrevTranslatedWorld, 1 ), View.PrevTranslatedWorldToClip );
|
|
float2 PrevScreen = PrevClip.xy / PrevClip.w;
|
|
float2 PrevUV = PrevScreen.xy * View.ScreenPositionScaleBias.xy + View.ScreenPositionScaleBias.wz;
|
|
|
|
OutColor.rgb = Texture.SampleLevel( Sampler, PrevUV * HZBUvFactorAndInvFactor.xy, Level ).rgb;
|
|
OutColor.a = 1;
|
|
|
|
// Off screen masking
|
|
float2 Vignette = saturate( abs( PrevScreen ) * 5 - 4 );
|
|
#else
|
|
OutColor.rgb = Texture.SampleLevel( Sampler, HitUVz.xy * HZBUvFactorAndInvFactor.xy, Level ).rgb;
|
|
OutColor.a = 1;
|
|
|
|
// Off screen masking
|
|
float2 HitScreenPos = ( HitUVz.xy - View.ScreenPositionScaleBias.wz ) / View.ScreenPositionScaleBias.xy;
|
|
float2 Vignette = saturate( abs( HitScreenPos ) * 5 - 4 );
|
|
#endif
|
|
|
|
//PrevScreen sometimes has NaNs or Infs. DX11 is protected because saturate turns NaNs -> 0.
|
|
//Do a SafeSaturate so other platforms get the same protection.
|
|
OutColor *= SafeSaturate( 1.0 - dot( Vignette, Vignette ) );
|
|
|
|
// Transform NaNs to black, transform negative colors to black.
|
|
OutColor.rgb = -min(-OutColor.rgb, 0.0);
|
|
|
|
return OutColor;
|
|
}
|