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