OpenGL / OpenTK填充室内空间

时间:2015-04-20 07:41:22

标签: opengl

我正在寻找一种用颜色“填充”三维几何体的方法,很可能在以后的某个时间使用纹理。

假设您可以将头部物理地移动到混凝土墙中,从逻辑上讲,您只能看到黑暗。但是,在OpenGL中,当您执行此操作时,由于剔除以及绘制几何图形的方式,世界自然是空心透明的。我想在其中模拟黑暗/颜色/纹理。

我知道有些游戏通过将纹理/颜色直接覆盖在hud上来做到这一点 - 因此会使玩家失明。

有没有另外一种方法可以做到这一点?假设玩家站在水中一半;他们可以部分地看到海浪下面。如何填写它以防止他们能够清楚地看到现在屏幕下方的一半?

这个概念甚至叫什么?

1 个答案:

答案 0 :(得分:6)

相机前方纹理的问题是纹理是2D,但您想要显示3D体积的切片。首先,你要谈到的是一个内心深处的想法,我会指向“3D /体积纹理”。对于半水中站立,您需要“体积渲染” “吸收”(由@ user3670102讨论)。

3D纹理

这里的一般想法是你有一些功能可以在3D空间中的任何地方定义颜色,而不仅仅是在表面上(与常规纹理映射一样)。这很不错,因为您可以将几何体放在任何位置,并根据3D位置在片段着色器中对其进行着色。考虑在体积中切片并查看交叉点颜色。

对于墙头效果,您可以在播放器前面绘制一个全屏多边形(在近剪裁平面上,尽管你可能想要向前推一点,所以它不会太小)和基于3D功能为它着色。现在看起来它看起来很稳固并且可以移动播放器所做的广告而不是像你在屏幕上便宜地粘贴纹理一样。

enter image description here

可以使用3D纹理定义实际功能,但这是非常耗费内存的。相反,您可以查看程序性3D颜色(程序木材或砖块着色器作为示例非常常见)。即使假设通过体积“挤出”2D纹理也可以工作,或者更好的是根据您正在绘制的交叉点/表面的角度对3个纹理(每个轴一个)进行加权。

检测几何和近剪裁平面的交点可能是最困难的一点。如果我是你,我会用z缓冲区查看技巧,并确保将所有内容绘制为固体非自相交几何体。一个简单的想法可能是在用正面绘制所有东西之后绘制背面。如果你能看到背面,那么近平面的一部分必须在某物内。对于这些像素,您可以计算世界空间中的近剪裁平面位置并应用3D纹理。虽然我怀疑有两种方法比画两次更快。

实际上可能没有任何光线可以达到你所看到的并且它应该是黑色的,但我想只是忽略它并直接渲染颜色,熄灭。

吸收

这听起来比实际更难。如果你有一些透明的固体,这是一种颜色(“均匀”),那么它会消除光线,进一步的光线必须通过它。想想许多阿尔法透明的表面,采取限制,你有一个指数。剩余的光线接近1/exp(dist)exp(-dist)。谷歌“啤酒法”。来自here

vec3 Absorbance = WaterColor * WaterDensity * -WaterDepth;
vec3 Transmittance = exp(Absorbance);

通过某种方式找到距离的一种好方法是使用着色器渲染背面(或海底/水底),使用着色器绘制距离浮点纹理。然后切换到减色混合并渲染所有正面(或水面)。你留下的纹理包含上述等式的距离/深度。

体积渲染

结合这两个想法,材料既是透明的固体,但颜色(可能是密度)在整个体积中变化。如果你有大量的数据并希望它快速,这开始变得相当复杂。一种直接的渲染方法是通过3D纹理(或程序函数,无论你使用什么)在数值上整合光线,同时应用吸收函数。基本强力欧拉积分可以为近平面上的每个像素开始射线,然后以均匀距离向前行进。在游行的每一步中,假设颜色保持不变并应用吸收,记录您剩余的光量。快速谷歌提出this