From my understanding is that to mirror in OpenGL, you basically draw the scene, then you flip everything over and draw it again, except only make it visible through the mirror, thus creating a perfectly flipped image in the mirror. But the problem I see, is that when doing this, the only mirrors that can see other mirrors are ones rendered after the previous mirrors. So if I render mirror 1 then mirror 2, mirror 1 can't see mirror 2, but mirror 2 can see mirror 1. How do I effectively mirror a mirror without this happening?
问题:
回答1:
There are two common ways to render reflections with multiple/recursive reflections...
Render to a texture and apply that texture to the mirror surface.
An advantage of this is you can use the mirror textures of other mirrors from the previous frame. While this introduces small delay, it doesn't hurt performance when you want to see through many mirrors. If this is an issue you could re-render to the reflection textures a few times before the main camera render.
You can also use this method if the mirror isn't perfectly planar, for example this works well for ripples in water. In fact this can even be extended with cube maps to support approximate arbitrary reflections.
- http://www.bonzaisoftware.com/tnp/gl-water-tutorial/ (overkill for planar reflections, but quite related)
- http://ivanleben.blogspot.com.au/2008/03/water-reflections-with-opengl.html
- http://renderingwonders.wordpress.com/2011/01/03/chapter-08-%E2%80%93-buffer-objects-storage-is-now-in-your-hands-%E2%80%93-fbo-textures/
- http://cgvr.cs.uni-bremen.de/teaching/cg_literatur/Cube_map_tutorial/cube_map.html
Portal rendering where, as you say, use the stencil buffer to mask off the mirror surface, flip the scene around the mirror's plane, and re-render.
Mirror rendering is just a special case of portal rendering. This can be done recursively but it gets quite complicated as you have to manage the depth buffer correctly. You will also need a spatial data structure for your scene, so you don't have to do a full re-render and only render what you can see through the mirror (or it gets very slow very quickly). If you go down this path, I'd suggest taking it slowly and include lots of visual debugging and use a simple and intuitive test scene.
(There are lots of pages on single-reflection stencil buffer use, but this isn't what you're after so I won't bother listing some)
- http://en.wikibooks.org/wiki/OpenGL_Programming/Mini-Portal
- http://en.wikibooks.org/wiki/OpenGL_Programming/Mini-Portal_Recursive
- http://www.fairyengine.com/articles/portals.htm
- http://www.benjaminklingler.com/portal-rendering.html
*Please note these links are just the result of a few minutes googling. Feel free to edit and remove/add.
回答2:
The simplest way is to use the stencil buffer. Check out this page.
The basic idea is:
- You render the surface of the mirror and mark it with 1 .
- You re-render the entrie scene, mirrored by the mirror surface (you can do this with matrices) and only render where the stencil buffer is 1 (Effectively drawing only where the mirror surface was.
- Repeat with different values, or clear the stencil buffer for additional mirrors. If you want to have mirrors reflecting other mirrors you'll need to draw the other mirror surface, mark it with 2 in the stencil buffer, but only where it was 1 alread.
If you have mirrors reflecting mirrors you have to do all the possible combinations (first render mirror 1, then mirror in 2 in mirror 1's reflection, then render mirror 2 in the original scene then mirror 1's reflection in mirror 2's reflection, and so on...).
You can't do infinite mirror reflections with this algorithm (only a limitted amount of reflections). Only ray-tracing can do that.