summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-02-24 18:11:03 -0800
committeryum <yum.food.vr@gmail.com>2026-02-24 18:11:03 -0800
commitaacad28954ceb792ecc7ebd90338466b9f70d456 (patch)
tree8a9a7b793caa594728d322646d4f3417f9b532bb
parent142805d05c999ab1c36cdecffcc305c66dd15feb (diff)
Implement wrapped lighting (direct & IBL diffuse)
-rwxr-xr-x3ner.shader8
-rwxr-xr-xfeatures.cginc4
-rwxr-xr-xglobals.cginc4
-rwxr-xr-xlighting.cginc33
-rwxr-xr-xmath.cginc9
-rw-r--r--poi.cginc72
6 files changed, 122 insertions, 8 deletions
diff --git a/3ner.shader b/3ner.shader
index aaf0dd0..d08f2c7 100755
--- a/3ner.shader
+++ b/3ner.shader
@@ -86,6 +86,14 @@ Shader "yum_food/3ner"
_Brightness_Clamp_Max("Max", Range(0, 10)) = 10
[HideInInspector] m_end_Brightness_Clamp("Brightness Clamp", Float) = 0
//endex
+
+ //ifex _Wrapped_Lighting_Enabled==0
+ [HideInInspector] m_start_Wrapped_Lighting("Wrapped Lighting", Float) = 0
+ [ThryToggle(_WRAPPED_LIGHTING)] _Wrapped_Lighting_Enabled("Enable", Float) = 0
+ _Wrapped_Lighting_Amount("Amount", Range(0, 1)) = 0.5
+ [HideInInspector] m_end_Wrapped_Lighting("Wrapped Lighting", Float) = 0
+ //endex
+
[HideInInspector] m_end_Main("Main", Float) = 0
[HideInInspector] m_start_Gimmicks("Gimmicks", Float) = 0
diff --git a/features.cginc b/features.cginc
index 00e6519..d7e81e9 100755
--- a/features.cginc
+++ b/features.cginc
@@ -23,6 +23,10 @@
#pragma shader_feature_local _BRIGHTNESS_CLAMP
//endex
+//ifex _Wrapped_Lighting_Enabled==0
+#pragma shader_feature_local _WRAPPED_LIGHTING
+//endex
+
//ifex _Bent_Normals_Enabled==0
#pragma shader_feature_local _BENT_NORMALS
//endex
diff --git a/globals.cginc b/globals.cginc
index 031fdc5..d3b2a87 100755
--- a/globals.cginc
+++ b/globals.cginc
@@ -37,6 +37,10 @@ float _Brightness_Clamp_Min;
float _Brightness_Clamp_Max;
#endif // _BRIGHTNESS_CLAMP
+#if defined(_WRAPPED_LIGHTING)
+float _Wrapped_Lighting_Amount;
+#endif // _WRAPPED_LIGHTING
+
#if defined(_AMBIENT_OCCLUSION)
texture2D _OcclusionMap;
float4 _OcclusionMap_ST;
diff --git a/lighting.cginc b/lighting.cginc
index 500141b..cae24d0 100755
--- a/lighting.cginc
+++ b/lighting.cginc
@@ -147,19 +147,40 @@ float3 yumSH9(float4 n, float3 worldPos, inout LightIndirect light) {
//
// L0+L1: dot4 per channel (n.w=1 picks up the L0 term from SHA*.w)
// L2: four quadratic terms packed into vB via swizzle multiply, plus L22
- float4 n4 = float4(n.xyz, 1.0);
float3 L0 = float3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);
- float3 L01 = float3(dot(unity_SHAr, n4), dot(unity_SHAg, n4), dot(unity_SHAb, n4));
- float4 vB = n4.xyzz * n4.yzzx;
+ float3 L1 = float3(dot(unity_SHAr, n), dot(unity_SHAg, n), dot(unity_SHAb, n));
+ float4 vB = n.xyzz * n.yzzx;
float3 L2 = float3(dot(unity_SHBr, vB), dot(unity_SHBg, vB), dot(unity_SHBb, vB))
+ unity_SHC * (n.x * n.x - n.y * n.y);
+#if defined(_WRAPPED_LIGHTING)
+ // Original coefficients: 1, 2/3, 1/4.
+ // Wrapped coefficients: 1, (2-w)/3, ((1-w)^2)/4.
+
+ // Setting w=0, the l1 band is:
+ // (2-w)/3 = 2/3
+ // 2-w = 2
+ // 1-w/2 = 1
+ float wrap_amount = _Wrapped_Lighting_Amount;
+ float l1_wrap = 1.0f - wrap_amount * 0.75f;
+ L1 *= l1_wrap;
+
+ // The l2 band is:
+ // ((1-w)^2)/4 = 1/4
+ // (1-w)^2 = 1
+ float l2_wrap = (1.0f-wrap_amount);
+ l2_wrap *= l2_wrap;
+ L2 *= l2_wrap;
+#else
+ float l1_wrap = 1.0f;
+#endif // _WRAPPED_LIGHTING
+
light.L00 = L0;
light.L01r = unity_SHAr.xyz;
light.L01g = unity_SHAg.xyz;
light.L01b = unity_SHAb.xyz;
- return L01 + L2;
+ return L0 + L1 + L2;
}
float4 getIndirectDiffuse(v2f i, Pbr pbr, inout LightIndirect light) {
@@ -234,7 +255,11 @@ void GetLighting(v2f i, Pbr pbr, out LightData data) {
// Direct lighting
data.direct.dir = getDirectLightDirection(i);
data.direct.H = normalize(data.common.V + data.direct.dir);
+#if defined(_WRAPPED_LIGHTING)
+ data.direct.NoL = wrapNoL(saturate(dot(pbr.normal, data.direct.dir)), _Wrapped_Lighting_Amount);
+#else
data.direct.NoL = saturate(dot(pbr.normal, data.direct.dir));
+#endif
data.direct.NoH = saturate(dot(pbr.normal, data.direct.H));
data.direct.LoH = saturate(dot(data.direct.dir, data.direct.H));
#if defined(_CLEARCOAT)
diff --git a/math.cginc b/math.cginc
index 02d0fe0..3d7e92e 100755
--- a/math.cginc
+++ b/math.cginc
@@ -32,15 +32,16 @@ float sin_noise_3d_fbm(float3 uvw, uint octaves, float k, float strength) {
return result;
}
-// Wrap a dot product. Assume it's already clamped.
+// Wrap NoL. Assume it's already clamped.
// At k=0, you get standard lambertian shading.
// At k=0.5, you get half-lambertian shading.
// At k=1.0, you get flat shading.
// k must be on [0, 1].
// Energy preserving, within some small bound.
-float wrapDotProduct(float XoY, float k) {
- float lambertian = XoY;
- float half_lambertian = pow(max(1e-4, (XoY + 0.5f) / (1.0f + 0.5f)), 2);
+float wrapNoL(float NoL, float k) {
+ float lambertian = NoL;
+ float tmp = (NoL + 0.5f) / (1.0f + 0.5f);
+ float half_lambertian = tmp * tmp;
float flat = RCP_PI;
if (k < 0.5) {
diff --git a/poi.cginc b/poi.cginc
new file mode 100644
index 0000000..b92e414
--- /dev/null
+++ b/poi.cginc
@@ -0,0 +1,72 @@
+#ifndef __POI_INC
+#define __POI_INC
+
+/*
+MIT License
+
+Copyright (c) 2023 Poiyomi Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+static const float Epsilon = 1e-10;
+float3 RGBtoHCV(in float3 RGB)
+{
+ // Based on work by Sam Hocevar and Emil Persson
+ float4 P = (RGB.g < RGB.b) ? float4(RGB.bg, -1.0, 2.0 / 3.0) : float4(RGB.gb, 0.0, -1.0 / 3.0);
+ float4 Q = (RGB.r < P.x) ? float4(P.xyw, RGB.r) : float4(RGB.r, P.yzx);
+ float C = Q.x - min(Q.w, Q.y);
+ float H = abs((Q.w - Q.y) / (6 * C + Epsilon) + Q.z);
+ return float3(H, C, Q.x);
+}
+
+float3 RGBtoHSV(in float3 RGB)
+{
+ float3 HCV = RGBtoHCV(RGB);
+ float S = HCV.y / (HCV.z + Epsilon);
+ return float3(HCV.x, S, HCV.z);
+}
+
+float3 HUEtoRGB(in float H)
+{
+ float R = abs(H * 6 - 3) - 1;
+ float G = 2 - abs(H * 6 - 2);
+ float B = 2 - abs(H * 6 - 4);
+ return saturate(float3(R, G, B));
+}
+
+float3 HSVtoRGB(in float3 HSV)
+{
+ float3 RGB = HUEtoRGB(HSV.x);
+ return ((RGB - 1) * HSV.y + 1) * HSV.z;
+}
+
+float calculateluminance(float3 color)
+{
+ return color.r * 0.299 + color.g * 0.587 + color.b * 0.114;
+}
+
+bool SceneHasReflections()
+{
+ float width, height;
+ unity_SpecCube0.GetDimensions(width, height);
+ return !(width * height < 2);
+}
+
+#endif // __POI_INC