From 20234b7fdc550fd3d2542391ac5bb735a7edb820 Mon Sep 17 00:00:00 2001 From: yum Date: Fri, 6 Mar 2026 15:10:27 -0800 Subject: Switch from #ifdef to uniform branches for decals Makes code much smaller & simpler, and shader locker constant folding should make it just as efficient. --- decal.cginc | 236 +++++++++++---------------------------------------------- features.cginc | 20 ----- globals.cginc | 111 +++++++-------------------- 3 files changed, 72 insertions(+), 295 deletions(-) diff --git a/decal.cginc b/decal.cginc index 5f60fe7..aee7cf0 100644 --- a/decal.cginc +++ b/decal.cginc @@ -27,206 +27,58 @@ float2 decal_rotate(float2 uv, float rotation) { return float2(d.x * c - d.y * s, d.x * s + d.y * c) + 0.5; } +#define APPLY_DECAL(N) \ + { \ + float2 uv = get_uv_by_channel(i, _Decal##N##_UV_Channel); \ + uv -= _Decal##N##_MainTex_ST.zw; \ + uv *= _Decal##N##_MainTex_ST.xy; \ + if (_Decal##N##_Rotation_Enabled) \ + uv = decal_rotate(uv, _Decal##N##_Rotation); \ + float4 albedo = decal_sample(_Decal##N##_MainTex, uv, _Decal##N##_UV_Mode); \ + albedo *= _Decal##N##_Color; \ + albedo.a *= _Decal##N##_Opacity; \ + if (_Decal##N##_Mask_Enabled) { \ + float2 mask_uv = get_uv_by_channel(i, _Decal##N##_Mask_UV_Channel); \ + mask_uv -= _Decal##N##_Mask_ST.zw; \ + mask_uv *= _Decal##N##_Mask_ST.xy; \ + float mask = decal_sample(_Decal##N##_Mask, mask_uv, _Decal##N##_UV_Mode); \ + if (_Decal##N##_Mask_Invert) mask = 1 - mask; \ + albedo.a *= mask; \ + } \ + if (_Decal##N##_Albedo_Clamp) albedo.rgb = saturate(albedo.rgb); \ + [forcecase] \ + switch (_Decal##N##_Mix_Mode) { \ + case DECAL_MIX_MODE_ALPHA_BLEND: \ + pbr.albedo = alpha_blend(albedo, pbr.albedo); \ + break; \ + case DECAL_MIX_MODE_MULTIPLY: \ + pbr.albedo.rgb *= lerp(1, albedo.rgb, albedo.a); \ + break; \ + case DECAL_MIX_MODE_ADD_PRODUCT: \ + pbr.albedo.rgb += lerp(0, albedo.rgb * pbr.albedo.rgb, albedo.a); \ + break; \ + } \ + if (_Decal##N##_Metallic_Gloss_Enabled) { \ + float4 mg = decal_sample(_Decal##N##_Metallic_Gloss, uv, _Decal##N##_UV_Mode); \ + pbr.metallic = lerp(pbr.metallic, mg.r, albedo.a); \ + pbr.smoothness = lerp(pbr.smoothness, mg.a, albedo.a); \ + pbr.roughness_perceptual = clamp(1 - pbr.smoothness, MIN_PERCEPTUAL_ROUGHNESS, 1); \ + pbr.roughness = clamp(pbr.roughness_perceptual * pbr.roughness_perceptual, MIN_ROUGHNESS, 1); \ + } \ + } + void applyDecals(v2f i, inout Pbr pbr) { #if defined(_DECAL0) - { - float2 uv = get_uv_by_channel(i, _Decal0_UV_Channel); - uv -= _Decal0_MainTex_ST.zw; - uv *= _Decal0_MainTex_ST.xy; -#if defined(_DECAL0_ROTATION) - uv = decal_rotate(uv, _Decal0_Rotation); -#endif - float4 albedo = decal_sample(_Decal0_MainTex, uv, _Decal0_UV_Mode); - albedo *= _Decal0_Color; - albedo.a *= _Decal0_Opacity; - -#if defined(_DECAL0_MASK) - float2 mask_uv = get_uv_by_channel(i, _Decal0_Mask_UV_Channel); - mask_uv -= _Decal0_Mask_ST.zw; - mask_uv *= _Decal0_Mask_ST.xy; - // For now, mask gets the same sampling mode as the decal. - float mask = decal_sample(_Decal0_Mask, mask_uv, _Decal0_UV_Mode); -#if defined(_DECAL0_MASK_INVERT) - mask = 1 - mask; -#endif // _DECAL0_MASK_INVERT - albedo.a *= mask; -#endif // _DECAL0_MASK - -#if defined(_DECAL0_ALBEDO_CLAMP) - albedo.rgb = saturate(albedo.rgb); -#endif // _DECAL0_ALBEDO_CLAMP - - [forcecase] - switch (_Decal0_Mix_Mode) { - case DECAL_MIX_MODE_ALPHA_BLEND: - pbr.albedo = alpha_blend(albedo, pbr.albedo); - break; - case DECAL_MIX_MODE_MULTIPLY: - pbr.albedo.rgb *= lerp(1, albedo.rgb, albedo.a); - break; - case DECAL_MIX_MODE_ADD_PRODUCT: - pbr.albedo.rgb += lerp(0, albedo.rgb * pbr.albedo.rgb, albedo.a); - break; - } - -#if defined(_DECAL0_METALLIC_GLOSS) - float4 mg = decal_sample(_Decal0_Metallic_Gloss, uv, _Decal0_UV_Mode); - pbr.metallic = lerp(pbr.metallic, mg.r, albedo.a); - pbr.smoothness = lerp(pbr.smoothness, mg.a, albedo.a); - pbr.roughness_perceptual = clamp(1 - pbr.smoothness, MIN_PERCEPTUAL_ROUGHNESS, 1); - pbr.roughness = clamp(pbr.roughness_perceptual * pbr.roughness_perceptual, MIN_ROUGHNESS, 1); -#endif // _DECAL0_METALLIC_GLOSS - } + APPLY_DECAL(0) #endif - #if defined(_DECAL1) - { - float2 uv = get_uv_by_channel(i, _Decal1_UV_Channel); - uv -= _Decal1_MainTex_ST.zw; - uv *= _Decal1_MainTex_ST.xy; -#if defined(_DECAL1_ROTATION) - uv = decal_rotate(uv, _Decal1_Rotation); -#endif - float4 albedo = decal_sample(_Decal1_MainTex, uv, _Decal1_UV_Mode); - albedo *= _Decal1_Color; - albedo.a *= _Decal1_Opacity; - -#if defined(_DECAL1_MASK) - float2 mask_uv = get_uv_by_channel(i, _Decal1_Mask_UV_Channel); - mask_uv -= _Decal1_Mask_ST.zw; - mask_uv *= _Decal1_Mask_ST.xy; - float mask = decal_sample(_Decal1_Mask, mask_uv, _Decal1_UV_Mode); -#if defined(_DECAL1_MASK_INVERT) - mask = 1 - mask; -#endif // _DECAL1_MASK_INVERT - albedo.a *= mask; -#endif // _DECAL1_MASK - -#if defined(_DECAL1_ALBEDO_CLAMP) - albedo.rgb = saturate(albedo.rgb); -#endif // _DECAL1_ALBEDO_CLAMP - - [forcecase] - switch (_Decal1_Mix_Mode) { - case DECAL_MIX_MODE_ALPHA_BLEND: - pbr.albedo = alpha_blend(albedo, pbr.albedo); - break; - case DECAL_MIX_MODE_MULTIPLY: - pbr.albedo.rgb *= lerp(1, albedo.rgb, albedo.a); - break; - case DECAL_MIX_MODE_ADD_PRODUCT: - pbr.albedo.rgb += lerp(0, albedo.rgb * pbr.albedo.rgb, albedo.a); - break; - } - -#if defined(_DECAL1_METALLIC_GLOSS) - float4 mg = decal_sample(_Decal1_Metallic_Gloss, uv, _Decal1_UV_Mode); - pbr.metallic = lerp(pbr.metallic, mg.r, albedo.a); - pbr.smoothness = lerp(pbr.smoothness, mg.a, albedo.a); - pbr.roughness_perceptual = clamp(1 - pbr.smoothness, MIN_PERCEPTUAL_ROUGHNESS, 1); - pbr.roughness = clamp(pbr.roughness_perceptual * pbr.roughness_perceptual, MIN_ROUGHNESS, 1); -#endif // _DECAL1_METALLIC_GLOSS - } + APPLY_DECAL(1) #endif - #if defined(_DECAL2) - { - float2 uv = get_uv_by_channel(i, _Decal2_UV_Channel); - uv -= _Decal2_MainTex_ST.zw; - uv *= _Decal2_MainTex_ST.xy; -#if defined(_DECAL2_ROTATION) - uv = decal_rotate(uv, _Decal2_Rotation); -#endif - float4 albedo = decal_sample(_Decal2_MainTex, uv, _Decal2_UV_Mode); - albedo *= _Decal2_Color; - albedo.a *= _Decal2_Opacity; - -#if defined(_DECAL2_MASK) - float2 mask_uv = get_uv_by_channel(i, _Decal2_Mask_UV_Channel); - mask_uv -= _Decal2_Mask_ST.zw; - mask_uv *= _Decal2_Mask_ST.xy; - float mask = decal_sample(_Decal2_Mask, mask_uv, _Decal2_UV_Mode); -#if defined(_DECAL2_MASK_INVERT) - mask = 1 - mask; -#endif // _DECAL2_MASK_INVERT - albedo.a *= mask; -#endif // _DECAL2_MASK - -#if defined(_DECAL2_ALBEDO_CLAMP) - albedo.rgb = saturate(albedo.rgb); -#endif // _DECAL2_ALBEDO_CLAMP - - [forcecase] - switch (_Decal2_Mix_Mode) { - case DECAL_MIX_MODE_ALPHA_BLEND: - pbr.albedo = alpha_blend(albedo, pbr.albedo); - break; - case DECAL_MIX_MODE_MULTIPLY: - pbr.albedo.rgb *= lerp(1, albedo.rgb, albedo.a); - break; - case DECAL_MIX_MODE_ADD_PRODUCT: - pbr.albedo.rgb += lerp(0, albedo.rgb * pbr.albedo.rgb, albedo.a); - break; - } - -#if defined(_DECAL2_METALLIC_GLOSS) - float4 mg = decal_sample(_Decal2_Metallic_Gloss, uv, _Decal2_UV_Mode); - pbr.metallic = lerp(pbr.metallic, mg.r, albedo.a); - pbr.smoothness = lerp(pbr.smoothness, mg.a, albedo.a); - pbr.roughness_perceptual = clamp(1 - pbr.smoothness, MIN_PERCEPTUAL_ROUGHNESS, 1); - pbr.roughness = clamp(pbr.roughness_perceptual * pbr.roughness_perceptual, MIN_ROUGHNESS, 1); -#endif // _DECAL2_METALLIC_GLOSS - } + APPLY_DECAL(2) #endif - #if defined(_DECAL3) - { - float2 uv = get_uv_by_channel(i, _Decal3_UV_Channel); - uv -= _Decal3_MainTex_ST.zw; - uv *= _Decal3_MainTex_ST.xy; -#if defined(_DECAL3_ROTATION) - uv = decal_rotate(uv, _Decal3_Rotation); -#endif - float4 albedo = decal_sample(_Decal3_MainTex, uv, _Decal3_UV_Mode); - albedo *= _Decal3_Color; - albedo.a *= _Decal3_Opacity; - -#if defined(_DECAL3_MASK) - float2 mask_uv = get_uv_by_channel(i, _Decal3_Mask_UV_Channel); - mask_uv -= _Decal3_Mask_ST.zw; - mask_uv *= _Decal3_Mask_ST.xy; - float mask = decal_sample(_Decal3_Mask, mask_uv, _Decal3_UV_Mode); -#if defined(_DECAL3_MASK_INVERT) - mask = 1 - mask; -#endif // _DECAL3_MASK_INVERT - albedo.a *= mask; -#endif // _DECAL3_MASK - -#if defined(_DECAL3_ALBEDO_CLAMP) - albedo.rgb = saturate(albedo.rgb); -#endif // _DECAL3_ALBEDO_CLAMP - - [forcecase] - switch (_Decal3_Mix_Mode) { - case DECAL_MIX_MODE_ALPHA_BLEND: - pbr.albedo = alpha_blend(albedo, pbr.albedo); - break; - case DECAL_MIX_MODE_MULTIPLY: - pbr.albedo.rgb *= lerp(1, albedo.rgb, albedo.a); - break; - case DECAL_MIX_MODE_ADD_PRODUCT: - pbr.albedo.rgb += lerp(0, albedo.rgb * pbr.albedo.rgb, albedo.a); - break; - } - -#if defined(_DECAL3_METALLIC_GLOSS) - float4 mg = decal_sample(_Decal3_Metallic_Gloss, uv, _Decal3_UV_Mode); - pbr.metallic = lerp(pbr.metallic, mg.r, albedo.a); - pbr.smoothness = lerp(pbr.smoothness, mg.a, albedo.a); - pbr.roughness_perceptual = clamp(1 - pbr.smoothness, MIN_PERCEPTUAL_ROUGHNESS, 1); - pbr.roughness = clamp(pbr.roughness_perceptual * pbr.roughness_perceptual, MIN_ROUGHNESS, 1); -#endif // _DECAL3_METALLIC_GLOSS - } + APPLY_DECAL(3) #endif } diff --git a/features.cginc b/features.cginc index 621c7f0..c3c5aa1 100755 --- a/features.cginc +++ b/features.cginc @@ -160,38 +160,18 @@ //ifex _Decal0_Enabled==0 #pragma shader_feature_local _DECAL0 -#pragma shader_feature_local _DECAL0_ALBEDO_CLAMP -#pragma shader_feature_local _DECAL0_METALLIC_GLOSS -#pragma shader_feature_local _DECAL0_ROTATION -#pragma shader_feature_local _DECAL0_MASK -#pragma shader_feature_local _DECAL0_MASK_INVERT //endex //ifex _Decal1_Enabled==0 #pragma shader_feature_local _DECAL1 -#pragma shader_feature_local _DECAL1_ALBEDO_CLAMP -#pragma shader_feature_local _DECAL1_METALLIC_GLOSS -#pragma shader_feature_local _DECAL1_ROTATION -#pragma shader_feature_local _DECAL1_MASK -#pragma shader_feature_local _DECAL1_MASK_INVERT //endex //ifex _Decal2_Enabled==0 #pragma shader_feature_local _DECAL2 -#pragma shader_feature_local _DECAL2_ALBEDO_CLAMP -#pragma shader_feature_local _DECAL2_METALLIC_GLOSS -#pragma shader_feature_local _DECAL2_ROTATION -#pragma shader_feature_local _DECAL2_MASK -#pragma shader_feature_local _DECAL2_MASK_INVERT //endex //ifex _Decal3_Enabled==0 #pragma shader_feature_local _DECAL3 -#pragma shader_feature_local _DECAL3_ALBEDO_CLAMP -#pragma shader_feature_local _DECAL3_METALLIC_GLOSS -#pragma shader_feature_local _DECAL3_ROTATION -#pragma shader_feature_local _DECAL3_MASK -#pragma shader_feature_local _DECAL3_MASK_INVERT //endex //ifex _Matcap0_Enabled==0 diff --git a/globals.cginc b/globals.cginc index 44417ac..c7529b1 100755 --- a/globals.cginc +++ b/globals.cginc @@ -249,93 +249,38 @@ float _Parallax_Heightmap_Ray_Marching_Steps; #define DECAL_MIX_MODE_MULTIPLY 1 #define DECAL_MIX_MODE_ADD_PRODUCT 2 -#if defined(_DECAL0) -float4 _Decal0_Color; -texture2D _Decal0_MainTex; -float4 _Decal0_MainTex_ST; -float _Decal0_Opacity; -int _Decal0_UV_Mode; -int _Decal0_UV_Channel; -int _Decal0_Mix_Mode; -#if defined(_DECAL0_ROTATION) -float _Decal0_Rotation; -#endif // _DECAL0_ROTATION -#if defined(_DECAL0_MASK) -texture2D _Decal0_Mask; -float4 _Decal0_Mask_ST; -int _Decal0_Mask_UV_Channel; -#endif // _DECAL0_MASK -#if defined(_DECAL0_METALLIC_GLOSS) -texture2D _Decal0_Metallic_Gloss; -float4 _Decal0_Metallic_Gloss_ST; -#endif // _DECAL0_METALLIC_GLOSS -#endif // _DECAL0 +#define DECAL_GLOBALS(N) \ + float4 _Decal##N##_Color; \ + texture2D _Decal##N##_MainTex; \ + float4 _Decal##N##_MainTex_ST; \ + float _Decal##N##_Opacity; \ + int _Decal##N##_UV_Mode; \ + int _Decal##N##_UV_Channel; \ + int _Decal##N##_Mix_Mode; \ + float _Decal##N##_Rotation_Enabled; \ + float _Decal##N##_Rotation; \ + float _Decal##N##_Mask_Enabled; \ + texture2D _Decal##N##_Mask; \ + float4 _Decal##N##_Mask_ST; \ + int _Decal##N##_Mask_UV_Channel; \ + float _Decal##N##_Mask_Invert; \ + float _Decal##N##_Albedo_Clamp; \ + float _Decal##N##_Metallic_Gloss_Enabled; \ + texture2D _Decal##N##_Metallic_Gloss; \ + float4 _Decal##N##_Metallic_Gloss_ST; +#if defined(_DECAL0) +DECAL_GLOBALS(0) +#endif #if defined(_DECAL1) -float4 _Decal1_Color; -texture2D _Decal1_MainTex; -float4 _Decal1_MainTex_ST; -float _Decal1_Opacity; -int _Decal1_UV_Mode; -int _Decal1_UV_Channel; -int _Decal1_Mix_Mode; -#if defined(_DECAL1_ROTATION) -float _Decal1_Rotation; -#endif // _DECAL1_ROTATION -#if defined(_DECAL1_MASK) -texture2D _Decal1_Mask; -float4 _Decal1_Mask_ST; -int _Decal1_Mask_UV_Channel; -#endif // _DECAL1_MASK -#if defined(_DECAL1_METALLIC_GLOSS) -texture2D _Decal1_Metallic_Gloss; -float4 _Decal1_Metallic_Gloss_ST; -#endif // _DECAL1_METALLIC_GLOSS -#endif // _DECAL1 - +DECAL_GLOBALS(1) +#endif #if defined(_DECAL2) -float4 _Decal2_Color; -texture2D _Decal2_MainTex; -float4 _Decal2_MainTex_ST; -float _Decal2_Opacity; -int _Decal2_UV_Mode; -int _Decal2_UV_Channel; -int _Decal2_Mix_Mode; -#if defined(_DECAL2_ROTATION) -float _Decal2_Rotation; -#endif // _DECAL2_ROTATION -#if defined(_DECAL2_MASK) -texture2D _Decal2_Mask; -float4 _Decal2_Mask_ST; -int _Decal2_Mask_UV_Channel; -#endif // _DECAL2_MASK -#if defined(_DECAL2_METALLIC_GLOSS) -texture2D _Decal2_Metallic_Gloss; -float4 _Decal2_Metallic_Gloss_ST; -#endif // _DECAL2_METALLIC_GLOSS -#endif // _DECAL2 - +DECAL_GLOBALS(2) +#endif #if defined(_DECAL3) -float4 _Decal3_Color; -texture2D _Decal3_MainTex; -float4 _Decal3_MainTex_ST; -float _Decal3_Opacity; -int _Decal3_UV_Mode; -int _Decal3_UV_Channel; -int _Decal3_Mix_Mode; -#if defined(_DECAL3_ROTATION) -float _Decal3_Rotation; -#endif // _DECAL3_ROTATION -#if defined(_DECAL3_MASK) -texture2D _Decal3_Mask; -float4 _Decal3_Mask_ST; -int _Decal3_Mask_UV_Channel; -#endif // _DECAL3_MASK -#if defined(_DECAL3_METALLIC_GLOSS) -texture2D _Decal3_Metallic_Gloss; -float4 _Decal3_Metallic_Gloss_ST; -#endif // _DECAL3_METALLIC_GLOSS -#endif // _DECAL3 +DECAL_GLOBALS(3) +#endif #define MATCAP_MODE_REPLACE 0 #define MATCAP_MODE_ADD 1 -- cgit v1.2.3