yum-archive/2ner
A toon shader for Unity's BIRP.
git clone https://git.yummers.dev/yum-archive/2ner
0bdd125
master
1#ifndef __FACE_ME_INC 2#define __FACE_ME_INC 3 4#include "cnlohr.cginc" 5#include "interpolators.cginc" 6 7#if defined(_FACE_ME) 8// Rotate the object's position and normal so that it always faces the camera. 9void face_me(inout appdata v) { 10 [branch] 11 if (_Face_Me_Enabled_Dynamic) { 12 float3 object_center = mul(unity_ObjectToWorld, float4(0, 0, 0, 1)); 13 // Get forward axis of object coordinate system, i.e. the orientation of 14 // the hip bone. 15 // Then project it onto the xz plane. 16 float3 forward_axis = mul(unity_ObjectToWorld, float3(0, 0, 1)); 17 forward_axis.y = 0; 18 forward_axis = normalize(forward_axis); 19 float4 worldPos = mul(unity_ObjectToWorld, v.vertex); 20 float3 rd = normalize(object_center - getCenterCamPos()); 21 // We apply a factor of -1 to shift the result forward by a phase shift of pi. 22 float cos_t = -dot(normalize(rd.xz), forward_axis.xz); 23 // We want to get sin(t) using the identity: 24 // || a x b || = || a || || b || sin(t) 25 // For normal vectors, this simplifies to: 26 // || a x b || = sin(t) 27 // The issue is that the norm operator loses the sign. 28 // We can estimate the sign by assuming that `rd` and `forward_axis` are on 29 // the xz plane. 30 // If that's the case, then the cross product is necessarily constrained to 31 // the y axis. 32 float sin_t_sign = sign(cross(rd, forward_axis).y); 33 // Here we use the identity: 34 // sin(t) = sqrt(1 - cos(t)^2) 35 // We simply apply the sign correction `sin_t_sign` to the result. 36 // We then invert it, since the goal is not to amplify the rotation, but 37 // to negate it. 38 // Finally, we add a phase correction to make the abomination face us. 39 float sin_t = -sqrt(1 - cos_t * cos_t) * sin_t_sign; 40 41 // Double the angle using double-angle formulas 42 if (isVR()) { 43 float sin_2t = 2 * sin_t * cos_t; 44 float cos_2t = cos_t * cos_t - sin_t * sin_t; // or: 2 * cos_t * cos_t - 1 45 sin_t = sin_2t; 46 cos_t = cos_2t; 47 } 48 49 // Use the doubled angle values in your rotation matrix 50 float2x2 face_me_rot = float2x2(cos_t, -sin_t, sin_t, cos_t); 51 worldPos.xz = mul(face_me_rot, (worldPos.xz - object_center.xz)) + object_center.xz; 52 v.vertex = mul(unity_WorldToObject, worldPos); 53 54 float3 world_normal = UnityObjectToWorldNormal(v.normal); 55 world_normal.xz = mul(face_me_rot, world_normal.xz); 56 v.normal = normalize(mul(unity_WorldToObject, world_normal)); 57 58 float3 world_tangent = UnityObjectToWorldDir(v.tangent.xyz); 59 world_tangent.xz = mul(face_me_rot, world_tangent.xz); 60 v.tangent.xyz = normalize(mul(unity_WorldToObject, world_tangent)); 61 } 62} 63#endif // _FACE_ME 64 65#endif // __FACE_ME_INC 66