Swapping between objects or even entire 3D scenes is
something that graphics programmers will always have to deal with. Deciding exactly how to accomplish such a
task leaves room for innovation from not only a visual standpoint but a
technical one as well. Screen fades,
wipes, and dissolve effects are all common forms of transitions used in graphical
programming. For this project I chose to
recreate a dissolve effect and wipe transition in C++ OpenGL using the Stencil
Buffer to control it.
The
Stencil Buffer is an interesting tool that most modern graphics hardware takes
advantage of, it opens the door to a wide variety of effects like the ones I
chose to create as well as much more. The Stencil buffer acts very similarly
like an actual stencil in real world would. OpenGL allows us to directly interact with the
Stencil Buffer manipulating how each pixel show within the effect area will be
affected by it. What this means for us
is we can literally draw out a patter to be displayed through the Stencil
Buffer. But how do we accomplish such a task? It is not as hard as you might
think, but there are definitely a few things to make sure are turned on before
you start to battle with the Stencil Buffer.
By default the Stencil Buffer is
not being used so in order to start manipulating it need to enable it, by
simply calling glEnable(GL_STENCIL_TEST); now that we are using the Stencil Buffer we
need to make sure to clear it out each frame otherwise it will overwrite
itself. By calling
glClear(GL_STENCIL_BUFFER_BIT); we also want to turn off depth and color mask
otherwise the Stencil buffer will interfere with those values when and in this
case we don’t want that to happen so similarly disable them by passing in
GL_FALSE to both.
Now this is where the fun starts,
We want to set up the pattern we want to be seen through the stencil buffer, so
if we were doing a transition the first frame would basically be empty, but as
the transition progressed more and more of the screens design would be drawn
until the other object is fully visible and the first one is gone. We do this by setting the stencil buffer to
always fail everywhere we draw a pixel.
We then draw whatever pattern we want displayed through the stencil
buffer. An example would be in a
shooter, when a bullet it’s a wall they don’t replace the entire texture on the
building or even the model with one that has a bullet hole, no they use the
stencil buffer and choose a few pixels on the wall to reveal the bullet hole
texture through it. We can also use this
to draw interesting shapes and patters like spirals or zig zags. Once we are satisfied with the pattern we drawn
either by pixel using something like glDrawPixels() or possibly a whole object
(to make a star shape or something drawing as you would with any other model)
we then turn off writing to the stencil buffer.
We now set the stencil buffer to pass wherever it did not previously
fail as well as turning back on our depth and color masks so our display
objects are drawn correctly. We now draw
our first object, the one we want to be displayed everywhere the stencil
pattern isn’t. Once that image has been
drawn we set the stencil buffer to only draw where the it previously failed
meaning the second object will only appear where the stencil pattern was drawn.
The image below is a perfect example of what
we are trying to do. The 1’s are where
the stencil buffer was set to fail and the blank spaces is where it
passed. When we draw the objects over
one another we can see based on the value different parts of the red and green
rectangles are revealed.
Congratulations you are now using
the stencil buffer from here, each frame you can change the stencil buffer pattern
to allow more and more of the second object to be seen or hidden based on what
you are trying to accomplish. Those are the basics of how to use the stencil
buffer to switch between, see through, and draw over objects in specific
locations. When creating my two effects
(wipe and dissolve) I used the same basic technique but handled drawing to my
stencil buffer differently.
For the wipe effect I picked a
starting location in this specific example I used bottom left and slowly drew a
larger and larger square expanding outwards until the stencil pattern
completely covered the screen revealing the second object underneath. I could then reverse the process to re reveal
the first object.
The dissolve effect was a little
bit more difficult, I had to gain access to different parts of the screen and
randomly draw pixels into the stencil buffer thus causing random bits of the
object to change until finally the entire screen was covered in stencil buffer
pixels and the second object is revealed.
This gives the impression that the object is dissolving into the second
object as you saw chunks of it slowly switch over until the new object is
visible.
Overall this process allowed me to
gain a much better understanding of how the stencil buffer is used and what
types of effects can be accomplished with them like I mentioned above. It allows us to represent other objects,
color, or patterns without changing textures or swapping out whole models and
makes for great for screen transitions.
The Stencil Buffer is a powerful tool which I will definitely be using
more of, and I hope you will too.
References:
1. Advanced Graphics Programming Using OpenGL By Tom McRynolds, David Blyth (Pages 196-199)
Used for basic tutorial of how to use a Stencil Buffer.
2. http://www.opengl.org/sdk/docs/man2/xhtml/glDrawPixels.xml
How to use glDrawPixels.
3. http://www.opengl.org/sdk/docs/man2/xhtml/glRasterPos.xml
How to use glRasterPos
4. http://psysal.livejournal.com/67933.html
More Stencil Buffer How To.