/******************************************************************************/ /* Project - MudBun Publisher - Long Bunny Labs http://LongBunnyLabs.com Author - Ming-Lun "Allen" Chou http://AllenChou.net */ /******************************************************************************/ #pragma kernel generate_flat_marching_cubes_mesh #pragma kernel generate_smooth_marching_cubes_mesh #pragma kernel generate_marching_splats #pragma kernel generate_flat_marching_cubes_mesh_2d #pragma kernel generate_smooth_marching_cubes_mesh_2d #pragma kernel generate_marching_splats_2d #pragma kernel update_marching_cubes_auto_smooth_indirect_dispatch_args #pragma kernel marching_cubes_update_auto_smooth #pragma kernel marching_cubes_compute_auto_smooth // yes I know I'm using a lot of registers #pragma warning (disable : 4714) #include "../../Shader/ComputeCommon.cginc" #include "../../Shader/AutoSmoothFuncs.cginc" #include "../../Shader/BrushFuncs.cginc" #include "../../Shader/GenPointDefs.cginc" #include "../../Shader/IndirectArgsDefs.cginc" #include "../../Shader/MarchingCubesFuncs.cginc" #include "../../Shader/Math/MathConst.cginc" #include "../../Shader/MeshingModeDefs.cginc" #include "../../Shader/NormalFuncs.cginc" #include "../../Shader/RenderModeDefs.cginc" [numthreads(kThreadGroupSize, 1, 1)] void generate_flat_marching_cubes_mesh(int3 id : SV_DispatchThreadID) { #if defined(MUDBUN_DISABLE_MARCHING_CUBES_FLAT_MESH) return; #endif uint iNode = uint(id.x); if (iNode >= uint(aNumNodesAllocated[currentNodeDepth + 1])) return; for (int i = 1; i <= currentNodeDepth; ++i) iNode += aNumNodesAllocated[i]; if (iNode >= nodePoolSize) return; int iBrushMask = get_brush_mask_index(iNode); SdfBrushMaterial cubeMat; MARCHING_CUBES(nodePool[iNode].center, currentNodeSize, sdf_masked_brushes, iBrushMask, false, cubeMat, // tStmtPre int iVertBase = 0; InterlockedAdd(indirectDrawArgs[0], 3, iVertBase); , // vStmt int iGenPoint = iVertBase + iVert; aGenPoint[iVertBase + iVert].posNorm = float4(aVertPos[iVert], pack_normal(aVertNorm[iVert] * (invertNormals ? -1.0f : 1.0f))); aGenPoint[iVertBase + iVert].material = pack_material(cubeMat); aGenPoint[iVertBase + iVert].vertId = auto_smooth_vert_data_id(aEdgeCenter[iVert]); aGenPoint[iVertBase + iVert].iBrushMask = iBrushMask; aGenPoint[iVertBase + iVert].sdfValue = surfaceShift; , // tStmtPost { } ); } [numthreads(kThreadGroupSize, 1, 1)] void generate_smooth_marching_cubes_mesh(int3 id : SV_DispatchThreadID) { #if defined(MUDBUN_DISABLE_MARCHING_CUBES_SMOOTH_MESH) || defined(MUDBUN_FAST_ITERATION) return; #endif uint iNode = uint(id.x); if (iNode >= uint(aNumNodesAllocated[currentNodeDepth + 1])) return; for (int i = 1; i <= currentNodeDepth; ++i) iNode += aNumNodesAllocated[i]; if (iNode >= nodePoolSize) return; int iBrushMask = get_brush_mask_index(iNode); SdfBrushMaterial cubeMat; MARCHING_CUBES(nodePool[iNode].center, currentNodeSize, sdf_masked_brushes, iBrushMask, true, cubeMat, // tStmtPre int iVertBase = 0; InterlockedAdd(indirectDrawArgs[0], 3, iVertBase); , // vStmt int iGenPoint = iVertBase + iVert; aGenPoint[iGenPoint].posNorm = float4(aVertPos[iVert], pack_normal(aVertNorm[iVert] * (invertNormals ? -1.0f : 1.0f))); aGenPoint[iGenPoint].material = pack_material(aVertMat[iVert]); aGenPoint[iGenPoint].vertId = auto_smooth_vert_data_id(aEdgeCenter[iVert]); aGenPoint[iGenPoint].iBrushMask = iBrushMask; aGenPoint[iGenPoint].sdfValue = surfaceShift; , // tStmtPost { } ); } [numthreads(kThreadGroupSize, 1, 1)] void generate_marching_splats(int3 id : SV_DispatchThreadID) { #if defined(MUDBUN_DISABLE_MARCHING_CUBES_SPLATS) || defined(MUDBUN_FAST_ITERATION) return; #endif uint iNode = uint(id.x); if (iNode >= uint(aNumNodesAllocated[currentNodeDepth + 1])) return; for (int i = 1; i <= currentNodeDepth; ++i) iNode += aNumNodesAllocated[i]; if (iNode >= nodePoolSize) return; int numTris = 0; float3 avgPos = 0.0f; float3 avgNorm = 0.0f; float avgWeight = 0.0f; int iBrushMask = get_brush_mask_index(iNode); SdfBrushMaterial cubeMat; MARCHING_CUBES(nodePool[iNode].center, currentNodeSize, sdf_masked_brushes, iBrushMask, false, cubeMat, // tStmtPre { } , // vStmt { } , // tStmtPost float3 c = cross(aVertPos[1] - aVertPos[0], aVertPos[2] - aVertPos[0]); float w = length(c); avgPos += w * (aVertPos[0] + aVertPos[1] + aVertPos[2]); if (w > kEpsilon) avgNorm += w * normalize(c); avgWeight += w; ++numTris; ); if (numTris > 0) { avgPos /= avgWeight * 3.0f; avgNorm = normalize(avgNorm); int iVertBase; int iGenPoint = 0; switch (renderMode) { case kRenderModeCircleSplats: InterlockedAdd(indirectDrawArgs[0], 3, iVertBase); iGenPoint = uint(iVertBase) / 3; break; case kRenderModeQuadSplats: InterlockedAdd(indirectDrawArgs[0], 6, iVertBase); iGenPoint = uint(iVertBase) / 6; break; } float scaleMult = pow(saturate(avgWeight / (0.2f * voxelSize * voxelSize)), 0.1f); cubeMat.metallicSmoothnessSizeTightness.z *= scaleMult; aGenPoint[iGenPoint].posNorm = float4(avgPos, pack_normal(avgNorm * (invertNormals ? -1.0f : 1.0f))); aGenPoint[iGenPoint].material = pack_material(cubeMat); aGenPoint[iGenPoint].iBrushMask = iBrushMask; aGenPoint[iGenPoint].sdfValue = surfaceShift; } } [numthreads(kThreadGroupSize, 1, 1)] void generate_flat_marching_cubes_mesh_2d(int3 id : SV_DispatchThreadID) { #if defined(MUDBUN_DISABLE_MARCHING_CUBES_FLAT_MESH) || defined(MUDBUN_FAST_ITERATION) return; #endif uint iNode = uint(id.x); if (iNode >= uint(aNumNodesAllocated[currentNodeDepth + 1])) return; for (int i = 1; i <= currentNodeDepth; ++i) iNode += aNumNodesAllocated[i]; if (iNode >= nodePoolSize) return; int iBrushMask = get_brush_mask_index(iNode); SdfBrushMaterial cubeMat; MARCHING_CUBES_2D(nodePool[iNode].center, currentNodeSize, sdf_masked_brushes, iBrushMask, false, cubeMat, // tStmtPre int iVertBase = 0; InterlockedAdd(indirectDrawArgs[0], 3, iVertBase); , // vStmt int iGenPoint = iVertBase + iVert; aGenPoint[iGenPoint].posNorm = float4(aVertPos[iVert], pack_normal(aVertNorm[iVert])); aGenPoint[iGenPoint].material = pack_material(cubeMat); aGenPoint[iGenPoint].iBrushMask = iBrushMask; aGenPoint[iGenPoint].sdfValue = aVertSdfValue[iVert] + surfaceShift; aGenPoint[iGenPoint].norm2d = pack_normal(aVertNorm2d[iVert]); , // tStmtPost { } ); } [numthreads(kThreadGroupSize, 1, 1)] void generate_smooth_marching_cubes_mesh_2d(int3 id : SV_DispatchThreadID) { #if defined(MUDBUN_DISABLE_MARCHING_CUBES_SMOOTH_MESH) || defined(MUDBUN_FAST_ITERATION) return; #endif uint iNode = uint(id.x); if (iNode >= uint(aNumNodesAllocated[currentNodeDepth + 1])) return; for (int i = 1; i <= currentNodeDepth; ++i) iNode += aNumNodesAllocated[i]; if (iNode >= nodePoolSize) return; int iBrushMask = get_brush_mask_index(iNode); SdfBrushMaterial cubeMat; MARCHING_CUBES_2D(nodePool[iNode].center, currentNodeSize, sdf_masked_brushes, iBrushMask, true, cubeMat, // tStmtPre int iVertBase = 0; InterlockedAdd(indirectDrawArgs[0], 3, iVertBase); , // vStmt int iGenPoint = iVertBase + iVert; aGenPoint[iGenPoint].posNorm = float4(aVertPos[iVert], pack_normal(aVertNorm[iVert])); aGenPoint[iGenPoint].material = pack_material(aVertMat[iVert]); aGenPoint[iGenPoint].iBrushMask = iBrushMask; aGenPoint[iGenPoint].sdfValue = aVertSdfValue[iVert] + surfaceShift; aGenPoint[iGenPoint].norm2d = pack_normal(aVertNorm2d[iVert]); , // tStmtPost { } ); } [numthreads(kThreadGroupSize, 1, 1)] void generate_marching_splats_2d(int3 id : SV_DispatchThreadID) { #if defined(MUDBUN_DISABLE_MARCHING_CUBES_SPLATS) || defined(MUDBUN_FAST_ITERATION) return; #endif uint iNode = uint(id.x); if (iNode >= uint(aNumNodesAllocated[currentNodeDepth + 1])) return; for (int i = 1; i <= currentNodeDepth; ++i) iNode += aNumNodesAllocated[i]; if (iNode >= nodePoolSize) return; int numTris = 0; float3 avgPos = 0.0f; float avgSdfValue = 0.0f; float avgWeight = 0.0f; int iBrushMask = get_brush_mask_index(iNode); SdfBrushMaterial cubeMat; MARCHING_CUBES_2D(nodePool[iNode].center, currentNodeSize, sdf_masked_brushes, iBrushMask, false, cubeMat, // tStmtPre { } , // vStmt { } , // tStmtPost float3 c = cross(aVertPos[1] - aVertPos[0], aVertPos[2] - aVertPos[0]); float w = length(c); avgPos += w * (aVertPos[0] + aVertPos[1] + aVertPos[2]); avgSdfValue += w * (aVertSdfValue[0] + aVertSdfValue[1] + aVertSdfValue[2]); avgWeight += w; ++numTris; ); if (numTris > 0) { float normFactor = 1.0f / (avgWeight * 3.0f); avgPos *= normFactor; avgSdfValue *= normFactor; int iVertBase; int iGenPoint = 0; switch (renderMode) { case kRenderModeCircleSplats: InterlockedAdd(indirectDrawArgs[0], 3, iVertBase); iGenPoint = uint(iVertBase) / 3; break; case kRenderModeQuadSplats: InterlockedAdd(indirectDrawArgs[0], 6, iVertBase); iGenPoint = uint(iVertBase) / 6; break; } float scaleMult = pow(saturate(avgWeight / (0.2f * voxelSize * voxelSize)), 0.1f); cubeMat.metallicSmoothnessSizeTightness.z *= scaleMult; aGenPoint[iGenPoint].posNorm = float4(avgPos, pack_normal(float3(0.0f, 0.0f, -1.0f) * (invertNormals ? -1.0f : 1.0f))); aGenPoint[iGenPoint].material = pack_material(cubeMat); aGenPoint[iGenPoint].iBrushMask = iBrushMask; aGenPoint[iGenPoint].sdfValue = avgSdfValue + surfaceShift; } } [numthreads(1, 1, 1)] void update_marching_cubes_auto_smooth_indirect_dispatch_args(int3 id : SV_DispatchThreadID) { indirectDispatchArgs[0] = max(1, uint(indirectDrawArgs[0] + kThreadGroupSize - 1) / kThreadGroupSize); } [numthreads(kThreadGroupSize, 1, 1)] void marching_cubes_update_auto_smooth(int3 id : SV_DispatchThreadID) { if (id.x >= indirectDrawArgs[0]) return; uint iGenPoint = uint(id.x); uint iTriBase = iGenPoint - (iGenPoint % 3); float3 pos0 = aGenPoint[iTriBase ].posNorm.xyz; float3 pos1 = aGenPoint[iTriBase + 1].posNorm.xyz; float3 pos2 = aGenPoint[iTriBase + 2].posNorm.xyz; float3 v01 = pos1 - pos0; float3 v12 = pos2 - pos1; float3 c = cross(v01, v12); float area = length(c); update_auto_smooth_vert_data(aGenPoint[iGenPoint].vertId, aGenPoint[iGenPoint].posNorm.w, area); } [numthreads(kThreadGroupSize, 1, 1)] void marching_cubes_compute_auto_smooth(int3 id : SV_DispatchThreadID) { if (id.x >= indirectDrawArgs[0]) return; uint iGenPoint = uint(id.x); float3 pos = aGenPoint[iGenPoint].posNorm.xyz; int iBrushMask = aGenPoint[iGenPoint].iBrushMask; SdfBrushMaterial mat; sdf_masked_brushes(pos, iBrushMask, mat); float3 autoSmoothNormal = compute_auto_smooth_normal(aGenPoint[iGenPoint].vertId, unpack_normal(aGenPoint[iGenPoint].posNorm.w)); aGenPoint[iGenPoint].posNorm.w = pack_normal(autoSmoothNormal); aGenPoint[iGenPoint].material = pack_material(mat); //aGenPoint[iGenPoint].material.color = pack_rgba(float4(n, 1.0f)); }