summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2025-06-30 10:14:43 -0700
committeryum <yum.food.vr@gmail.com>2025-06-30 10:14:43 -0700
commitc2f86fa940195d07e2c82614985b249418f0d4f6 (patch)
tree3a060bc60e78f49be8cc6b6b6bcc1830e5219c03
parent4f786eba18f5535b1cba10ef0e4dc2a269dde705 (diff)
more brdf tweaks - mainly fix how reflectance is handled
-rw-r--r--2ner.cginc7
-rw-r--r--2ner.shader2
-rw-r--r--yum_brdf.cginc6
-rw-r--r--yum_lighting.cginc51
-rw-r--r--yum_pbr.cginc3
5 files changed, 56 insertions, 13 deletions
diff --git a/2ner.cginc b/2ner.cginc
index e1bf6f7..d1af3da 100644
--- a/2ner.cginc
+++ b/2ner.cginc
@@ -430,8 +430,11 @@ float4 frag(v2f i, uint facing : SV_IsFrontFace
float4 lit = YumBRDF(i, l, pbr);
#endif
- lit.rgb += LightVolumeSpecular(pbr.albedo, pbr.smoothness, pbr.metallic,
- pbr.normal, l.view_dir, l.L00, l.L01r, l.L01g, l.L01b);
+ [branch]
+ if (_UdonLightVolumeEnabled) {
+ lit.rgb += LightVolumeSpecular(pbr.albedo, pbr.smoothness, pbr.metallic,
+ pbr.normal, l.view_dir, l.L00, l.L01r, l.L01g, l.L01b);
+ }
#if defined(_HARNACK_TRACING)
pbr.albedo = harnack_output.color;
diff --git a/2ner.shader b/2ner.shader
index 7a36dfa..f010022 100644
--- a/2ner.shader
+++ b/2ner.shader
@@ -2118,7 +2118,7 @@ Shader "yum_food/2ner"
[HideInInspector] m_FilamentStuff("Filament stuff", Float) = 0
[NonModifiableTextureData]_DFG("DFG", 2D) = "white" {}
- [ThryWideEnum(Water, 0.02, Skin, 0.028, Eyes, 0.025, Hair, 0.046, Teeth, 0.058, Fabric, 0.05, Stone, 0.045, Plastic, 0.045, Glass, 0.06, Gemstone, 0.07, Diamond, 0.18)]_reflectance("Reflectance", Float) = 0.028
+ [ThryWideEnum(Water, 0.35, Skin, 0.42, Eyes, 0.39, Hair, 0.54, Teeth, 0.6, Fabric, 0.55, Stone, 0.55, Plastic, 0.50, Glass, 0.56, Gemstone, 0.9, Diamond, 1.0)]_reflectance("Reflectance", Float) = 0.55
_ExposureOcclusion("Exposure Occlusion", Float) = 1
[Helpbox]_reflectance_help("Values are documented in the filament whitepaper here https://google.github.io/filament/Filament.html#toc4.8.3.2", Float) = 1
//ifex _Material_Type_Cloth_Enabled==0
diff --git a/yum_brdf.cginc b/yum_brdf.cginc
index 224afc6..67c425c 100644
--- a/yum_brdf.cginc
+++ b/yum_brdf.cginc
@@ -119,10 +119,7 @@ float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) {
float3 direct_standard;
{
- // Fix reflectance calculation - _reflectance is already a 0-1 value, not an f0 value
- // Default reflectance for dielectrics is typically 0.5, which gives f0 = 0.04
- const float dielectric_f0 = _reflectance;
- // f0 = amount of light reflected back when viewing surface at a right angle
+ const float dielectric_f0 = computeDielectricF0(_reflectance);
const float3 f0 = lerp(dielectric_f0, pbr.albedo, pbr.metallic);
const float3 dfg = PrefilteredDFG_LUT(pbr.roughness_perceptual, NoV);
const float3 E = specularDFG(dfg, f0);
@@ -178,7 +175,6 @@ float4 YumBRDF(v2f i, const YumLighting light, YumPbr pbr) {
float3 diffuseColor = computeDiffuseColor(pbr.albedo, pbr.metallic);
float3 Fd = diffuseColor * light.diffuse * (1.0 - E) * pbr.ao;
- // Apply energy compensation to indirect specular (critical fix)
float3 Fr = E * light.specular * specularSingleBounceAO;
indirect_standard = Fr + Fd;
diff --git a/yum_lighting.cginc b/yum_lighting.cginc
index 8920688..103eb18 100644
--- a/yum_lighting.cginc
+++ b/yum_lighting.cginc
@@ -125,8 +125,10 @@ float GetLodRoughness(float roughness) {
}
float3 getIndirectSpecular(v2f i, YumPbr pbr, float3 view_dir, float diffuse_luminance) {
- float roughness = GetLodRoughness(pbr.roughness_perceptual);
- float3 reflect_dir = reflect(-view_dir, pbr.normal);
+ float3 reflect_dir = reflect(-view_dir, pbr.normal);
+
+ // Apply dominant direction modification for rough surfaces
+ float3 dominant_reflect_dir = lerp(reflect_dir, pbr.normal, pbr.roughness * pbr.roughness);
UnityGIInput data;
data.worldPos = i.worldPos;
@@ -144,7 +146,8 @@ float3 getIndirectSpecular(v2f i, YumPbr pbr, float3 view_dir, float diffuse_lum
data.probePosition[1] = unity_SpecCube1_ProbePosition;
#endif
- const float3 env_refl = UnityGI_prefilteredRadiance(data, roughness, reflect_dir);
+ // Pass perceptualRoughness directly - UnityGI_prefilteredRadiance handles remapping internally
+ const float3 env_refl = UnityGI_prefilteredRadiance(data, pbr.roughness_perceptual, dominant_reflect_dir);
#if defined(_FALLBACK_CUBEMAP)
// Check if there's no valid scene cubemap
@@ -157,7 +160,7 @@ float3 getIndirectSpecular(v2f i, YumPbr pbr, float3 view_dir, float diffuse_lum
reflectVector = BoxProjectedCubemapDirection(reflectVector, data.worldPos, /*probe_position=*/0, /*box_min=*/-1, /*box_max=*/1);
#endif
- half mip = roughness * UNITY_SPECCUBE_LOD_STEPS;
+ half mip = pbr.roughness_perceptual * UNITY_SPECCUBE_LOD_STEPS;
float4 envSample = UNITY_SAMPLE_TEXCUBE_LOD(_Fallback_Cubemap, reflectVector, mip);
canned_refl = DecodeHDR(envSample, _Fallback_Cubemap_HDR) * _Fallback_Cubemap_Brightness * diffuse_luminance;
}
@@ -173,6 +176,45 @@ float3 getIndirectSpecular(v2f i, YumPbr pbr, float3 view_dir, float diffuse_lum
}
float3 yumSH9(float4 n, float3 worldPos, inout YumLighting light) {
+//#define YUM_SH9_STANDARD
+#if defined(YUM_SH9_STANDARD)
+ // Unity gives us the first three bands (L0-L2) of SH coefficients as follows:
+ // unity_SHA*.w: L0 coefficients
+ // unity_SHA*.xyz: L1 coefficients
+ // unity_SHB*: first four of the L2 coefficients
+ // unity_SHC: last L2 coefficient
+
+ // Parse out coefficients into a simpler but less efficient format.
+ float3 L00 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
+ float3 L1_1 = float3(unity_SHAr.x, unity_SHAg.x, unity_SHAb.x);
+ float3 L10 = float3(unity_SHAr.y, unity_SHAg.y, unity_SHAb.y);
+ float3 L11 = float3(unity_SHAr.z, unity_SHAg.z, unity_SHAb.z);
+ float3 L2_2 = float3(unity_SHBr.x, unity_SHBg.x, unity_SHBb.x);
+ float3 L2_1 = float3(unity_SHBr.y, unity_SHBg.y, unity_SHBb.y);
+ float3 L20 = float3(unity_SHBr.z, unity_SHBg.z, unity_SHBb.z);
+ float3 L21 = float3(unity_SHBr.w, unity_SHBg.w, unity_SHBb.w);
+ float3 L22 = unity_SHC;
+
+ // Equation 13 from "An Efficient Representation for Irradiance Environment
+ // Maps" by Ramamoorthi and Hanrahan. Note that the order of some
+ // coefficients is different, and normalization constants have been
+ // premultiplied by Unity.
+ float3 L0 = L00;
+ float3 L1 = L1_1 * n.x + L10 * n.y + L11 * n.z;
+ float3 L2 =
+ L2_2 * n.x * n.y +
+ L2_1 * n.y * n.z +
+ L20 * n.z * n.z +
+ L21 * n.x * n.z +
+ L22 * (n.x * n.x - n.y * n.y);
+
+ light.L00 = L00;
+ light.L01r = unity_SHAr.xyz;
+ light.L01g = unity_SHAg.xyz;
+ light.L01b = unity_SHAb.xyz;
+
+ return L0 + L1 + L2;
+#else
LightVolumeSH(worldPos, light.L00, light.L01r, light.L01g, light.L01b);
#if defined(_SPHERICAL_HARMONICS_L1)
return LightVolumeEvaluate(n.xyz, light.L00, light.L01r, light.L01g, light.L01b);
@@ -184,6 +226,7 @@ float3 yumSH9(float4 n, float3 worldPos, inout YumLighting light) {
return LightVolumeEvaluate(n.xyz, light.L00, 0, 0, 0);
}
#endif
+#endif
}
float4 getIndirectDiffuse(v2f i, float4 vertexLightColor,
diff --git a/yum_pbr.cginc b/yum_pbr.cginc
index 08bdd67..8df2fde 100644
--- a/yum_pbr.cginc
+++ b/yum_pbr.cginc
@@ -129,7 +129,8 @@ YumPbr GetYumPbr(v2f i, float3x3 tangentToWorld) {
#endif
applyDecals(i, result.albedo, normal_tangent, result.metallic, result.smoothness, result.emission);
- result.smoothness = min(0.99, result.smoothness);
+ const float min_roughness_perceptual = 0.045f;
+ result.smoothness = min(1.0f - min_roughness_perceptual, result.smoothness);
propagateRoughness(result.smoothness, result.roughness_perceptual, result.roughness);
#if defined(_OKLCH_CORRECTION)