javascript - 如何使用模板在 webgl 中创建 2d 剪贴蒙版?

标签 javascript webgl mask clip stencil-buffer

我一直在研究一种创建类似于 this one 的剪贴蒙版的方法。 (以 SVG 格式完成)。

根据我的发现,我选择通过模板来实现这一目标。然而我的实现是非常不正确的。我不完全确定 gl.stencilOpgl.stencilFunc 是如何工作的,因为我似乎需要渲染两次屏蔽我的主要内容的片段。在渲染主要内容之前一次,在渲染主要内容之后一次使用不同的参数。

这是工作测试:https://dl.dropboxusercontent.com/u/1595444/experiments/two.js/issues/issue-56/stencil-buffer/test/clip.html

enter image description here

此测试的相关片段/部分可以在 ../src/renderers/webgl.js 中找到,从 L67 开始:

if (this._mask) {

  gl.enable(gl.STENCIL_TEST);
  gl.stencilFunc(gl.ALWAYS, 1, 1);

  gl.colorMask(false, false, false, true);
  gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);

  // Renders the mask through gl.drawArrays L111
  webgl[this._mask._renderer.type].render.call(
    this._mask, gl, program, this);

  gl.colorMask(true, true, true, true);
  gl.stencilFunc(gl.NOTEQUAL, 0, 1);
  gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);

}

// Renders main content through a series of gl.drawArrays calls
_.each(this.children, webgl.group.renderChild, {
  gl: gl,
  program: program
});

if (this._mask) {

  gl.colorMask(false, false, false, false);
  gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR);

  // Re-render mask so main content doesn't flicker
  webgl[this._mask._renderer.type].render.call(
    this._mask, gl, program, this);

  gl.colorMask(true, true, true, true);
  gl.stencilFunc(gl.NOTEQUAL, 0, 1);
  gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);

  gl.disable(gl.STENCIL_TEST);

}

模拟 webgl 模板以像 svg 示例一样工作的指导将非常感激。

最佳答案

您需要做的是:

  • 绘制模板区域(在您的例子中为蓝色矩形),
  • 停止在模板中绘制
  • 绘制您想要考虑使用模板的场景
  • 停止模板

如下:

if (this._mask) {
    // Clearing the stencil buffer
    gl.clearStencil(0);
    gl.clear(gl.STENCIL_BUFFER_BIT);

    // Replacing the values at the stencil buffer to 1 on every pixel we draw
    gl.stencilFunc(gl.ALWAYS, 1, 1);
    gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);

    // disable color (u can also disable here the depth buffers)
    gl.colorMask(false, false, false, false);

    gl.enable(gl.STENCIL_TEST);

    // Renders the mask through gl.drawArrays L111
    webgl[this._mask._renderer.type].render.call(this._mask, gl, program, this);

    // Telling the stencil now to draw/keep only pixels that equals 1 - which we set earlier
    gl.stencilFunc(gl.EQUAL, 1, 1);
    gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
    // enabling back the color buffer
    gl.colorMask(true, true, true, true);
}

// Renders main content through a series of gl.drawArrays calls
_.each(this.children, webgl.group.renderChild, {
   gl: gl,
   program: program
});

// Stop considering the stencil
if (this._mask) {
   gl.disable(gl.STENCIL_TEST);
}

关于javascript - 如何使用模板在 webgl 中创建 2d 剪贴蒙版?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24687437/

相关文章:

javascript - 在javascript中搜索和删除数组元素

javascript - 如何判断现有站点是否正在使用 WebGL?

textures - 如何在 WebGL 中将不同的纹理映射到立方体的不同面?

javascript - 我如何使用 WebGL 创建基于 float 的 RGBA 纹理?

python - `Pandas argmax` 在屏蔽后获取所有 `True` 索引(Python 3)(例如 (pd.Series > 0).argmax()))

css - 创意 SVG 蒙版

python-3.x - OpenCV 掩码结果

javascript - 我的 JavaScript 有什么问题吗?

javascript - 可变数量的嵌套 for 循环

javascript - (插件 commonjs) SyntaxError : Unexpected token when packaging vue component with rollup