在《我的世界》中,当您注视水面时,您所看到的越暗。有人知道如何编写类似的代码吗?
我的世界
没有效果的类似游戏
在《我的世界》中,当您注视水面时,您所看到的越暗。有人知道如何编写类似的代码吗?
我的世界
没有效果的类似游戏
Answers:
根据深度,本质上有两种不同的照明水的方法:
Minecraft使用基于体素的照明,其工作原理是将光传播到相邻的立方体,从而根据块类型降低亮度。黑暗的海洋是该系统的副作用。
水可以阻挡阳光并将每块光线减少3级(而不是默认的1级),这意味着海洋与表面的每个距离的亮度为:
0 (surface): 15 (direct sunlight)
1: 12
2: 9
3: 6
4: 3
5 and below: 0 (darkness)
资料来源:Minecraft Wiki-Light
在具有传统照明模型的游戏中,可以通过测量光源和海底之间的水量来产生这种效果。然后根据该距离使光衰减。有几种方法可以做到这一点:
如果您拥有平坦的表面,则可以通过将表面法线从水体中通过,并将该法线的点积与表面位置传递到几何着色器中,轻松地计算光线在水中的传播距离。
有效水距为
其中的位置是顶点,是表面下方的光线方向与水表面朝向水体的法线之间的角度。
在日落时,由于光线在进入水中时会发生折射,因此只能到达不到50度的位置。
这是一篇博客文章,有一个很好的解释:数码相机:全内反射
另一篇更多详细信息:数码相机:斯涅尔折射定律
如果您在与水平行的表面上使用高度图,则变为。如果太阳位于水面正上方,则正确系数等于1。
对于点光源,必须根据与光源的相对位置为每个顶点计算。
在固定水位或固定光方向的情况下,方程的某些部分恒定不变,出于性能考虑,不应在着色器中对其进行计算。
如果将水表面渲染到单独的深度图(从光源看),则可以使用该深度纹理来计算光在撞击水面之前在水中传播的距离。
为此,您可以将每个顶点投影到顶点着色器中光源的视图投影中,并在像素着色器中进行纹理查找。
如果表面相对平坦,则应使用折射光源以获得更好的结果。
*您可以通过计算从光源的POV开始的深度来确定最近的固体表面前面的水量,如下所示:
现在,结果纹理包含在光照视图空间中的光照前的水量,因此在使用它之前必须先将其转换回原来的值。这种方法可以计算定向光(负折射),但是如果表面非常不规则,并且水体之间有大量空气影响相同的碎片,则会导致不正确的环境光。
利弊与普通阴影贴图相同,不同之处在于,在计算深度时您需要一个额外的缓冲区,并且由于必须绘制更多的几何图形,因此性能较差。
到目前为止,光线跟踪是渲染透明卷的最准确但也是最昂贵的解决方案。有两种方法:1.从海底向海面跟踪; 2.从光源向水向跟踪。地板上的每个点都需要多条光线才能计算亮度。
提水时还需要考虑以下几点:
水中的光在传播到观察者时再次散射,因此您应该将其混合为纯色。
如果观察者被淹没了,您可以根据深度缓冲区的最终结果渲染雾。雾的颜色,但其密度不应随观察者与地面的距离而变化!(《我的世界》仅使用效果的这一部分。)
如果观察者从上方注视着水,则需要根据表面和水下几何图形之间的深度差来计算雾。雾的颜色应随深度差的增加而稍微变暗,但应仅更改为雾完全不透明的点。
雾的颜色还应该取决于每个像素的视图方向,因此在两种情况下向下观看时,雾的颜色都会稍暗。
如果您使用无缝平铺3D纹理代替假冒腐蚀剂的贴花,则可以避免在垂直表面上拉伸。靠近表面的散射光的强度在三个维度上变化,因此使用2D纹理通常会在场景中的某个位置产生拉伸。您可以通过将地板的顶点位置投影到其他坐标系中来建模变化的灯光角度。
另一种可能性是根据光线坐标系中的表面位置来计算光线密度,尽管这很可能会降低性能。
随着深度的增加,苛性碱的褪色速度应快于漫射光。
颜色的分散程度不同,因此浅色应随深度的增加而变化。这也防止了例如海滩与水面相交的陡峭边缘。
由于折射,光照射到海底的距离比通常要陡得多。在约斯涅耳定律,维基百科的文章有角度和矢量公式。
我相信《我的世界》中的天空照明效果是直下的-无论太阳在哪里,事物都被其上方的阴影所遮蔽。然后,从手电筒等发出的局部照明具有衰减效果-距离光源越远,立方体得到的光越少。
如果采用这种方式,则每一层水都会累积遮盖其下方的一层,因此每一层都会逐渐变暗。树木的叶子提供了这样的阴影,但是不是累积的。无论是1还是100个树叶立方体,您都可以在树下得到相同的阴影。
这是使用的方法的一个线索是,离观看者越远,水不会变得越暗-仅当您下楼时。是的,远处确实会起雾效果,但水暗效果不会。
因此,用伪代码计算照明的基本公式将是这样的……
light_on_cube = 1.0
for each cube above target cube, from lowest to highest {
if cube being examined is tree foliage
light_on_cube = 0.5
else if cube being examined is water
light_on_cube = light_on_cube - 0.1
else if cube being examined is solid
light_on_cube = 0
}
这对于计算悬垂处或洞穴中的光照不是完美的,因为使用此方法在悬垂处会变暗。但是,既可以添加本地光源(手电筒,火等),也可以将被阳光照亮的块作为光源。这样的事情可能会做...
这里的想法是,如果一个立方体被太阳或手电筒照亮,它旁边的那个立方体也将以某种方式被照亮。而且,您离那个发光的立方体越远,光线就越少。这是一种估计漫射照明的模糊方式,但我认为(?)可行。
也许我对这个问题有误解,但是为什么不能仅根据块的深度更改块的颜色呢?
如果您具有深度d(以块为单位,从0开始),则亮度的合理公式为:
L =(1- 米)e - kd + m
码: L = (1.0 - m) * exp(-k * d) + m;
k控制变暗的速度(越高=越快)。合理的值为0.5。
m是您想要的最小亮度。
L从0到1。
如果您不知道如何在使用的任何图形API中更改块的颜色,请作为一个单独的问题(说明使用的API,以及是否使用着色器)进行询问。
e^-kd
位只是指数衰减,对于在某个值(深度)上逐渐趋于零的事物,这是标准功能。与的相乘(1-m)
和相乘m
只是按比例缩放并抵消了衰减,因此衰减以的最小值结束,m
但仍从开始1
。 zh.wikipedia.org/wiki/Exponential_decay