102 lines
3.3 KiB
HLSL
102 lines
3.3 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "/Engine/Private/Common.ush"
|
|
|
|
#define RASTER_MODE_REGULAR 0
|
|
#define RASTER_MODE_JITTER 1
|
|
#define RASTER_MODE_CONSERVATIVE 2
|
|
|
|
#ifndef RASTER_MODE
|
|
#define RASTER_MODE RASTER_MODE_REGULAR
|
|
#endif
|
|
|
|
float4x4 Transform;
|
|
|
|
#if RASTER_MODE == RASTER_MODE_JITTER
|
|
float2 JitterScale;
|
|
#elif RASTER_MODE == RASTER_MODE_CONSERVATIVE
|
|
float2 HalfPixelSize;
|
|
#endif
|
|
|
|
float4 AddPoint(float4 InPos, float4 InAABB)
|
|
{
|
|
if (InPos.w < 0.0f)
|
|
{
|
|
InAABB.xy = min(InAABB.xy, InPos.xy);
|
|
InAABB.zw = max(InAABB.zw, InPos.xy);
|
|
}
|
|
else
|
|
{
|
|
InAABB.xy = min(InAABB.xy, InPos.xy / InPos.w);
|
|
InAABB.zw = max(InAABB.zw, InPos.xy / InPos.w);
|
|
}
|
|
return InAABB;
|
|
}
|
|
|
|
void Main(
|
|
in float3 InPosition : ATTRIBUTE0,
|
|
#if RASTER_MODE == RASTER_MODE_JITTER
|
|
in float2 InJitter : ATTRIBUTE1,
|
|
#elif RASTER_MODE == RASTER_MODE_CONSERVATIVE
|
|
in float2 InPrevNextVertex0 : ATTRIBUTE1,
|
|
in float2 InPrevNextVertex1 : ATTRIBUTE2,
|
|
in float2 InPrevNextVertex2 : ATTRIBUTE3,
|
|
#endif
|
|
out float4 OutPosition : SV_Position
|
|
#if RASTER_MODE == RASTER_MODE_CONSERVATIVE
|
|
,out float4 OutClipPosition : CLIP_POSITION
|
|
,out float4 OutTriangleAABB : TRIANGLE_AABB
|
|
#endif
|
|
)
|
|
{
|
|
#if RASTER_MODE == RASTER_MODE_REGULAR
|
|
|
|
OutPosition = mul(float4(InPosition, 1.0f), Transform);
|
|
|
|
#elif RASTER_MODE == RASTER_MODE_JITTER
|
|
|
|
float4x4 JitteredTransform = Transform;
|
|
JitteredTransform[3].xy += InJitter * JitterScale;
|
|
OutPosition = mul(float4(InPosition, 1.0f), JitteredTransform);
|
|
|
|
#elif RASTER_MODE == RASTER_MODE_CONSERVATIVE
|
|
|
|
// See "GPU Gems 2 Chapter 42. Conservative Rasterization".
|
|
// We construct a slightly bigger triangle by displacing the edges by HalfPixelSize.
|
|
// This new triangle should then conservatively cover all pixels touched by the original triangle.
|
|
// We pass a triangle AABB to the pixel shader to discard false positive pixels.
|
|
|
|
const float3 PrevVertexPos = float3(InPrevNextVertex0.x, InPrevNextVertex0.y, InPrevNextVertex1.x);
|
|
const float3 NextVertexPos = float3(InPrevNextVertex1.y, InPrevNextVertex2.x, InPrevNextVertex2.y);
|
|
|
|
const float4 PrevPosition = mul(float4(PrevVertexPos, 1.0f), Transform);
|
|
const float4 CurrPosition = mul(float4(InPosition, 1.0f), Transform);
|
|
const float4 NextPosition = mul(float4(NextVertexPos, 1.0f), Transform);
|
|
|
|
// Compute the triangle AABB
|
|
OutTriangleAABB = float4(9999999.0f, 9999999.0f, -9999999.0f, -9999999.0f);
|
|
OutTriangleAABB = AddPoint(PrevPosition, OutTriangleAABB);
|
|
OutTriangleAABB = AddPoint(CurrPosition, OutTriangleAABB);
|
|
OutTriangleAABB = AddPoint(NextPosition, OutTriangleAABB);
|
|
OutTriangleAABB += float4(-HalfPixelSize, HalfPixelSize);
|
|
|
|
// Compute equations of the planes through the two edges
|
|
float3 Planes[2];
|
|
Planes[0] = cross(CurrPosition.xyw - PrevPosition.xyw, PrevPosition.xyw);
|
|
Planes[1] = cross(NextPosition.xyw - CurrPosition.xyw, CurrPosition.xyw);
|
|
|
|
// Move the planes by the appropriate semidiagonal
|
|
Planes[0].z -= dot(HalfPixelSize, abs(Planes[0].xy));
|
|
Planes[1].z -= dot(HalfPixelSize, abs(Planes[1].xy));
|
|
|
|
// Compute the intersection point of the planes.
|
|
OutPosition = CurrPosition;
|
|
OutPosition.xyw = cross(Planes[0], Planes[1]);
|
|
OutPosition /= abs(OutPosition.w);
|
|
OutPosition.z = CurrPosition.z / CurrPosition.w; // Keep the depth of the non-dilated vertex. Slightly incorrect, but seems to work.
|
|
|
|
OutClipPosition = OutPosition;
|
|
|
|
#endif
|
|
}
|