103 lines
3.8 KiB
Markdown
103 lines
3.8 KiB
Markdown
|
## 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
|
|||
|
```c#
|
|||
|
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
|
|||
|
);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
##
|
|||
|
```c#
|
|||
|
Pass {
|
|||
|
BloomCombine,
|
|||
|
BloomHorizontal,
|
|||
|
BloomPrefilter,
|
|||
|
BloomVertical,
|
|||
|
Copy
|
|||
|
}
|
|||
|
```
|
|||
|
Bloom循环的主要内逻辑为:
|
|||
|
1. copy之前的渲染结果。
|
|||
|
2. 进行一次预处理。
|
|||
|
3. 取得2个RT,首先进行水平高斯模糊,之后进行垂直高斯模糊。因为水平模糊已经进行一次采样,所以垂直采样的次数可以减半了。
|
|||
|
4. 释放中间产生水平高斯的RT。
|
|||
|
5. 进行反向叠加产生结果循环。(垂直高斯模糊后的结果)
|
|||
|
6. 释放垂直高斯的RT。
|
|||
|
|
|||
|
## 预处理
|
|||
|
Bloom通常在艺术上用于仅使某些东西发光,但是我们的效果目前适用于所有对象,不管它有多亮。尽管从物理上讲没有意义,但是我们可以通过引入亮度阈值来限制影响效果的因素。实际上就是提取亮度高的区域。
|
|||
|
c# DoBloom():
|
|||
|
```c#
|
|||
|
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:
|
|||
|
```c#
|
|||
|
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函数。
|
|||
|
```c#
|
|||
|
#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`中的给低分辨率结果乘以强度之后在于高分辨率结果叠加。
|