summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryum <yum.food.vr@gmail.com>2026-02-25 18:48:24 -0800
committeryum <yum.food.vr@gmail.com>2026-02-25 18:48:24 -0800
commit0e0584159c47c0229e1ba2120dcc782c7250d09f (patch)
treea8fd6b7eaf357ed76f072b4baf748f2cdb830400
parente299d8bbb242f6a2bb59d07f7dd1354eb018fedf (diff)
add matcap & rim lighting backend code
-rw-r--r--matcap.cginc107
1 files changed, 107 insertions, 0 deletions
diff --git a/matcap.cginc b/matcap.cginc
new file mode 100644
index 0000000..3b9fb15
--- /dev/null
+++ b/matcap.cginc
@@ -0,0 +1,107 @@
+#ifndef __MATCAPS_INC
+#define __MATCAPS_INC
+
+#include "globals.cginc"
+#include "lighting.cginc"
+#include "pbr.cginc"
+#include "texture_utils.cginc"
+
+#if defined(_MATCAP0) || defined(_RIM_LIGHTING0)
+float2 getMatcapUV(v2f i, Pbr pbr) {
+ const float3 cam_normal = normalize(mul(UNITY_MATRIX_V, float4(pbr.normal, 0)));
+ const float3 cam_view_dir = normalize(mul(UNITY_MATRIX_V, float4(-i.eyeVec, 0)));
+ const float3 cam_refl = -reflect(cam_view_dir, cam_normal);
+ float m = 2.0 * sqrt(
+ cam_refl.x * cam_refl.x +
+ cam_refl.y * cam_refl.y +
+ (cam_refl.z + 1) * (cam_refl.z + 1));
+ return cam_refl.xy / m + 0.5;
+}
+
+void applyMatcapImpl(inout float3 color, float3 sample, uint mode, float mask)
+{
+ [forcecase]
+ switch(mode) {
+ case MATCAP_MODE_REPLACE:
+ color.rgb = lerp(color.rgb, sample, mask);
+ break;
+ case MATCAP_MODE_ADD:
+ color.rgb += lerp(0, sample, mask);
+ break;
+ case MATCAP_MODE_MULTIPLY:
+ color.rgb *= lerp(1, sample, mask);
+ break;
+ case MATCAP_MODE_SUBTRACT:
+ color.rgb -= lerp(0, sample, mask);
+ break;
+ case MATCAP_MODE_ADD_PRODUCT:
+ color.rgb += lerp(0, sample * color.rgb, mask);
+ break;
+ default:
+ break;
+ }
+}
+
+void applyMatcap(inout Pbr pbr, float3 sample, uint mode, float mask)
+{
+ applyMatcapImpl(pbr.albedo.rgb, sample, mode, mask);
+}
+
+float2 quantizeMatcapUV(float2 muv, float muv_r, float steps) {
+ float muv_r_q = floor(muv_r * steps) / steps;
+ const float epsilon = 1e-4f;
+ return muv_r_q * (muv / max(epsilon, muv_r));
+}
+#endif // _MATCAP0 || _RIM_LIGHTING0
+
+void applyMatcapsAndRimLighting(v2f i, inout Pbr pbr, inout Lighting light_data) {
+#if defined(_MATCAP0) || defined(_RIM_LIGHTING0)
+ float2 muv = getMatcapUV(i, pbr);
+ float2 muv_centered = muv * 2 - 1;
+ float muv_r = length(muv_centered);
+#endif
+
+#if defined(_MATCAP0)
+#if defined(_MATCAP0_QUANTIZATION)
+ float2 m0uv = quantizeMatcapUV(muv, muv_r, _Matcap0_Quantization_Steps);
+#else
+ float2 m0uv = muv;
+#endif
+ float3 m0 = _Matcap0.Sample(linear_repeat_s, m0uv);
+ m0 = _Matcap0_Invert ? 1 - m0 : m0;
+ m0 *= _Matcap0_Strength;
+#if defined(_MATCAP0_MASK)
+ float m0_mask = _Matcap0_Mask.Sample(linear_repeat_s, UV_SCOFF(i, _Matcap0_Mask_ST, /*which_channel=*/0));
+#else
+ float m0_mask = 1;
+#endif
+ applyMatcap(pbr, m0, _Matcap0_Mode, m0_mask);
+#endif // _MATCAP0
+
+#if defined(_RIM_LIGHTING0)
+ // 1 at rim center, 0 outside blur radius.
+ float rl0_inner = smoothstep(
+ _Rim_Lighting0_Center - _Rim_Lighting0_Blur,
+ _Rim_Lighting0_Center,
+ muv_r);
+ float rl0_outer = 1 - smoothstep(
+ _Rim_Lighting0_Center,
+ _Rim_Lighting0_Center + _Rim_Lighting0_Blur,
+ muv_r);
+ float rl0_dist = rl0_inner * rl0_outer;
+#if defined(_RIM_LIGHTING0_QUANTIZATION)
+ rl0_dist = floor(rl0_dist * _Rim_Lighting0_Quantization_Steps) / _Rim_Lighting0_Quantization_Steps;
+#endif
+ float3 rl0 = _Rim_Lighting0_Color * rl0_dist;
+#if defined(_RIM_LIGHTING0_MASK)
+ float rl0_mask = _Rim_Lighting0_Mask.Sample(linear_repeat_s, UV_SCOFF(i, _Rim_Lighting0_Mask_ST, /*which_channel=*/0));
+#else
+ float rl0_mask = 1;
+#endif
+ applyMatcap(pbr, rl0, _Rim_Lighting0_Mode, rl0_mask);
+#endif // _RIM_LIGHTING0
+
+}
+
+#endif
+