You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
7.4 KiB
Plaintext

/******************************************************************************/
/*
Project - MudBun
Publisher - Long Bunny Labs
http://LongBunnyLabs.com
Author - Ming-Lun "Allen" Chou
http://AllenChou.net
*/
/******************************************************************************/
#pragma kernel clear_voxel_hash_table
#pragma kernel clear_auto_smooth_vert_data_table
#pragma kernel clear_voxel_cache
#pragma kernel register_top_nodes
#pragma kernel update_branching_indirect_dispatch_args
#pragma kernel allocate_child_nodes
#pragma kernel update_voxel_indirect_dispatch_args
// yeah...I know
#pragma warning(disable: 4714) // //Shader warning in 'VoxelGen.compute': Program 'allocate_child_nodes', warning X4714 : sum of temp registers and indexable temp registers times 64 threads exceeds the recommended total 16384. Performance may be reduced at kernel allocate_child_nodes(on d3d11)
#include "../../Shader/ComputeCommon.cginc"
#include "../../Shader/AabbTreeFuncs.cginc"
#include "../../Shader/AutoSmoothDefs.cginc"
#include "../../Shader/BrushFuncs.cginc"
#include "../../Shader/GenPointDefs.cginc"
#include "../../Shader/IndirectArgsDefs.cginc"
#include "../../Shader/Math/MathConst.cginc"
#include "../../Shader/VoxelFuncs.cginc"
#include "../../Shader/VoxelCacheFuncs.cginc"
#include "../../Shader/VoxelHashFuncs.cginc"
#include "../../Shader/VoxelModeDefs.cginc"
[numthreads(kClearThreadGroupSize, 1, 1)]
void clear_voxel_hash_table(int id : SV_DispatchThreadID)
{
if (id.x >= nodeHashTableSize)
return;
nodeHashTable[id.x] = init_voxel_hash_entry();
}
[numthreads(kClearThreadGroupSize, 1, 1)]
void clear_auto_smooth_vert_data_table(int id : SV_DispatchThreadID)
{
if (id.x >= autoSmoothVertDataPoolSize)
return;
autoSmoothVertDataTable[id.x].id = kNullAutoSmoothCacheId;
autoSmoothVertDataTable[id.x].numNormals = 0;
}
[numthreads(kClearThreadGroupSize, 1, 1)]
void clear_voxel_cache(int id : SV_DispatchThreadID)
{
if (id.x >= int(voxelCacheSize))
return;
voxelCacheIdTable[id.x] = kNullVoxelCacheId;
voxelCache[id.x].data = kFltMax;
}
[numthreads(kThreadGroupSize, 1, 1)]
void register_top_nodes(int3 id : SV_DispatchThreadID)
{
int iBrush = id.x;
if (iBrush >= numBrushes)
return;
register_brush_aabb(iBrush);
}
[numthreads(1, 1, 1)]
void update_branching_indirect_dispatch_args(int3 id : SV_DispatchThreadID)
{
indirectDispatchArgs[0] =
max
(
1,
uint
(
min
(
nodePoolSize,
aNumNodesAllocated[currentNodeDepth + 1]
)
* (enable2dMode ? (currentNodeBranchingFactor * currentNodeBranchingFactor) : (currentNodeBranchingFactor * currentNodeBranchingFactor * currentNodeBranchingFactor))
+ kThreadGroupSize - 1
) / kThreadGroupSize
);
}
[numthreads(kThreadGroupSize, 1, 1)]
void allocate_child_nodes(uint3 id : SV_DispatchThreadID)
{
uint f = currentNodeBranchingFactor;
uint ff = f * f;
uint fff = ff * f;
uint iNode = uint(id.x) / (enable2dMode ? ff : fff);
if (iNode >= uint(aNumNodesAllocated[currentNodeDepth + 1]))
return;
for (int i = 1; i <= currentNodeDepth; ++i)
iNode += aNumNodesAllocated[i];
if (iNode >= nodePoolSize)
return;
uint3 childNodeCoord = (id.x / uint3(1, f, ff)) % f;
float childSize = currentNodeSize / currentNodeBranchingFactor;
float3 childCenter = nodePool[iNode].center - ((f / 2) - 0.5f - childNodeCoord) * childSize;
if (enable2dMode)
childCenter.z = 0.0f;
float childDiag = (enable2dMode ? 1.415f : 1.733f) * childSize;
float halfChildDiag = 0.5f * childDiag;
SdfBrushMaterial mat;
float d = sdf_masked_brushes(childCenter, get_brush_mask_index(iNode), mat, false, halfChildDiag);
if (d == kCull)
return;
// ray-traced voxel?
if (renderMode == kRenderModeRayTracedVoxels
&& currentNodeDepth == maxNodeDepth - 1)
{
if (d > 0.0f)
return;
switch (rayTracedVoxelPaddingMode)
{
case kVoxelPaddingModeNone:
if (d < -childDiag)
return;
break;
case kVoxelPaddingModeByDistance:
if (d < -childDiag - rayTracedVoxelInternalPaddingDistance)
return;
break;
case kVoxelPaddingModeFull:
break;
}
int iChildNode = -1;
iChildNode = register_alloc_child_node(childCenter, childSize, currentNodeDepth + 1, iNode, childNodeCoord);
if (iChildNode < 0)
return;
float halfChildSize = 0.5f * childSize;
Aabb childAabb = make_aabb(childCenter - halfChildSize, childCenter + halfChildSize);
nodePool[iChildNode].iBrushMask = allocate_node_brush_mask(iChildNode, childAabb);
aGenPoint[iChildNode].sdfValue = min(0.0f, d);
aGenPoint[iChildNode].material = pack_material(mat);
aGenPoint[iChildNode].iBrushMask = get_brush_mask_index(iChildNode);
switch (rayTracedVoxelMode)
{
case kVoxelModeFlatCubes:
case kVoxelModeFlatSpheres:
{
float3 n;
SDF_NORMAL(n, nodePool[iChildNode].center, sdf_masked_brushes, aGenPoint[iChildNode].iBrushMask, 1e-2f * voxelNodeSizes[3]);
aGenPoint[iChildNode].posNorm.w = pack_normal(n);
}
break;
}
return;
}
if (d > halfChildDiag || (d < -childDiag && !enable2dMode))
{
// could deviation from round/chamfer/pipe/engrave/distortion/modifier possibly bring solid surface close to voxel?
bool deviationClose = false;
bool bumpToleranceByOneStep = false;
FOR_EACH_BRUSH(get_brush_mask_index(iNode),
switch (aBrush[iBrush].op)
{
case kSdfUnionRound:
case kSdfUnionChamfer:
case kSdfSubtractRound:
case kSdfSubtractChamfer:
case kSdfIntersectRound:
case kSdfIntersectChamfer:
case kSdfPipe:
case kSdfEngrave:
{
bumpToleranceByOneStep = true;
break;
}
case kSdfDistort:
case kSdfModify:
{
float deviation = aBrush[iBrush].blend;
float res = sdf_distortion_modifier_bounds_query(childCenter, aBrush[iBrush]);
if (res <= childDiag
&& abs(d) - deviation <= childDiag)
{
deviationClose = true;
}
break;
}
}
if (deviationClose)
break;
);
if (!deviationClose
&& bumpToleranceByOneStep
&& abs(d) - 0.5f * voxelSize <= halfChildDiag)
{
deviationClose = true;
}
if (!deviationClose)
return;
}
int iChildNode = -1;
if (renderMode != kRenderModeRayTracedVoxels)
{
// fast
iChildNode = allocate_node(childCenter, currentNodeDepth + 1, iNode, int(id.x));
}
else
{
// slightly slower, used when per-voxel spatial hash is needed (e.g. voxel raytracing)
iChildNode = register_alloc_child_node(childCenter, childSize, currentNodeDepth + 1, iNode, childNodeCoord);
}
if (iChildNode < 0)
return;
float halfChildSize = 0.5f * childSize;
Aabb childAabb = make_aabb(childCenter - halfChildSize, childCenter + halfChildSize);
nodePool[iChildNode].iBrushMask = allocate_node_brush_mask(iChildNode, childAabb);
}
[numthreads(1, 1, 1)]
void update_voxel_indirect_dispatch_args(int3 id : SV_DispatchThreadID)
{
indirectDispatchArgs[0] =
max
(
1,
uint
(
min
(
nodePoolSize,
aNumNodesAllocated[currentNodeDepth + 1]
)
+ kThreadGroupSize - 1
) / kThreadGroupSize
);
}