• Photoshop图层混合模式公式(Unity,CG实现)


    本文主要目的来自于在unity符合美术在ps里面的演示效果。

    两个图层叠加到一起的效果,废话不多说直接看效果:

    图片资源在文章末尾

    完整代码也在末尾

    目录

    目录

    Multiply 正片叠底

     Screen 滤色

     Color Dodge 颜色减淡

     Color Burn 颜色加深

    Linear Dodge 线形减淡

    Linear Burn 线形加深

    Overlay 叠加

     Hard Light 强光

    Soft Light 柔光

    亮光 vivid light

    Linear Light 线形光

    Pin Light 点光

    Hard Mix 实色混合

    Difference 差值

    Excusion 排除

    Hue 色相

    HSV那几个模式异常说明:

    完整代码:

    测试效果图片资源:


    Multiply 正片叠底

    公式:

    Ans = A * B;

    half4 finalRGBA = half4(colorA.xyz * colorB.xyz,1);

    效果对比:

    核心代码:

    half4 finalRGBA =  half4(1 - (1 - colorA.xyz) * (1 -colorB.xyz),1);
    

     Screen 滤色

    公式:

    Ans = 1 - (1 - colorA ) * (1 - colorB);

    效果对比:

     核心代码:

    half4 finalRGBA =  half4(1 - (1 - colorA.xyz) * (1 -colorB.xyz),1);

     Color Dodge 颜色减淡
     

    公式:

    ans=colorA / ( 1 - colorB);

    效果对比:(unity存在些许过曝的情况)

    核心代码:

    finalRGBA = half4(colorA.xyz * (rcp(1 - colorB.xyz)),1);

     Color Burn 颜色加深

    公式:

    ans=1 -  (1 - colorA)/ colorB;

    效果对比:

    核心代码:

    finalRGBA = half4(1- rcp(colorB.xyz) * (1 - colorA.xyz),1);

    Linear Dodge 线形减淡

    公式:

    Ans  = colorA + colorB;

     效果对比:

    核心代码:

    finalRGBA = half4(colorB.xyz + colorA.xyz,1);

    Linear Burn 线形加深

    公式:

     Ans  = colorA + colorB  - 1 ;

    效果对比:

    核心代码:

    finalRGBA = half4(colorB.xyz + colorA.xyz - 1,1);

    Overlay 叠加


    公式:


    colorB<=0.5 :  Ans=2*colorA*colorB
    colorB>0.5: Ans=1 - 2 * (1-colorA) * ( 1 - colorB)

    效果对比:

    核心代码:

    1. half3 c1 = colorA.xyz * colorB.xyz * 2 *OA ;
    2. half3 c2 = (1 - 2 * (1 - colorA.xyz) *(1 - colorB.xyz)) * (1 - OA);
    3. finalRGBA = half4(c1+ c2,1);

     Hard Light 强光

    公式:

    colorA <= 0.5:  Ans = 2 * colorA * colorB
    colorA > 0.5   : Ans = 1 - 2 * (1 - colorA) * (1 - colorB)

    效果对比:

    核心代码:

    1. half3 OB = step(colorB.xyz,0.5);
    2. half3 c1 = colorA.xyz * colorB.xyz * 2 *OB ;
    3. half3 c2 = (1 - 2 * (1 - colorA.xyz) *(1 - colorB.xyz)) * (1 - OB);

    Soft Light 柔光

    公式:



    colorA <= 0.5 : Ans = ( 2 * A - 1 ) * ( B - B * B ) + B;
    colorA > 0.5 : Ans = ( 2 * A - 1 ) * ( sqrt ( B ) - B ) + B;

    效果对比:

    核心代码:

    1. half3 OB = step(colorB.xyz,0.5);
    2. half3 c1 = ((2 * colorB - 1) * (colorA - colorA * colorA) + colorA) * OB ;
    3. half3 c2 = ((2 * colorB - 1) * (sqrt(colorA)- colorA) + colorA) * (1 - OB);

    亮光 vivid light

    效果与ps中存在部分差异,但目前没找到原因,盲猜是因为自己没有模拟出图层上下级关系。

    公式:

    colorB <= 0.5 :  Ans = colorA - (1 - colorA) * ( 1 - 2 * colorB) / (2 * colorB);

    colorB > 0.5  :  Ans = colorA + colorA * (2 * colorB - 1)/(2 * (1 - colorB));

    效果对比:

    上下层级不同的情况下(unity没有层级)

     

    核心代码:

    1. float3 c1 = colorB - (1 - colorB) * (1 - 2 * colorA) / (2 * colorA);
    2. float3 c2 = colorB + colorB * (2 * colorA - 1) / (2 * (1 - colorA));
    3. float3 OB = step(colorA.xyz,0.5);
    4. c1 *= OB;
    5. c2 *= (1 - OB);
    6. finalRGBA = float4(c1+ c2,1);

    Linear Light 线形光


    公式:

    Ans = colorB + 2 * colorA - 1;

    效果对比:

    核心代码:

    finalRGBA = float4(colorA + 2 * colorB) - 1;

    Pin Light 点光

    公式:

    colorB < 2 * colorA - 1 :  Ans = 2 * colorA - 1;

     2 * A - 1 < B < 2 * A    :  Ans = colorB;
    colorB > 2 * colorA      :  Ans = 2 * colorA;

    效果展示:

    核心代码:

    1. half3 OB = step(colorA,2 *colorB - 1);
    2. half3 c1 = (2 * colorB - 1) * OB;
    3. half3 OB1 = (1 - OB) * step(colorA , 2 * colorB);
    4. half3 c2 = colorA * OB1;
    5. half3 OB2 = 1 - step(colorA ,2 * colorB);
    6. half3 c3 = 2 * colorB * OB2;
    7. finalRGBA = half4(c1 + c2 + c3,1);

    Hard Mix 实色混合


    公式:


    colorA < 1 - colorB :  Ans = 0;
    colorA > 1 - colorB :  Ans = 1;

    效果展示:

    核心代码:

    1. half3 OA = step(colorB, 1 - colorA);
    2. half3 c1 = 0 * OA;
    3. half3 OA1 = step(1 - colorA,colorB);
    4. half3 c2 = 1 * OA1;
    5. finalRGBA = half4(c1 + c2,1);

    Difference 差值

    公式:

    Ans=|colorA-colorB|

    效果展示:

    核心代码:

    finalRGBA = half4(abs(colorB.xyz - colorA.xyz),1);

    Excusion 排除

    公式:

    Ans=colorA+colorB-(colorA×colorB) * 2

    效果展示:

    核心代码:

    finalRGBA = half4(colorB + colorA - 2 * colorB * colorA);

    Hue 色相

    公式:


    Ans( HSV) =HB SA  VA

    (HSV空间下) Ans = (colorB.x,colorA.y,colorB.z);

    该效果再HSV空间下进行计算(后续需要转化为RGB)

    效果展示:

     核心代码:

    1. float3 c1 = float3(colorBHSV.x,colorAHSV.yz);
    2. c1 = HSV2RGB(c1);
    3. finalRGBA = half4(c1,1);

    HSV那几个模式异常说明:

    • 这几个模式按照公式去计算并不能正常的得到目标结果所以,复刻不出来但是不是很懂怎么回事经测试转颜色空间并无差别且计算并无问题,具体的的混合算法来源也无差别出自官方文档维基百科等都是显示该结果,或为还有部分转化过程,待查证。
    • 饱和度混合模式保留底层的亮度和色调,同时采用顶层的色度。
    • 颜色混合模式保留底层的亮度,同时采用顶层的色调和色度。
    • 亮度混合模式保留底层的色调和色度,同时采用顶层的亮度。、

    颜色混合未完待续。

    完整代码:

    1. Shader "Unlit/TestPs"
    2. {
    3. Properties
    4. {
    5. _MainTexA ("TextureA", 2D) = "white" {}
    6. _MainTexB ("TextureB", 2D) = "white" {}
    7. }
    8. SubShader
    9. {
    10. Tags { "RenderType"="Opaque" }
    11. LOD 100
    12. Pass
    13. {
    14. CGPROGRAM
    15. #pragma vertex vert
    16. #pragma fragment frag
    17. // make fog work
    18. #pragma multi_compile_fog
    19. #include "UnityCG.cginc"
    20. struct appdata
    21. {
    22. float4 vertex : POSITION;
    23. float2 uv : TEXCOORD0;
    24. };
    25. struct v2f
    26. {
    27. float4 uv : TEXCOORD0;
    28. float4 vertex : SV_POSITION;
    29. };
    30. float3 RGB2HSV(float3 c)
    31. {
    32. float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
    33. float4 p = lerp(float4(c.bg, K.wz), float4(c.gb, K.xy), step(c.b, c.g));
    34. float4 q = lerp(float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r));
    35. float d = q.x - min(q.w, q.y);
    36. float e = 1.0e-10;
    37. return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
    38. }
    39. // Official HSV to RGB conversion
    40. float3 HSV2RGB( float3 c ){
    41. float3 rgb = clamp( abs(fmod(c.x*6.0+float3(0.0,4.0,2.0),6)-3.0)-1.0, 0, 1);
    42. rgb = rgb*rgb*(3.0-2.0*rgb);
    43. return c.z * lerp( float3(1,1,1), rgb, c.y);
    44. }
    45. sampler2D _MainTexA;
    46. float4 _MainTexA_ST;
    47. sampler2D _MainTexB;
    48. float4 _MainTexB_ST;
    49. v2f vert (appdata v)
    50. {
    51. v2f o;
    52. o.vertex = UnityObjectToClipPos(v.vertex);
    53. o.uv.xy = TRANSFORM_TEX(v.uv.xy, _MainTexA);
    54. o.uv.zw = TRANSFORM_TEX(v.uv.xy, _MainTexB);
    55. UNITY_TRANSFER_FOG(o,o.vertex);
    56. return o;
    57. }
    58. half4 frag (v2f i) : SV_Target
    59. {
    60. float4 colorA = tex2D(_MainTexA, i.uv.xy);
    61. float colorALum = Luminance(colorA.xyz);
    62. float4 colorB = tex2D(_MainTexB, i.uv.zw);
    63. float3 colorAHSV = RGB2HSV(colorA.xyz);
    64. float3 colorBHSV = RGB2HSV(colorB.xyz);
    65. float colorBLum = Luminance(colorA.xyz);
    66. float4 finalRGBA = 0;
    67. // opacity 正片叠底
    68. finalRGBA = float4(colorA.xyz * colorB.xyz,1);
    69. // Screen 滤色
    70. // finalRGBA = float4(1 - (1 - colorA.xyz) * (1 -colorB.xyz),1);
    71. // Color Dodge 颜色减淡
    72. // finalRGBA = float4(colorA.xyz * (rcp(1 - colorB.xyz)),1);
    73. // Color Burn 颜色加深
    74. // finalRGBA = float4(1- rcp(colorB.xyz) * (1 - colorA.xyz),1);
    75. // Linear Dodge 线形减淡
    76. // finalRGBA = float4(colorB.xyz + colorA.xyz,1);
    77. // Linear Burn 线形加深
    78. // finalRGBA = float4(colorB.xyz + colorA.xyz - 1,1);
    79. // overlay 叠加
    80. // float3 OA = step(colorA.xyz,0.5);
    81. // float3 c1 = colorA.xyz * colorB.xyz * 2 *OA ;
    82. // float3 c2 = (1 - 2 * (1 - colorA.xyz) *(1 - colorB.xyz)) * (1 - OA);
    83. // finalRGBA = float4(c1+ c2,1);
    84. // hard light 强光
    85. // float3 OB = step(colorB.xyz,0.5);
    86. // float3 c1 = colorA.xyz * colorB.xyz * 2 *OB ;
    87. // float3 c2 = (1 - 2 * (1 - colorA.xyz) *(1 - colorB.xyz)) * (1 - OB);
    88. // soft light 柔光
    89. // float3 OB = step(colorB.xyz,0.5);
    90. // float3 c1 = ((2 * colorB - 1) * (colorA - colorA * colorA) + colorA) * OB ;
    91. // float3 c2 = ((2 * colorB - 1) * (sqrt(colorA)- colorA) + colorA) * (1 - OB);
    92. // vivid light 亮光///
    93. // float3 c1 = colorB - (1 - colorB) * (1 - 2 * colorA) / (2 * colorA);
    94. // float3 c2 = colorB + colorB * (2 * colorA - 1) / (2 * (1 - colorA));
    95. // float3 OB = step(colorA.xyz,0.5);
    96. // c1 *= OB;
    97. // c2 *= (1 - OB);
    98. // finalRGBA = float4(c1+ c2,1);
    99. // linear Light 线性光
    100. // finalRGBA = float4(colorA + 2 * colorB) - 1;
    101. // 点光(存在等于符号问题)
    102. // B<2*A-1: C=2*A-1
    103. // 2*A-1<B<2*A: C=B
    104. // B>2*A: C=2*A
    105. // float3 OB = step(colorA,2 *colorB - 1);
    106. // float3 c1 = (2 * colorB - 1) * OB;
    107. // float3 OB1 = (1 - OB) * step(colorA , 2 * colorB);
    108. // float3 c2 = colorA * OB1;
    109. // float3 OB2 = 1 - step(colorA ,2 * colorB);
    110. // float3 c3 = 2 * colorB * OB2;
    111. // finalRGBA = float4(c1 + c2 + c3,1);
    112. // 混合实色
    113. // float3 OA = step(colorB, 1 - colorA);
    114. // float3 c1 = 0 * OA;
    115. // float3 OA1 = step(1 - colorA,colorB);
    116. // float3 c2 = 1 * OA1;
    117. // finalRGBA = float4(c1 + c2,1);
    118. // 差值
    119. // finalRGBA = float4(abs(colorB.xyz - colorA.xyz),1);
    120. // Excusion 排除
    121. // finalRGBA = float4(colorB + colorA - 2 * colorB * colorA);
    122. // hue 色相
    123. // float3 c1 = float3(colorBHSV.x,colorAHSV.yz);
    124. // c1 = HSV2RGB(c1);
    125. // finalRGBA = half4(c1,1);
    126. return finalRGBA;
    127. }
    128. ENDCG
    129. }
    130. }
    131. }

    测试效果图片资源:

     

  • 相关阅读:
    操作系统:操作系统概论
    深入探讨 AutoGPT:彻底改变游戏的自主 AI
    3年测试经验,测试用例应该达到这个水平才合格
    关于领域驱动设计,大家都理解错了
    基于Spring Boot的租房网站设计与实现
    【大厂AI课学习笔记NO.68】开源和开源发展情况
    SpringBoot 实现EMQ设备的上下线告警
    Java手写链表和案例拓展
    Could not load dynamic library ‘libcudart.so.11.0‘; dlerror: libcudart.so.11.0:
    Java#24(常见API--2)
  • 原文地址:https://blog.csdn.net/fairen/article/details/127672616