259 lines
7.5 KiB
HLSL
259 lines
7.5 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "../../Common.ush"
|
|
#include "Brick.ush"
|
|
#include "Voxel.ush"
|
|
|
|
// *** The following SV_DepthLessEqual support is based on MaterialTemplate.ush implementation: ***
|
|
// Whether to use the hidden d3d11 feature that supports depth writes with ZCull by only pushing into the screen
|
|
//@todo - use for other SM5 platforms
|
|
#define SUPPORTS_CONSERVATIVE_DEPTH_WRITES ((COMPILER_HLSL && FEATURE_LEVEL >= FEATURE_LEVEL_SM5) || COMPILER_PSSL || (COMPILER_METAL && FEATURE_LEVEL >= FEATURE_LEVEL_SM5) || SWITCH_PROFILE || SWITCH_PROFILE_FORWARD)
|
|
|
|
#if SUPPORTS_CONSERVATIVE_DEPTH_WRITES
|
|
|
|
#if COMPILER_HLSL || COMPILER_METAL_SHADER_CONVERTER || COMPILER_METAL || SWITCH_PROFILE || SWITCH_PROFILE_FORWARD
|
|
#define DEPTH_LE_OUTPUT SV_DepthLessEqual
|
|
#elif COMPILER_PSSL
|
|
#define DEPTH_LE_OUTPUT S_DEPTH_LE_OUTPUT
|
|
#else
|
|
#error SUPPORTS_CONSERVATIVE_DEPTH_WRITES enabled for unsupported platform
|
|
#endif
|
|
|
|
#else
|
|
#define DEPTH_LE_OUTPUT SV_DEPTH
|
|
#endif
|
|
|
|
void DrawBricksVS(
|
|
uint VertexID : SV_VertexID,
|
|
uint InstanceID : SV_InstanceID,
|
|
out uint OutBrickOffset : TEXCOORD0,
|
|
out uint OutBounds : TEXCOORD1,
|
|
out float3 RayOrigin : TEXCOORD2,
|
|
out float3 RayDirection : TEXCOORD3,
|
|
out float4 OutPosition : SV_POSITION
|
|
)
|
|
{
|
|
uint LocalBrickID = VertexID / VertsPerBrick;
|
|
InstanceID = InstanceID * BricksPerInstance + LocalBrickID;
|
|
VertexID = VertexID - LocalBrickID * VertsPerBrick;
|
|
|
|
uint NumBricks = GetNumBricks();
|
|
|
|
BRANCH
|
|
if( InstanceID >= NumBricks )
|
|
{
|
|
OutPosition = float4(0,0,0,1);
|
|
OutBrickOffset = 0u;
|
|
OutBounds = 0u;
|
|
RayOrigin = 0;
|
|
RayDirection = 0;
|
|
return;
|
|
}
|
|
|
|
FBrick Brick = BrickBuffer[ InstanceID ];
|
|
|
|
float3 BrickPos;
|
|
float CubeSize;
|
|
DecodeBrickKey( Brick.Key, BrickPos, CubeSize );
|
|
|
|
float3 WorldMin = BrickPos * CubeSize;
|
|
float3 WorldMax = WorldMin + CubeSize;
|
|
|
|
if(1)
|
|
{
|
|
uint2 RootBlock = BlockBuffer.Load2( 8 * Brick.BlockOffset );
|
|
|
|
uint3 BrickMin, BrickMax;
|
|
BlockBounds( RootBlock, BrickMin, BrickMax );
|
|
|
|
BrickMax--;
|
|
|
|
uint BrickBounds;
|
|
BrickBounds = BrickMin.x;
|
|
BrickBounds |= BrickMin.y << 2;
|
|
BrickBounds |= BrickMin.z << 4;
|
|
BrickBounds |= BrickMax.x << 6;
|
|
BrickBounds |= BrickMax.y << 8;
|
|
BrickBounds |= BrickMax.z << 10;
|
|
BrickMax++;
|
|
|
|
OutBounds = BrickBounds;
|
|
|
|
float3 UnitMin = BrickMin * 0.25;
|
|
float3 UnitMax = BrickMax * 0.25;
|
|
|
|
float3 NewWorldMin = lerp( WorldMin, WorldMax, UnitMin );
|
|
float3 NewWorldMax = lerp( WorldMin, WorldMax, UnitMax );
|
|
|
|
WorldMin = NewWorldMin;
|
|
WorldMax = NewWorldMax;
|
|
}
|
|
|
|
OutBrickOffset = Brick.BlockOffset;
|
|
|
|
#if DRAW_RECTS
|
|
float3 Bounds[2] = { WorldMin, WorldMax };
|
|
|
|
// Screen rect from bounds
|
|
float3 RectMin = float3( 1, 1, 1 );
|
|
float3 RectMax = float3( -1, -1, -1 );
|
|
|
|
UNROLL for( uint i = 0; i < 8; i++ )
|
|
{
|
|
float3 PointWorld;
|
|
PointWorld.x = Bounds[ (i >> 0) & 1 ].x;
|
|
PointWorld.y = Bounds[ (i >> 1) & 1 ].y;
|
|
PointWorld.z = Bounds[ (i >> 2) & 1 ].z;
|
|
|
|
float4 PointClip = mul( float4( PointWorld, 1 ), View.TranslatedWorldToClip );
|
|
float3 PointScreen = PointClip.xyz / PointClip.w;
|
|
|
|
RectMin = min( RectMin, PointScreen );
|
|
RectMax = max( RectMax, PointScreen );
|
|
}
|
|
|
|
#if PLATFORM_SUPPORTS_RECT_LIST
|
|
OutPosition.x = VertexID == 1 ? RectMax.x : RectMin.x;
|
|
OutPosition.y = VertexID == 2 ? RectMax.y : RectMin.y;
|
|
OutPosition.z = RectMax.z;
|
|
OutPosition.w = 1;
|
|
#else
|
|
OutPosition.x = VertexID & 1 ? RectMax.x : RectMin.x;
|
|
OutPosition.y = VertexID & 2 ? RectMax.y : RectMin.y;
|
|
OutPosition.z = RectMax.z;
|
|
OutPosition.w = 1;
|
|
#endif
|
|
#else
|
|
bool3 Corner;
|
|
Corner.z = ( VertexID >> 0 ) & 1;
|
|
Corner.y = ( VertexID >> 1 ) & 1;
|
|
Corner.x = ( VertexID >> 2 ) & 1;
|
|
|
|
float3 Position = Corner ? WorldMax : WorldMin;
|
|
|
|
OutPosition = mul( float4( Position, 1 ), View.TranslatedWorldToClip );
|
|
#endif
|
|
|
|
FRay Ray;
|
|
Ray.Origin = View.TranslatedWorldCameraOrigin;
|
|
Ray.Direction = mul( float4( OutPosition.xy, 0, 1 ), View.ClipToTranslatedWorld ).xyz;
|
|
|
|
// Transform to local space
|
|
RayOrigin = Ray.Origin / CubeSize - BrickPos;
|
|
RayDirection = Ray.Direction / CubeSize;
|
|
|
|
//OutPosition.z = 1.0 - InstanceID / 1000000.0;
|
|
}
|
|
|
|
|
|
ENABLE_RE_Z
|
|
void DrawBricksPS(
|
|
in nointerpolation uint BrickOffset : TEXCOORD0,
|
|
in nointerpolation uint BrickBounds : TEXCOORD1,
|
|
in noperspective float3 RayOrigin : TEXCOORD2,
|
|
in noperspective float3 RayDirection : TEXCOORD3,
|
|
in centroid float4 SvPosition : SV_Position,
|
|
out float4 OutColor : SV_Target0,
|
|
out float OutDepth : DEPTH_LE_OUTPUT )
|
|
{
|
|
FRay Ray;
|
|
Ray.Origin = RayOrigin;
|
|
Ray.Direction = RayDirection;
|
|
Ray.Time[0] = 0;
|
|
Ray.Time[1] = 1e24;
|
|
|
|
const float Epsilon = 1e-8;
|
|
float3 Replacement = select( Ray.Direction > 0, Epsilon, -Epsilon );
|
|
Ray.Direction = select( abs( Ray.Direction ) < Epsilon, Replacement, Ray.Direction );
|
|
|
|
#if 0
|
|
OutColor = 0.1;
|
|
#elif 0
|
|
float3 BrickPos = CubePos.xyz;
|
|
float CubeSize = rcp(CubePos.w);
|
|
//float CubeSize = CubePos.w;
|
|
|
|
float3 WorldMin = BrickPos * CubeSize;
|
|
float3 WorldMax = WorldMin + CubeSize;
|
|
|
|
float3 Bounds[2] = { WorldMin, WorldMax };
|
|
|
|
// Ray intersect with box
|
|
float3 InvDir = rcp( Ray.Direction );
|
|
float3 PlaneIntersect0 = ( Bounds[0] - Ray.Origin ) * InvDir;
|
|
float3 PlaneIntersect1 = ( Bounds[1] - Ray.Origin ) * InvDir;
|
|
float3 MinIntersection = min( PlaneIntersect0, PlaneIntersect1 );
|
|
float3 MaxIntersection = max( PlaneIntersect0, PlaneIntersect1 );
|
|
|
|
Ray.Time[0] = max( Ray.Time[0], max3( MinIntersection.x, MinIntersection.y, MinIntersection.z ) );
|
|
Ray.Time[1] = min( Ray.Time[1], min3( MaxIntersection.x, MaxIntersection.y, MaxIntersection.z ) );
|
|
|
|
OutColor = Ray.Time[0] <= Ray.Time[1] ? 0.1 : 0;
|
|
|
|
if( Ray.Time[0] > Ray.Time[1] )
|
|
discard;
|
|
#elif 0
|
|
float3 Bounds[2] = { float3(0,0,0), float3(1,1,1) };
|
|
|
|
// Ray intersect with box
|
|
float3 InvDir = rcp( Ray.Direction );
|
|
float3 PlaneIntersect0 = ( Bounds[0] - Ray.Origin ) * InvDir;
|
|
float3 PlaneIntersect1 = ( Bounds[1] - Ray.Origin ) * InvDir;
|
|
float3 MinIntersection = min( PlaneIntersect0, PlaneIntersect1 );
|
|
float3 MaxIntersection = max( PlaneIntersect0, PlaneIntersect1 );
|
|
|
|
Ray.Time[0] = max( Ray.Time[0], max3( MinIntersection.x, MinIntersection.y, MinIntersection.z ) );
|
|
Ray.Time[1] = min( Ray.Time[1], min3( MaxIntersection.x, MaxIntersection.y, MaxIntersection.z ) );
|
|
|
|
OutColor = Ray.Time[0] <= Ray.Time[1] ? 0.1 : 0;
|
|
|
|
if( Ray.Time[0] > Ray.Time[1] )
|
|
discard;
|
|
#else
|
|
|
|
float3 Bounds[2] = { float3(0,0,0), float3(1,1,1) };
|
|
|
|
{
|
|
uint3 Min, Max;
|
|
Min.x = BitFieldExtractU32( BrickBounds, 2, 0 );
|
|
Min.y = BitFieldExtractU32( BrickBounds, 2, 2 );
|
|
Min.z = BitFieldExtractU32( BrickBounds, 2, 4 );
|
|
Max.x = BitFieldExtractU32( BrickBounds, 2, 6 );
|
|
Max.y = BitFieldExtractU32( BrickBounds, 2, 8 );
|
|
Max.z = BitFieldExtractU32( BrickBounds, 2, 10 );
|
|
Max++;
|
|
|
|
Bounds[0] = Min * 0.25;
|
|
Bounds[1] = Max * 0.25;
|
|
}
|
|
|
|
Ray.Time = Intersect( Ray, Bounds );
|
|
|
|
FRayCastCounters Counters = (FRayCastCounters)0;
|
|
if( Ray.Time[0] < Ray.Time[1] )
|
|
{
|
|
#if VOXEL_NUM_LEVELS == 2
|
|
//Ray.Time[0] = RayCastBrick_L1( Ray, BrickOffset, Counters );
|
|
//Ray.Time[0] = RayCastBrick_L2( Ray, BrickOffset, Counters );
|
|
Ray.Time[0] = RayCastBrick_L2_WhileWhile( Ray, BrickOffset, Counters );
|
|
//Ray.Time[0] = RayCastBrick_L2_Flat( Ray, BrickOffset, Counters );
|
|
#else
|
|
Ray.Time[0] = RayCastBrick_L1( Ray, BrickOffset, Counters );
|
|
#endif
|
|
OutColor.r = Counters.Tests / 20.0;
|
|
OutColor.g = Counters.Steps / 20.0;
|
|
OutColor.g = Counters.StepIn / 10.0;
|
|
OutColor.b = Counters.StepOut / 10.0;
|
|
|
|
OutColor = OutColor.r;
|
|
//OutColor.rgb = VisualizeCount( Counters.StepOut );
|
|
|
|
//OutColor.rgb = frac( Ray.Time[1] / 1000 );
|
|
}
|
|
|
|
OutDepth = View.ViewToClip[3][2] / Ray.Time[0] + View.ViewToClip[2][2];
|
|
|
|
if( Ray.Time[0] >= Ray.Time[1] )
|
|
discard;
|
|
#endif
|
|
} |