diff options
| author | yum <yum.food.vr@gmail.com> | 2026-02-24 18:11:03 -0800 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2026-02-24 18:11:03 -0800 |
| commit | aacad28954ceb792ecc7ebd90338466b9f70d456 (patch) | |
| tree | 8a9a7b793caa594728d322646d4f3417f9b532bb | |
| parent | 142805d05c999ab1c36cdecffcc305c66dd15feb (diff) | |
Implement wrapped lighting (direct & IBL diffuse)
| -rwxr-xr-x | 3ner.shader | 8 | ||||
| -rwxr-xr-x | features.cginc | 4 | ||||
| -rwxr-xr-x | globals.cginc | 4 | ||||
| -rwxr-xr-x | lighting.cginc | 33 | ||||
| -rwxr-xr-x | math.cginc | 9 | ||||
| -rw-r--r-- | poi.cginc | 72 |
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) @@ -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 |
