Add additional HitNormal feature to Global SDF trace output
This commit is contained in:
@@ -24,6 +24,7 @@ struct GlobalSDFTrace
|
|||||||
float3 WorldDirection;
|
float3 WorldDirection;
|
||||||
float MaxDistance;
|
float MaxDistance;
|
||||||
float StepScale;
|
float StepScale;
|
||||||
|
bool NeedsHitNormal;
|
||||||
|
|
||||||
void Init(float3 worldPosition, float3 worldDirection, float minDistance, float maxDistance, float stepScale = 1.0f)
|
void Init(float3 worldPosition, float3 worldDirection, float minDistance, float maxDistance, float stepScale = 1.0f)
|
||||||
{
|
{
|
||||||
@@ -32,12 +33,14 @@ struct GlobalSDFTrace
|
|||||||
MinDistance = minDistance;
|
MinDistance = minDistance;
|
||||||
MaxDistance = maxDistance;
|
MaxDistance = maxDistance;
|
||||||
StepScale = stepScale;
|
StepScale = stepScale;
|
||||||
|
NeedsHitNormal = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Global SDF ray trace hit information.
|
// Global SDF ray trace hit information.
|
||||||
struct GlobalSDFHit
|
struct GlobalSDFHit
|
||||||
{
|
{
|
||||||
|
float3 HitNormal;
|
||||||
float HitTime;
|
float HitTime;
|
||||||
uint HitCascade;
|
uint HitCascade;
|
||||||
uint StepsCount;
|
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.
|
// 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;
|
float distance = data.CascadePosDistance[3].w * 2.0f;
|
||||||
if (distance <= 0.0f)
|
if (distance <= 0.0f)
|
||||||
return 60000;
|
return 60000;
|
||||||
UNROLL
|
UNROLL
|
||||||
for (uint cascade = minCascade; cascade < 4; cascade++)
|
for (uint cascade = 0; cascade < 4; cascade++)
|
||||||
{
|
{
|
||||||
float4 cascadePosDistance = data.CascadePosDistance[cascade];
|
float4 cascadePosDistance = data.CascadePosDistance[cascade];
|
||||||
float cascadeMaxDistance = cascadePosDistance.w * 2;
|
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.
|
// 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);
|
float3 gradient = float3(0, 0.00001f, 0);
|
||||||
distance = 60000;
|
distance = 60000;
|
||||||
if (data.CascadePosDistance[3].w <= 0.0f)
|
if (data.CascadePosDistance[3].w <= 0.0f)
|
||||||
return gradient;
|
return gradient;
|
||||||
UNROLL
|
UNROLL
|
||||||
for (uint cascade = minCascade; cascade < 4; cascade++)
|
for (uint cascade = 0; cascade < 4; cascade++)
|
||||||
{
|
{
|
||||||
float4 cascadePosDistance = data.CascadePosDistance[cascade];
|
float4 cascadePosDistance = data.CascadePosDistance[cascade];
|
||||||
float cascadeMaxDistance = cascadePosDistance.w * 2;
|
float cascadeMaxDistance = cascadePosDistance.w * 2;
|
||||||
@@ -109,19 +112,17 @@ float3 SampleGlobalSDFGradient(const GlobalSDFData data, Texture3D<float> tex[4]
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ray traces the Global SDF.
|
// 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.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 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 chunkMarginDistance = (float)GLOBAL_SDF_RASTERIZE_CHUNK_MARGIN / data.Resolution; // Size of the chunk margin in SDF distance (0-1)
|
||||||
float nextIntersectionStart = 0.0f;
|
float nextIntersectionStart = 0.0f;
|
||||||
float traceMaxDistance = min(trace.MaxDistance, data.CascadePosDistance[3].w * 2);
|
float traceMaxDistance = min(trace.MaxDistance, data.CascadePosDistance[3].w * 2);
|
||||||
float3 traceEndPosition = trace.WorldPosition + trace.WorldDirection * traceMaxDistance;
|
float3 traceEndPosition = trace.WorldPosition + trace.WorldDirection * traceMaxDistance;
|
||||||
UNROLL
|
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];
|
float4 cascadePosDistance = data.CascadePosDistance[cascade];
|
||||||
float cascadeMaxDistance = cascadePosDistance.w * 2;
|
float cascadeMaxDistance = cascadePosDistance.w * 2;
|
||||||
@@ -173,6 +174,18 @@ GlobalSDFHit RayTraceGlobalSDF(const GlobalSDFData data, Texture3D<float> tex[4]
|
|||||||
// Surface hit
|
// Surface hit
|
||||||
hit.HitTime = max(stepTime + stepDistance - minSurfaceThickness, 0.0f);
|
hit.HitTime = max(stepTime + stepDistance - minSurfaceThickness, 0.0f);
|
||||||
hit.HitCascade = cascade;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user