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.
278 lines
8.1 KiB
HLSL
278 lines
8.1 KiB
HLSL
/******************************************************************************/
|
|
/*
|
|
Project - MudBun
|
|
Publisher - Long Bunny Labs
|
|
http://LongBunnyLabs.com
|
|
Author - Ming-Lun "Allen" Chou
|
|
http://AllenChou.net
|
|
*/
|
|
/******************************************************************************/
|
|
|
|
#ifndef MUDBUN_SPLAT_COMMON
|
|
#define MUDBUN_SPLAT_COMMON
|
|
|
|
#ifdef MUDBUN_VALID
|
|
|
|
#include "../GenPointDefs.cginc"
|
|
#include "../Math/Codec.cginc"
|
|
#include "../Math/Vector.cginc"
|
|
#include "../Math/Quaternion.cginc"
|
|
#include "../MeshingModeDefs.cginc"
|
|
#include "../Noise/ClassicNoise3D.cginc"
|
|
#include "../Noise/SimplexNoise3D.cginc"
|
|
#include "../Noise/RandomNoise.cginc"
|
|
#include "../NormalDefs.cginc"
|
|
#include "../RenderModeDefs.cginc"
|
|
#include "../SDF/Util.cginc"
|
|
#include "../VoxelDefs.cginc"
|
|
|
|
#ifdef MUDBUN_QUAD_SPLATS
|
|
static const float2 splatVertOffsetLsTableQuad[6] =
|
|
{
|
|
float2(-0.5f, -0.5f),
|
|
float2( 0.5f, 0.5f),
|
|
float2( 0.5f, -0.5f),
|
|
float2(-0.5f, -0.5f),
|
|
float2(-0.5f, 0.5f),
|
|
float2( 0.5f, 0.5f),
|
|
};
|
|
#else
|
|
static const float2 splatVertOffsetLsTableTri[3] =
|
|
{
|
|
float2(-0.866f, -0.5f),
|
|
float2( 0.0f , 1.0f),
|
|
float2( 0.866f, -0.5f),
|
|
};
|
|
#endif
|
|
|
|
#endif
|
|
|
|
void mudbun_splat_vert
|
|
(
|
|
uint id,
|
|
out uint iGenPoint,
|
|
out float4 vertexWs,
|
|
out float3 vertexLs,
|
|
out float3 normalWs,
|
|
out float3 normalLs,
|
|
out float3 tangentWs,
|
|
out float3 tangentLs,
|
|
out float3 centerWs,
|
|
out float3 centerLs,
|
|
out float2 tex,
|
|
out float hash,
|
|
out float sdfValue,
|
|
out float3 normal2dLs,
|
|
out float3 normal2dWs
|
|
)
|
|
{
|
|
#if MUDBUN_VALID
|
|
|
|
iGenPoint = id;
|
|
|
|
uint iOffset = 0;
|
|
#ifdef MUDBUN_QUAD_SPLATS
|
|
iGenPoint = id / 6;
|
|
iOffset = id % 6;
|
|
#else
|
|
iGenPoint = id / 3;
|
|
iOffset = id % 3;
|
|
#endif
|
|
|
|
switch (meshingMode)
|
|
{
|
|
case kMeshingModeSurfaceNets:
|
|
case kMeshingModeDualContouring:
|
|
iGenPoint *= 6;
|
|
break;
|
|
}
|
|
|
|
float3 rawCenterLs = aGenPoint[iGenPoint].posNorm.xyz;
|
|
float3 noiseSeedBase = rawCenterLs * splatJitterNoisiness / voxelSize;
|
|
float noiseSeedOffset = 10.0f * splatJitterNoisiness;
|
|
|
|
normalLs = unpack_normal(aGenPoint[iGenPoint].posNorm.w);
|
|
normal2dLs = unpack_normal(aGenPoint[iGenPoint].norm2d);
|
|
|
|
float normalShift = splatNormalShift;
|
|
if (splatNormalShiftJitter > kEpsilon)
|
|
{
|
|
float noiseRes = mbn_cnoise(noiseSeedBase + noiseSeedOffset);
|
|
normalShift = sign(normalShift) * max(0.0f, abs(normalShift) * (1.0f + (noiseRes - 0.5f) * splatNormalShiftJitter));
|
|
}
|
|
|
|
centerLs = rawCenterLs + normalShift * normalLs;
|
|
|
|
float3 originalNormalLs = normalLs;
|
|
|
|
// jitter orientation after normal shift has been applied
|
|
noiseSeedOffset += noiseSeedOffset;
|
|
if (splatOrientationJitter > kEpsilon)
|
|
{
|
|
float3 axisNoiseRes = snoise_grad(noiseSeedBase).xyz;
|
|
float angleNoiseRes = mbn_cnoise(noiseSeedBase + noiseSeedOffset);
|
|
float angle = angleNoiseRes * kPi;
|
|
float4 q = quat_axis_angle(normalize_safe(axisNoiseRes, normalLs), angle * splatOrientationJitter);
|
|
normalLs = quat_rot(q, normalLs);
|
|
}
|
|
|
|
float3 normalJitter = float3(0.01f * (mbn_rand(centerLs) * 0.6f + 0.4f), 0.0f, 0.0f); // mitigate singularities
|
|
tangentLs = normalize(find_ortho_consistent(normalLs + normalJitter));
|
|
|
|
noiseSeedOffset += noiseSeedOffset;
|
|
if (splatPositionJitter > kEpsilon)
|
|
{
|
|
float noiseRes = mbn_cnoise(noiseSeedBase + noiseSeedOffset);
|
|
float angle = noiseRes * kPi;
|
|
float4 q = quat_axis_angle(normalLs, angle);
|
|
float3 jitterDirLs = quat_rot(q, tangentLs);
|
|
centerLs += jitterDirLs * noiseRes * splatPositionJitter * voxelSize;
|
|
}
|
|
centerWs = mul(localToWorld, float4(centerLs, 1.0f)).xyz;
|
|
|
|
//float3 camDir = normalize(UNITY_MATRIX_V._m20_m21_m22);
|
|
float3 camDir = normalize(_WorldSpaceCameraPos - centerWs);
|
|
|
|
normalWs = normalize(mul(localToWorldIt, float4(normalLs, 0.0f)).xyz);
|
|
normal2dWs = normalize(mul(localToWorldIt, float4(normal2dLs, 0.0f)).xyz);
|
|
tangentWs = normalize(mul(localToWorldIt, float4(tangentLs, 0.0f)).xyz);
|
|
|
|
#if defined(MUDBUN_SHADOW_PASS)
|
|
float3 geomNormal =
|
|
splatShadowsMatchCameraFacing > 0
|
|
? normalize(lerp(normalWs, camDir, splatCameraFacing))
|
|
: normalWs;
|
|
#else
|
|
float3 geomNormal = normalize(lerp(normalWs, camDir, splatCameraFacing));
|
|
#endif
|
|
|
|
float3 geomTangent = normalize(find_ortho_consistent(geomNormal + normalJitter));
|
|
float3 geomTangent2 = normalize(cross(geomTangent, geomNormal));
|
|
|
|
noiseSeedOffset += noiseSeedOffset;
|
|
if (splatRotationJitter > kEpsilon)
|
|
{
|
|
float noiseRes = mbn_cnoise(noiseSeedBase + noiseSeedOffset);
|
|
float angle = noiseRes * splatRotationJitter * kPi;
|
|
float4 q = quat_axis_angle(geomNormal, angle);
|
|
geomTangent = quat_rot(q, geomTangent);
|
|
geomTangent2 = quat_rot(q, geomTangent2);
|
|
}
|
|
|
|
if (splatOriginalNormalBlend > kEpsilon)
|
|
{
|
|
normalLs = lerp(normalLs, originalNormalLs, splatOriginalNormalBlend);
|
|
normalWs = normalize(mul(localToWorldIt, float4(normalLs, 0.0f)).xyz);
|
|
}
|
|
|
|
if (should_quantize_normal())
|
|
{
|
|
normalLs = quantize_normal(normalLs);
|
|
normalWs = normalize(mul(localToWorldIt, float4(normalLs, 0.0f)).xyz);
|
|
}
|
|
|
|
if (splatNormalsMatchCameraFacing > 0)
|
|
{
|
|
normalWs = camDir;
|
|
normalLs = normalize(mul(localToWorld, float4(normalWs, 0.0f)).xyz);
|
|
}
|
|
|
|
#ifdef MUDBUN_QUAD_SPLATS
|
|
tex = splatVertOffsetLsTableQuad[iOffset];
|
|
#else
|
|
tex = splatVertOffsetLsTableTri[iOffset];
|
|
#endif
|
|
|
|
float sizeMult = aGenPoint[iGenPoint].material.size;
|
|
noiseSeedOffset += noiseSeedOffset;
|
|
if (splatSizeJitter > kEpsilon)
|
|
{
|
|
float noiseRes = mbn_cnoise(noiseSeedBase + noiseSeedOffset);
|
|
sizeMult = max(0.0f, sizeMult * (1.0f + (noiseRes - 0.5f) * splatSizeJitter));
|
|
}
|
|
|
|
float effectiveSplatSize = splatSize * sizeMult;
|
|
float2 splatVertOffsetLs = effectiveSplatSize * tex;
|
|
float3 splatVertOffsetWs = splatVertOffsetLs.x * localToWorldScale.xyz * geomTangent + splatVertOffsetLs.y * localToWorldScale.xyz * geomTangent2;
|
|
vertexWs = float4(centerWs + splatVertOffsetWs, 1.0f);
|
|
vertexLs = mul(worldToLocal, vertexWs).xyz;
|
|
|
|
#if !defined(MUDBUN_SHADOW_PASS)
|
|
vertexWs.xyz -= splatScreenSpaceFlattening * project_vec(splatVertOffsetWs, camDir);
|
|
#endif
|
|
|
|
hash = aGenPoint[iGenPoint].material.hash;
|
|
|
|
sdfValue = aGenPoint[iGenPoint].sdfValue;
|
|
|
|
#endif
|
|
}
|
|
|
|
void mudbun_splat_vert
|
|
(
|
|
uint id,
|
|
out float4 vertexWs,
|
|
out float3 vertexLs,
|
|
out float3 normalWs,
|
|
out float3 normalLs,
|
|
out float3 tangentWs,
|
|
out float3 tangentLs,
|
|
out float3 centerWs,
|
|
out float3 centerLs,
|
|
out float4 color,
|
|
out float4 emissionHash,
|
|
out float2 metallicSmoothness,
|
|
out float2 tex,
|
|
out float4 textureWeight,
|
|
out float sdfValue,
|
|
out float3 normal2dLs,
|
|
out float3 normal2dWs
|
|
)
|
|
{
|
|
#ifdef MUDBUN_VALID
|
|
|
|
uint iGenPoint = 0;
|
|
mudbun_splat_vert(id, iGenPoint, vertexWs, vertexLs, normalWs, normalLs, tangentWs, tangentLs, centerWs, centerLs, tex, emissionHash.a, sdfValue, normal2dLs, normal2dWs);
|
|
|
|
color = unpack_rgba(aGenPoint[iGenPoint].material.color);
|
|
emissionHash.rgb = unpack_rgba(aGenPoint[iGenPoint].material.emissionTightness).rgb;
|
|
if (!IsGammaSpace())
|
|
{
|
|
color.rgb = gamma_to_linear_space(color.rgb);
|
|
emissionHash.rgb = gamma_to_linear_space(emissionHash.rgb);
|
|
}
|
|
|
|
metallicSmoothness = unpack_saturated(aGenPoint[iGenPoint].material.metallicSmoothness);
|
|
textureWeight = unpack_rgba(aGenPoint[iGenPoint].material.textureWeight);
|
|
|
|
if (splatColorJitter > kEpsilon)
|
|
{
|
|
float noiseRes = mbn_cnoise(3 * splatJitterNoisiness + aGenPoint[iGenPoint].posNorm.xyz * splatJitterNoisiness / voxelSize);
|
|
color.rgb = saturate(color.rgb + splatColorJitter * (noiseRes - 0.5f));
|
|
}
|
|
|
|
#else
|
|
|
|
vertexWs = float4(0.0f, 0.0f, 0.0f, 1.0f);
|
|
vertexLs = float3(0.0f, 0.0f, 0.0f);
|
|
normalWs = float3(0.0f, 0.0f, 0.0f);
|
|
normalLs = float3(0.0f, 0.0f, 0.0f);
|
|
normalWs = float3(0.0f, 0.0f, 0.0f);
|
|
tangentWs = float3(0.0f, 0.0f, 0.0f);
|
|
tangentLs = float3(0.0f, 0.0f, 0.0f);
|
|
centerWs = float3(0.0f, 0.0f, 0.0f);
|
|
centerLs = float3(0.0f, 0.0f, 0.0f);
|
|
color = float4(0.0f, 0.0f, 0.0f, 1.0f);
|
|
emissionHash = float4(0.0f, 0.0f, 0.0f, 0.0f);
|
|
metallicSmoothness = float2(0.0f, 0.0f);
|
|
tex = float2(0.0f, 0.0f);
|
|
textureWeight = int4(1.0f, 0.0f, 0.0f, 0.0f);
|
|
sdfValue = 0.0f;
|
|
normal2dLs = float3(0.0f, 0.0f, 0.0f);
|
|
normal2dWs = float3(0.0f, 0.0f, 0.0f);
|
|
|
|
#endif
|
|
}
|
|
|
|
#endif
|