5

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

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

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

在此处输入图像描述

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

<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:初始化着色器。
4

4 回答 4

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)删除颜色和深度书写

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

于 2013-07-04T23:20:01.257 回答
1

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

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

另外:官方 WebGL 参考表

于 2013-07-01T06:48:10.067 回答
1

尝试添加这些行

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

它对我来说适用于 OpenGL ES。

于 2016-06-29T12:57:11.883 回答
0

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

编辑:

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

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

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

于 2013-06-22T21:28:12.227 回答