Unity Shader PostProcessing - 10 - ColorSpreading 颜色传播后效

141 篇文章 34 订阅

看到Color Spread Post-Processing Effect Tutorial in Unity上的颜色传播效果图还不错,看到效果图那刻,就知道如何实现了。

先来看看我们实现的最终效果

效果

在这里插入图片描述

实践

准备一个颜色鲜艳的场景

在这里插入图片描述

灰化图像

            fixed4 frag (v2f i) : SV_Target {
                fixed4 col = tex2D(_MainTex, i.uv);
                return LinearRgbToLuminance(col);
            }

在这里插入图片描述

2D屏幕颜色传播效果

简单的添加一个2D屏幕UV中心的效果,是个最简单的思路
在这里插入图片描述

                float2 centerPos = 0.5;
                float dist = length(i.uv - centerPos);
                bool color = false;
                if (_SpreadingRadius != 0) {
                    color = step(dist, _SpreadingRadius);
                }
                fixed4 col = tex2D(_MainTex, i.uv);
                return lerp(LinearRgbToLuminance(col), col, color);

3D世界坐标颜色传播效果

接下来是扩展到3D坐标

确定世界坐标传播中心点

            float3 _SpreadingCenterPos;

将屏幕深度转为世界坐标

之前写的一篇:Unity Shader - 根据片段深度重建片段的世界坐标

核心Shader伪代码:

float depth = Linear01Depth(tex2D(_DepthTex, i.uv).r);
wp = _camWorldPos.xyz + _frustumCornerRay.xyz * depth;

世界坐标半径才着色

            fixed4 frag (v2f i) : SV_Target {
                // depth to world pos
                float depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv));
                float3 wp = _WorldSpaceCameraPos.xyz + i.ray * depth;
                float3 centerPos = _SpreadingCenterPos;
                float3 vec = wp - centerPos;
                // 判断半径着色
                float dist = dot(vec, vec);
                bool color = false;
                if (_SpreadingRadius != 0) {
                    color = step(dist, _SpreadingRadius * _SpreadingRadius);
                }
                fixed4 col = tex2D(_MainTex, i.uv);
                return lerp(LinearRgbToLuminance(col), col, color);
            }

在这里插入图片描述

添加边缘柔和

            fixed4 frag (v2f i) : SV_Target {
                // depth to world pos
                float depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv));
                float3 wp = _WorldSpaceCameraPos.xyz + i.ray * depth;
                float3 centerPos = _SpreadingCenterPos;
                float3 vec = wp - centerPos;
                // 判断半径着色
                float dist = length(vec);
                float tint = 0;
                tint = step(dist, _SpreadingRadius);
                float fadeOutWidth = _BoundaryFadeOutWidth;
                if (tint == 0 && fadeOutWidth != 0) {
                    tint = 1 - saturate((dist - _SpreadingRadius) / fadeOutWidth); // 这里可以优化为乘法
                }
                fixed4 col = tex2D(_MainTex, i.uv);
                return lerp(LinearRgbToLuminance(col), col, tint);
            }

在这里插入图片描述

添加噪点来过渡

用回我自己的Noise
在这里插入图片描述

                // depth to world pos
                float depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv));
                float3 wp = _WorldSpaceCameraPos.xyz + i.ray * depth;
                float3 centerPos = _SpreadingCenterPos;
                float3 vec = wp - centerPos;
                // 判断半径着色
                float dist = length(vec);
                float radius = _SpreadingRadius;

                float2 noiseUV = wp.xz * _WorldPosScale;
                float noise = tex2D(_NoiseTex, noiseUV).r * _NoiseScale;
                return noise;

看看效果
在这里插入图片描述
混合效果

只要用我们的着色半径减去看似随机的噪点值即可。

            fixed4 frag (v2f i) : SV_Target {
                // depth to world pos
                float depth = Linear01Depth(SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv));
                float3 wp = _WorldSpaceCameraPos.xyz + i.ray * depth;
                float3 centerPos = _SpreadingCenterPos;
                float3 vec = wp - centerPos;
                // 判断半径着色
                float dist = length(vec);
                float radius = _SpreadingRadius;

                float2 noiseUV = wp.xz * _WorldPosScale;
                float noise = tex2D(_NoiseTex, noiseUV).r * _NoiseScale;
                // return noise;

                radius -= noise;

                float tint = 0;
                tint = step(dist, radius);
                float fadeOutWidth = _BoundaryFadeOutWidth;
                if (tint == 0 && fadeOutWidth != 0) {
                    tint = 1 - saturate((dist - radius) / fadeOutWidth); // 这里可以优化为乘法
                }

                fixed4 col = tex2D(_MainTex, i.uv);
                return lerp(LinearRgbToLuminance(col), col, tint);
            }

在这里插入图片描述

给0~1边缘的着色

                // boundary color
                bool isBoundary = tint > 0 && tint < 1;
                fixed4 bc = _BoundaryTintColor;
                bc = lerp(1, lerp(1, bc, _BoundaryTintColor.a), isBoundary);

                // tint source color
                fixed4 tintCol = tex2D(_MainTex, i.uv);
                // gray color
                fixed4 grayCol = LinearRgbToLuminance(tintCol);
                return lerp(grayCol, tintCol, tint) * bc;

在这里插入图片描述
在这里插入图片描述

给0~1边缘添加亮度

                fixed4 bc = _BoundaryTintColor + _BoundaryBrightness;

在这里插入图片描述

最后添加整体应用的强度

                // combined col
                fixed4 combinedCol = lerp(grayCol, tintCol, tint) * bc;
                // whole intensity
                return lerp(tintCol, combinedCol, _WholeIntensity);

在这里插入图片描述

Project

backup : UnityShader_ColorSpreading_2018.3.0f2

References

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值