体素游戏中,环境光剔除(Ambient Occuling)实现过程中的各项异性问题的解决

    在上一篇文章中(https://blog.csdn.net/zhetianyun/article/details/103054640),我们实现了体素的环境光剔除功能,但是忽略了一个视觉上的小瑕疵:在体素的某一个平面上,由于顶点连接方向(顺时针和逆时针)的不同,导致各向异性问题的产生,这里用实际效果展示更形象些:

                                              

                                                                           这是各向异性的效果。

                                               

                                                                            这是没有各项异性的效果。

这两张图中,我们可以发现箭头所指的地方的区别:前者是直角,后者是45度斜角。明显后者的阴影效果更符合视觉效果。

    各项异性问题的描述:

立方体是由六个面组成,每个面有两个三角形(计算机中最小的渲染单元)。想象如下的情形:

                                      

         这是一个小方块的其中某一个面以及顶点id。按照我们上一篇文章的技术方案,假设现在只有顶点1正好是阴影顶点,2,3,4三个点都是正常的顶点。在第一个面上,因为顶点1被两个三角形所公用(△123和△134),所以这两个三角形都会被渲染成阴影,也就是上面第一张效果图:整个面都带有阴影。在第二个面上,因为顶点1只被第一个/或第二个三角形使用(△124和△234),所以只有△124被渲染成阴影,而△234的渲染中没有阴影,这就是上面第二张效果图所看到的。关于△124的阴影颜色,怎样从顶点1变化到顶点2 和顶点4,我们先暂时留作下次的作业。

      综上所述,我们知道了体素的阴影出现各项异性的原因是,处于阴影位置处的顶点正好被该平面上的另外一个三角形所公用导致的。

解决方案

我们需要把这四个顶点移动一下就可以解决这个问题,解决的思路草图如下:

                                    

这样△123 和 △134 变成了△124 和△234。

代码实现过程

private void calculateAnisotropy()
    {
        List<Color> meshColor = new List<Color>();
        cubeMesh.mesh.GetColors(meshColor);
        int[] tri = cubeMesh.mesh.triangles;

        List<int> quard = new List<int>();
        for (int i = 0; i < tri.Length; i += 6) // 这里设置步长为6,是因为我们要拿到一个拿到一个完整的面,一个面有两个三角形,所以以6个顶点分割这个cube的所有顶点,最后我们构造了六个平面
        {
            quard.Clear();
            if (!quard.Contains(tri[i]))
            {
                quard.Add(tri[i]);
            }
            if (!quard.Contains(tri[i + 1]))
            {
                quard.Add(tri[i + 1]);
            }
            if (!quard.Contains(tri[i + 2]))
            {
                quard.Add(tri[i + 2]);
            }
            if (!quard.Contains(tri[i + 3]))
            {
                quard.Add(tri[i + 3]);
            }
            if (!quard.Contains(tri[i + 4]))
            {
                quard.Add(tri[i + 4]);
            }
            if (!quard.Contains(tri[i + 5]))
            {
                quard.Add(tri[i + 5]);
            }
            // 获取了平面上的四个点 顺序是原始顺序,因为阴影保存在顶点color的alpha值中,所以根据对角两个顶点的 alpha 值加和判断平面是否需要 flip
            if (meshColor[quard[0]].a + meshColor[quard[2]].a < meshColor[quard[1]].a + meshColor[quard[3]].a)
            {
                tri[i] = quard[3];
                tri[i + 1] = quard[0];
                tri[i + 2] = quard[1];

                tri[i + 3] = quard[3];
                tri[i + 4] = quard[1];
                tri[i + 5] = quard[2];
            }
        }
        cubeMesh.mesh.triangles = tri;
        cubeMesh.mesh.RecalculateTangents();
    }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值