html - 使用预乘 alpha 时,WebGL 中的 Alpha 渐变不平滑

标签 html opengl-es libgdx webgl blending

我有一款 LibGDX 游戏,其中有平滑渐变的卡通云。游戏中还有其他渐变示例也存在类似问题,但云彩是最明显的示例。它们在 Android、iOS 和游戏的桌面版本中看起来不错,但在 WebGL 版本中,渐变绘制得不那么平滑。似乎只有 alpha 梯度有问题。其他渐变看起来还不错。

我在 Chrome 和 IE 中尝试了 3 种不同的设备,所有 3 种设备都产生了相同的结果。您可以在此处找到 HTML5 版本的测试。

https://wordbuzzhtml5.appspot.com/canvas/

我在 github 上添加了一个示例 IntelliJ 项目

https://github.com/WillCalderwood/CloudTest

如果您有 intelliJ,请克隆该项目,打开 build.gradle 文件,按 Alt-F12,键入 gradlew html:superdev,然后浏览至 http://localhost:8080/html/

关键代码是render() here

这里底部的图像是桌面版本,顶部是 WebGL 版本,两者运行在相同的硬件上。

enter image description here

这幅画没有任何巧妙之处。这只是一个调用

    spriteBatch.draw(texture, getLeft(), getBottom(), getWidth(), getHeight());

我正在使用默认着色器,纹理包含预乘 alpha,混合函数设置为

    spriteBatch.setBlendFunction(GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA);

这是实际图像,尽管 alpha 没有像我的打包程序那样预乘。

enter image description here

有谁知道这可能的原因以及我该如何解决?

更新

这似乎只有在使用混合模式 GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA 时才会发生

另一个更新

我试过将整个游戏更改为使用非预乘 alpha 纹理。我使用 Texture Packer,它可以帮助修复非预乘 alpha 经常出现的光晕问题。所有这些在 Android 和桌面版本中都运行良好。在 WebGL 版本中,虽然我得到了平滑的渐变,但我仍然得到了一个小的光晕效果,所以我也不能用它作为解决方案。

还有另一个更新

这是一张新图片。桌面版在上,网页版在下。左边的混合模式 GL20.GL_ONE, GL20.GL_ONE_MINUS_SRC_ALPHA 右边的 GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA

enter image description here

这是左下角图像的放大版本,通过增加对比度来显示问题。

enter image description here

我还对片段着色器做了很多尝试,以尝试弄清楚发生了什么。如果我设置

gl_FragColor = vec4(c.a, c.a, c.a, 1.0);

那么渐变是平滑的,但是如果我设置

gl_FragColor = vec4(c.r, c.r, c.r, 1.0);

然后我得到 strip 。我认为这指向一个精度问题,因为颜色 channel 已被预乘过程挤压到光谱的较暗端。

最佳答案

WebGL 对待 alpha 的方式与标准 OpenGL 略有不同,并且经常会导致问题。

This site很好地解释了差异。

The biggest difference between OpenGL and WebGL is that OpenGL renders to a backbuffer that is not composited with anything so, or effectively not composited with anything by the OS's window manager, so it doesn't matter what your alpha is.

WebGL is composited by the browser with the web page and the default is to use pre-multiplied alpha the same as .png tags with transparency and 2d canvas tags.*

该站点还针对人们面临的典型问题提供了解决方法。这有点复杂,但应该可以解决您的问题。

我不打算在这里粘贴整篇文章,但我怀疑您最好坚持使用非预乘,并确保在每次渲染后清除 alpha channel 。该网站提供了更多详细信息。

关于html - 使用预乘 alpha 时,WebGL 中的 Alpha 渐变不平滑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31481029/

相关文章:

javascript - 如何停止 dragend 在拖放中的默认行为?

iphone - iOS : UIScrollView and OpenGL

c - CreateContext 期间的 BAD_CONFIG

java - Android - 带有 OPENGL + 纹理的 3D 立方体

java - libGDX 我应该在哪里使用 dispose/如何使对象成为一次性对象?

html - 堆叠一些图像

java - 获取所选元素内的所有元素作为 Element Jsoup android 的数组

html - 将 div 相对(绝对)定位到固定的导航栏

java - LibGDX applyLinearImpulse 试图实现重力....困惑

java - LibGdx:表格显示不正确