diff options
| author | yum <yum.food.vr@gmail.com> | 2024-09-29 17:54:36 -0700 |
|---|---|---|
| committer | yum <yum.food.vr@gmail.com> | 2024-09-29 17:54:36 -0700 |
| commit | 6e34fcb7d82a7c7480768a2eadaaa5b77400ed09 (patch) | |
| tree | 40db2c22d08bb1ee4d229aa8076a0399bfcbf9b2 | |
| parent | 2e6a2df16dc5fa9758de06240e44b781b05e6f5a (diff) | |
Add new eye gimmick
| -rw-r--r-- | Editor/tooner.cs | 72 | ||||
| -rw-r--r-- | eyes.cginc | 141 | ||||
| -rw-r--r-- | feature_macros.cginc | 1 | ||||
| -rw-r--r-- | globals.cginc | 19 | ||||
| -rw-r--r-- | math.cginc | 74 | ||||
| -rw-r--r-- | tooner.shader | 20 | ||||
| -rw-r--r-- | tooner_lighting.cginc | 17 |
7 files changed, 343 insertions, 1 deletions
diff --git a/Editor/tooner.cs b/Editor/tooner.cs index 869d912..fb0cc7c 100644 --- a/Editor/tooner.cs +++ b/Editor/tooner.cs @@ -525,6 +525,9 @@ public class ToonerGUI : ShaderGUI { bc = FindProperty("_Global_Emission_Factor"); editor.FloatProperty(bc, "Global emissions multiplier"); + bc = FindProperty("_Global_Emission_Additive_Factor"); + editor.FloatProperty(bc, "Global emissions additive factor"); + EditorGUI.indentLevel -= 1; } @@ -1454,6 +1457,7 @@ public class ToonerGUI : ShaderGUI { EditorGUI.indentLevel -= 1; } + void DoGimmickEyes00() { MaterialProperty bc; bc = FindProperty("_Gimmick_Eyes00_Enable_Static"); @@ -1500,6 +1504,73 @@ public class ToonerGUI : ShaderGUI { EditorGUI.indentLevel -= 1; } + void DoGimmickEyes02() { + MaterialProperty bc; + bc = FindProperty("_Gimmick_Eyes02_Enable_Static"); + bool enabled = (bc.floatValue != 0.0); + EditorGUI.BeginChangeCheck(); + enabled = EditorGUILayout.Toggle("Eyes 02", enabled); + EditorGUI.EndChangeCheck(); + bc.floatValue = enabled ? 1.0f : 0.0f; + SetKeyword("_GIMMICK_EYES_02", enabled); + + if (!enabled) { + return; + } + + EditorGUI.indentLevel += 1; + + bc = FindProperty("_Gimmick_Eyes02_N"); + editor.RangeProperty(bc, "n"); + bc = FindProperty("_Gimmick_Eyes02_A0"); + editor.RangeProperty(bc, "a0"); + bc = FindProperty("_Gimmick_Eyes02_A1"); + editor.RangeProperty(bc, "a1"); + bc = FindProperty("_Gimmick_Eyes02_A2"); + editor.RangeProperty(bc, "a2"); + bc = FindProperty("_Gimmick_Eyes02_A3"); + editor.RangeProperty(bc, "a3"); + bc = FindProperty("_Gimmick_Eyes02_A4"); + editor.RangeProperty(bc, "a4"); + + bc = FindProperty("_Gimmick_Eyes02_Animate"); + enabled = (bc.floatValue != 0.0); + EditorGUI.BeginChangeCheck(); + enabled = EditorGUILayout.Toggle("Animate", enabled); + EditorGUI.EndChangeCheck(); + bc.floatValue = enabled ? 1.0f : 0.0f; + if (enabled) { + EditorGUI.indentLevel += 1; + bc = FindProperty("_Gimmick_Eyes02_Animate_Speed"); + editor.FloatProperty(bc, "Speed"); + + bc = FindProperty("_Gimmick_Eyes02_Animate_Strength"); + editor.FloatProperty(bc, "Strength"); + EditorGUI.indentLevel -= 1; + } + + bc = FindProperty("_Gimmick_Eyes02_UV_X_Symmetry"); + enabled = (bc.floatValue != 0.0); + EditorGUI.BeginChangeCheck(); + enabled = EditorGUILayout.Toggle("UV x symmetry", enabled); + EditorGUI.EndChangeCheck(); + bc.floatValue = enabled ? 1.0f : 0.0f; + + bc = FindProperty("_Gimmick_Eyes02_UV_Adjust"); + editor.VectorProperty(bc, "UV scale & offset"); + + bc = FindProperty("_Gimmick_Eyes02_Albedo"); + editor.ColorProperty(bc, "Albedo"); + bc = FindProperty("_Gimmick_Eyes02_Metallic"); + editor.FloatProperty(bc, "Metallic"); + bc = FindProperty("_Gimmick_Eyes02_Roughness"); + editor.FloatProperty(bc, "Roughness"); + bc = FindProperty("_Gimmick_Eyes02_Emission"); + editor.ColorProperty(bc, "Emission"); + + EditorGUI.indentLevel -= 1; + } + void DoGimmickHalo00() { MaterialProperty bc; bc = FindProperty("_Gimmick_Halo00_Enable_Static"); @@ -1803,6 +1874,7 @@ public class ToonerGUI : ShaderGUI { DoGimmickSpherizeLocation(); DoGimmickEyes00(); DoGimmickEyes01(); + DoGimmickEyes02(); DoGimmickHalo00(); DoGimmickPixellate(); DoGimmickTrochoid(); @@ -1,6 +1,7 @@ #include "globals.cginc" #include "interpolators.cginc" #include "iq_sdf.cginc" +#include "math.cginc" #ifndef __EYES_INC #define __EYES_INC @@ -185,5 +186,145 @@ Eyes01PBR eyes01_march(v2f i) #endif // _GIMMICK_EYES_01 +#if defined(_GIMMICK_EYES_02) + +struct chaos_data +{ + uint n; // degrees of symmetry + int p; + float a0; + float a1; + float a2; + float a3; + float a4; + complex z; +}; + +void iterate0(inout struct chaos_data d) +{ + complex z_conj = cconjugate(d.z); + complex z_conj_n_1 = cpow(z_conj, d.n); + complex z_n = cpow(d.z, d.n); + + complex next = + cmul(( + complex(d.a0, 0) + + d.a1 * cmul(d.z, cconjugate(d.z)) + + complex(d.a2 * creal(z_n), 0) + + complex(0, d.a3) + ), + d.z) + + d.a4 * z_conj_n_1; + + d.z = next; +} + +void iterate1(inout struct chaos_data d) +{ + complex z_conj = cconjugate(d.z); + complex z_conj_n_1 = cpow(z_conj, d.n - 1); + complex z_n = cpow(d.z, d.n); + + complex next = + (d.a0 + + d.a1 * (d.z.x * d.z.x - d.z.y * d.z.y) + + d.a2 * creal(z_n) + + d.a3 * creal(cmul(cpow((cdiv(d.z, abs(d.z))), d.n * d.p), abs(d.z)))) * + d.z + + d.a4 * (z_conj_n_1); + + d.z = next; +} + +// Return a number on (0, inf) +float get_chaos(in float2 uv, inout chaos_data d) +{ + complex z = uv; + // Remap onto [-1, 1] + float scale = 2.0; + z = z * scale * 2 - scale; + d.z = z; + + for (int i = 0; i < 6; i++) { + iterate0(d); + } + + float l = d.z.x * d.z.x - d.z.y * d.z.y; + if (l < 1) { + float b = .1; + return b/l; + } else { + return 0; + } +} + +float3 get_chaos_normal(in float2 uv, inout chaos_data d) +{ + float2 small_step = float2(.0001, 0); + float dx = get_chaos(uv + small_step.xy, d) - get_chaos(uv, d); + float dz = get_chaos(uv + small_step.yx, d) - get_chaos(uv, d); + float dy = small_step.x; + + float3 normal = float3(dx, dy, dz); + return UnityObjectToWorldNormal(normalize(normal)); +} + +bool eyes02_march(float2 uv, inout float3 normal) +{ + float2 uv_scale = _Gimmick_Eyes02_UV_Adjust.xy; + float2 uv_center = _Gimmick_Eyes02_UV_Adjust.zw; + uv -= 0.5; + + if (_Gimmick_Eyes02_UV_X_Symmetry) { + uv.x = abs(uv.x); + } + + uv -= (uv_center - 0.5); + uv /= uv_scale; + + uv += 0.5; + + float t20 = _Time[0] * _Gimmick_Eyes02_Animate_Speed; + float t = _Time[1] * _Gimmick_Eyes02_Animate_Speed; + + struct chaos_data d; + d.n = _Gimmick_Eyes02_N; + d.p = _Gimmick_Eyes02_N; + d.a0 = _Gimmick_Eyes02_A0; + d.a1 = _Gimmick_Eyes02_A1; + d.a2 = _Gimmick_Eyes02_A2; + d.a3 = _Gimmick_Eyes02_A3; + d.a4 = _Gimmick_Eyes02_A4; + + if (_Gimmick_Eyes02_Animate) { + float effect = 1; + float e = _Gimmick_Eyes02_Animate_Strength; + if (round(effect) == 0) { + d.a0 += (sin(t * 1.1) * .01 + sin(t20 * 1.1) * .75) * e; + d.a1 += (sin(t * 1.3) * .01 + sin(t20 * 1.3) * .75) * e; + d.a2 += (sin(t * 1.7) * .01 + sin(t20 * 1.7) * 1) * e; + d.a3 += (sin(t * 1.9) * .01 + sin(t20 * 1.9) * .75) * e; + d.a4 += (sin(t * 2.3) * .02 + sin(t20 * 2.3) * .4) * e; + } else if (round(effect) == 1) { + d.a0 += (sin(t * 1.1) * .01 + sin(t20 * 1.1) * .75) * e; + d.a1 += (sin(t * 1.3) * .01 + sin(t20 * 1.3) * .75) * e; + d.a2 += (sin(t * 1.7) * .01 + sin(t20 * 1.7) * 1) * e; + d.a3 += (sin(t * 1.9) * .0005 + sin(t20 * 1.9) * .05) * e; + d.a4 += (sin(t * 2.3) * .02 + sin(t20 * 2.3) * 1) * e; + } + } + + float c = get_chaos(uv, d); + c = exp(-c); + + if (c < 1) { + normal = get_chaos_normal(uv, d); + } + bool is_ray_hit = (c < 1); + return is_ray_hit; +} + +#endif // _GIMMICK_EYES_02 + #endif // __EYES_INC diff --git a/feature_macros.cginc b/feature_macros.cginc index 40f2bc3..f53e904 100644 --- a/feature_macros.cginc +++ b/feature_macros.cginc @@ -141,6 +141,7 @@ #pragma shader_feature_local _ _GIMMICK_SPHERIZE_LOCATION #pragma shader_feature_local _ _GIMMICK_EYES_00 #pragma shader_feature_local _ _GIMMICK_EYES_01 +#pragma shader_feature_local _ _GIMMICK_EYES_02 #pragma shader_feature_local _ _GIMMICK_HALO_00 #pragma shader_feature_local _ _PIXELLATE #pragma shader_feature_local _ _TROCHOID diff --git a/globals.cginc b/globals.cginc index 832d2cd..63cf7fd 100644 --- a/globals.cginc +++ b/globals.cginc @@ -282,6 +282,7 @@ float _Emission1Multiplier; float _Emission1_UV_Select; #endif float _Global_Emission_Factor; +float _Global_Emission_Additive_Factor; #if defined(_AMBIENT_OCCLUSION) texture2D _Ambient_Occlusion; @@ -597,6 +598,24 @@ texture2D _Gimmick_Eyes00_Effect_Mask; float _Gimmick_Eyes01_Radius; #endif +#if defined(_GIMMICK_EYES_02) +float _Gimmick_Eyes02_N; +float _Gimmick_Eyes02_A0; +float _Gimmick_Eyes02_A1; +float _Gimmick_Eyes02_A2; +float _Gimmick_Eyes02_A3; +float _Gimmick_Eyes02_A4; +float _Gimmick_Eyes02_Animate; +float _Gimmick_Eyes02_Animate_Strength; +float _Gimmick_Eyes02_Animate_Speed; +float _Gimmick_Eyes02_UV_X_Symmetry; +float4 _Gimmick_Eyes02_UV_Adjust; +float4 _Gimmick_Eyes02_Albedo; +float _Gimmick_Eyes02_Metallic; +float _Gimmick_Eyes02_Roughness; +float3 _Gimmick_Eyes02_Emission; +#endif + #if defined(_PIXELLATE) float _Gimmick_Pixellate_Enable_Static; float _Gimmick_Pixellate_Resolution_U; @@ -3,6 +3,80 @@ #ifndef __MATH_INC #define __MATH_INC +// Complex numbers +typedef float2 complex; + +float creal(complex z0) +{ + return z0.x; +} + +float cimag(complex z0) +{ + return z0.y; +} + +float cnorm2(complex z0) +{ + return z0.x * z0.x + z0.y * z0.y; +} + +float cnorm(complex z0) +{ + return sqrt(cnorm2(z0)); +} + +complex cconjugate(complex z) +{ + return float2(z.x, -z.y); +} + +complex cmul(complex z0, complex z1) +{ + return float2(z0.x * z1.x - z0.y * z1.y, z0.x * z1.y + z0.y * z1.x); +} + +complex cdiv(complex z0, complex z1) +{ + float re = creal(z0) * creal(z1) + cimag(z0) * cimag(z1); + float im = cimag(z0) * cimag(z1) - creal(z0) * creal(z1); + float z1_norm2 = cnorm2(z1); + return float2(re, im) / z1_norm2; +} + +// Evaluates z0**n. +// Uses Euler's identity to support fractional values of `n`. +// Expensive. +complex cpow_fractional(complex z0, float n) +{ + float r = sqrt(z0.x * z0.x + z0.y * z0.y); + float t = atan(z0.y / z0.x); + return pow(r, n) * float2(cos(t * n), sin(t * n)); +} + +// Evaluates z0**n. +// Utilizes recursive squaring to support high values of `n`. +// Cheap. +complex cpow(complex z0, uint n) +{ + if (n == 0) { + return 1; + } + + complex z = z0; + while (n > 1) { + if (n % 2 == 0) { + z = cmul(z, z); + n /= 2; + } else { + z = cmul(z, z0); + n -= 1; + } + } + return z; +} + +// Quaternions float4 qmul(float4 q1, float4 q2) { return float4( diff --git a/tooner.shader b/tooner.shader index 335f050..2f1b87e 100644 --- a/tooner.shader +++ b/tooner.shader @@ -167,6 +167,7 @@ Shader "yum_food/tooner" _Emission1Multiplier("Emission multiplier", Range(0, 2)) = 1 _Emission1_UV_Select("UV channel", Range(0,7)) = 0 _Global_Emission_Factor("Global emission factor", Float) = 1 + _Global_Emission_Additive_Factor("Global emission additive factor", Float) = 0 [NoScaleOffset] _Tex_NormalStr("Normal texture strength", Range(0, 10)) = 1 @@ -485,6 +486,23 @@ Shader "yum_food/tooner" _Gimmick_Eyes01_Enable_Static("Enable eyes 01", Float) = 0.0 _Gimmick_Eyes01_Radius("Radius (meters, obj space)", Float) = 1.0 + _Gimmick_Eyes02_Enable_Static ("Enable (static)", Float) = 0 + _Gimmick_Eyes02_N ("n", Range(2, 16)) = 5 + _Gimmick_Eyes02_A0 ("a0", Range(-6, 6)) = 1.5 + _Gimmick_Eyes02_A1 ("a1", Range(-6, 6)) = -1.75 + _Gimmick_Eyes02_A2 ("a2", Range(-6, 6)) = .01 + _Gimmick_Eyes02_A3 ("a3", Range(-2, 2)) = 0 + _Gimmick_Eyes02_A4 ("a4", Range(-2, 2)) = .5 + _Gimmick_Eyes02_Animate ("animate", Float) = 0.0 + _Gimmick_Eyes02_Animate_Strength ("animation strength", Float) = 1.0 + _Gimmick_Eyes02_Animate_Speed ("animation speed", Float) = 1.0 + _Gimmick_Eyes02_UV_X_Symmetry ("UV x symmetry", Float) = 1.0 + _Gimmick_Eyes02_UV_Adjust ("UV scale and center", Vector) = (0.9, 1.1, .753, .675) + _Gimmick_Eyes02_Albedo ("Albedo", Color) = (1, 1, 1, 1) + _Gimmick_Eyes02_Metallic ("Metallic", Range(0, 1)) = 0 + _Gimmick_Eyes02_Roughness ("Roughness", Range(0, 1)) = 0.5 + _Gimmick_Eyes02_Emission ("Emission", Color) = (0, 0, 0, 1) + _Gimmick_Halo00_Enable_Static("Enable halo", Float) = 0.0 _Gimmick_Pixellate_Enable_Static("Enable pixellation", Float) = 0.0 @@ -622,6 +640,7 @@ Shader "yum_food/tooner" #include "tooner_lighting.cginc" ENDCG } + /* Pass { Tags { "RenderType"="Opaque" @@ -701,6 +720,7 @@ Shader "yum_food/tooner" #include "mochie_shadow_caster.cginc" ENDCG } + */ } CustomEditor "ToonerGUI" } diff --git a/tooner_lighting.cginc b/tooner_lighting.cginc index eec82af..c91598d 100644 --- a/tooner_lighting.cginc +++ b/tooner_lighting.cginc @@ -1430,6 +1430,18 @@ float4 effect(inout v2f i) } #endif + +#if defined(_GIMMICK_EYES_02) + float3 eyes02_normal = i.normal; + bool eyes02_hit = eyes02_march(i.uv0, eyes02_normal); + { + albedo.rgb += eyes02_hit * _Gimmick_Eyes02_Albedo.rgb; + normal = lerp(normal, eyes02_normal, eyes02_hit); + roughness = lerp(roughness, _Gimmick_Eyes02_Roughness, eyes02_hit); + metallic = lerp(metallic, _Gimmick_Eyes02_Metallic, eyes02_hit); + } +#endif + #if defined(_MATCAP0) || defined(_MATCAP1) || defined(_RIM_LIGHTING0) || defined(_RIM_LIGHTING1) || defined(_RIM_LIGHTING2) || defined(_RIM_LIGHTING3) float3 matcap_emission = 0; float2 matcap_uv; @@ -2151,7 +2163,9 @@ float4 effect(inout v2f i) #endif albedo.a = 1; #endif - return float4(lit.rgb + _Gimmick_Flat_Color_Emission * _Global_Emission_Factor, albedo.a); + return float4(lit.rgb + + _Gimmick_Flat_Color_Emission * _Global_Emission_Factor, + albedo.a); } #endif @@ -2207,6 +2221,7 @@ float4 effect(inout v2f i) result.rgb *= result.a; #endif result.rgb += getOverlayEmission(ov, i) * _Global_Emission_Factor; + result.rgb += _Global_Emission_Additive_Factor * albedo.rgb; return result; } |
