Add additional HitNormal feature to Global SDF trace output
This commit is contained in:
@@ -24,6 +24,7 @@ struct GlobalSDFTrace
|
||||
float3 WorldDirection;
|
||||
float MaxDistance;
|
||||
float StepScale;
|
||||
bool NeedsHitNormal;
|
||||
|
||||
void Init(float3 worldPosition, float3 worldDirection, float minDistance, float maxDistance, float stepScale = 1.0f)
|
||||
{
|
||||
@@ -32,12 +33,14 @@ struct GlobalSDFTrace
|
||||
MinDistance = minDistance;
|
||||
MaxDistance = maxDistance;
|
||||
StepScale = stepScale;
|
||||
NeedsHitNormal = false;
|
||||
}
|
||||
};
|
||||
|
||||
// Global SDF ray trace hit information.
|
||||
struct GlobalSDFHit
|
||||
{
|
||||
float3 HitNormal;
|
||||
float HitTime;
|
||||
uint HitCascade;
|
||||
uint StepsCount;
|
||||
@@ -54,13 +57,13 @@ struct GlobalSDFHit
|
||||
};
|
||||
|
||||
// Samples the Global SDF and returns the distance to the closest surface (in world units) at the given world location.
|
||||
float SampleGlobalSDF(const GlobalSDFData data, Texture3D<float> tex[4], float3 worldPosition, uint minCascade = 0)
|
||||
float SampleGlobalSDF(const GlobalSDFData data, Texture3D<float> tex[4], float3 worldPosition)
|
||||
{
|
||||
float distance = data.CascadePosDistance[3].w * 2.0f;
|
||||
if (distance <= 0.0f)
|
||||
return 60000;
|
||||
UNROLL
|
||||
for (uint cascade = minCascade; cascade < 4; cascade++)
|
||||
for (uint cascade = 0; cascade < 4; cascade++)
|
||||
{
|
||||
float4 cascadePosDistance = data.CascadePosDistance[cascade];
|
||||
float cascadeMaxDistance = cascadePosDistance.w * 2;
|
||||
@@ -77,14 +80,14 @@ float SampleGlobalSDF(const GlobalSDFData data, Texture3D<float> tex[4], float3
|
||||
}
|
||||
|
||||
// Samples the Global SDF and returns the gradient vector (derivative) at the given world location. Normalize it to get normal vector.
|
||||
float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<float> tex[4], float3 worldPosition, out float distance, uint minCascade = 0)
|
||||
float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<float> tex[4], float3 worldPosition, out float distance)
|
||||
{
|
||||
float3 gradient = float3(0, 0.00001f, 0);
|
||||
distance = 60000;
|
||||
if (data.CascadePosDistance[3].w <= 0.0f)
|
||||
return gradient;
|
||||
UNROLL
|
||||
for (uint cascade = minCascade; cascade < 4; cascade++)
|
||||
for (uint cascade = 0; cascade < 4; cascade++)
|
||||
{
|
||||
float4 cascadePosDistance = data.CascadePosDistance[cascade];
|
||||
float cascadeMaxDistance = cascadePosDistance.w * 2;
|
||||
@@ -109,19 +112,17 @@ float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<float> tex[4]
|
||||
}
|
||||
|
||||
// Ray traces the Global SDF.
|
||||
GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D<float> tex[4], Texture3D<float> mips[4], const GlobalSDFTrace trace, uint minCascade = 0)
|
||||
GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D<float> tex[4], Texture3D<float> mips[4], const GlobalSDFTrace trace)
|
||||
{
|
||||
GlobalSDFHit hit;
|
||||
GlobalSDFHit hit = (GlobalSDFHit)0;
|
||||
hit.HitTime = -1.0f;
|
||||
hit.HitCascade = 0;
|
||||
hit.StepsCount = 0;
|
||||
float chunkSizeDistance = (float)GLOBAL_SDF_RASTERIZE_CHUNK_SIZE / data.Resolution; // Size of the chunk in SDF distance (0-1)
|
||||
float chunkMarginDistance = (float)GLOBAL_SDF_RASTERIZE_CHUNK_MARGIN / data.Resolution; // Size of the chunk margin in SDF distance (0-1)
|
||||
float nextIntersectionStart = 0.0f;
|
||||
float traceMaxDistance = min(trace.MaxDistance, data.CascadePosDistance[3].w * 2);
|
||||
float3 traceEndPosition = trace.WorldPosition + trace.WorldDirection * traceMaxDistance;
|
||||
UNROLL
|
||||
for (uint cascade = minCascade; cascade < 4 && hit.HitTime < 0.0f; cascade++)
|
||||
for (uint cascade = 0; cascade < 4 && hit.HitTime < 0.0f; cascade++)
|
||||
{
|
||||
float4 cascadePosDistance = data.CascadePosDistance[cascade];
|
||||
float cascadeMaxDistance = cascadePosDistance.w * 2;
|
||||
@@ -173,6 +174,18 @@ GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D<float> tex[4]
|
||||
// Surface hit
|
||||
hit.HitTime = max(stepTime + stepDistance - minSurfaceThickness, 0.0f);
|
||||
hit.HitCascade = cascade;
|
||||
if (trace.NeedsHitNormal)
|
||||
{
|
||||
// Calculate hit normal from SDF gradient
|
||||
float texelOffset = 1.0f / data.Resolution;
|
||||
float xp = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x + texelOffset, cascadeUV.y, cascadeUV.z), 0).x;
|
||||
float xn = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x - texelOffset, cascadeUV.y, cascadeUV.z), 0).x;
|
||||
float yp = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x, cascadeUV.y + texelOffset, cascadeUV.z), 0).x;
|
||||
float yn = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x, cascadeUV.y - texelOffset, cascadeUV.z), 0).x;
|
||||
float zp = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x, cascadeUV.y, cascadeUV.z + texelOffset), 0).x;
|
||||
float zn = tex[cascade].SampleLevel(SamplerLinearClamp, float3(cascadeUV.x, cascadeUV.y, cascadeUV.z - texelOffset), 0).x;
|
||||
hit.HitNormal = normalize(float3(xp - xn, yp - yn, zp - zn));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user