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.

364 lines
11 KiB
Plaintext

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