WebGL:如何使对象的一部分透明?

时间:2013-06-22 17:58:38

标签: html5 opengl-es 3d webgl

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

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

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

enter image description here

我试图更改片段着色器中的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:Shader脚本。
  • buffers.js:所有这里都是对象。
  • shaders.js:初始着色器。

4 个答案:

答案 0 :(得分:5)

您应该使用模板缓冲区。 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)去除颜色&amp;深度写作

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

3)这里绘制你的三角形:)

4)启用深度&amp;立方体的颜色写作

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

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

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。没有免费的午餐:)

答案 1 :(得分:1)

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

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

另外:official WebGL reference sheet

答案 2 :(得分:1)

尝试添加这些行

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

OpenGL ES对我有用。

答案 3 :(得分:0)

或者从球网中移除一些三角形,或者将纹理应用于具有透明部分的三角形,打开混合并关闭任何类型的剔除,这样就不会松开反向三角形。

编辑:

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

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

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