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
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
|
|
);
|
|
}
|
|
|