目录
前言:
在之前的文章我已经实现了标题所述的内容功能: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"
}