好不容易挤出时间来学习,得千万别浪费了,而且最近看到十几年,几十年的图形专业大佬,真的感叹,人外有人天外有天。
OK,如题,这次实现的是比较简单大众都了解的:Bloom,泛光效果。
CSharp叫传入Shader阈值:
[Header("Pickup luminance")]
[Range(0f, 1f)]
public float luminanceThreshold_hash = 0.5f; // 提取泛光亮度的赋值
...
RenderTexture luminanceRT = RenderTexture.GetTemporary(Screen.width, Screen.height, 0);
luminanceRT.filterMode = FilterMode.Bilinear;
luminanceRT.name = "luminanceRT";
mat.SetFloat(_LuminanceThreshold_hash, luminanceThreshold_hash);
Graphics.Blit(source, destination, mat, 0);
RenderTexture.ReleaseTemporary(luminanceRT);
Shader处理:只要大于阈值的都标1,否则0。
fixed4 frag_pickupLuminance (v2f_common i) : SV_Target {
fixed4 col = tex2D(_MainTex, i.uv);
#if _PICKUP__LUMINANACE_0
return step(_LuminanceThreshold, LinearRgbToLuminance(col.rgb));
#elif _PICKUP__LUMINANACE_1
float luminance = LinearRgbToLuminance(col.rgb);
return step(_LuminanceThreshold, luminance) * col;
#elif _PICKUP__LUMINANACE_2
return _LuminanceThreshold == 1 ? 0 : saturate((col - _LuminanceThreshold) / (1 - _LuminanceThreshold));
#else // _PICKUP__LUMINANACE_3
return saturate(col - _ColorThreshold);
#endif
}
下面是不同pickup luminance 方法的几种结果:
不同的提取结果,对最终的叠加结果肯定也是不一样的,根据自己需要来选择或是添加不同的pickup luminance 方法。
这里我还是懒得再写,直接用之前的高斯模糊(也可以使用其他模糊方式,如:均值模糊,等),结果如下:
我在阅读References中的Direct3D轮回:游戏特效之全屏泛光(Bloom),里面引用了MS的三个Shader中,有还对原图的饱和度用调整的。这里我就不添加了,因为效果的切确需要是因人而异的来改动Shader就好。
下面是调整饱和度的代码:
float BloomIntensity;
float BaseIntensity;
float BloomSaturation;
float BaseSaturation;
// 减缓颜色的饱和度
float4 AdjustSaturation(float4 color, float saturation)
{
// 人眼更喜欢绿光,因此选取0.3, 0.59, 0.11三个值
float grey = dot(color, float3(0.3, 0.59, 0.11));
return lerp(grey, color, saturation);
}
float4 ThePixelShader(float2 texCoord : TEXCOORD0) : COLOR0
{
// 提取原始场景贴图及模糊场景贴图的像素颜色
float4 bloom = tex2D(BloomSampler, texCoord);
float4 base = tex2D(BaseSampler, texCoord);
// 柔化原有像素颜色
bloom = AdjustSaturation(bloom, BloomSaturation) * BloomIntensity;
base = AdjustSaturation(base, BaseSaturation) * BaseIntensity;
// 结合模糊像素值微调原始像素值
base *= (1 - saturate(bloom));
// 叠加原始场景贴图及模糊场景贴图,即在原有像素基础上叠加模糊后的像素,实现发光效果
return base + bloom;
}
而我的混合提取的模糊图 + 原图的方式就很简单:
sampler2D _GlowTex;
float _BloomIntensity;
fixed4 frag_merge_and_output(v2f_common i) : SV_Target {
fixed4 srcCol = tex2D(_MainTex, i.uv);
fixed4 glowCol = tex2D(_GlowTex, i.uv);
return lerp(srcCol, saturate(srcCol + glowCol), _BloomIntensity);
}
backup : UnityShader_DepthOfFieldTesting_2018.3.0f2