1

我正在尝试使用 Cocos2d HTML5 框架,但我认为这是一个标准的 WebGL 问题,我无法确定,因为我对该主题没有很好的了解。如果我有一个带有半透明像素(例如软边缘)的标准 PNG 图像,并且如果背景(画布或 RenderTexture 后面的其他元素)填充了非黑色,则绘制到 RenderTexture 时的精灵最终会浸入即使不应该出现背景。例如,如果我正在绘制的图形是红色并且我使用绿色背景,则半透明像素最终会变成黄色。请参阅这些图片以获取说明:

在纯黑色背景下的外观,这就是我想要的 在纯黑色背景下的外观,这就是我想要的

出现在非黑色背景下,背景渗出 出现在非黑色背景下,背景渗出

当我放置任何非 100% 不透明的图像时,背景中的任何内容都会显示出来。

完整的基于 JavaScript 的 RenderTexture 类代码可以在 cocos2d-html5 Github Repository 的 cocos2d/misc_nodes/CCRenderTexture.js 下查看。它是 Cocos2d-x C++ / Objective C 的转换(不存在这个问题)。在 cocosd-iphone 问题跟踪器上有一个报告的问题 #937,描述了几年前非 HTML 版本的相同问题。此后已解决,但我似乎无法确定分辨率是什么或如何将其转换为 WebGL 格式。我确定这是一个混合问题,但我尝试更改混合模式(从 GL_ONE、GL_ONE_MINUS_SRC_ALPHA 到 GL_SRC_ALPHA、GL_ONE_MINUS_SRC_ALPHA 等)无济于事。

OpenGL / WebGL 专家的任何帮助将不胜感激。如果我在这个 RenderTexture 之外使用 Cocos2d 中的标准“精灵”,则问题不存在。此外,MotionStreak 功能似乎也可以正常工作,但我需要 RenderTexture 创建动态纹理以供进一步使用。

4

1 回答 1

2

WebGL 默认与图像和画布 2D 相同,即它期望画布的内容为 RGBA,它期望 RGB 与 alpha 相乘(换句话说,如果 alpha 为零,则 RGB 也必须为零,因为任何东西乘以零等于零)。最后用 GL_ONE、GL_ONE_MINUS_SOURCE_ALPHA 与它背后的任何东西混合。

如果你想要它不同,你有 2 个选择

  1. 告诉 WebGL 不要有 alpha

    你可以通过创建一个没有 alpha 的上下文来做到这一点

    gl = canvas.getContext("experimental-webgl", { alpha: false });
    

    这可能是您的情况的最佳选择。由于不会有 alpha,因此不需要混合,这比与背景混合更快,这是浏览器通常必须做的。

  2. 告诉 WebGL 你的 RGB 值没有被预乘

    gl = canvas.getContext("experimental-webgl", { premultipledAlpha: false });

    这意味着浏览器仍会将您的 WebGL 画布与背景混合,它只会使用 GL_SRC_ALPHA、GL_ONE_MINUS_SRC_ALPHA 来代替。你仍然会看到后面的绿色。

还有一些其他解决方案可能在特殊情况下有用

  1. 如果您需要在目标中使用 alpha 进行某些计算,您可以在完成后将 alpha 清除为 1

    ...render scene...
    
    gl.colorMask(false, false, false, true);
    gl.clearColor(0, 0, 0, 1);
    gl.clear(gl.COLOR_BUFFER_BIT);
    

    混合仍然会发生,您只是看不到它,因为您的所有 alpha 都设置为 1。这不是最佳解决方案,但如果您需要目标 alpha,它可能是您唯一的解决方案。

  2. 如果你不想看透画布后面的东西,那么给画布一个背景色

    <canvas style="background-color: green;"></cavnas>
    

    将画布的背景颜色设置为黑色也可以,但这也是一种浪费,因为它仍然会将画布与黑色混合。如果那是您想要的,那么只需首先关闭 alpha。

于 2013-10-31T00:07:56.173 回答