简体   繁体   中英

Split object open in shape of another object in OpenGL ES 2.0

Lets say I have a square 'S'. I need to make a circle 'C' go through it in such a way that the S would split open and C would pass through it. Although I need to give it a 3D effect, 2D would also be fine (At least I'll get a head start). Is there a way to do this using some built-in feature or maybe a way to translate individual pixels or a part of an object? I'm not sure how you map a hole inside an object but you could make an object of the hole's shape with the colour of your background to make it look like a hole right? But the real question is how to make the square split open? (The halves would somehow drift apart and then rejoin).

Ok, since "You want the circle to move over time (from frame to frame) and the square to disappear wherever the circle is and once was" , an it's just in 2D, you can use the stencil buffer for this.

The stencil buffer basically stores an integer value for each pixel and lets you change this value and compare it to newly drawn pixels, in order to exclude pixels from drawing. So what we want to do is draw the circle into the stencil buffer (setting it to 1 wherever a circle pixel is) and then draw the square wherever no circle pixel was drawn (wherever the stencil buffer is 0). The only difference to the "usual" stenciling approach is, that we don't clear the stencil buffer in between frames, so that it keeps the circle values wheever the circle once has been. So when you sweep the circle across the screen over time, the square won't be drawn wherever a circle pixel has once been (of course with the same temporal discretization errors like drawn pixels where the circle should have been, but wasn't because it was moved too fast between frames).

So first we draw the circle into the stencil buffer (if you want to use the circle only for stenciling and not draw an actual circle to the screen, you can disable color writes with glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); , but don't forget to reenable color writes afterwards):

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);   //but don't clear stencil

glEnable(GL_STENCIL_TEST);    //use stenciling

glStencilFunc(GL_ALWAYS, 1, -1);    //draw everywhere, use 1 as ref value
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);   //set pixels to ref value (1)
//draw circle

glStencilFunc(GL_NOTEQUAL, 1, -1);    //draw wherever not 1 (no circle pixels)
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);    //leave stencil values unchanged
//draw square

This is just a basic example. You can use the stencil buffer for other things, too. At the moment the circle will change the stencil value no matter if it is behind another already drawn object, but this can be fine-tuned by changing the values in glStencilOp (which configure how to change the stencil value depending on if the stencil test failed, succceeded and depth test failed, or both succeeded), while glStencilFunc controls what test is to be performed and against which reference value (the value of the newly drawn object). But this example and the linked documentation should get you started on the matter.

But still keep in mind that the stencil buffer is really for rather "on-the-fly" image space stenciling operations. If this gets much more complicated and you need to perform actual geometrical operations on your objects, or if this needs to be done in 3D (keyword: Constructive Solid Geometry (CSG) ), then OpenGL is not the right tool for the job and in this case an actual geometry library would be the best idea. All OpenGL does is draw simple things (like points, lines, or triangles) to the screen, nothing else. It is neither a scene management, nor a geometry, nor an image processing library (though it might be "misused" for the latter not that difficultly).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM