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

2023-09-08 10:37:13 作者:懒得起名

我有一个三维球的浏览器,现在我想挖一个洞,就可以看到它的后面。

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

我怎样才能使它possiable?

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

我试着改变片段着色器阿尔法(在code区域是正方形不是三角形,无所谓):

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.

所以,现在我想如果有一种方法,使 bleanding 在片段着色器,我可以在其他块。

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

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

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

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

推荐答案

您应该使用模板缓存。 2个步骤:一,借鉴模板的三角形。二,绘制立方体模板测试。

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)激活模板缓存。配置:无测试和编写mask_id值

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)拆下色和放大器;深度写作

2) Remove color & depth writing

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

3)这里绘制三角形:)

3) here draw your triangle :)

4)启用深度放;颜色写作多维数据集

4) Enabled depth & color writing for the cube

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

5)配置模板多维数据集:没有写作和测试模板值

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)在这里画出你的立方体:)

6) here draw your cube :)

7)清理:清除模板测试

7) cleanup: remove stencil test

glDisable(GL_STENCIL_TEST);

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

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

这code与OpenGL ES的2对iOS平台上运行良好。它不依赖任何扩展。 WebGL的使用相同的API。

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

唯一的小缺点:在三角形的边界没有MSAA。天下没有免费的午餐:)

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