Custom SRP 12 - HDR

https://catlikecoding.com/unity/tutorials/custom-srp/hdr/

1 High Dynamic Range

之前的教程,都是用低动态颜色范围,即 LDR 进行渲染.每个颜色通道被限定到 0 - 1 ,该模式下,(0,0,0)代表黑色,(1,1,1)代表白色.尽管我们的 shader 可以产生超过 1 的颜色值,但是 GPU 在存储时也会限制到 1 .

可以用 Frame Debugger 来查看 render target 的类型. 普通相机通常用 B8G8R8A8_SRGB,也就是每个通道 8 位的 RGBA buffer ,每个像素就是 32 位,同时RGB是存储在 sRGB 空间的.我们当前是工作在 linear space ,因此GPU在从 buffer 读取和写入时,都会自动帮我们进行转换.当渲染完成,显示到显示器时,会将 Buffer 当作 sRGB 颜色数据.

HDR 通常是 R16G16B16A16,每个通道16位,每个像素64位.这时每个通道都是一个有符号的浮点数,而不是0-1.

有些情况下,当亮度会超过1 时,LDR就不合适了,比如太阳,或距离光源特别近时,光的强度让我们不敢直视,这时就需要用 high-dynamic-range HDR buffer 来进行渲染,以存储超过 1 的颜色值.

1.1 HDR Reflection Probes

反射探针有选项,用来在渲染反射图时,使用HDR.这通常体现在反射的高光上.如下图左侧是 HDR 反射,右侧的 LDR 反射,高光就弱了不少

1.2 HDR Cameras

摄像机也有HDR 属性,包含两个选项: Off 和 Use Graphics Settings.

Use Graphics Settings 表示摄像机允许 HDR 渲染,但是最终是不是 HDR,取决于渲染管线.因此我们向 CustomRenderPipelineAsset 增加 HDR 开关,并一路传递到 CameraRenderer,并根据参数和Camera.allowHDR 来最终确定是否启用 HDR.

1.3 HDR Render Textures

HDR 只有在后效中才有意义,因为我们无法改变 frame buffer 的格式,因此在 CameraRenderer 中,如果启用的后效,则创建 HDR RenderTarget,否则还是用LDR.

//*******************
//   CameraRenderer.cs

void Setup()
{
    ...
    // 如果开启了后处理,则渲染到临时 RT 上
    if (postFXStack.IsActive)
    {
        // 获取的 RenderTexture 数据是随机的,因此要清除
        if (clearFlags > CameraClearFlags.Color)
            clearFlags = CameraClearFlags.Color;

        buffer.GetTemporaryRT(frameBufferId, 
            camera.pixelWidth, camera.pixelHeight,
            32, FilterMode.Bilinear, 
            useHDR ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default);
        buffer.SetRenderTarget(frameBufferId, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
    }
    ...
}

其实,如果没有后效,在渲染过程中希望用HDR,那么也是需要创建中间 Render Texture 进行渲染,渲染完成后拷贝到 final frame buffer.

场景渲染完后(在FrameDebugger)中,可以看到渲染结果偏暗,这是因为我们的 RT 是 HDR linear space 的,被错误的当sRGB 直接显示到屏幕上了.

1.4 HDR Post Processing

到目前为止,渲染结果看起来没什么不同,因为我们没有针对 HDR 做任何处理,当 RT 被渲染到 LDR 时,被 clamp 到 0-1 了.Bloom 可能会稍微亮一点,但也不会亮太多,因为后面的 prefiltering pass 过程会 clamp 颜色,因此我们需要从 CameraRenderer 将 HDR 开关传递给后效模块,并为 prefiltering pass 在需要时使用 HDR 格式的RT.同时为 DoBloom 过程中的 RT,也使用 HDR.

void DoBloom(int sourceId)
{
    ...
    RenderTextureFormat format = useHDR ? RenderTextureFormat.DefaultHDR : RenderTextureFormat.Default;
    // 源图 -> 半分辨率图
    buffer.GetTemporaryRT(bloomPreFilterID, width, height, 0, FilterMode.Bilinear, format);
    Draw(sourceId, bloomPreFilterID, Pass.BloomPrefilter);
    ...
}

HDR/LDR bloom 之间的区别可能很明显,也可能不明显,这取决于场景的亮度.我们通常将 bloom threshold 设置为 1, 这样只有 HDR 颜色会参与到 bloom 中.这样只有那些特别亮的地方才会有辉光.

由于 bloom 会平均颜色值,因此即使一个很亮的像素,也会隐形到较大的一个区域,可以通过 prefiltering 的结果和最终屏幕结果对比,看到这种光现象,即使一个像素,也会产生一个圆形的辉光.

例如,对于一个 2x2 的块其颜色是 0,0,0,1,下采样平均后是 0.25.而如果是 HDR 中的 0,0,0,10 平均值则是2.5,到LDR时就全变成 1 了.

1.5 Fighting Fireflies

HDR的一个缺点就是会产生一个比周围亮很多的小的图像区域,当这个区域只有一个像素大小,或者更小,随摄像机的移动或旋转,会有强烈的闪烁。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值