243 lines
12 KiB
C
243 lines
12 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_COMMON_PRIVATE_H
|
|
#define FFX_BRIXELIZER_COMMON_PRIVATE_H
|
|
|
|
#include "ffx_brixelizer_common.h"
|
|
#include "ffx_brixelizer_host_gpu_shared_private.h"
|
|
|
|
FfxInt32x3 to_int3(FfxUInt32x3 a) { return FfxInt32x3(FfxInt32(a.x), FfxInt32(a.y), FfxInt32(a.z)); }
|
|
FfxFloat32x3 to_float3(FfxUInt32x3 a) { return FfxFloat32x3(FfxFloat32(a.x), FfxFloat32(a.y), FfxFloat32(a.z)); }
|
|
FfxFloat32x3 to_float3(FfxInt32x3 a) { return FfxFloat32x3(FfxFloat32(a.x), FfxFloat32(a.y), FfxFloat32(a.z)); }
|
|
|
|
FfxUInt32 FfxBrixelizerPackDistance(FfxFloat32 distance)
|
|
{
|
|
FfxUInt32 uval = ffxAsUInt32(distance);
|
|
FfxUInt32 sign_bit = uval >> FfxUInt32(31);
|
|
return (uval << 1) | sign_bit;
|
|
}
|
|
|
|
FfxFloat32 FfxBrixelizerUnpackDistance(FfxUInt32 uval)
|
|
{
|
|
FfxUInt32 sign_bit = (uval & 1);
|
|
return ffxAsFloat((uval >> FfxUInt32(1)) | (sign_bit << FfxUInt32(31)));
|
|
}
|
|
|
|
// Returns the minimal absolute value with its sign unchanged
|
|
FfxFloat32 FfxBrixelizerUnsignedMin(FfxFloat32 a, FfxFloat32 b) { return abs(a) < abs(b) ? a : b; }
|
|
// sign without zero
|
|
FfxFloat32 FfxBrixelizerGetSign(FfxFloat32 v) { return v < FfxFloat32(0.0) ? -FfxFloat32(1.0) : FfxFloat32(1.0); }
|
|
|
|
FfxFloat32 dot2(FfxFloat32x3 v) { return dot(v, v); }
|
|
FfxFloat32 dot2(FfxFloat32x2 v) { return dot(v, v); }
|
|
|
|
// https://www.shadertoy.com/view/4sXXRN
|
|
// The MIT License
|
|
// Copyright © 2014 Inigo Quilez
|
|
// 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.
|
|
//
|
|
// It computes the distance to a triangle.
|
|
//
|
|
// See here: http://iquilezles.org/www/articles/triangledistance/triangledistance.htm
|
|
//
|
|
// In case a mesh was rendered, only one square root would be needed for the
|
|
// whole mesh. In this example the triangle is given a thckness of 0.01 units
|
|
// for display purposes. Like the square root, this thickness should be added
|
|
// only once for the whole mesh too.
|
|
FfxFloat32 CalculateDistanceToTriangle(FfxFloat32x3 p, FfxFloat32x3 a, FfxFloat32x3 b, FfxFloat32x3 c) {
|
|
FfxFloat32x3 ba = b - a;
|
|
FfxFloat32x3 pa = p - a;
|
|
FfxFloat32x3 cb = c - b;
|
|
FfxFloat32x3 pb = p - b;
|
|
FfxFloat32x3 ac = a - c;
|
|
FfxFloat32x3 pc = p - c;
|
|
FfxFloat32x3 nor = cross(ba, ac);
|
|
|
|
return sqrt( //
|
|
(sign(dot(cross(ba, nor), pa)) + //
|
|
sign(dot(cross(cb, nor), pb)) + //
|
|
sign(dot(cross(ac, nor), pc)) < //
|
|
FfxFloat32(2.0)) //
|
|
? //
|
|
min(min( //
|
|
dot2(ba * ffxSaturate(dot(ba, pa) / dot2(ba)) - pa), //
|
|
dot2(cb * ffxSaturate(dot(cb, pb) / dot2(cb)) - pb)), //
|
|
dot2(ac * ffxSaturate(dot(ac, pc) / dot2(ac)) - pc)) //
|
|
: //
|
|
dot(nor, pa) * dot(nor, pa) / dot2(nor) //
|
|
); //
|
|
}
|
|
|
|
FfxFloat32 CalculateDistanceToTriangleSquared(FfxFloat32x3 ba, //
|
|
FfxFloat32x3 pa, //
|
|
FfxFloat32x3 cb, //
|
|
FfxFloat32x3 pb, //
|
|
FfxFloat32x3 ac, //
|
|
FfxFloat32x3 pc, //
|
|
FfxFloat32x3 nor, //
|
|
FfxFloat32x3 cross_ba_nor, //
|
|
FfxFloat32x3 cross_cb_nor, //
|
|
FfxFloat32x3 cross_ac_nor, //
|
|
FfxFloat32 dot2_ba, //
|
|
FfxFloat32 dot2_cb, //
|
|
FfxFloat32 dot2_ac, //
|
|
FfxFloat32 dot2_nor //
|
|
) {
|
|
return //
|
|
( //
|
|
(sign(dot(cross_ba_nor, pa)) + //
|
|
sign(dot(cross_cb_nor, pb)) + //
|
|
sign(dot(cross_ac_nor, pc)) < //
|
|
FfxFloat32(2.0)) //
|
|
? //
|
|
min(min( //
|
|
dot2(ba * ffxSaturate(dot(ba, pa) / dot2_ba) - pa), //
|
|
dot2(cb * ffxSaturate(dot(cb, pb) / dot2_cb) - pb)), //
|
|
dot2(ac * ffxSaturate(dot(ac, pc) / dot2_ac) - pc)) //
|
|
: //
|
|
dot(nor, pa) * dot(nor, pa) / dot2_nor //
|
|
); //
|
|
}
|
|
|
|
#define brixelizerreal FfxFloat32
|
|
#define brixelizerreal2 FfxFloat32x2
|
|
#define brixelizerreal3 FfxFloat32x3
|
|
#define brixelizerreal4 FfxFloat32x4
|
|
|
|
#ifdef FFX_HLSL
|
|
# define brixelizerreal3x2 float3x2
|
|
#else
|
|
# define brixelizerreal3x2 mat3x2
|
|
#endif
|
|
|
|
brixelizerreal3 to_brixelizerreal3(FfxUInt32x3 a) { return brixelizerreal3(brixelizerreal(a.x), brixelizerreal(a.y), brixelizerreal(a.z)); }
|
|
|
|
// Offsets the plane equation for the nearest grid point
|
|
brixelizerreal FfxBrixelizerOffsetByMax(brixelizerreal de, brixelizerreal2 ne, brixelizerreal offset)
|
|
{
|
|
de += max(FfxFloat32(0.0), ne.x) + abs(ne.x * offset);
|
|
de += max(FfxFloat32(0.0), ne.y) + abs(ne.y * offset);
|
|
return de;
|
|
}
|
|
|
|
// Offsets the plane equation for the next grid point
|
|
brixelizerreal FfxBrixelizerOffsetByMin(brixelizerreal de, brixelizerreal2 ne, brixelizerreal offset)
|
|
{
|
|
de += min(FfxFloat32(0.0), ne.x) - abs(ne.x * offset);
|
|
de += min(FfxFloat32(0.0), ne.y) - abs(ne.x * offset);
|
|
return de;
|
|
}
|
|
|
|
void FfxBrixelizerGet2DEdge(FFX_PARAMETER_OUT brixelizerreal2 ne,
|
|
FFX_PARAMETER_OUT brixelizerreal de,
|
|
brixelizerreal orientation,
|
|
brixelizerreal edge_x,
|
|
brixelizerreal edge_y,
|
|
brixelizerreal vertex_x,
|
|
brixelizerreal vertex_y,
|
|
brixelizerreal offset)
|
|
{
|
|
ne = brixelizerreal2(-orientation * edge_y, orientation * edge_x);
|
|
de = -(ne.x * vertex_x + ne.y * vertex_y);
|
|
de = FfxBrixelizerOffsetByMax(de, ne, offset);
|
|
}
|
|
|
|
void FfxBrixelizerGet2DEdges(
|
|
FFX_PARAMETER_OUT brixelizerreal3 de_xy,
|
|
FFX_PARAMETER_OUT brixelizerreal3x2 ne_xy,
|
|
FFX_PARAMETER_OUT brixelizerreal3 de_xz,
|
|
FFX_PARAMETER_OUT brixelizerreal3x2 ne_xz,
|
|
FFX_PARAMETER_OUT brixelizerreal3 de_yz,
|
|
FFX_PARAMETER_OUT brixelizerreal3x2 ne_yz,
|
|
FFX_PARAMETER_OUT brixelizerreal3 gn,
|
|
brixelizerreal3 TRIANGLE_VERTEX_0,
|
|
brixelizerreal3 TRIANGLE_VERTEX_1,
|
|
brixelizerreal3 TRIANGLE_VERTEX_2,
|
|
brixelizerreal offset,
|
|
bool invert)
|
|
{
|
|
brixelizerreal3 e0 = TRIANGLE_VERTEX_1.xyz - TRIANGLE_VERTEX_0.xyz;
|
|
brixelizerreal3 e1 = TRIANGLE_VERTEX_2.xyz - TRIANGLE_VERTEX_1.xyz;
|
|
brixelizerreal3 e2 = TRIANGLE_VERTEX_0.xyz - TRIANGLE_VERTEX_2.xyz;
|
|
if (invert) {
|
|
e0 = -e0;
|
|
e1 = -e1;
|
|
e2 = -e2;
|
|
}
|
|
|
|
gn = normalize(cross(e2, e0));
|
|
|
|
brixelizerreal orientation_xy = brixelizerreal(gn.z < FfxFloat32(0.0) ? -FfxFloat32(1.0) : FfxFloat32(1.0));
|
|
FfxBrixelizerGet2DEdge(/* out */ ne_xy[0], /* out */ de_xy[0], orientation_xy, e0.x, e0.y, TRIANGLE_VERTEX_0.x, TRIANGLE_VERTEX_0.y, offset);
|
|
FfxBrixelizerGet2DEdge(/* out */ ne_xy[1], /* out */ de_xy[1], orientation_xy, e1.x, e1.y, TRIANGLE_VERTEX_1.x, TRIANGLE_VERTEX_1.y, offset);
|
|
FfxBrixelizerGet2DEdge(/* out */ ne_xy[2], /* out */ de_xy[2], orientation_xy, e2.x, e2.y, TRIANGLE_VERTEX_2.x, TRIANGLE_VERTEX_2.y, offset);
|
|
brixelizerreal orientation_xz = brixelizerreal(gn.y > FfxFloat32(0.0) ? -FfxFloat32(1.0) : FfxFloat32(1.0));
|
|
FfxBrixelizerGet2DEdge(/* out */ ne_xz[0], /* out */ de_xz[0], orientation_xz, e0.x, e0.z, TRIANGLE_VERTEX_0.x, TRIANGLE_VERTEX_0.z, offset);
|
|
FfxBrixelizerGet2DEdge(/* out */ ne_xz[1], /* out */ de_xz[1], orientation_xz, e1.x, e1.z, TRIANGLE_VERTEX_1.x, TRIANGLE_VERTEX_1.z, offset);
|
|
FfxBrixelizerGet2DEdge(/* out */ ne_xz[2], /* out */ de_xz[2], orientation_xz, e2.x, e2.z, TRIANGLE_VERTEX_2.x, TRIANGLE_VERTEX_2.z, offset);
|
|
brixelizerreal orientation_yz = brixelizerreal(gn.x < FfxFloat32(0.0) ? -FfxFloat32(1.0) : FfxFloat32(1.0));
|
|
FfxBrixelizerGet2DEdge(/* out */ ne_yz[0], /* out */ de_yz[0], orientation_yz, e0.y, e0.z, TRIANGLE_VERTEX_0.y, TRIANGLE_VERTEX_0.z, offset);
|
|
FfxBrixelizerGet2DEdge(/* out */ ne_yz[1], /* out */ de_yz[1], orientation_yz, e1.y, e1.z, TRIANGLE_VERTEX_1.y, TRIANGLE_VERTEX_1.z, offset);
|
|
FfxBrixelizerGet2DEdge(/* out */ ne_yz[2], /* out */ de_yz[2], orientation_yz, e2.y, e2.z, TRIANGLE_VERTEX_2.y, TRIANGLE_VERTEX_2.z, offset);
|
|
}
|
|
|
|
bool FfxBrixelizerEvalEdge(brixelizerreal2 vertex, brixelizerreal3 de, brixelizerreal3x2 ne)
|
|
{
|
|
return (ne[0].x * vertex.x + ne[0].y * vertex.y + de[0] >= brixelizerreal(FfxFloat32(0.0))) &&
|
|
(ne[1].x * vertex.x + ne[1].y * vertex.y + de[1] >= brixelizerreal(FfxFloat32(0.0))) &&
|
|
(ne[2].x * vertex.x + ne[2].y * vertex.y + de[2] >= brixelizerreal(FfxFloat32(0.0)));
|
|
}
|
|
|
|
// We need those non-POT versions around for culling
|
|
FfxUInt32x3 FfxBrixelizerUnflatten(FfxUInt32 flat_bx_coord, FfxUInt32x3 dim)
|
|
{
|
|
return FfxUInt32x3(flat_bx_coord % dim.x, (flat_bx_coord / dim.x) % dim.y, flat_bx_coord / (dim.x * dim.y));
|
|
}
|
|
|
|
FfxUInt32x2 FfxBrixelizerUnflatten(FfxUInt32 flat_bx_coord, FfxUInt32x2 dim)
|
|
{
|
|
return FfxUInt32x2(flat_bx_coord % dim.x, (flat_bx_coord / dim.x) % dim.y);
|
|
}
|
|
|
|
FfxUInt32 FfxBrixelizerFlatten(FfxUInt32x3 voxel_coord, FfxUInt32x3 dim)
|
|
{
|
|
return voxel_coord.x + voxel_coord.y * dim.x + voxel_coord.z * dim.x * dim.y;
|
|
}
|
|
|
|
#endif // FFX_BRIXELIZER_COMMON_PRIVATE_H
|