OpenGL 和 WebGL 之间的 Alpha 渲染差异

问题描述 投票:0回答:2

我使用完全相同的 C++ 代码渲染相同的场景,一次使用 Windows 上的本机 OpenGL,一次使用 Emscripten 渲染 WebGL。场景中的所有内容看起来都完全相同,除非我使用 alpha != 1.0 渲染某些内容。区别如下: enter image description here

蓝色立方体的颜色是

(0.0, 0.0, 1.0, 0.5)

用于渲染立方体的着色器除了绘制颜色之外什么也不做。
右边是 OpenGL 的样子,也是预期的结果,只是蓝色,半透明。左边是 Emscripten+WebGL 的样子。看起来渲染出来的颜色实际上是
(0.5, 0.5, 1.0, 0.5)

我使用的混合功能是标准的:

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

WebGL 中的 alpha 是否有某种差异?什么可能导致这种情况发生?

c++ opengl webgl emscripten
2个回答
13
投票

您是否将画布设置为非预乘?

gl = someCanvas.getContext("webgl", { premultipliedAlpha: false });

WebGL 的默认值为 true。大多数 OpenGL 应用程序的默认值是 false

WebGL 与页面的其余部分合成。至少是画布或其内部的任何内容(文档正文)的背景颜色。

要查看这是否是问题所在,请尝试将画布的背景颜色设置为紫色或会突出的颜色

<canvas ... style="background-color: #F0F;"></canvas>

或者在CSS中

canvas { background-color: #F0F; }

OpenGL 应用程序很少在任何东西上进行合成,而 WebGL 应用程序总是有效地进行合成。

一些解决方案

  • 关闭阿尔法

    如果您的目的地不需要 alpha,您可以将其关闭

    gl = someCanvas.getContext("webgl", { alpha: false });
    

    现在 alpha 将有效为 1

  • 在帧结束时将 alpha 设置为 1

    // clear only the alpha channel to 1
    gl.clearColor(1, 1, 1, 1);
    gl.colorMask(false, false, false, true);
    gl.clear(gl.COLOR_BUFFER_BIT);
    

    如果需要,请不要忘记将颜色遮罩设置回全部 true 稍后清除颜色缓冲区

  • 将画布的背景颜色设置为黑色

    canvas { background-color: #000; }
    

如果可能的话我会选择关闭 Alpha。如果将 alpha 设置为关闭,则浏览器可能会在将画布绘制到浏览器中时关闭混合。根据 GPU 的不同,速度可能会提高 10-20% 或更多。不能保证任何浏览器都会进行这种优化,只是可以做到这一点,而使用其他两种解决方案则不可能或至少不太可能


0
投票

我在使用 Emscripten、SDL3 和 OpenGL ES 2.0 时也遇到了同样的问题。比较 WASM 和 EXE 构建(围绕主角的白色曲线):

enter image description here

您应该像这样禁用

alpha
premultipliedAlpha

#ifdef __EMSCRIPTEN__
#include <emscripten/html5.h>
#include <SDL3/SDL_opengles2.h>
#else
#include <glad/glad.h>
#endif // __EMSCRIPTEN__

SDL_AppResult SDL_AppInit(void **appstate, int argc, char *argv[])
{
    // ...
    // Paste the following code after SDL_CreateWindow and before SDL_GL_CreateContext
#ifdef __EMSCRIPTEN__
    EmscriptenWebGLContextAttributes attrs;
    emscripten_webgl_init_context_attributes(&attrs);

    attrs.alpha = EM_FALSE; // Disable alpha blending
    attrs.premultipliedAlpha = EM_FALSE; // Disable premultiplied alpha
    attrs.depth = EM_TRUE; // Enable depth testing
    attrs.stencil = EM_FALSE; // Disable stencil testing
    attrs.antialias = EM_FALSE; // Disable anti-aliasing

    EMSCRIPTEN_WEBGL_CONTEXT_HANDLE ctx = emscripten_webgl_create_context("#canvas", &attrs);
#endif // __EMSCRIPTEN__
    // ...
}

问题解决了:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.