【问题标题】:WebGL : How do make part of an object transparent?WebGL:如何使对象的一部分透明?
【发布时间】:2017-11-10 13:51:40
【问题描述】:

我在浏览器中有一个 3D 球,现在我想在它上面挖一个洞看看它的背面。

我怎样才能让它成为可能?

例如,我希望立方体的白色三角形部分可以是透明的(我的意思是我们可以看到立方体后面的背景)。

我尝试在片段着色器中更改 alpha(代码中的区域是正方形而不是三角形,没关系):

<script id="shader-fs-alpha" type="x-shader/x-fragment">
    precision mediump float;

    varying vec4 vColor;

    uniform float uAlpha;

    void main(void) {
      if( gl_FragCoord.x < 350.0 && gl_FragCoord.x > 300.0
        && gl_FragCoord.y < 300.0 && gl_FragCoord.y > 230.0
        ) {
        gl_FragColor = vec4(0, 0 ,0, 0.0);
      } else {
        gl_FragColor = vec4(vColor.rgb, 1.0);
      }
    }
</script>

这确实有效,但该区域变成白色(不透明),所以我尝试启用混合,但这会使整个立方体透明。

所以现在我想如果有办法在片段着色器中启用bleanding,我可以在else 块中禁用它。

这是我的整个项目https://gist.github.com/royguo/5873503

  • index.html : 此处为着色器脚本。
  • buffers.js : 所有对象都在这里。
  • shaders.js:初始化着色器。

【问题讨论】:

    标签: html opengl-es 3d webgl


    【解决方案1】:

    您应该使用模板缓冲区。 2 步骤: 一、在模板上画出三角形。二、用模板测试绘制立方体。

    // you can use this code multiple time without clearing stencil
    // just increment mask_id
    mask_id = 1;
    
    // allow to draw inside or outside mask
    invert_mask = false;
    

    1) 激活模板缓冲区。配置它:不测试并写入 mask_id 值

    glEnable(GL_STENCIL_TEST);
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
    glStencilFunc(GL_ALWAYS, mask_id, 0);
    

    2) 去除颜色和深度书写

    glDepthMask(GL_FALSE);
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    

    3) 在这里画出你的三角形:)

    4) 为立方体启用深度和颜色书写

    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glDepthMask(GL_TRUE);
    

    5) 为立方体配置stencil:无写入和测试stencil值

    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
    glStencilFunc(invert_mask ? GL_NOTEQUAL : GL_EQUAL, mask_id, 0xff);
    

    6) 在这里画你的立方体:)

    7) 清理:移除模板测试

    glDisable(GL_STENCIL_TEST);
    

    在创建 opengl 上下文时不要忘记请求模板(参见 WebGLContextAttributes,getContext 的第二个参数)

    此代码在 Ios 平台上与 Opengl ES 2 一起运行良好。它不依赖于任何扩展。 WebGL 使用相同的 API。

    唯一的小缺陷:三角形边框上没有 msaa。没有免费的午餐:)

    【讨论】:

      【解决方案2】:

      您可以将没有对象(或对象内部)的部分场景渲染到纹理,然后将纹理投影到对象前面的表面上。只需确保表面直接面向相机(平行于凸轮空间中的 x-y 平面),并且纹理以与屏幕相同的中心和透视进行渲染。

      如果您需要帮助,请使用Learning WebGL: Rendering to Textures。您还应该检查光照选项,以确保表面本身不受对象获得的光照的影响。

      还有:official WebGL reference sheet

      【讨论】:

        【解决方案3】:

        尝试添加这些行

        glEnable (GL_BLEND);                                                              
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        

        OpenGL ES 对我有用。

        【讨论】:

          【解决方案4】:

          或者从球网格中移除一些三角形,或者对它应用具有透明部分的纹理,打开混合并关闭任何类型的剔除,这样你就不会丢失面向背面的三角形。

          编辑:

          这里有一个关于在 webGL 中混合的教程:http://learningwebgl.com/blog/?p=859 你有多种模式可供选择,我将如何混合两个像素,通过调整 alpha 值,你可以拥有任何你想要的东西。

          最终,您将 alpha 设置为 1.0 的纹理应用到所有地方,除了那些应该是“空心”然后启用混合的部分。我希望我说清楚了。

          提示:不要阅读文档(有时这比帮助更令人困惑),试试这个http://www.nihilogic.dk/labs/webgl_cheat_sheet/WebGL_Cheat_Sheet.htm,。它以非常好的方式列出了所有功能。

          【讨论】:

          • 能否提供更多细节?我真的需要你的帮助,谢谢!
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-07-05
          • 2013-01-29
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多