这的确有点像是一个立方体,但又有种说不出的奇怪。立方体的某些本应被遮挡住的面被绘制在了这个立方体其他面之上。之所以这样是因为OpenGL是一个三角形一个三角形地来绘制你的立方体的,所以即便之前那里有东西它也会覆盖之前的像素。因为这个原因,有些三角形会被绘制在其它三角形上面,虽然它们本不应该是被覆盖的。
幸运的是,OpenGL存储深度信息在一个叫做Z缓冲(Z-buffer)的缓冲中,它允许OpenGL决定何时覆盖一个像素而何时不覆盖。通过使用Z缓冲,我们可以配置OpenGL来进行深度测试。
要想有正确的投影性质,需要使用一个非线性的深度方程,它是与 1/z 成正比的。它做的就是在z值很小的时候提供非常高的精度,而在z值很远的时候提供更少的精度。花时间想想这个:我们真的需要对1000单位远的深度值和只有1单位远的充满细节的物体使用相同的精度吗?线性方程并不会考虑这一点。屏幕空间中的深度值是非线性的,即它在z值很小的时候有很高的精度,而z值很大的时候有较低的精度。片段的深度值会随着距离迅速增加,所以几乎所有的顶点的深度值都是接近于1.0的。
然而,我们也可以让片段非线性的深度值变换为线性的。要实现这个,我们需要仅仅反转深度值的投影变换。这也就意味着我们需要首先将深度值从[0, 1]范围重新变换到[-1, 1]范围的标准化设备坐标(裁剪空间)。接下来我们需要像投影矩阵那样反转这个非线性方程(方程2),并将这个反转的方程应用到最终的深度值上。最终的结果就是一个线性的深度值了。听起来是可行的,对吧?
首先我们将深度值变换为NDC,不是非常困难:
float z = depth * 2.0 - 1.0;
接下来使用获取到的z值,应用逆变换来获取线性的深度值:
float linearDepth = (2.0 * near * far) / (far + near - z * (far - near));
这个方程是用投影矩阵推导得出的,它使用了方程2来非线性化深度值,返回一个near与far之间的深度值。这篇注重数学的文章为感兴趣的读者详细解释了投影矩阵,它也展示了这些方程是怎么来的。
[SL]John_Stapp 发表于 2020-6-3 11:29
有趣的着色器越来越多,等我这个地图做完很想试试。国内现在有什么用了着色器的地图可以玩吗? ...
晴路卡 发表于 2020-6-3 13:50
只能想到用来做些奇怪的东西...
深拥v 发表于 2020-6-3 15:09
着色器目前国内做的不多吧
(至少mcbbs还没专门开个板块做这个)
👴是hlnb 发表于 2020-6-14 22:48
以后就有香草光影了?
欢迎光临 Minecraft(我的世界)中文论坛 (https://www.mcbbs.net/) | Powered by Discuz! X3.5 |