Unity URPShader:实现和PS一样的色相/饱和度调整参数效果(修复)

目录

前言:

一、问题原因

二、算法修复

三、全代码


前言:

在之前的文章我已经实现了标题所述的内容功能:Unity URPShader:实现和PS一样的色相/饱和度调整参数效果-CSDN博客

但在偶然测试的时候,发现当采样的图片为白色或者是调整的颜色为白色时,会导致最终的画面渲染为黑色,今天对其进行修复。

一、问题原因

产生这样的原因在于颜色传入时,色相算法与饱和度算法计算出的颜色都是黑色,所以导致问题出错。回到PS后,在调节色相或者是饱和度时,其中白色依然不会改变,唯有亮度参数会对其进行效果改变。

二、算法修复

只需要判断输入的颜色是否时白色即可,以下时算法调整的地方:

复制代码
  half isWhite = saturate(floor(color.r * color.g * color.b));
                if (isWhite < 0.5)
                {
                    //Hue
                    half3 hsv = RGB2HSV(color.rgb);
                    hsv.x = frac(hsv.x + _Hue / 360.0);
                    color.rgb = HSV2RGB(hsv);
                    //Saturation
                    color.rgb = Saturation(color.rgb, _Saturation);
                }

三、全代码

复制代码
Shader "Background_Custom_HSV"
{
    Properties
    {
        _PatternTex ("贴图", 2D) = "black" { }
        [Header(BaseColor)]
        [Space]
        [HDR]_Color0 ("颜色", Color) = (1, 1, 1, 1)
 
        [Header(HSL)]
        [Space]
        _Hue ("Hue", Range(-180, 180)) = 0.0
        _Saturation ("Saturation", Range(-100, 100)) = 0.0
        _Lightness ("Lightness", Range(-100, 100)) = 0.0
 
    }
    SubShader
    {
        Tags { "RenderType" = "Transparent" "Queue" = "Transparent" "RenderPipeline" = "UniversalPipeline" "IgnoreProjector" = "True" }
 
        Pass
        {
            Blend SrcAlpha OneMinusSrcAlpha
            ZWrite Off
            Cull Back
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag
 
            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
 
 
            TEXTURE2D(_PatternTex);
            SAMPLER(sampler_PatternTex);
 
            CBUFFER_START(UnityPerMaterial)
                half3 _Color0;
                float _Hue;
                float _Saturation;
                float _Lightness;
            CBUFFER_END
 
            struct Attributes
            {
                float4 positionOS : POSITION;
                float2 texcoord : TEXCOORD0;
            };
 
            struct Varyings
            {
                float4 positionHS : SV_POSITION;
                float2 uv : TEXCOORD0;
            };
 
     
            // RGB转HSV/HSB
            half3 RGB2HSV(half3 c)
            {
                half4 K = half4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
                half4 P = lerp(half4(c.bg, K.wz), half4(c.gb, K.xy), step(c.b, c.g));
                half4 Q = lerp(half4(P.xyw, c.r), half4(c.r, P.yzx), step(P.x, c.r));
                half D = Q.x - min(Q.w, Q.y);
                half E = 1e-10;
                return half3(abs(Q.z + (Q.w - Q.y) / (6.0 * D + E)), D / (Q.x + E), Q.x);
            }
            
            // HSV/HSB转RGB
            half3 HSV2RGB(half3 c)
            {
                half4 K = half4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
                half3 P = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
                return c.z * lerp(K.xxx, saturate(P - K.xxx), c.y);
            }
 
 
            half3 Saturation(half3 color, float saturation)
            {
                half rgbMax = max(color.r, max(color.g, color.b));
                half rgbMin = min(color.r, min(color.g, color.b));
                half delta = rgbMax - rgbMin;
                // if (delta > 0)
                // {
                //     half value = rgbMax + rgbMin;
                //     half L = value * 0.5;
                //     half S = lerp(delta / value, delta / (2.0 - value), step(0.5, delta));
                //     half percent = saturation * 0.01;
                //     half alpha = 0;
                //     half3 final_color = 0;
                //     if (percent >= 0)
                //     {
                //         if (percent + S >= 1)
                //             alpha = S;
                //         else
                //             alpha = 1 - percent;
                //         alpha = 1 / alpha - 1;
                //         final_color = color + (color - half3(L, L, L)) * alpha;
                //     }
                //     else
                //     {
                //         alpha = percent;
                //         final_color = L + (color - half3(L, L, L)) * (1 + alpha);
                //     }
                
                //     return final_color;
                // }
                // else
                //     return color;
                half value = rgbMax + rgbMin;
                half L = value * 0.5;
                half S = lerp(delta / value, delta / (2.0 - value), step(0.5, delta));
                half percent = saturation * 0.01;
                half3 final_color = lerp(L + (color - L.xxx) * (1 + percent),
                color + (color - L.xxx) * (1.0 / (lerp(1.0 - percent, S, step(1.0, percent + S))) - 1.0),
                step(0.0, percent));
 
                final_color = lerp(color, final_color, ceil(delta));
                return final_color;
            }
            
            Varyings vert(Attributes v)
            {
                Varyings o;
                o.positionHS = TransformObjectToHClip(v.positionOS.xyz);
                o.uv = v.texcoord;
                return o;
            }
 
            half4 frag(Varyings i) : SV_Target
            {
                half4 color = SAMPLE_TEXTURE2D(_PatternTex, sampler_PatternTex, i.uv);
                color.rgb *= i.colors.rgb;

                half isWhite = saturate(floor(color.r * color.g * color.b));
                if (isWhite < 0.5)
                {
                    //Hue
                    half3 hsv = RGB2HSV(color.rgb);
                    hsv.x = frac(hsv.x + _Hue / 360.0);
                    color.rgb = HSV2RGB(hsv);
                    //Saturation
                    color.rgb = Saturation(color.rgb, _Saturation);
                }
                //Value
                half value = _Lightness * 0.01;
                // if (value > 0)
                //     color.rgb = (1 - value) * color.rgb + half3(1.0, 1.0, 1.0) * value;
                // else if (value < 0)
                //     color.rgb = color.rgb * (1.0 + value);
                color.rgb = lerp(color.rgb * (1.0 + value), lerp(color.rgb, half3(1.0, 1.0, 1.0), value), step(0.0, _Lightness));
                color.rgb = saturate(color.rgb);

                return color;
            }
            ENDHLSL
        }
    }
 
    FallBack "Hidden/Universal Render Pipeline/FallbackError"
}
相关推荐
虾球xz5 小时前
游戏引擎学习第298天:改进排序键 - 第1部分
人工智能·学习·游戏引擎
EQ-雪梨蛋花汤8 小时前
【Part 3 Unity VR眼镜端播放器开发与优化】第一节|基于Unity的360°全景视频播放实现方案
unity·音视频·vr
数数科技的数据干货11 小时前
如何避免你的高付费用户活跃度下降?
大数据·人工智能·游戏
上海云盾商务经理杨杨14 小时前
2025年高防IP与游戏盾深度对比:如何选择最佳防护方案?
网络协议·tcp/ip·安全·web安全·游戏
Magnum Lehar18 小时前
vulkan游戏引擎的platform文件实现
游戏引擎
benben04419 小时前
AI独立游戏素材生成实操
人工智能·游戏
关于不上作者榜就原神启动那件事1 天前
纸牌游戏(基于集合,和自定义排序实现)
游戏
海 月1 天前
Unity EventCenter 消息中心的设计与实现
unity·消息中心
虾球xz1 天前
游戏引擎学习第307天:排序组可视化
c++·学习·算法·游戏引擎
虾球xz1 天前
游戏引擎学习第306天:图结构排序的调试
c++·学习·算法·游戏引擎