Alpha渲染与OpenGL和WebGL之间的区别

sho*_*osh 7 c++ opengl webgl emscripten

我使用相同的C++代码渲染相同的场景,一次使用Windows上的原生OpenGL,一次使用Emscripten到WebGL.场景中的所有内容看起来完全相同,除非我使用alpha!= 1.0渲染内容.区别如下: 在此输入图像描述

蓝色立方体颜色是(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);
Run Code Online (Sandbox Code Playgroud)

WebGL中的alpha存在某种差异吗?什么可能导致这种情况发生?

gma*_*man 11

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

gl = someCanvas.getContext("webgl", { premultipliedAlpha: false });
Run Code Online (Sandbox Code Playgroud)

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

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

要查看这是否是问题,请尝试将画布的背景颜色设置为紫色或将突出显示的内容

<canvas ... style="background-color: #F0F;"></canvas>
Run Code Online (Sandbox Code Playgroud)

或者在css

canvas { background-color: #F0F; }
Run Code Online (Sandbox Code Playgroud)

OpenGL应用程序很少被合成,因为WebGL应用程序总是有效地合成.

一些解决方案

  • 关掉alpha

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

    gl = someCanvas.getContext("webgl", { alpha: false });
    
    Run Code Online (Sandbox Code Playgroud)

    现在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);
    
    Run Code Online (Sandbox Code Playgroud)

    如果以后需要清除颜色缓冲区,请不要忘记将颜色掩码设置为全部

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

    canvas { background-color: #000; }
    
    Run Code Online (Sandbox Code Playgroud)

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