#ifndef __MATCAPS_INC #define __MATCAPS_INC #include "globals.cginc" #include "lighting.cginc" #include "math.cginc" #include "pbr.cginc" #include "texture_utils.cginc" #if defined(_MATCAP0) || defined(_MATCAP1) || defined(_RIM_LIGHTING0) #define HAS_MATCAP_RL #endif #if defined(HAS_MATCAP_RL) 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.xyz, 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 // HAS_MATCAP_RL void apply_matcaps_and_rim_lighting(v2f i, inout Pbr pbr, inout LightData light_data) { #if defined(HAS_MATCAP_RL) 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); #if defined(_MATCAP0_ALBEDO_CLAMP) pbr.albedo.rgb = saturate(pbr.albedo.rgb); #endif #endif // _MATCAP0 #if defined(_MATCAP1) #if defined(_MATCAP1_QUANTIZATION) float2 m1uv = quantizeMatcapUV(muv, muv_r, _Matcap1_Quantization_Steps); #else float2 m1uv = muv; #endif float3 m1 = _Matcap1.Sample(linear_repeat_s, m1uv); m1 = _Matcap1_Invert ? 1 - m1 : m1; m1 *= _Matcap1_Strength; #if defined(_MATCAP1_MASK) float m1_mask = _Matcap1_Mask.Sample(linear_repeat_s, UV_SCOFF(i, _Matcap1_Mask_ST, /*which_channel=*/0)); #else float m1_mask = 1; #endif applyMatcap(pbr, m1, _Matcap1_Mode, m1_mask); #if defined(_MATCAP1_ALBEDO_CLAMP) pbr.albedo.rgb = saturate(pbr.albedo.rgb); #endif #endif // _MATCAP1 #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; switch(_Rim_Lighting0_Mode) { case MATCAP_MODE_ADD: // Fall through. case MATCAP_MODE_SUBTRACT: rl0 = lerp(0, _Rim_Lighting0_Color, rl0_dist); break; case MATCAP_MODE_MULTIPLY: rl0 = lerp(1, _Rim_Lighting0_Color, rl0_dist); break; default: rl0 = lerp(pbr.albedo.xyz, _Rim_Lighting0_Color, rl0_dist); break; } #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