Java 如何在 OpenGL 中绘制镜像某物的镜子?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20511599/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I draw a mirror mirroring something in OpenGL?
提问by
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 withoutthis happening?
根据我的理解,要在 OpenGL 中进行镜像,您基本上绘制场景,然后将所有内容翻转并再次绘制,除了仅使其通过镜子可见,从而在镜子中创建完美翻转的图像。但我看到的问题是,在执行此操作时,唯一可以看到其他镜子的镜子是在前一个镜子之后渲染的镜子。因此,如果我渲染镜像 1 然后镜像 2,镜像 1 无法看到镜像 2,但镜像 2 可以看到镜像 1。如何有效地镜像镜像而不发生这种情况?
回答by Sorin
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.
- 您渲染镜子的表面并用 1 标记它。
- 您重新渲染由镜面镜像的入口场景(您可以使用矩阵执行此操作)并且仅在模板缓冲区为 1 的位置进行渲染(有效地仅在镜面所在的位置绘制。
- 用不同的值重复,或清除额外镜像的模板缓冲区。如果你想让镜子反射其他镜子,你需要绘制另一个镜子表面,在模板缓冲区中用 2 标记它,但只在它已经是 1 的地方标记。
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...).
如果您有镜子反射镜,则必须进行所有可能的组合(首先渲染镜子 1,然后在镜子 1 的反射中渲染镜子 2,然后在原始场景中渲染镜子 2,然后在镜子 2 的反射中渲染镜子 1 的反射,依此类推。 ...)。
You can't do infinite mirror reflections with this algorithm (only a limitted amount of reflections). Only ray-tracing can do that.
你不能用这个算法做无限的镜面反射(只有有限的反射量)。只有光线追踪才能做到这一点。
回答by jozxyqk
There are two common ways to render reflections withmultiple/recursive reflections...
有两种常见的方法可以使用多重/递归反射来渲染反射......
Render to a textureand 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 renderingwhere, as you say, use the stencil bufferto 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 lotsof 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://www.bonzaisoftware.com/tnp/gl-water-tutorial/(平面反射的矫枉过正,但相当相关)
- 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-纹理/
- http://cgvr.cs.uni-bremen.de/teaching/cg_literatur/Cube_map_tutorial/cube_map.html
门户渲染,如您所说,使用模板缓冲区遮蔽镜面,围绕镜面翻转场景,然后重新渲染。
镜像渲染只是门户渲染的一个特例。这可以递归完成,但它会变得非常复杂,因为您必须正确管理深度缓冲区。您还需要场景的空间数据结构,因此您不必进行完整的重新渲染,只需渲染您可以通过镜子看到的内容(或者它会很快变得非常慢)。如果你沿着这条路走下去,我建议慢慢来,包括大量的可视化调试,并使用一个简单直观的测试场景。
(有很多关于单反射模板缓冲区使用的页面,但这不是你想要的,所以我不会费心列出一些)
*Please note these links are just the result of a few minutes googling. Feel free to edit and remove/add.
*请注意,这些链接只是谷歌搜索几分钟的结果。随意编辑和删除/添加。