yum-archive/2ner
A toon shader for Unity's BIRP.
git clone https://git.yummers.dev/yum-archive/2ner
f478606
master
1#ifndef __SSFD_INC 2#define __SSFD_INC 3 4#include "globals.cginc" 5 6float ssfd(float2 uv, float scale, float max_fwidth, float2 uv_offset, texture3D noise) 7{ 8 //float uv_fw = fwidth(uv.x) + fwidth(uv.y); 9 // Original paper uses SVD instead of fwidth. 10 float2x2 M = float2x2(ddx(uv), ddy(uv)); 11 float2x2 MtM = mul(transpose(M), M); 12 float trace = MtM[0][0] + MtM[1][1]; 13 float det = determinant(MtM); 14 // Calculate eigenvalues using quadratic formula. 15 float tmp = sqrt(trace * trace - 4 * det); 16 float e1 = (trace + tmp) * 0.5; 17 float e2 = (trace - tmp) * 0.5; 18 float2 singular_values = sqrt(float2(e1, e2)); 19 // Logic from original paper: the smaller eigenvalue corresponds to the 20 // largest amount of stretching, so we use it to determine when to 21 // subdivide. 22 float uv_fw = singular_values.y; 23 uv_fw *= scale; 24 25 uint width, height, depth; 26 noise.GetDimensions(width, height, depth); 27 float bayer_res = sqrt(depth); 28 29 // Suppose max_fwidth is 1. 30 // uv_fw is 16. That means UV is changing a lot per pixel. That means we want to shrink the scale of the UV. 31 // Factor is 16. 32 // log_2(factor) is 4. 33 // Divide original by 16. 34 float fw_factor = uv_fw / max_fwidth; 35 // log_b(x) = log_a(x) / log_a(b) 36 float fractal_level = log2(fw_factor) / log2(bayer_res); 37 float fractal_level_floor = floor(fractal_level); 38 float fractal_remainder = fractal_level - fractal_level_floor; 39 40 uv *= pow(bayer_res, -fractal_level_floor); 41 uv += uv_offset * pow(bayer_res, -fractal_level_floor); 42 43 float n_layers = depth; 44 float not_used_lo = 1/(n_layers*2); 45 float not_used_hi = 1 - not_used_lo; 46 47 float uvw = (not_used_hi - not_used_lo) * (1 - fractal_remainder) + not_used_lo; 48 49 float3 uv_3d = float3(uv, uvw); 50 51 float dither = noise.SampleLevel(linear_repeat_s, uv_3d, 0); 52 53 return dither; 54} 55 56#endif // __SSFD_INC 57