summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2024-10-08 17:32:09 -0700
committeryum <yum.food.vr@gmail.com>2024-10-08 17:32:09 -0700
commita396182815db14f5a6eed26799dd425506a70686 (patch)
tree38f1d2ca8cb3cd6bd8b87fdcb2678ac2e911e90b
parentbcadf1d091efe76e7a1b2393f87f7e24128b723b (diff)
Add fog parameters; add Unity fog to fwd/add passes
-rw-r--r--Editor/tooner.cs20
-rw-r--r--fog.cginc101
-rw-r--r--globals.cginc12
-rw-r--r--interpolators.cginc30
-rw-r--r--math.cginc7
-rw-r--r--pbr.cginc2
-rw-r--r--tooner.shader10
-rw-r--r--tooner_lighting.cginc28
-rw-r--r--tooner_outline_pass.cginc1
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;
}
diff --git a/fog.cginc b/fog.cginc
index c0eabf7..a8f456c 100644
--- a/fog.cginc
+++ b/fog.cginc
@@ -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
diff --git a/math.cginc b/math.cginc
index 46e19e1..968f888 100644
--- a/math.cginc
+++ b/math.cginc
@@ -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;
diff --git a/pbr.cginc b/pbr.cginc
index 0da16dc..886ee66 100644
--- a/pbr.cginc
+++ b/pbr.cginc
@@ -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"