3.8 KiB
3.8 KiB
Post-FX Stack
为了效率跳过。
void Draw(RenderTargetIdentifier from,RenderTargetIdentifier to,Pass pass)
to代表绘制的RT id,通过buffer.SetRenderTarget()
来设置。from为原始渲染结果,使用buffer.SetGlobalTexture()
来向Shader传递贴图资源。
Bloom
对图像进行双线性采样,以生成分辨率不断对半分的Bloom金字塔。
给_BloomPyramid1
~_BloomPyramid16
传递id。
创建一个DoBloom方法。首先将摄像机的像素宽度和高度减半,然后选择默认的渲染纹理格式。最初,我们将从源复制到金字塔中的第一个纹理。追踪那些标识符。
OnBloom
循环整个级别的贴图,并调用Draw()
绘制,之后计算后一级别的贴图的数据准备下一次循环,直到循环完成或者贴图分辨为1*1时候。
Draw
void Draw (
RenderTargetIdentifier from, RenderTargetIdentifier to, Pass pass
) {
buffer.SetGlobalTexture(fxSourceId, from);
buffer.SetRenderTarget(
to, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store
);
buffer.DrawProcedural(
Matrix4x4.identity, settings.Material, (int)pass,
MeshTopology.Triangles, 3
);
}
Pass {
BloomCombine,
BloomHorizontal,
BloomPrefilter,
BloomVertical,
Copy
}
Bloom循环的主要内逻辑为:
- copy之前的渲染结果。
- 进行一次预处理。
- 取得2个RT,首先进行水平高斯模糊,之后进行垂直高斯模糊。因为水平模糊已经进行一次采样,所以垂直采样的次数可以减半了。
- 释放中间产生水平高斯的RT。
- 进行反向叠加产生结果循环。(垂直高斯模糊后的结果)
- 释放垂直高斯的RT。
预处理
Bloom通常在艺术上用于仅使某些东西发光,但是我们的效果目前适用于所有对象,不管它有多亮。尽管从物理上讲没有意义,但是我们可以通过引入亮度阈值来限制影响效果的因素。实际上就是提取亮度高的区域。 c# DoBloom():
Vector4 threshold;
threshold.x = Mathf.GammaToLinearSpace(bloom.threshold);
threshold.y = threshold.x * bloom.thresholdKnee;
threshold.z = 2f * threshold.y;
threshold.w = 0.25f / (threshold.y + 0.00001f);
threshold.y -= threshold.x;
buffer.SetGlobalVector(bloomThresholdId, threshold);
Shader:
float3 ApplyBloomThreshold (float3 color) {
float brightness = Max3(color.r, color.g, color.b);
float soft = brightness + _BloomThreshold.y;
soft = clamp(soft, 0.0, _BloomThreshold.z);
soft = soft * soft * _BloomThreshold.w;
float contribution = max(soft, brightness - _BloomThreshold.x);
contribution /= max(brightness, 0.00001);
return color * contribution;
}
float4 BloomPrefilterPassFragment (Varyings input) : SV_TARGET {
float3 color = ApplyBloomThreshold(GetSource(input.fxUV).rgb);
return float4(color, 1.0);
}
解决白色辉光显得块状化问题
使用在Core RP Library的Filtering include文件中定义的SampleTexture2DBicubic函数。
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Filtering.hlsl"
float4 GetSourceBicubic (float2 fxUV) {
return SampleTexture2DBicubic(
TEXTURE2D_ARGS(_PostFXSource, sampler_linear_clamp), fxUV,
_PostFXSource_TexelSize.zwxy, 1.0, 0.0
);
}
之后再合并结果的时候对低分辨的贴图使用该函数进行采样。在案例中被设置为可开启项。
强制控制
在BloomCombinePassFragment
中的给低分辨率结果乘以强度之后在于高分辨率结果叠加。