diff options
| author | yum <yum.food.vr@gmail.com> | 2024-10-08 17:32:09 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2024-10-08 17:32:09 -0700 |
| commit | a396182815db14f5a6eed26799dd425506a70686 (patch) | |
| tree | 38f1d2ca8cb3cd6bd8b87fdcb2678ac2e911e90b | |
| parent | bcadf1d091efe76e7a1b2393f87f7e24128b723b (diff) | |
Add fog parameters; add Unity fog to fwd/add passes
| -rw-r--r-- | Editor/tooner.cs | 20 | ||||
| -rw-r--r-- | fog.cginc | 101 | ||||
| -rw-r--r-- | globals.cginc | 12 | ||||
| -rw-r--r-- | interpolators.cginc | 30 | ||||
| -rw-r--r-- | math.cginc | 7 | ||||
| -rw-r--r-- | pbr.cginc | 2 | ||||
| -rw-r--r-- | tooner.shader | 10 | ||||
| -rw-r--r-- | tooner_lighting.cginc | 28 | ||||
| -rw-r--r-- | tooner_outline_pass.cginc | 1 |
9 files changed, 147 insertions, 64 deletions
diff --git a/Editor/tooner.cs b/Editor/tooner.cs index 5fc26bd..156e8c2 100644 --- a/Editor/tooner.cs +++ b/Editor/tooner.cs @@ -2018,6 +2018,26 @@ public class ToonerGUI : ShaderGUI { } EditorGUI.indentLevel += 1; + + bc = FindProperty("_Gimmick_Fog_00_Density"); + RangeProperty(bc, "Density"); + bc = FindProperty("_Gimmick_Fog_00_Radius"); + FloatProperty(bc, "Radius"); + bc = FindProperty("_Gimmick_Fog_00_Step_Size"); + FloatProperty(bc, "Step size"); + bc = FindProperty("_Gimmick_Fog_00_Max_Ray"); + FloatProperty(bc, "Max ray length (m)"); + bc = FindProperty("_Gimmick_Fog_00_Noise_Scale"); + FloatProperty(bc, "Noise scale"); + bc = FindProperty("_Gimmick_Fog_00_Noise_Exponent"); + FloatProperty(bc, "Noise exponent"); + bc = FindProperty("_Gimmick_Fog_00_Normal_Cutoff"); + RangeProperty(bc, "Normal cutoff"); + bc = FindProperty("_Gimmick_Fog_00_Albedo_Cutoff"); + RangeProperty(bc, "Albedo cutoff"); + bc = FindProperty("_Gimmick_Fog_00_Ray_Origin_Randomization"); + RangeProperty(bc, "Ray origin randomization"); + EditorGUI.indentLevel -= 1; } @@ -13,28 +13,46 @@ struct Fog00PBR { float4 albedo; float3 normal; float depth; + float ao; }; -#define FOG_MAX_RAY 10 -#define FOG_RADIUS 25 -#define FOG_NOISE_SCALE 2 float map(float3 p) { float density = 0; - float t = _Time[1]; - density += perlin_noise_3d(p * FOG_NOISE_SCALE * 1.0 + t) * saturate(FOG_RADIUS - length(p)) / 2.0; - density += perlin_noise_3d(p * FOG_NOISE_SCALE * 1.7 + t) * saturate(FOG_RADIUS - length(p)) / 4.0; - density += perlin_noise_3d(p * FOG_NOISE_SCALE * 2.9 + t) * saturate(FOG_RADIUS - length(p)) / 8.0; - density += perlin_noise_3d(p * FOG_NOISE_SCALE * 4.3 + t) * saturate(FOG_RADIUS - length(p)) / 16.0; - - return density; + float t = _Time[1] * 0.5; + float radius = saturate(_Gimmick_Fog_00_Radius - length(p)); + float tmp; + tmp = perlin_noise_3d(p * _Gimmick_Fog_00_Noise_Scale * 3.1 + t) * radius * 0.5; + density += tmp; + tmp = perlin_noise_3d(p * _Gimmick_Fog_00_Noise_Scale * 1.7 + t) * radius * 0.5; + density *= 0.5; + density += tmp; + tmp = perlin_noise_3d(p * _Gimmick_Fog_00_Noise_Scale * 1.0 + t) * radius * 0.5; + density *= 0.5; + density += tmp; + + density = pow(density, _Gimmick_Fog_00_Noise_Exponent); + + // Note: this term annihilates performance by creating large open areas. Long + // avgerage view ray = bad perf! + #if 1 + tmp = perlin_noise_3d(p * _Gimmick_Fog_00_Noise_Scale * 0.167 + t/4) * radius - 0.5; + tmp *= 0.2; + density += tmp; + #endif + + return saturate(density); } float3 get_normal(float3 p) { - float3 e = float3(0.01, 0, 0); + float3 e = float3(0.001, 0, 0); + float center = map(p); + + // Prevent NaN + float e2 = 1E-9; return normalize(float3( - map(p + e.xyz) - map(p), - map(p + e.yxz) - map(p), - map(p + e.zyx) - map(p))); + map(p + e.xyz) - center, + map(p + e.yxz) - center, + map(p + e.zyx) - center) + e2); } Fog00PBR getFog00(v2f i) { @@ -61,11 +79,11 @@ Fog00PBR getFog00(v2f i) { float3 ro = cam_pos; bool no_intersection = false; - if (length(ro) > FOG_RADIUS) { + if (length(ro) > _Gimmick_Fog_00_Radius) { float3 l = ro; float a = 1; float b = 2 * dot(rd, l); - float c = dot(l, l) - FOG_RADIUS * FOG_RADIUS; + float c = dot(l, l) - _Gimmick_Fog_00_Radius * _Gimmick_Fog_00_Radius; float t0, t1; if (solveQuadratic(a, b, c, t0, t1)) { no_intersection = (t0 < 0) * (t1 < 0); @@ -77,37 +95,54 @@ Fog00PBR getFog00(v2f i) { // Factor of 10 on `screen_uv*10` eliminates visible striping artifact that // is visible with no factor. - float dither = rand2(screen_uv*10) - 0.5; - ro += rd * (1.0 + dither); + float dither = rand2(screen_uv*10) * _Gimmick_Fog_00_Step_Size * _Gimmick_Fog_00_Ray_Origin_Randomization; + ro += rd * (0.1 + dither); float world_pos_depth_hit_l = length(world_pos_depth_hit - ro); float4 acc = 0; - float step_size = 0.5; uint step_count = floor(min( - FOG_MAX_RAY / step_size, - world_pos_depth_hit_l / step_size)); + _Gimmick_Fog_00_Max_Ray / _Gimmick_Fog_00_Step_Size, + world_pos_depth_hit_l / _Gimmick_Fog_00_Step_Size)); step_count *= (1 - no_intersection); - float density = 0.5; - float3 normal_weighted_sum = 0; + float3 normal = i.normal; + float ao = 0; for (uint ii = 0; ii < step_count; ii++) { - float3 p = ro + (rd * step_size) * ii; + float3 p = ro + (rd * _Gimmick_Fog_00_Step_Size) * ii; + float4 c = float4(1, 1, 1, map(p)); -#if 1 - float3 n = get_normal(p); - normal_weighted_sum += n * c.a; -#endif - c *= density; + c.a = saturate(c.a * _Gimmick_Fog_00_Density * _Gimmick_Fog_00_Step_Size); + acc += c * (1.0 - acc.a); + + const float ao_str = 0.3; + float cur_ao = saturate(length(ro) / _Gimmick_Fog_00_Radius) * ao_str + (1.0 - ao_str); + ao = cur_ao * (1.0 - acc.a) + acc.a * ao; + + // Performance hack: stop blending normals after enough accumulation. + if (acc.a < _Gimmick_Fog_00_Normal_Cutoff) { + float3 n = get_normal(p); + float n_interp = saturate(c.a * (1.0 - acc.a) * rcp(_Gimmick_Fog_00_Normal_Cutoff)); + normal = MY_BLEND_NORMALS(normal, n, n_interp); + } + if (acc.a > _Gimmick_Fog_00_Albedo_Cutoff) { + acc /= acc.a; + break; + } + // Performance hack: stop iterating if we go outside of the sphere. + if (dot(p, p) > _Gimmick_Fog_00_Radius * _Gimmick_Fog_00_Radius) { + break; + } } Fog00PBR pbr; - pbr.albedo = saturate(acc); - pbr.albedo.rgb = saturate(pow(pbr.albedo.rgb, 3.0) * 5); + pbr.albedo.rgb = 1; + pbr.albedo.a = saturate(acc.a); + pbr.ao = ao; -#if 0 - pbr.normal = normalize(normal_weighted_sum); +#if 1 + pbr.normal = normalize(normal); #else pbr.normal = i.normal; #endif diff --git a/globals.cginc b/globals.cginc index 906ee1c..523e254 100644 --- a/globals.cginc +++ b/globals.cginc @@ -706,5 +706,17 @@ float _Gimmick_AL_Chroma_00_Hue_Shift_Theta; #endif #endif +#if defined(_GIMMICK_FOG_00) +float _Gimmick_Fog_00_Max_Ray; +float _Gimmick_Fog_00_Radius; +float _Gimmick_Fog_00_Step_Size; +float _Gimmick_Fog_00_Noise_Scale; +float _Gimmick_Fog_00_Noise_Exponent; +float _Gimmick_Fog_00_Density; +float _Gimmick_Fog_00_Normal_Cutoff; +float _Gimmick_Fog_00_Albedo_Cutoff; +float _Gimmick_Fog_00_Ray_Origin_Randomization; +#endif + #endif diff --git a/interpolators.cginc b/interpolators.cginc index 9763bca..57b78e4 100644 --- a/interpolators.cginc +++ b/interpolators.cginc @@ -35,14 +35,15 @@ struct v2f float2 uv5 : TEXCOORD5; float2 uv6 : TEXCOORD6; float2 uv7 : TEXCOORD7; - SHADOW_COORDS(8) #endif - float3 worldPos : TEXCOORD9; - float3 normal : TEXCOORD10; - float3 objPos : TEXCOORD11; - float3 centerCamPos : TEXCOORD12; + float2 fogCoord: TEXCOORD8; + SHADOW_COORDS(9) + float3 worldPos : TEXCOORD10; + float3 normal : TEXCOORD11; + float3 objPos : TEXCOORD12; + float3 centerCamPos : TEXCOORD13; - float2 screenPos : TEXCOORD13; + float2 screenPos : TEXCOORD14; UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO @@ -81,18 +82,19 @@ struct v2f float2 uv5 : TEXCOORD5; float2 uv6 : TEXCOORD6; float2 uv7 : TEXCOORD7; - SHADOW_COORDS(8) #endif - float3 normal : TEXCOORD9; - float4 tangent : TEXCOORD10; - float3 worldPos : TEXCOORD11; - float3 objPos : TEXCOORD12; - float3 centerCamPos : TEXCOORD13; + float2 fogCoord: TEXCOORD8; + unityShadowCoord4 _ShadowCoord : TEXCOORD9; + float3 normal : TEXCOORD10; + float4 tangent : TEXCOORD11; + float3 worldPos : TEXCOORD12; + float3 objPos : TEXCOORD13; + float3 centerCamPos : TEXCOORD14; - float2 screenPos : TEXCOORD14; + float2 screenPos : TEXCOORD15; #if defined(VERTEXLIGHT_ON) - float3 vertexLightColor : TEXCOORD15; + float3 vertexLightColor : TEXCOORD16; #endif UNITY_VERTEX_INPUT_INSTANCE_ID @@ -3,6 +3,13 @@ #ifndef __MATH_INC #define __MATH_INC +// Hacky parameterizable whiteout blending. Probably some big mistakes but it +// passes the eyeball test. +// At w=0.5, this looks kinda like whiteout blending. +// At w=0, this returns n0. +// At w=1, this returns n1. +#define MY_BLEND_NORMALS(n0, n1, w) normalize(float3((n0.xy * (1 - w) + n1.xy * w), lerp(1, n0.z, (1-w)) * lerp(1, n1.z, w))) + // Complex numbers typedef float2 complex; @@ -460,6 +460,8 @@ float4 getLitColor( #endif #endif + UNITY_APPLY_FOG(i.fogCoord, pbr.rgb); + return float4(pbr.rgb, albedo.a); } diff --git a/tooner.shader b/tooner.shader index 79286c9..7c56a48 100644 --- a/tooner.shader +++ b/tooner.shader @@ -619,6 +619,15 @@ Shader "yum_food/tooner" _Mochie_UI_Show("UI show", Float) = 0 _Gimmick_Fog_00_Enable_Static("Enable fog 00", Float) = 0 + _Gimmick_Fog_00_Max_Ray("Max ray", Float) = 25 + _Gimmick_Fog_00_Radius("Radius", Float) = 25 + _Gimmick_Fog_00_Step_Size("Step size (meters)", Float) = 1 + _Gimmick_Fog_00_Noise_Scale("Noise scale", Float) = 1 + _Gimmick_Fog_00_Noise_Exponent("Noise exponent", Float) = 2.0 + _Gimmick_Fog_00_Density("Density", Range(0,2)) = 1.0 + _Gimmick_Fog_00_Normal_Cutoff("Normal cutoff (alpha)", Range(0,1)) = 0.5 + _Gimmick_Fog_00_Albedo_Cutoff("Albedo cutoff (alpha)", Range(0,1)) = 0.9 + _Gimmick_Fog_00_Ray_Origin_Randomization("Enable ray origin randomization", Range(0,1)) = 1 } SubShader { @@ -648,6 +657,7 @@ Shader "yum_food/tooner" #pragma multi_compile_fwdbase #pragma multi_compile_instancing + #pragma multi_compile_fog #pragma multi_compile _ VERTEXLIGHT_ON #include "feature_macros.cginc" diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc index fb7899d..325ccb3 100644 --- a/tooner_lighting.cginc +++ b/tooner_lighting.cginc @@ -24,13 +24,6 @@ #ifndef TOONER_LIGHTING #define TOONER_LIGHTING -// Hacky parameterizable whiteout blending. Probably some big mistakes but it -// passes the eyeball test. -// At w=0.5, this looks kinda like whiteout blending. -// At w=0, this returns n0. -// At w=1, this returns n1. -#define MY_BLEND_NORMALS(n0, n1, w) normalize(float3((n0.xy * (1 - w) + n1.xy * w), lerp(1, n0.z, (1-w)) * lerp(1, n1.z, w))) - void getVertexLightColor(inout v2f i) { #if defined(VERTEXLIGHT_ON) @@ -213,7 +206,7 @@ v2f vert(appdata v) o.screenPos = TransformStereoScreenSpaceTex(suv + 0.5 * o.pos.w, o.pos.w); getVertexLightColor(o); - + UNITY_TRANSFER_FOG(o, o.pos); return o; } @@ -1390,15 +1383,6 @@ float4 effect(inout v2f i, out float depth) } #endif -#if defined(_GIMMICK_FOG_00) - { - Fog00PBR pbr = getFog00(i); - albedo = pbr.albedo; - normal = pbr.normal; - depth = pbr.depth; - } -#endif - #if defined(_RENDERING_CUTOUT) #if defined(_RENDERING_CUTOUT_STOCHASTIC) float ar = rand2(i.uv0); @@ -2214,6 +2198,16 @@ float4 effect(inout v2f i, out float depth) float ao = 1; #endif +#if defined(_GIMMICK_FOG_00) + { + Fog00PBR pbr = getFog00(i); + albedo = pbr.albedo; + normal = pbr.normal; + ao = pbr.ao; + depth = pbr.depth; + } +#endif + #if defined(_GIMMICK_FLAT_COLOR) if (round(_Gimmick_Flat_Color_Enable_Dynamic)) { albedo = _Gimmick_Flat_Color_Color; diff --git a/tooner_outline_pass.cginc b/tooner_outline_pass.cginc index e7591e6..960039e 100644 --- a/tooner_outline_pass.cginc +++ b/tooner_outline_pass.cginc @@ -6,6 +6,7 @@ #include "clones.cginc" #include "cnlohr.cginc" #include "globals.cginc" +#include "interpolators.cginc" #include "math.cginc" #include "pbr.cginc" #include "oklab.cginc" |
