engine/dep/include/FidelityFX/gpu/brixelizer/ffx_brixelizer_debug_visualization.h

199 lines
8.6 KiB
C

// This file is part of the FidelityFX SDK.
//
// Copyright (C) 2024 Advanced Micro Devices, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files(the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and /or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFX_BRIXELIZER_DEBUG_VISUALIZATION_H
#define FFX_BRIXELIZER_DEBUG_VISUALIZATION_H
#include "ffx_brixelizer_host_gpu_shared.h"
#define FFX_BRIXELIZER_TRAVERSAL_EPS (GetDebugInfoPreviewSDFSolveEpsilon() / FfxFloat32(8.0))
#include "ffx_brixelizer_trace_ops.h"
// XXX -- tmp
FfxUInt32 FfxBrixelizerGetVoxelCascade(FfxUInt32 voxel_id)
{
return voxel_id >> FFX_BRIXELIZER_CASCADE_ID_SHIFT;
}
#define FLT_INF 1e30f
// By Morgan McGuire @morgan3d, http://graphicscodex.com
// Reuse permitted under the BSD license.
// https://www.shadertoy.com/view/4dsSzr
FfxFloat32x3 FFX_HeatmapGradient(FfxFloat32 t)
{
return clamp((pow(t, 1.5) * 0.8 + 0.2) * FfxFloat32x3(smoothstep(0.0, 0.35, t) + t * 0.5, smoothstep(0.5, 1.0, t), max(1.0 - t * 1.7, t * 7.0 - 6.0)), 0.0, 1.0);
}
// License?
FfxFloat32x3 FFX_RandomColor(FfxFloat32x2 uv) {
uv = ffxFract(uv * FfxFloat32(15.718281828459045));
FfxFloat32x3 seeds = FfxFloat32x3(FfxFloat32(0.123), FfxFloat32(0.456), FfxFloat32(0.789));
seeds = ffxFract((uv.x + FfxFloat32(0.5718281828459045) + seeds) * ((seeds + FFX_MODULO(uv.x, FfxFloat32(0.141592653589793))) * FfxFloat32(27.61803398875) + FfxFloat32(4.718281828459045)));
seeds = ffxFract((uv.y + FfxFloat32(0.5718281828459045) + seeds) * ((seeds + FFX_MODULO(uv.y, FfxFloat32(0.141592653589793))) * FfxFloat32(27.61803398875) + FfxFloat32(4.718281828459045)));
seeds = ffxFract((FfxFloat32(0.5718281828459045) + seeds) * ((seeds + FFX_MODULO(uv.x, FfxFloat32(0.141592653589793))) * FfxFloat32(27.61803398875) + FfxFloat32(4.718281828459045)));
return seeds;
}
FfxFloat32x3 FFX_ViewSpaceToWorldSpace(FfxFloat32x4 view_space_coord)
{
return FFX_TRANSFORM_VECTOR(GetDebugInfoInvView(), view_space_coord).xyz;
}
FfxFloat32x3 FFX_InvProjectPosition(FfxFloat32x3 coord, FfxFloat32x4x4 mat)
{
coord.y = (FfxFloat32(1.0) - coord.y);
coord.xy = FfxFloat32(2.0) * coord.xy - 1;
FfxFloat32x4 projected = FFX_TRANSFORM_VECTOR(mat, FfxFloat32x4(coord, 1));
projected.xyz /= projected.w;
return projected.xyz;
}
FfxFloat32x3 FFX_ScreenSpaceToViewSpace(FfxFloat32x3 screen_uv_coord)
{
return FFX_InvProjectPosition(screen_uv_coord, GetDebugInfoInvProj());
}
FfxFloat32 FFX_HitEdgeDist(FfxFloat32x3 hit, FfxFloat32x3 boxMin, FfxFloat32x3 boxMax)
{
FfxFloat32x3 a = min(abs(hit - boxMin), abs(hit - boxMax));
return min(min(a.x + a.y, a.x + a.z), a.y + a.z);
}
// modified from inigo quilez
FfxFloat32 FFX_BoxHitDist(FfxUInt32x2 tid, FfxFloat32x3 ro, FfxFloat32x3 rd, FfxFloat32x3 boxMin, FfxFloat32x3 boxMax)
{
FfxFloat32x3 halfSize = (boxMax - boxMin) / 2.0f;
FfxFloat32x3 center = boxMin + halfSize;
FfxFloat32x3 rop = ro - center;
FfxFloat32x3 ird = 1.0f / rd;
FfxFloat32x3 n = rop * ird;
FfxFloat32x3 k = abs(ird) * halfSize;
FfxFloat32x3 t1 = -n - k;
FfxFloat32x3 t2 = -n + k;
FfxFloat32 tNear = max(max(t1.x, t1.y), t1.z);
FfxFloat32 tFar = min(min(t2.x, t2.y), t2.z);
if (tNear > tFar || tFar < 0.0f) return FLT_INF;
FfxFloat32 nearEdgeDist = FFX_HitEdgeDist(ro + tNear * rd, boxMin, boxMax);
FfxFloat32 farEdgeDist = FFX_HitEdgeDist(ro + tFar * rd, boxMin, boxMax);
const FfxFloat32 nearClip = 0.1f;
if (tNear > nearClip && nearEdgeDist / tNear < 0.001f) {
return tNear;
} else if (tFar > nearClip && farEdgeDist / tFar < 0.001f) {
return tFar;
}
return FLT_INF;
}
void FfxBrixelizerDebugVisualization(FfxUInt32x2 tid)
{
FfxUInt32 width, height;
GetDebugOutputDimensions(width, height);
FfxFloat32x2 uv = (FfxFloat32x2(tid.xy) + FfxFloat32(0.5).xx) / FfxFloat32x2(width, height);
FfxFloat32x3 screen_uv_space_ray_origin = FfxFloat32x3(uv, FfxFloat32(0.5));
FfxFloat32x3 view_space_ray = FFX_ScreenSpaceToViewSpace(screen_uv_space_ray_origin);
FfxFloat32x3 view_space_ray_direction = normalize(view_space_ray);
FfxFloat32x3 ray_direction = normalize(FFX_ViewSpaceToWorldSpace(FfxFloat32x4(view_space_ray_direction, FfxFloat32(0.0))));
FfxFloat32x3 ray_origin = FFX_ViewSpaceToWorldSpace(FfxFloat32x4(0.0, 0.0, 0.0, 1.0));
FfxBrixelizerRayDesc ray_desc;
ray_desc.start_cascade_id = GetDebugInfoStartCascadeIndex();
ray_desc.end_cascade_id = GetDebugInfoEndCascadeIndex();
ray_desc.t_min = GetDebugInfoTMin();
ray_desc.t_max = GetDebugInfoTMax();
ray_desc.origin = ray_origin;
ray_desc.direction = ray_direction;
FfxBrixelizerHitRaw hit_payload;
FfxBoolean hit = FfxBrixelizerTraverseRaw(ray_desc, hit_payload);
FfxFloat32 hit_dist = FLT_INF;
FfxFloat32x3 out_color = FfxFloat32x3(0.0f, 0.0f, 0.0f);
if (hit) {
hit_dist = hit_payload.t;
switch (GetDebugInfoDebugState()) {
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_DISTANCE: {
FfxFloat32 dist = (hit_payload.t - ray_desc.t_min) / (ray_desc.t_max - ray_desc.t_min);
out_color = FfxFloat32x3(0.0f, smoothstep(0.0f, 1.0f, dist), smoothstep(0.0f, 1.0f, 1.0f - dist));
break;
}
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_UVW: {
FfxFloat32x3 uvw = FfxFloat32x3(
FfxBrixelizerUnpackUnsigned8Bits((hit_payload.uvwc >> 0) & 0xff),
FfxBrixelizerUnpackUnsigned8Bits((hit_payload.uvwc >> 8) & 0xff),
FfxBrixelizerUnpackUnsigned8Bits((hit_payload.uvwc >> 16) & 0xff)
);
out_color = uvw;
break;
}
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_ITERATIONS:
out_color = FFX_HeatmapGradient(FfxFloat32(hit_payload.iter_count) / FfxFloat32(64));
break;
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_GRAD: {
out_color = FfxBrixelizerGetHitNormal(hit_payload) * FfxFloat32(0.5) + FfxFloat32(0.5);
break;
}
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_BRICK_ID:
out_color = FFX_RandomColor(FfxFloat32x2(FfxFloat32(hit_payload.brick_id % 256) / FfxFloat32(256.0), FfxFloat32((hit_payload.brick_id / 256) % 256) / FfxFloat32(256.0)));
break;
case FFX_BRIXELIZER_TRACE_DEBUG_MODE_CASCADE_ID: {
FfxUInt32 voxel_id = LoadBricksVoxelMap(FfxBrixelizerBrickGetIndex(hit_payload.brick_id));
FfxUInt32 cascade_id = FfxBrixelizerGetVoxelCascade(voxel_id);
out_color = FFX_RandomColor(FfxFloat32x2(FfxFloat32(cascade_id % 256) / FfxFloat32(256.0), FfxFloat32((cascade_id / 256) % 256) / FfxFloat32(256.0)));
break;
}
}
} else {
out_color = FFX_HeatmapGradient(FfxFloat32(hit_payload.iter_count) / FfxFloat32(64));
}
FfxFloat32 aabb_hit_dist = FLT_INF;
FfxFloat32x3 aabb_color = FfxFloat32x3(0.0f, 0.0f, 0.0f);
FfxUInt32 num_debug_aabbs = min(GetDebugInfoMaxAABBs(), LoadContextCounter(FFX_BRIXELIZER_CONTEXT_COUNTER_NUM_DEBUG_AABBS));
for (FfxUInt32 i = 0; i < num_debug_aabbs; ++i) {
FfxBrixelizerDebugAABB aabb = GetDebugAABB(i);
FfxFloat32 this_hit_dist = FFX_BoxHitDist(tid, ray_desc.origin, ray_desc.direction, aabb.aabbMin, aabb.aabbMax);
if (this_hit_dist < aabb_hit_dist) {
aabb_hit_dist = this_hit_dist;
aabb_color = aabb.color;
}
}
if (aabb_hit_dist < hit_dist) {
out_color = aabb_color;
} else if (aabb_hit_dist < FLT_INF) {
out_color = ffxLerp(out_color, aabb_color, 0.25f);
}
StoreDebugOutput(tid, out_color);
}
#endif // ifndef FFX_BRIXELIZER_DEBUG_VISUALIZATION_H