美文网首页
[全屏后处理]Lut校色

[全屏后处理]Lut校色

作者: 想变的很强的日向彻 | 来源:发表于2019-08-02 16:05 被阅读0次

前言

Unity后处理,说简单点,采样到屏幕的纹理Texture,然后通过一定的计算将此纹理操作一通,然后得到我们想要的效果,后处理效果有很多,校色,亮度,饱和度,模糊,bloom,景深,描边等等。好的后处理的使用可以使我们的游戏看上去更加逼真,能起到锦上添花的作用,不过全屏的纹理一般尺寸和分辨率都会比较大,在使用时要特别注意开销,适当降低采样率和分辨率是不错的选择。

Lut校色

校色的效果类似于给我们的画面加滤镜,熟悉unity shader的话,我们都知道,一种做法是将全屏图像采样,然后通过在片元着色器中对每个像素值进行计算来得到我们想要的效果。但是这种方法弊端也很明显,首先,符合我们需求的算法不好选取,更重要的是在片元着色器中进行复杂的计算开销极大(有人会说在顶点着色器中计算,但是由于算法一般不会过于简单,所以开销仍不可小视)。更为方便和实用的方式是由美术在PS中导出多张校色图,然后我们通过一定的计算将原图像和校色图混合,得到新的纹理显示在屏幕上。

思路:将原图的RGB分量映射到一个立方体的XYZ坐标,然后用这个XYZ坐标值在校色图中进行采样

校色图示例:

256*16

有人会问校色图尺寸的选取有什么讲究吗,这里我们看到图片的分辨率是256*16也就是16*16*16,可以看到正好可以组成一个每个方向有16个颜色值的立方体纹理,也就是Texture3D。

关键:将校色图颜色值映射到Texture3D

private void CreateTexture()

    {

        int h = m_LutTexture.height;

        var c = m_LutTexture.GetPixels();

        var newC = new Color[c.Length];

        for (int i = 0; i < h; i++)

        {

            for (int j = 0; j < h; j++)

            {

                for (int k = 0; k < h; k++)

                {

                    newC[i + j * h + k * h * h] = c[i + j * h * h + k * h];

                }

            }

        }

        m_Texture3D = new Texture3D(h, h, h, TextureFormat.ARGB32, false);

        m_Texture3D.SetPixels(newC);

        m_Texture3D.Apply();

    }

可以想象一下,将这256*16个像素值均匀的填充到一个16*16*16的立方体中,采样时就将这样的原像素值比如(0.5, 0.5, 0.5)正好采样到立方体纹理中正中心的像素值,每个属于(0,0,0,0)到(1,1,1,1)的值都对应特定的像素值,而我们前面说到每个方向只有16个像素,即正方向8个,负方向8个,可是我们的原始像素值的大小确实数不清的,这没关系,Unity会将这16个像素中间空余的像素进行差值,来保证我们Texture3D中的任何坐标都是可以取到特定的像素值,而且差值得到的像素值看上去是连续的。

这种做法还有一个好处,美术可以在ps中调整他们觉得满意的效果,而我们的逻辑是不需要改动的,得到的效果也是非常不错的。

相关文章

网友评论

      本文标题:[全屏后处理]Lut校色

      本文链接:https://www.haomeiwen.com/subject/kqbldctx.html