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.
188 lines
7.4 KiB
Plaintext
188 lines
7.4 KiB
Plaintext
2 weeks ago
|
/******************************************************************************/
|
||
|
/*
|
||
|
Project - MudBun
|
||
|
Publisher - Long Bunny Labs
|
||
|
http://LongBunnyLabs.com
|
||
|
Author - Ming-Lun "Allen" Chou
|
||
|
http://AllenChou.net
|
||
|
*/
|
||
|
/******************************************************************************/
|
||
|
|
||
|
#ifndef MUDBUN_DECAL
|
||
|
#define MUDBUN_DECAL
|
||
|
|
||
|
#include "Render/ShaderCommon.cginc"
|
||
|
|
||
|
#if MUDBUN_VALID
|
||
|
|
||
|
#include "BrushFuncs.cginc"
|
||
|
|
||
|
struct DecalResults
|
||
|
{
|
||
|
bool hit;
|
||
|
float3 pos;
|
||
|
SdfBrushMaterial mat;
|
||
|
float sdfValue;
|
||
|
};
|
||
|
|
||
|
#define SDF_DECAL_MASKED_BRUSHES(res, p, brushMask, mat) \
|
||
|
{ \
|
||
|
int iStack = -1; \
|
||
|
float3 pStack[kMaxBrushGroupDepth]; \
|
||
|
float resStack[kMaxBrushGroupDepth]; \
|
||
|
SdfBrushMaterial matStack[kMaxBrushGroupDepth]; \
|
||
|
\
|
||
|
res = kInfinity; \
|
||
|
mat = init_brush_material(); \
|
||
|
float3 groupP = p; \
|
||
|
float groupRes = kInfinity; \
|
||
|
SdfBrushMaterial groupMat = init_brush_material(); \
|
||
|
FOR_EACH_BRUSH_EXTERN_MASK(brushMask, \
|
||
|
switch (aBrush[iBrush].type) \
|
||
|
{ \
|
||
|
case kSdfBeginGroup: \
|
||
|
iStack = min(kMaxBrushGroupDepth - 1, iStack + 1); \
|
||
|
pStack[iStack] = p; \
|
||
|
resStack[iStack] = res; \
|
||
|
matStack[iStack] = mat; \
|
||
|
res = kInfinity; \
|
||
|
mat = init_brush_material(); \
|
||
|
break; \
|
||
|
case kSdfEndGroup: \
|
||
|
groupP = p; \
|
||
|
groupRes = res; \
|
||
|
groupMat = mat; \
|
||
|
p = pStack[iStack]; \
|
||
|
res = resStack[iStack]; \
|
||
|
mat = matStack[iStack]; \
|
||
|
break; \
|
||
|
} \
|
||
|
res = sdf_brush_apply(res, groupRes, groupMat, groupP, aBrush[iBrush], mat); \
|
||
|
switch (aBrush[iBrush].type) \
|
||
|
{ \
|
||
|
case kSdfEndGroup: \
|
||
|
iStack = max(-1, iStack - 1); \
|
||
|
break; \
|
||
|
} \
|
||
|
); \
|
||
|
}
|
||
|
|
||
|
bool sdf_decal_aabb_contains(Aabb aabb, float3 p)
|
||
|
{
|
||
|
// TODO: use max blend
|
||
|
aabb.boundsMin -= 5.0f;
|
||
|
aabb.boundsMax += 5.0f;
|
||
|
|
||
|
return aabb_contains(aabb, p);
|
||
|
}
|
||
|
|
||
|
// stmt = statements processing "iData" of hit leaf AABB nodes
|
||
|
// will gracefully handle maxed-out stacks
|
||
|
#define SDF_DECAL_AABB_TREE_CONTAINS(tree, root, p, stmt) \
|
||
|
{ \
|
||
|
int stackTop = 0; \
|
||
|
int stack[kAabbTreeNodeStackSize]; \
|
||
|
stack[stackTop] = root; \
|
||
|
\
|
||
|
int numIters = 0; \
|
||
|
while (stackTop >= 0 && numIters < 128 /* safeguard */) \
|
||
|
{ \
|
||
|
int index = stack[stackTop--]; \
|
||
|
if (index < 0) \
|
||
|
continue; \
|
||
|
\
|
||
|
if (!sdf_decal_aabb_contains(tree[index].aabb, p)) \
|
||
|
continue; \
|
||
|
\
|
||
|
if (tree[index].iChildA < 0) \
|
||
|
{ \
|
||
|
int iData = tree[index].iData; \
|
||
|
\
|
||
|
stmt \
|
||
|
} \
|
||
|
else \
|
||
|
{ \
|
||
|
stackTop = min(stackTop + 1, kAabbTreeNodeStackSize - 1); \
|
||
|
stack[stackTop] = tree[index].iChildA; \
|
||
|
stackTop = min(stackTop + 1, kAabbTreeNodeStackSize - 1); \
|
||
|
stack[stackTop] = tree[index].iChildB; \
|
||
|
} \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
DecalResults sdf_decal
|
||
|
(
|
||
|
float3 p
|
||
|
)
|
||
|
{
|
||
|
p = mul(worldToLocal, float4(p, 1.0f)).xyz;
|
||
|
|
||
|
DecalResults res;
|
||
|
res.hit = false;
|
||
|
res.pos = p;
|
||
|
res.mat = init_brush_material();
|
||
|
res.sdfValue = kInfinity;
|
||
|
|
||
|
// don't crash Unity previews
|
||
|
#ifdef MUDBUN_PROCEDURAL
|
||
|
|
||
|
BRUSH_MASK(brushMask);
|
||
|
BRUSH_MASK_CLEAR_ALL(brushMask);
|
||
|
|
||
|
SDF_DECAL_AABB_TREE_CONTAINS(aabbTree, aabbRoot, p,
|
||
|
BRUSH_MASK_SET(brushMask, iData);
|
||
|
);
|
||
|
|
||
|
float d = kInfinity;
|
||
|
SDF_DECAL_MASKED_BRUSHES(d, p, brushMask, res.mat);
|
||
|
|
||
|
if (d > 0.0f)
|
||
|
discard;
|
||
|
|
||
|
res.sdfValue = d;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
#else
|
||
|
|
||
|
struct SdfBrushMaterialDummy
|
||
|
{
|
||
|
float4 color;
|
||
|
float4 emissionHash;
|
||
|
float4 metallicSmoothnessSizeTightness;
|
||
|
float4 textureWeight;
|
||
|
};
|
||
|
|
||
|
struct DecalResults
|
||
|
{
|
||
|
bool hit;
|
||
|
float3 pos;
|
||
|
SdfBrushMaterialDummy mat;
|
||
|
float sdfValue;
|
||
|
};
|
||
|
|
||
|
DecalResults sdf_decal
|
||
|
(
|
||
|
float3 p
|
||
|
)
|
||
|
{
|
||
|
DecalResults res;
|
||
|
res.hit = false;
|
||
|
res.pos = p;
|
||
|
res.mat.color = 0.0f;
|
||
|
res.mat.emissionHash = 0.0f;
|
||
|
res.mat.metallicSmoothnessSizeTightness = 0.0f;
|
||
|
res.mat.textureWeight = 0.0f;
|
||
|
res.sdfValue = 0.0f;
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
#endif
|
||
|
|