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

/******************************************************************************/
/*
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