我想在photoshop中创建内部阴影着色器

问题描述 投票:1回答:1

我想重新创建名为“内部阴影”的photoshop效果作为纹理着色器。作为一个起点,我采用了“轮廓”的例子,但我不知道下一步该做什么,或者如何创建它。请有人可以分享一些代码示例或者可以帮助修改此着色器以获得内部阴影效果吗?

varying vec2 v_texCoord;
varying vec4 v_fragmentColor;
uniform vec3 u_outlineColor;
uniform float u_threshold;
uniform float u_radius;

void main()
{
    float radius = u_radius;
    vec4 accum = vec4(0.0);
    vec4 normal = vec4(0.0);

    normal = texture2D(CC_Texture0, vec2(v_texCoord.x, v_texCoord.y));

    accum += texture2D(CC_Texture0, vec2(v_texCoord.x - radius, v_texCoord.y - radius));
    accum += texture2D(CC_Texture0, vec2(v_texCoord.x + radius, v_texCoord.y - radius));
    accum += texture2D(CC_Texture0, vec2(v_texCoord.x + radius, v_texCoord.y + radius));
    accum += texture2D(CC_Texture0, vec2(v_texCoord.x - radius, v_texCoord.y + radius));

    accum *= u_threshold;
    accum.rgb =  u_outlineColor * accum.a;
    accum.a = 0.0;

    normal = ( accum * (1.0 - normal.a)) + (normal * normal.a);

    gl_FragColor = v_fragmentColor * normal;
}
shader shadow
1个回答
2
投票

首先,您需要计算图像的distance transform。最好的方法是使用jump flooding算法。

Jump Flooding

1)指定有效像素,例如使用步进功能。

        fixed4 frag (v2f i) : SV_Target
        {
            return step( _Threshold, tex2D( _MainTex, i.uv ).a );
        }

2)渲染种子图像以进行跳跃泛洪算法。在种子图像编码(0,0)中对于有效像素和实际UV位置对于无意义的像素(在上图中,RG编码U和BA以16位精度编码V)。

        fixed4 frag (v2f i) : SV_Target
        {
            return lerp(
                fixed4( 0.0, 0.0, 0.0, 0.0 ),
                fixed4( EncodeFloatRG( i.uv.x ), EncodeFloatRG( i.uv.y ) ),                 
                1.0 - step( 0.01, tex2D( _MainTex, i.uv ).r )
            );        
        }

3-10)跳跃洪水步骤。在每个步骤中,您必须迭代“邻居”像素并找到哪个包含编码的UV位置,最接近当前像素的UV位置。跳跃洪水必须从最远的“邻居”开始,然后逐渐缩小搜索距离。

        void JumpFlooding(half2 uv, half2 duv, inout half2 nearestPos, inout half nearestDist)
        {
            fixed4 seed = tex2D( _MainTex, uv + duv * _MainTex_TexelSize.xy );
            half2 pos = half2( DecodeFloatRG( seed.xy ), DecodeFloatRG( seed.zw ) );
            if( length(pos) > 0.0 )
            {
                half dist = distance( uv, pos );
                if( dist < nearestDist )
                {
                    nearestDist = dist;
                    nearestPos = pos;
                }
            }
        }

        fixed4 frag (v2f i) : SV_Target
        {
            half2 nearestPos = half2( 0, 0 );
            half nearestDist = 2.0;

            JumpFlooding( i.uv, half2( -_Offset, -_Offset ), nearestPos, nearestDist );
            JumpFlooding( i.uv, half2( -_Offset, 0 ), nearestPos, nearestDist );
            JumpFlooding( i.uv, half2( -_Offset, _Offset ), nearestPos, nearestDist );
            JumpFlooding( i.uv, half2( 0, _Offset ), nearestPos, nearestDist );
            JumpFlooding( i.uv, half2( _Offset, _Offset ), nearestPos, nearestDist );
            JumpFlooding( i.uv, half2( _Offset, 0 ), nearestPos, nearestDist );
            JumpFlooding( i.uv, half2( _Offset, -_Offset ), nearestPos, nearestDist );
            JumpFlooding( i.uv, half2( 0, -_Offset ), nearestPos, nearestDist );
            JumpFlooding( i.uv, half2( 0, 0 ), nearestPos, nearestDist );

            return fixed4( EncodeFloatRG( nearestPos.x ), EncodeFloatRG( nearestPos.y ) );
        }

11)最后,跳跃泛洪算法的最后结果编码到距离场。

        fixed4 frag (v2f i) : SV_Target
        {
            fixed4 seed = tex2D( _MainTex, i.uv );
            half2 pos = half2( DecodeFloatRG( seed.xy ), DecodeFloatRG( seed.zw ) );
            float dist = distance( i.uv, pos );                 
            return EncodeFloatRGBA( dist );
        }

现在你可以使用距离场来绘制内部阴影。

Inner shadow

        fixed4 frag (v2f i) : SV_Target
        {
            half4 color = _ShadowColor;

            half dist = DecodeFloatRGBA( tex2D(_DistTex, i.uv) );

            color.a *= ( 1.0 - smoothstep( _ShadowMinRange, _ShadowMaxRange, dist ) );

            return color;                          
        }
© www.soinside.com 2019 - 2024. All rights reserved.