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.

105 lines
3.1 KiB
Plaintext

/******************************************************************************/
/*
Project - MudBun
Publisher - Long Bunny Labs
http://LongBunnyLabs.com
Author - Ming-Lun "Allen" Chou
http://AllenChou.net
*/
/******************************************************************************/
#ifndef MUDBUN_AUTO_SMOOTH_FUNCS
#define MUDBUN_AUTO_SMOOTH_FUNCS
#include "AutoSmoothDefs.cginc"
#include "AllocationDefs.cginc"
#include "Math/Codec.cginc"
#include "Math/MathConst.cginc"
#include "Math/Vector.cginc"
#include "Noise/RandomNoise.cginc"
#include "VoxelDefs.cginc"
uint auto_smooth_vert_data_id(float3 p)
{
int3 q = int3(round(p / (0.125f * voxelSize)));
uint hash = kFnvDefaultBasis;
hash = fnv_hash_concat(hash, uint(q.x + 0x80000000));
hash = fnv_hash_concat(hash, uint(q.y + 0x80000000));
hash = fnv_hash_concat(hash, uint(q.z + 0x80000000));
return (hash << 1) | 1;
}
int update_auto_smooth_vert_data(uint id, float packedNormal, float weight)
{
uint slot = id % autoSmoothVertDataPoolSize;
weight = max(kEpsilon, weight);
int i = 0;
while (i++ < autoSmoothVertDataPoolSize)
{
uint prev = kNullAutoSmoothCacheId;
InterlockedCompareExchange(autoSmoothVertDataTable[slot].id, kNullAutoSmoothCacheId, id, prev);
if (prev == kNullAutoSmoothCacheId // newly registered
|| id == autoSmoothVertDataTable[slot].id) // already registered
{
uint iNormal = 0xFF;
InterlockedAdd(autoSmoothVertDataTable[slot].numNormals, 1, iNormal);
if (iNormal < kMaxAutoSmoothNormalPerVertex)
{
autoSmoothVertDataTable[slot].aNormal[iNormal] = packedNormal;
autoSmoothVertDataTable[slot].aWeight[iNormal] = weight;
}
else
{
return -1;
}
return slot;
}
else
{
// ID collision
slot = (slot + 1) % autoSmoothVertDataPoolSize;
}
}
return -1;
}
float3 compute_auto_smooth_normal(uint id, float3 vertNormal)
{
uint slot = id % autoSmoothVertDataPoolSize;
// look up data
int i = 0;
while (i++ < autoSmoothVertDataPoolSize)
{
if (autoSmoothVertDataTable[slot].id == kNullAutoSmoothCacheId)
return float3(0.0f, 0.0f, 0.0f); // total ID miss
if (autoSmoothVertDataTable[slot].id == id)
{
// ID hit
float3 totalAutoSmoothNormal = 0.0f;
for (uint iNormal = 0; iNormal < autoSmoothVertDataTable[slot].numNormals; ++iNormal)
{
float3 n = unpack_normal(autoSmoothVertDataTable[slot].aNormal[iNormal]);
float weight = autoSmoothVertDataTable[slot].aWeight[iNormal];
float3 weightedN = n * weight;
if (acos(clamp(dot(n, vertNormal), -1.0f, 1.0f)) < autoSmoothMaxAngle + kEpsilon)
totalAutoSmoothNormal += weightedN;
}
//return autoSmoothVertDataTable[slot].numNormals > kMaxAutoSmoothNormalPerVertex ? float3(1.0f, 0.0f, 0.0f) : float3(0.0f, 1.0f, 0.0f);
return normalize_safe(totalAutoSmoothNormal, vertNormal);
}
// ID miss
slot = (slot + 1) % autoSmoothVertDataPoolSize;
}
return float3(0.0f, 0.0f, 0.0f);
}
#endif