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:
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 :)
You could render part of the scene without the object (or the objects insides) to a texture and then project the texture onto a surface in front of the object. Just make sure that the surface faces the camera directly (is parallel to the x-y-plane in cam-space) and that the texture is rendered with the same center and perspective as the screen.
Use Learning WebGL: Rendering to Textures if you require help doing this. You should also check the light options to make sure the surface itself isn't affected by the lighting that your object gets.
Also: official WebGL reference sheet
try add these lines
glEnable (GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
It worked for me with OpenGL ES.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With