summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Editor/tooner.cs20
-rw-r--r--cnlohr.cginc35
-rw-r--r--feature_macros.cginc3
-rw-r--r--fog.cginc124
-rw-r--r--globals.cginc2
-rw-r--r--interpolators.cginc8
-rw-r--r--math.cginc24
-rw-r--r--noise.cginc92
-rw-r--r--tooner.shader2
-rw-r--r--tooner_lighting.cginc36
10 files changed, 334 insertions, 12 deletions
diff --git a/Editor/tooner.cs b/Editor/tooner.cs
index 8824de5..5fc26bd 100644
--- a/Editor/tooner.cs
+++ b/Editor/tooner.cs
@@ -2002,6 +2002,25 @@ public class ToonerGUI : ShaderGUI {
EditorGUI.indentLevel -= 1;
}
+ void DoGimmickFog0() {
+ MaterialProperty bc;
+
+ bc = FindProperty("_Gimmick_Fog_00_Enable_Static");
+ bool enabled = (bc.floatValue != 0.0);
+ EditorGUI.BeginChangeCheck();
+ enabled = Toggle("Fog 00", enabled);
+ EditorGUI.EndChangeCheck();
+ bc.floatValue = enabled ? 1.0f : 0.0f;
+ SetKeyword("_GIMMICK_FOG_00", enabled);
+
+ if (!enabled) {
+ return;
+ }
+
+ EditorGUI.indentLevel += 1;
+ EditorGUI.indentLevel -= 1;
+ }
+
void DoGimmicks() {
show_ui.Add(AddCollapsibleMenu("Gimmicks", "_Gimmicks"));
EditorGUI.indentLevel += 1;
@@ -2021,6 +2040,7 @@ public class ToonerGUI : ShaderGUI {
DoGimmickMirrorUVFlip();
DoGimmickLetterGrid();
DoGimmickAudiolinkChroma00();
+ DoGimmickFog0();
DoClones();
DoExplosion();
DoGeoScroll();
diff --git a/cnlohr.cginc b/cnlohr.cginc
index bed117d..c3163d2 100644
--- a/cnlohr.cginc
+++ b/cnlohr.cginc
@@ -50,4 +50,39 @@ float3 getCenterCamPos() {
#endif
}
+float GetLinearZFromZDepth_WorksWithMirrors(float zDepthFromMap, float2 screenUV)
+{
+ #if defined(UNITY_REVERSED_Z)
+ zDepthFromMap = 1 - zDepthFromMap;
+
+ // When using a mirror, the far plane is whack. This just checks for it and aborts.
+ if( zDepthFromMap >= 1.0 ) return _ProjectionParams.z;
+ #endif
+
+ float4 clipPos = float4(screenUV.xy, zDepthFromMap, 1.0);
+ clipPos.xyz = 2.0f * clipPos.xyz - 1.0f;
+ float4 camPos = mul(unity_CameraInvProjection, clipPos);
+ return -camPos.z / camPos.w;
+}
+
+float GetDepthOfWorldPos(float3 worldPos)
+{
+ float3 full_vec_eye_to_geometry = worldPos - _WorldSpaceCameraPos;
+ float3 world_dir = normalize(worldPos - _WorldSpaceCameraPos);
+ float4 objPos = mul(unity_WorldToObject, float4(worldPos, 1));
+ float4 clipPos = UnityObjectToClipPos(objPos);
+
+ float2 suv = clipPos * float2(0.5, 0.5 * _ProjectionParams.x);
+ float2 screenPos = TransformStereoScreenSpaceTex(suv + 0.5 * clipPos.w, clipPos.w);
+
+ float perspective_divide = 1.0 / clipPos.w;
+ float perspective_factor = length(full_vec_eye_to_geometry * perspective_divide);
+ float2 screen_uv = screenPos.xy * perspective_divide;
+ float eye_depth_world =
+ GetLinearZFromZDepth_WorksWithMirrors(
+ SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screen_uv),
+ screen_uv) * perspective_factor;
+ return eye_depth_world;
+}
+
#endif // __CNLOHR_INC
diff --git a/feature_macros.cginc b/feature_macros.cginc
index 0dcaced..65220e8 100644
--- a/feature_macros.cginc
+++ b/feature_macros.cginc
@@ -1,6 +1,8 @@
#ifndef __FEATURE_MACROS_INC
#define __FEATURE_MACROS_INC
+#define EXPERIMENT__CUSTOM_DEPTH
+
#pragma shader_feature_local _ _BASECOLOR_MAP
#pragma shader_feature_local _ _NORMAL_MAP
#pragma shader_feature_local _ _METALLIC_MAP
@@ -164,6 +166,7 @@
#pragma shader_feature_local _ _GIMMICK_AL_CHROMA_00_HUE_SHIFT
#pragma shader_feature_local _ SSR_ENABLED
#pragma shader_feature_local _ SSR_MASK
+#pragma shader_feature_local _ _GIMMICK_FOG_00
#endif // __FEATURE_MACROS_INC
diff --git a/fog.cginc b/fog.cginc
new file mode 100644
index 0000000..c0eabf7
--- /dev/null
+++ b/fog.cginc
@@ -0,0 +1,124 @@
+#include "globals.cginc"
+#include "interpolators.cginc"
+#include "math.cginc"
+#include "noise.cginc"
+#include "cnlohr.cginc"
+
+#ifndef __FOG_INC
+#define __FOG_INC
+
+#if defined(_GIMMICK_FOG_00)
+
+struct Fog00PBR {
+ float4 albedo;
+ float3 normal;
+ float depth;
+};
+
+#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;
+}
+
+float3 get_normal(float3 p) {
+ float3 e = float3(0.01, 0, 0);
+ return normalize(float3(
+ map(p + e.xyz) - map(p),
+ map(p + e.yxz) - map(p),
+ map(p + e.zyx) - map(p)));
+}
+
+Fog00PBR getFog00(v2f i) {
+
+ float3 cam_pos = _WorldSpaceCameraPos;
+ float3 obj_pos = i.worldPos;
+
+ float3 world_pos_depth_hit;
+ float2 screen_uv;
+ {
+ float3 full_vec_eye_to_geometry = i.worldPos - _WorldSpaceCameraPos;
+ float3 world_dir = normalize(i.worldPos - _WorldSpaceCameraPos);
+ float perspective_divide = 1.0 / i.pos.w;
+ float perspective_factor = length(full_vec_eye_to_geometry * perspective_divide);
+ screen_uv = i.screenPos.xy * perspective_divide;
+ float eye_depth_world =
+ GetLinearZFromZDepth_WorksWithMirrors(
+ SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, screen_uv),
+ screen_uv) * perspective_factor;
+ world_pos_depth_hit = _WorldSpaceCameraPos + eye_depth_world * world_dir;
+ }
+
+ float3 rd = normalize(obj_pos - cam_pos);
+ float3 ro = cam_pos;
+
+ bool no_intersection = false;
+ if (length(ro) > FOG_RADIUS) {
+ float3 l = ro;
+ float a = 1;
+ float b = 2 * dot(rd, l);
+ float c = dot(l, l) - FOG_RADIUS * FOG_RADIUS;
+ float t0, t1;
+ if (solveQuadratic(a, b, c, t0, t1)) {
+ no_intersection = (t0 < 0) * (t1 < 0);
+ ro += min(max(t0, 0), max(t1, 0)) * rd;
+ } else {
+ no_intersection = true;
+ }
+ }
+
+ // 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 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));
+ step_count *= (1 - no_intersection);
+ float density = 0.5;
+
+ float3 normal_weighted_sum = 0;
+ for (uint ii = 0; ii < step_count; ii++) {
+ float3 p = ro + (rd * 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;
+ acc += c * (1.0 - acc.a);
+ }
+
+ Fog00PBR pbr;
+ pbr.albedo = saturate(acc);
+ pbr.albedo.rgb = saturate(pow(pbr.albedo.rgb, 3.0) * 5);
+
+#if 0
+ pbr.normal = normalize(normal_weighted_sum);
+#else
+ pbr.normal = i.normal;
+#endif
+
+ float4 clip_pos = mul(UNITY_MATRIX_VP, float4(ro, 1.0));
+ pbr.depth = clip_pos.z / clip_pos.w;
+
+ return pbr;
+}
+
+#endif // _GIMMICK_FOG_00
+
+#endif // __FOG_INC
+
diff --git a/globals.cginc b/globals.cginc
index 9f73932..906ee1c 100644
--- a/globals.cginc
+++ b/globals.cginc
@@ -3,6 +3,8 @@
#ifndef __GLOBALS_INC
#define __GLOBALS_INC
+UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
+
SamplerState linear_repeat_s;
SamplerState linear_clamp_s;
SamplerState bilinear_repeat_s;
diff --git a/interpolators.cginc b/interpolators.cginc
index 5942922..9763bca 100644
--- a/interpolators.cginc
+++ b/interpolators.cginc
@@ -23,7 +23,7 @@ struct appdata
struct v2f
{
- float4 pos : SV_POSITION;
+ linear noperspective centroid float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float2 uv2 : TEXCOORD2;
@@ -42,7 +42,7 @@ struct v2f
float3 objPos : TEXCOORD11;
float3 centerCamPos : TEXCOORD12;
- float4 screenPos : TEXCOORD13;
+ float2 screenPos : TEXCOORD13;
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
@@ -69,7 +69,7 @@ struct appdata
struct v2f
{
- float4 pos : SV_POSITION;
+ linear noperspective centroid float4 pos : SV_POSITION;
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float2 uv2 : TEXCOORD2;
@@ -89,7 +89,7 @@ struct v2f
float3 objPos : TEXCOORD12;
float3 centerCamPos : TEXCOORD13;
- float4 screenPos : TEXCOORD14;
+ float2 screenPos : TEXCOORD14;
#if defined(VERTEXLIGHT_ON)
float3 vertexLightColor : TEXCOORD15;
diff --git a/math.cginc b/math.cginc
index c2903c8..46e19e1 100644
--- a/math.cginc
+++ b/math.cginc
@@ -197,5 +197,29 @@ float median(float3 x)
return median(x.x, x.y, x.z);
}
+// Yoinked from here
+// https://www.scratchapixel.com/lessons/3d-basic-rendering/minimal-ray-tracer-rendering-simple-shapes/ray-sphere-intersection.html
+bool solveQuadratic(float a, float b, float c, out float x0, out float x1)
+{
+ float discriminant = b * b - 4 * a * c;
+ if (discriminant < 0) {
+ return false;
+ } else if (discriminant == 0) {
+ x0 = -0.5 * b / a;
+ x1 = x0;
+ } else {
+ float q = (b > 0) ?
+ -0.5 * (b + sqrt(discriminant)) :
+ -0.5 * (b - sqrt(discriminant));
+ x0 = q/a;
+ x1 = c/q;
+ }
+ float tmp_min = min(x0, x1);
+ float tmp_max = max(x0, x1);
+ x0 = tmp_min;
+ x1 = tmp_max;
+ return true;
+}
+
#endif // __MATH_INC
diff --git a/noise.cginc b/noise.cginc
new file mode 100644
index 0000000..a58e56d
--- /dev/null
+++ b/noise.cginc
@@ -0,0 +1,92 @@
+#include "math.cginc"
+
+#ifndef __NOISE_INC
+#define __NOISE_INC
+
+float cubic_interp(float x)
+{
+ return x * x * (3.0 - 2.0 * x);
+}
+
+float2 cubic_interp(float2 x)
+{
+ return x * x * (3.0 - 2.0 * x);
+}
+
+float3 cubic_interp(float3 x)
+{
+ return x * x * (3.0 - 2.0 * x);
+}
+
+float quintic_interp(float x)
+{
+ return x * x * x * (x * (x * 6 - 15) + 10);
+}
+
+float2 quintic_interp(float2 x)
+{
+ return x * x * x * (x * (x * 6 - 15) + 10);
+}
+
+float perlin_noise(float2 p)
+{
+ float2 sq = floor(p);
+ float2 sqi = frac(p);
+
+ float r0 = rand2(sq + float2(0,0));
+ float r1 = rand2(sq + float2(1,0));
+ float r2 = rand2(sq + float2(0,1));
+ float r3 = rand2(sq + float2(1,1));
+
+ float2 u = cubic_interp(sqi);
+
+ return lerp(r0, r1, u.x) +
+ (r2 - r0) * u.y * (1.0 - u.x) +
+ (r3 - r1) * u.x * u.y;
+}
+
+float perlin_noise_3d(float3 p)
+{
+ float3 sq = floor(p);
+ float3 sqi = frac(p);
+
+ float r0 = rand3(sq + float3(0,0,0));
+ float r1 = rand3(sq + float3(1,0,0));
+ float r2 = rand3(sq + float3(0,1,0));
+ float r3 = rand3(sq + float3(1,1,0));
+ float r4 = rand3(sq + float3(0,0,1));
+ float r5 = rand3(sq + float3(1,0,1));
+ float r6 = rand3(sq + float3(0,1,1));
+ float r7 = rand3(sq + float3(1,1,1));
+
+ float3 u = cubic_interp(sqi);
+
+ return lerp(
+ lerp(r0, r1, u.x) +
+ (r2 - r0) * u.y * (1.0 - u.x) +
+ (r3 - r1) * u.x * u.y,
+ lerp(r4, r5, u.x) +
+ (r6 - r4) * u.y * (1.0 - u.x) +
+ (r7 - r5) * u.x * u.y,
+ u.z);
+}
+
+float simplex_noise(float2 p)
+{
+ float2 sq = floor(p);
+ float2 sqi = frac(p);
+
+ float r0 = rand2(sq + float2(0,0));
+ float r1 = rand2(sq + float2(1,0));
+ float r2 = rand2(sq + float2(0,1));
+ float r3 = rand2(sq + float2(1,1));
+
+ float2 u = quintic_interp(sqi);
+
+ return lerp(r0, r1, u.x) +
+ (r2 - r0) * u.y * (1.0 - u.x) +
+ (r3 - r1) * u.x * u.y;
+}
+
+#endif // __NOISE_INC
+
diff --git a/tooner.shader b/tooner.shader
index 5a3abba..79286c9 100644
--- a/tooner.shader
+++ b/tooner.shader
@@ -617,6 +617,8 @@ Shader "yum_food/tooner"
_Hue_Shift_HSV_UI_Show("UI show", Float) = 0
_Clones_UI_Show("UI show", Float) = 0
_Mochie_UI_Show("UI show", Float) = 0
+
+ _Gimmick_Fog_00_Enable_Static("Enable fog 00", Float) = 0
}
SubShader
{
diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc
index 6d70dbc..fb7899d 100644
--- a/tooner_lighting.cginc
+++ b/tooner_lighting.cginc
@@ -7,6 +7,7 @@
#include "cnlohr.cginc"
#include "disinfo.cginc"
#include "eyes.cginc"
+#include "fog.cginc"
#include "globals.cginc"
#include "halos.cginc"
#include "interpolators.cginc"
@@ -169,10 +170,6 @@ v2f vert(appdata v)
o.worldPos = mul(unity_ObjectToWorld, v.vertex);
o.objPos = v.vertex;
-#if defined(SSR_ENABLED)
- o.screenPos = ComputeGrabScreenPos(o.pos);
-#endif
-
#if defined(_FACE_ME_WORLD_Y)
if (!_FaceMeWorldY_Enable_Dynamic) {
o.normal = UnityObjectToWorldNormal(v.normal);
@@ -212,7 +209,8 @@ v2f vert(appdata v)
TRANSFER_SHADOW(o);
#endif
- o.screenPos = ComputeGrabScreenPos(o.pos);
+ float2 suv = o.pos * float2(0.5, 0.5 * _ProjectionParams.x);
+ o.screenPos = TransformStereoScreenSpaceTex(suv + 0.5 * o.pos.w, o.pos.w);
getVertexLightColor(o);
@@ -1271,8 +1269,14 @@ float4 pixellate_color(int2 px_res, float2 uv, float4 c)
}
#endif
-float4 effect(inout v2f i)
+float4 effect(inout v2f i, out float depth)
{
+#if defined(EXPERIMENT__CUSTOM_DEPTH)
+ {
+ float4 clip_pos = mul(UNITY_MATRIX_VP, float4(i.worldPos, 1.0));
+ depth = clip_pos.z / clip_pos.w;
+ }
+#endif
const float3 view_dir = normalize(_WorldSpaceCameraPos.xyz - i.worldPos);
const float3 view_dir_c = normalize(i.centerCamPos - i.worldPos);
#define VIEW_DIR(center_eye_fix) (center_eye_fix == 1 ? view_dir_c : view_dir)
@@ -1386,6 +1390,15 @@ float4 effect(inout v2f i)
}
#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);
@@ -2301,12 +2314,19 @@ float4 effect(inout v2f i)
return result;
}
-fixed4 frag(v2f i) : SV_Target
+fixed4 frag(v2f i
+#if defined(EXPERIMENT__CUSTOM_DEPTH)
+, out float depth: SV_DepthGreaterEqual
+#endif
+ ) : SV_Target
{
+#if !defined(EXPERIMENT__CUSTOM_DEPTH)
+ float depth;
+#endif
UNITY_APPLY_DITHER_CROSSFADE(i.pos.xy);
UNITY_SETUP_INSTANCE_ID(i);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
- return effect(i);
+ return effect(i, depth);
}
#endif // TOONER_LIGHTING