WebGL:如何使对象的一部分透明? [英] WebGL : How do make part of an object transparent?

查看:41
本文介绍了WebGL:如何使对象的一部分透明?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

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

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

所以现在我想是否有办法在片段着色器中启用 bleanding 并且我可以在 else 块中禁用它.

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

  • index.html : 这里的着色器脚本.
  • buffers.js:这里的所有对象.
  • shaders.js:初始化着色器.

解决方案

你应该使用模板缓冲区.2个步骤: 一,在模板上绘制三角形.二、用模板测试绘制立方体.

//您可以多次使用此代码而无需清除模板//只是增加 mask_idmask_id = 1;//允许在蒙版内部或外部绘制反转掩码 = 假;

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) 为立方体配置模板:无写入和测试模板值

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

I have a 3D ball in the browser , now I want to dig a hole on it to see its back.

How can I make it possiable ?

For example, I want the white triangle part of the cube could be transparent(I mean we could see the background behind the cube).

I've tried to change the alpha in fragment shader(the area in the code is a square not triangle, doesn't matter):

<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>

This actually works but the area turns to be white(not transparent), so then I tried to enable blending, but that makes the whole cube transparent.

So now I thought if there's a way to enable bleanding in fragment shader and I could disable it in the else block.

Here's my whole project https://gist.github.com/royguo/5873503:

  • index.html : Shader script here.
  • buffers.js : All obejcts here.
  • shaders.js : Init shaders.

解决方案

You should use stencil buffer. 2 steps: One, draw the triangle on stencil. Two, draw the cube with stencil test.

// 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) Activate stencil buffer. Configure it: no testing and write mask_id value

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

2) Remove color & depth writing

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

3) here draw your triangle :)

4) Enabled depth & color writing for the cube

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

5) Configure stencil for the cube: no writing and test stencil value

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

6) here draw your cube :)

7) cleanup: remove stencil test

glDisable(GL_STENCIL_TEST);

Don't forget to request a stencil when you create your opengl context (see WebGLContextAttributes, second parameter of getContext)

This code run well with Opengl ES 2 on Ios platform. It didn't depend of any extension. WebGL use the same API.

The only small defect: no msaa on triangle borders. There is no free lunch :)

这篇关于WebGL:如何使对象的一部分透明?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆