【问题标题】:Regl color and alpha blending of primitives图元的Regl颜色和alpha混合
【发布时间】:2019-01-27 01:19:37
【问题描述】:

我正在尝试弄清楚如何使用 Regl 实现基元之间的颜色和 alpha 混合。

我知道 Regl 命令有一个 blend property,我尝试复制以下 webgl 设置来解决问题:

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

在 Regl 中使用以下 blend 设置:

blend: {
  enable: true,
  func: { src: 'src alpha', dst:'one minus src alpha' }
},

但是混合似乎只对背景颜色起作用,而不是在点之间。 (参见下面的示例。)

示例: http://jsfiddle.net/8gyf7pek/13/

const canvas1 = document.querySelector('#c1');
const canvas2 = document.querySelector('#c2');

//////////////////////////////////////////////
// PURE WEBGL
//////////////////////////////////////////////

const gl = canvas1.getContext('webgl');
gl.enable(gl.BLEND);
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
const vertexShaderSource = `
  attribute vec2 position;
  attribute vec4 color;
  varying vec4 v_color;

  void main() {
    gl_PointSize = 50.0;
    gl_Position = vec4(position, 0, 1);
    v_color = color;
  }
`;

const fragmentShaderSource = `
  precision mediump float;
  varying vec4 v_color;
  void main() {
    gl_FragColor = v_color;
  }
`;

const vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
const program = createProgram(gl, vertexShader, fragmentShader);
gl.useProgram(program);

const positionAttributeLocation = gl.getAttribLocation(program, 'position');
const colorAttributeLocation = gl.getAttribLocation(program, 'color');
const positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);

const colorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
gl.enableVertexAttribArray(colorAttributeLocation);
gl.vertexAttribPointer(colorAttributeLocation, 4, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
  -0.05, -0.05, -0.05, 0.05, 0.05, 0.05, 0.05, -0.05,
]), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
const red = [1, 0, 0, 0.5];
const blue = [0, 0, 1, 0.5];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
  ...red, ...red,
  ...blue, ...blue,
]), gl.STATIC_DRAW);

gl.drawArrays(gl.POINTS, 0, 4);

function createShader(gl, type, shaderSource) {
  const shader = gl.createShader(type);
  gl.shaderSource(shader, shaderSource);
  gl.compileShader(shader);
  const success = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
  if(!success) {
    console.warn(gl.getShaderInfoLog(shader));
    gl.deleteShader(shader);
  }
  return shader;
}

function createProgram(gl, vertexShader, fragmentShader) {
  const program = gl.createProgram();
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  gl.linkProgram(program);
  const success = gl.getProgramParameter(program, gl.LINK_STATUS);
  if(!success) {
    console.log(gl.getProgramInfoLog(program));
    gl.deleteProgram(program);
  }
  return program;
}

//////////////////////////////////////////////
// REGL
//////////////////////////////////////////////

const regl = createREGL(canvas2);

regl.clear({ color: [0, 0, 0, 0], depth: 1 });

regl({
  frag: `
  precision mediump float;
  varying vec4 fragColor;
  void main () {
    gl_FragColor = fragColor;
  }`,

  vert: `
  precision mediump float;
  attribute vec2 position;
  attribute vec4 color;
  varying vec4 fragColor;
  uniform float pointWidth;
  void main () {
    fragColor = color;
	gl_PointSize = pointWidth;
    gl_Position = vec4(position, 0, 1);
  }`,

  attributes: {
    position: [
      [-0.05, -0.05],
      [-0.05, 0.05],
      [0.05, -0.05],
      [0.05, 0.05],
    ],
    color: [
      [1, 0, 0, 0.5],
      [1, 0, 0, 0.5],
      [0, 0, 1, 0.5],
      [0, 0, 1, 0.5]
    ],
  },

  uniforms: {
    pointWidth: 50,
  },
  
  blend: {
  	enable: true,
    func: { src: 'src alpha', dst:'one minus src alpha' }
  },

  count: 4,
  
  primitive: 'points',
})();
#bg {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  color: #808080;
  background: black;
}
#c1, #c2 {
  width: 240px;
  height: 240px;
  border: 1px solid white;
}
em {
  display: block;
}
<div id="bg">
  <canvas id="c1"></canvas>
  <canvas id="c2"></canvas>
  <em>Left is pure WebGL. Right is Regl.</em>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/regl/1.3.7/regl.min.js"></script>

我做错了吗?我怎样才能实现与纯 webgl 代码产生的相同类型的混合?谢谢!

【问题讨论】:

    标签: webgl alphablending blending color-blending regl


    【解决方案1】:

    感谢this great answer我想通了:

    简而言之,混合功能需要调整,深度测试需要禁用。 (但我仍然不知道为什么在 vanilla WebGL 示例中有效的混合功能在 Regl 中无效)

    1. 使用以下混合模式

      blend: {
        enable: true,
        func: {
          srcRGB: 'src alpha',
          srcAlpha: 'src alpha',
          dstRGB: 'one minus src alpha',
          dstAlpha: 'one minus src alpha',
        },
      },
      
    2. 禁用深度测试

      depth: { enable: false },
      

    这是我的问题中的固定示例:http://jsfiddle.net/8gyf7pek/22/

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-12
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-28
    相关资源
    最近更新 更多