• 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. }

    测试效果图片资源:

     

  • 相关阅读:
    函数式编程:一等函数(First-class Function)
    基于 BERT 实现的情感分析(文本分类)----概念与应用
    android studio 的 adb配置
    搜索引擎RAG召回效果评测MTEB介绍与使用入门
    计算机组成原理知识总结(五)中央处理器
    网络安全(黑客技术)—2024自学手册
    第十四章《多线程》第5节:线程同步
    基于KubeSphere图形编辑面板构建微服务项目的DevOps 系统
    sql数据库入门(1)
    生活常用类API推荐
  • 原文地址:https://blog.csdn.net/fairen/article/details/127672616