WebGL - 未清除时的意外行为 gl.COLOR_BUFFER_BIT

WebGL - unexpected behaviour while not clearing gl.COLOR_BUFFER_BIT

我试图在我的页面中实现一种运动模糊效果,并想简单地为主帧缓冲区指定一个混合函数

gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);

并且不清除我绘制例程中的 gl.COLOR_BUFFER_BIT

//gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(/*gl.COLOR_BUFFER_BIT |*/ gl.DEPTH_BUFFER_BIT);

我希望看到屏幕上充满了永远不会清除的旧颜色值,但实际结果与我将 color_buffer_bit 清除为白色一样

这是包含所有代码的测试页面的link,它非常简单,因为它只是在屏幕上用彩色粒子绘制一个函数

http://deepdown.altervista.org/WebGl/test/sample.html

如果我不指定,颜色缓冲区是否会被清除? 需要做什么才能在每个缓冲区中保留渲染的颜色而不被覆盖?

您可能会发现

简短的版本是,默认情况下 WebGL 会清除 drawingBuffer。

至于 alpha 问题

规范对所有这些都非常清楚。只是它是一个规范,并且非常详细且难以遵循,因为它超过 300 页,因为它不仅是 WebGL 规范,而且 WebGL 规范说它基于 OpenGL ES 2.0 规范和 GLSL ES 1.0 规范。

为什么要有 alpha 缓冲区?因为它是 HTML 并且所有其他元素都有 alpha。您可以将文本或背景颜色设置为 rgba(255,0,0,0.5)。您可以显示具有 alpha 透明度的 .PNG 文件,而 2D canvas 具有 alpha 和透明度,默认情况下 WebGL 也是如此。

将 alpha 设置为 false 是对非 HTML 基于应用程序(即端口)的让步。

因此,不利的一面是无法与页面的其余部分保持透明。 Not the best sample but here is one of the first examples of this。没有 alpha,你无法做到这一点。

至于如何混合,与网页混合默认使用premulitplied alpha。

否则,如果你想让东西堆积起来,你可能需要用添加剂混合来混合

 gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);

示例:

"use strict";
var m4 = twgl.m4;
var gl = twgl.getWebGLContext(document.getElementById("c"), { preserveDrawingBuffer: true } );
var programInfo = twgl.createProgramInfo(gl, ["vs", "fs"]);

var arrays = {
  position: [-1, -1, 0, 1, -1, 0, -1, 1, 0, -1, 1, 0, 1, -1, 0, 1, 1, 0],
};
var bufferInfo = twgl.createBufferInfoFromArrays(gl, arrays);

function rand(min, max) {
  return Math.random() * (max - min) + min;
}

function render(time) {
  
  gl.enable(gl.BLEND);
  gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
  
  var matrix = m4.identity();
  m4.translate(matrix, [rand(-1, 1), rand(-1, 1), 0], matrix);
  m4.scale(matrix, [rand(0.1, 0.2), rand(0.1, 0.2), 1], matrix);
  
  var color = [Math.random(), Math.random(), Math.random(), 0.1];
  var preMultipliedColor = [color[0] * color[3], color[1] * color[3], color[2] * color[3], color[3]];
  
  var uniforms = {
    matrix: matrix,
    color: preMultipliedColor,
  };

  gl.useProgram(programInfo.program);
  twgl.setBuffersAndAttributes(gl, programInfo, bufferInfo);
  twgl.setUniforms(programInfo, uniforms);
  twgl.drawBufferInfo(gl, gl.TRIANGLES, bufferInfo);

  requestAnimationFrame(render);
}
requestAnimationFrame(render);
.msg {
  display: flex;
  justify-content: center;
  align-content: center;
  align-items: center;
  width: 300px;
  height: 150px;
}
.msg>div {
  width: 200px;
}
canvas {
  position: absolute;
  left: 5px;
  top: 5px;
  border: 1px solid black;
}
<script src="https://twgljs.org/dist/twgl-full.min.js"></script>
  <script id="vs" type="notjs">
attribute vec4 position;
uniform mat4 matrix;

void main() {
  gl_Position = matrix * position;
}
  </script>
  <script id="fs" type="notjs">
precision mediump float;

uniform vec4 color;

void main() {
  gl_FragColor = color;
}
  </script>
<div class="msg"><div>lets put some text under the canvas so we can see if things are blending and
  being composited </div></div>
<canvas id="c"></canvas>