2D光漫射贴图

时间:2016-12-18 03:21:46

标签: java opengl libgdx light

我正在尝试在基于libGDX的游戏上实现一个简单的2D光引擎。我们的想法是创建没有着色器的光引擎。我不打算暂时渲染任何阴影。 我设法渲染了一个带有三角形和渐变的光照贴图,但问题是当多个光源重叠时,我得到了一些像这样的图片中的人工制品:

enter image description here

黄色光源在与其他光源重叠时产生暗边框。

我使用以下混合函数来渲染灯光:

Gdx.gl.glBlendFunc(GL20.GL_ONE, GL20.GL_ONE);

有没有办法摆脱这个黑暗的边界?

渐变从黄色变为黑色完全不透明度。由于GL_ONE被认为是加性的,颜色应该只是变亮了吗?

更新1:

使用Nico Schertler解释的着色器肯定更好,但仍有一些我不确定的参数。

enter image description here

这是我想出的片段着色器

void main() {
  float intensity = 0.02;
  vec2 pos = vPosition;
  float dist = distance(pos, u_origin) / u_radius;
  vec4 color = vec4(intensity * (vColor.rgb / ((dist * dist) + 0.01)), 1);
  gl_FragColor = color;
}

问题是我不确定常量intensity = 0.020.01我已添加到函数中以使其看起来不错。此外,半径变量现在是屏幕高度和宽度之间的最大值。

更新2:

我终于选择了以下等式:

void main() {
  float dist = distance(vPosition, u_origin) / u_radius;
  vec4 color = vec4((vColor.rgb) / (pow(dist, 2) + 0.01), vColor.a);

  gl_FragColor = color;
}

然后基于相同的等式与遮挡图组合(以使非照明的地方变暗)。这是最终输出:

ambient + occlusion

1 个答案:

答案 0 :(得分:2)

这在很大程度上取决于你如何照亮灯光。

E.g。如果你使用一些截断的二次函数作为光的亮度(相对于距中心的距离),即类似的东西:

enter image description here

如果您添加两个灯光,您将获得此个人资料:

enter image description here

enter image description here

在此配置文件中,您会看到明显的不连续性。这种不连续性的原因是截断原始函数。所以你很可能在你的图像中有任何形式的截断光功能(无论是二次,线性还是其他),这会导致两个光交叉处的明亮区域。

那么如何解决这个问题?物理上正确的光分布随着二次距离而下降(在2D中你也可以争论线性衰减),x是距光源的距离:

light = factor / x^2

此功能有两个问题。首先,它没有紧凑的支持。这意味着你必须绘制一个无限大的splat(或至少与屏幕一样大)。这可能不是一个大问题。一旦它变得非常小,你也可以切断它。第二个问题更严重。如果x转到0(即您直接位于灯光位置),则无法计算此值(它会趋于无穷大,因为所有光能都聚焦在没有区域的点上)。所以它真的取决于你想要用光照贴图做什么。当然,您可以采用类似于

的方式进行规范化
light = factor / ((x)^2 + epsilon)

,其中epsilon是一个非常小的数字。如果你的场景是从上面看的东西,这个epsilon可能是地面上光线的高度(平方)。然后,您将获得如下的个人资料:

enter image description here

Voila,没有不连续性。但是你很可能需要一个片段着色器来实现这一点。

如果你不关心身体的正确性,高斯啪啪也可能会给出漂亮的效果:

light = factor * exp(-x^2 / variance)