yum-archive/Tooner
A toon shader for Unity's BIRP.
git clone https://git.yummers.dev/yum-archive/Tooner
b904835
master
1#include "globals.cginc" 2#include "interpolators.cginc" 3#include "math.cginc" 4 5#ifndef __HALOS_INC 6#define __HALOS_INC 7 8#if defined(_GIMMICK_HALO_00) 9struct Halo00Params { 10 float3 period; 11 float3 count; 12 float2 uv; 13}; 14struct Halo00PBR { 15 float4 albedo; 16 float3 normal; 17}; 18 19float halo00_map(float3 p, float2 e) 20{ 21 return length(p) - 0.1; 22} 23 24float halo00_map_dr( 25 float3 p, 26 Halo00Params params, 27 out float3 which 28 ) 29{ 30 which = round(p / params.period); 31 // Direction to nearest neighboring cell. 32 float3 min_d = p - params.period * which; 33 float3 o = sign(min_d); 34 35 float d = 1E9; 36 float3 which_tmp = which; 37 for (int xi = 0; xi < 1; xi++) 38 for (int yi = 0; yi < 1; yi++) 39 { 40 float3 rid = which + float3(xi, yi, 0) * o; 41 rid = clamp(rid, ceil(-(params.count)*0.5), floor((params.count-1)*0.5)); 42 float3 r = p - params.period * rid; 43 float2 e = 0; 44 /* 45 float2 e = float2( 46 rand3(rid / 100.0), 47 rand3(rid / 100.0 + 1)); 48 */ 49 float cur_d = halo00_map(r, e); 50 which_tmp = 51 (cur_d < d ? rid : which_tmp); 52 d = min(d, cur_d); 53 } 54 55 which = which_tmp; 56 return d; 57} 58 59float3 halo00_calc_normal(float3 p, Halo00Params params) 60{ 61 const float3 small_step = float3(0.0001, 0.0, 0.0); 62 63 // TODO do we need full central differences? 64 float3 which; 65 float gradient_x = halo00_map_dr(p + small_step.xyy, params, which) - 66 halo00_map_dr(p - small_step.xyy, params, which); 67 float gradient_y = halo00_map_dr(p + small_step.yxy, params, which) - 68 halo00_map_dr(p - small_step.yxy, params, which); 69 float gradient_z = halo00_map_dr(p + small_step.yyx, params, which) - 70 halo00_map_dr(p - small_step.yyx, params, which); 71 72 float3 normal = float3(gradient_x, gradient_y, gradient_z); 73 74 return normalize(normal); 75} 76 77void __halo00_march(float3 ro, float3 rd, Halo00Params params, out Halo00PBR result) 78{ 79 float total_distance_traveled = 0.0; 80 const float MINIMUM_HIT_DISTANCE = 0.0001; 81 const float MAXIMUM_TRACE_DISTANCE = 10.0; 82 83 ro -= (1 - (params.count % 2)) * params.period * 0.5; 84 85#define HALO00_MARCH_STEPS 30 86 float distance_to_closest; 87 float3 current_position; 88 float3 which; 89 for (int i = 0; i < HALO00_MARCH_STEPS; i++) 90 { 91 current_position = ro + total_distance_traveled * rd; 92 93 distance_to_closest = halo00_map_dr(current_position, params, which); 94 95 if (distance_to_closest < MINIMUM_HIT_DISTANCE) 96 { 97 break; 98 } 99 100 if (total_distance_traveled > MAXIMUM_TRACE_DISTANCE) 101 { 102 break; 103 } 104 total_distance_traveled += distance_to_closest; 105 } 106 107 if (distance_to_closest < MINIMUM_HIT_DISTANCE) { 108 result.albedo = 1; 109 result.normal = halo00_calc_normal(current_position, params); 110 return; 111 } 112 113 result.albedo = 0; 114 result.normal = 0; 115 return; 116} 117 118Halo00PBR halo00_march(float3 worldPos, float2 uv) 119{ 120 Halo00PBR result; 121 Halo00Params params; 122 params.period = 0.2; 123 params.count = 5; 124 params.uv = uv; 125 126#define COORD_SCALE 2 127#define SCALEF4(f4, scale) float4((f4).x * (scale), (f4).y * (scale), (f4).z * (scale), (f4).w) 128#define F42OBJ(f4) mul(unity_WorldToObject, (SCALEF4(f4, COORD_SCALE))).xyz 129 float3 cam_pos = F42OBJ(float4(_WorldSpaceCameraPos, 1)).xyz; 130 float3 mesh_pos = F42OBJ(float4(worldPos, 1)).xyz; 131 float3 ro = cam_pos; 132 float3 rd = normalize((mesh_pos - cam_pos).xyz); 133 134 __halo00_march(ro, rd, params, result); 135 136 return result; 137} 138 139#endif // _GIMMICK_HALO_00 140 141#endif // _HALOS_INC