【问题标题】:How to use stenciling to create a 2d clipping mask in webgl?如何使用模板在 webgl 中创建 2d 剪贴蒙版?
【发布时间】:2014-09-01 11:18:57
【问题描述】:

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

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

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

此测试的相关 sn-p / 部分可以在 ../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 示例一样工作的指导。

【问题讨论】:

    标签: javascript webgl mask clip stencil-buffer


    【解决方案1】:

    你需要做的是:

    • 绘制您的模板区域(在您的情况下为蓝色矩形),
    • 停止在模具中绘图
    • 绘制您想要考虑模板的场景
    • 停止模板

    如下:

    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);
    }
    

    【讨论】:

    • 抱歉耽搁了,感谢您的帮助!这更接近,但仍然不完全正确。圆形和矩形都是四边形顶部的纹理。您正在实现掩盖四边形,但不是纹理(圆圈)。这是您的实施的更新版本:dl.dropboxusercontent.com/u/1595444/experiments/Two.js/issues/…
    • @jonobr1 该链接不再有效。请将代码嵌入到答案帖子中。
    猜你喜欢
    • 1970-01-01
    • 2020-08-08
    • 2016-07-07
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 2017-02-10
    • 1970-01-01
    • 2012-07-07
    相关资源
    最近更新 更多