文章目录
- 效果
- 实践
- 准备一个颜色鲜艳的场景
- 灰化图像
- 2D屏幕颜色传播效果
- 3D世界坐标颜色传播效果
- 确定世界坐标传播中心点
- 将屏幕深度转为世界坐标
- 世界坐标半径才着色
- 添加边缘柔和
- 添加噪点来过渡
- 给0~1边缘的着色
- 给0~1边缘添加亮度
- 最后添加整体应用的强度
- Project
- References
看到Color Spread Post-Processing Effect Tutorial in Unity上的颜色传播效果图还不错,看到效果图那刻,就知道如何实现了。
先来看看我们实现的最终效果
效果 fixed4 frag (v2f i) : SV_Target {
fixed4 col = tex2D(_MainTex, i.uv);
return LinearRgbToLuminance(col);
}
简单的添加一个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);
}
// boundary color
bool isBoundary = tint > 0 && tint
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?