119 lines
4.9 KiB
HLSL
119 lines
4.9 KiB
HLSL
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "Common.ush"
|
|
#include "SHCommon.ush"
|
|
#include "VolumetricLightmapShared.ush"
|
|
#include "DeferredShadingCommon.ush"
|
|
|
|
#ifndef QUADS_PER_INSTANCE
|
|
#define QUADS_PER_INSTANCE 0
|
|
#endif
|
|
|
|
struct FVisualizeVolumetricLightmapVSToPS
|
|
{
|
|
nointerpolation float3 BrickUVs : TEXCOORD0;
|
|
nointerpolation float FadeToAmbient : TEXCOORD1;
|
|
nointerpolation float4 CellSphere : TEXCOORD2;
|
|
float3 VertexPosition : TEXCOORD3;
|
|
};
|
|
|
|
float VisualizationRadiusScale;
|
|
float VisualizationMinScreenFraction;
|
|
|
|
void VisualizeVolumetricLightmapVS(
|
|
uint VertexId : SV_VertexID,
|
|
uint InstanceId : SV_InstanceID,
|
|
out FVisualizeVolumetricLightmapVSToPS Output,
|
|
out float4 OutPosition : SV_POSITION
|
|
)
|
|
{
|
|
uint EffectiveInstanceId = InstanceId * QUADS_PER_INSTANCE + VertexId / 4;
|
|
|
|
uint3 NumHighestDensityCells = View.VolumetricLightmapIndirectionTextureSize * View.VolumetricLightmapBrickSize;
|
|
|
|
uint3 CellVector = uint3(
|
|
EffectiveInstanceId % NumHighestDensityCells.x,
|
|
(EffectiveInstanceId / NumHighestDensityCells.x) % NumHighestDensityCells.y,
|
|
EffectiveInstanceId / (NumHighestDensityCells.x * NumHighestDensityCells.y));
|
|
|
|
float3 IndirectionTextureTexelCoordinate = CellVector / View.VolumetricLightmapBrickSize;
|
|
float4 BrickOffsetAndSize = View.VolumetricLightmapIndirectionTexture.Load(int4(IndirectionTextureTexelCoordinate, 0));
|
|
|
|
float PaddedBrickSize = View.VolumetricLightmapBrickSize + 1;
|
|
float3 LocalCellPosition = frac(IndirectionTextureTexelCoordinate / BrickOffsetAndSize.w) * View.VolumetricLightmapBrickSize;
|
|
Output.BrickUVs = (BrickOffsetAndSize.xyz * PaddedBrickSize + LocalCellPosition + .5f) * View.VolumetricLightmapBrickTexelSize;
|
|
|
|
float3 GridLocalCellPosition = round(LocalCellPosition);
|
|
bool bValidCell = all(abs(LocalCellPosition - GridLocalCellPosition) < .01f);
|
|
|
|
Output.CellSphere.xyz = (CellVector / (float3)NumHighestDensityCells - View.VolumetricLightmapWorldToUVAdd) / View.VolumetricLightmapWorldToUVScale;
|
|
float DetailVoxelWorldSize = 1.0f / ((float)View.VolumetricLightmapIndirectionTextureSize.x * View.VolumetricLightmapWorldToUVScale.x);
|
|
// Set visualization sphere radius as a fraction of the corresponding brick's world space size
|
|
Output.CellSphere.w = BrickOffsetAndSize.w * DetailVoxelWorldSize * VisualizationRadiusScale;
|
|
|
|
{
|
|
float DistanceToCamera = length(Output.CellSphere.xyz - DFHackToFloat(PrimaryView.WorldViewOrigin));
|
|
float SizeOnScreen = Output.CellSphere.w * View.ViewToClip[0][0] / DistanceToCamera;
|
|
Output.FadeToAmbient = saturate(SizeOnScreen * 100 - .01f);
|
|
// Maintain a minimum size on screen to reduce aliasing
|
|
SizeOnScreen = max(SizeOnScreen, VisualizationMinScreenFraction * sqrt(BrickOffsetAndSize.w));
|
|
Output.CellSphere.w = SizeOnScreen * DistanceToCamera / View.ViewToClip[0][0];
|
|
}
|
|
|
|
float2 TexCoord = float2(
|
|
((VertexId >> 0) & 1) ? 1.0f : -1.0f,
|
|
((VertexId >> 1) & 1) ? 1.0f : -1.0f);
|
|
|
|
float2 RescaledTexCoord = TexCoord * Output.CellSphere.w * sqrt(2.0);
|
|
|
|
Output.VertexPosition = Output.CellSphere.xyz + RescaledTexCoord.x * View.ViewRight + RescaledTexCoord.y * View.ViewUp;
|
|
OutPosition = mul(float4(Output.VertexPosition, 1), DFHackToFloat(PrimaryView.WorldToClip));
|
|
|
|
if (!bValidCell)
|
|
{
|
|
// This cell is not resident, emit a degenerate triangle
|
|
OutPosition = 0;
|
|
}
|
|
}
|
|
|
|
#define WRITE_TO_SHADING_MODEL (FEATURE_LEVEL >= FEATURE_LEVEL_SM4 && !FORWARD_SHADING)
|
|
|
|
float3 DiffuseColor;
|
|
|
|
void VisualizeVolumetricLightmapPS(
|
|
FVisualizeVolumetricLightmapVSToPS Input,
|
|
out float4 OutColor : SV_Target0
|
|
#if WRITE_TO_SHADING_MODEL
|
|
,out float4 OutGBufferB : SV_Target1
|
|
#endif
|
|
)
|
|
{
|
|
float3 RayDirection = Input.VertexPosition - DFHackToFloat(PrimaryView.WorldViewOrigin);
|
|
float2 SphereIntersections = RayIntersectSphere(DFHackToFloat(PrimaryView.WorldViewOrigin), RayDirection, Input.CellSphere);
|
|
float3 IntersectionPosition = DFHackToFloat(PrimaryView.WorldViewOrigin) + SphereIntersections.x * RayDirection;
|
|
clip(SphereIntersections.x);
|
|
|
|
FThreeBandSHVectorRGB IrradianceSH = GetVolumetricLightmapSH3(Input.BrickUVs);
|
|
|
|
float3 WorldNormal = normalize(IntersectionPosition - Input.CellSphere.xyz);
|
|
FThreeBandSHVector DiffuseTransferSH = CalcDiffuseTransferSH3(WorldNormal, 1);
|
|
float3 SphereLighting = max(float3(0,0,0), DotSH3(IrradianceSH, DiffuseTransferSH)) / PI;
|
|
|
|
float3 AmbientLighting = float3(IrradianceSH.R.V0.x, IrradianceSH.G.V0.x, IrradianceSH.B.V0.x) / PI;
|
|
// Lerp to ambient lighting in the distance to reduce aliasing
|
|
float3 FinalLighting = lerp(AmbientLighting, SphereLighting, Input.FadeToAmbient);
|
|
|
|
FinalLighting *= View.PreExposure;
|
|
|
|
// Use a diffuse color that matches the rest of the scene for LightingOnly and DetailLighting view modes
|
|
float3 EffectiveDiffuseColor = DiffuseColor * View.DiffuseOverrideParameter.w + View.DiffuseOverrideParameter.xyz;
|
|
OutColor = float4(EffectiveDiffuseColor * FinalLighting, 0);
|
|
|
|
//OutColor = float4(WorldNormal, 0);
|
|
|
|
#if WRITE_TO_SHADING_MODEL
|
|
// Shading model unlit
|
|
SetGBufferForUnlit(OutGBufferB);
|
|
|
|
#endif
|
|
} |