2011-07-31 29 views
2

我正在写一个飞行模拟器,并陷入了这个流派的经典问题:视锥体的近平面必须足够近以使飞机驾驶舱可见,远平面必须远离以启用可见距离长达40公里。如何摆脱OpenGL中的z战斗问题?

能见度距离或近/远比例的确超出了opengl的z缓冲精度能力,而远处的物体闪烁剧烈。这是一个花哨的3D引擎让你独自解决问题的地方,你需要真正的opengl知识:)。也许我找到了解决问题的正确方法(如果我错了,OpenGL专家会纠正我),但是我的解决方案忽略了重要的一点。改变渲染器进行双通道渲染:

    在第一遍远处的物体
  1. 和背景必须显示,近平面搬走,Z缓冲是幸福的,地形看起来不错,但近对象剪裁掉。
  2. 在第二阶段中,投影矩阵会针对近距离物体进行调整,并应显示驾驶舱。

的未解决的问题:在第二遍所有远处的物体和背景是不可见的,因此我有驾驶舱和它后面的黑色背景。第二轮的结果完全浪费了第一轮的结果。埃尔戈计划重叠不会发生。问题: 如何强制opengl在第二遍中忽略背景颜色,这样两个通过结果都会创建所需的叠加?

P.S.这是现状的图像(近/远飞机处于极端状态,使所有细节都可见,单程无投影调整)。

http://www.flickr.com/photos/[email protected]/5995604542/sizes/l/in/photostream/

的缓冲器清除每渲染周期和只发生一次,而不是所涉及的2遍之间。这里,清除码:

JoglContext jctx = (JoglContext) ctx; 
GLContext context = context(ctx); 
GL gl = context.getGL(); 
// Mask of which buffers to clear, this always includes color & depth 
int clearMask = GL.GL_DEPTH_BUFFER_BIT | GL.GL_COLOR_BUFFER_BIT; 
gl.glPushAttrib(GL.GL_DEPTH_BUFFER_BIT); 
gl.glDepthMask(true); 
gl.glClearColor(r, g, b, jctx.getAlphaClearValue()); 
gl.glClear(clearMask); 
gl.glPopAttrib(); 

您所描述的方法也用在2次:1。“长途”投影和地形2“短距离”和驾驶舱之间没有信息交换,但是第二后传递驾驶舱后面的背景是黑色的。也许glDepthRange功能帮助,必须检查手册。

zbuffer深度是24位。

回答

6

不要清除两遍之间的屏幕。如果您只想清除深度缓冲区,则清除只需深度缓冲区。不要通过GL_COLOR_BUFFER_BITglClear

在任何情况下,更好的方法来做到这一点(这样你就不必重新渲染所有东西)就是采用适当的深度范围。由于您的驾驶舱无法与场景相交,因此没有理由将其绘制到场景的深度范围内。因此,首先,使用一个合理的透视矩阵(即:一个具有相当大的z-near,几英尺左右的数量级)绘制场景。你的场景不包括你的驾驶舱。该渲染的glDepthRange应该是类似于[0.05,1.0]的东西。

之后,你绘制你的驾驶舱,使用合理的透视矩阵只是驾驶舱。 glDepthRange这是[0,0.05]。这应该会为您提供场景和驾驶舱的深度精度。

哦,并确保你得到一个24位深度缓冲区。

+0

感谢您的及时响应,Nicol。我的评论过于冗长,不得不粘贴到原文中。请仔细看看glDepthRange。 – Paul

2

驾驶舱与外部是模板缓冲区的经典案例,很像HUD与场景。模板的优点是您根本不需要z,因此您可以将近平面设置得更远。另外,你所看到的Windows不会改变(除非你在驾驶舱内旋转你的虚拟头部),所以这是一次画一次重用 - 很多事情。

另外,logarithmic z可能是一个有趣的读取你。

+0

谢谢达蒙,听起来非常有用!如何应用模板缓冲区/ sb函数,然后提供OpenGL初学者的一些提示? – Paul

+0

模板有点令人困惑,因为它不是很明显,你需要做什么,至少这是我第一次看到它。有很多选择。主要功能[glStencilFunc](http://www.opengl.org/sdk/docs/man3/xhtml/glStencilFunc.xml)和[glStencilOp](http://www.opengl.org/sdk/docs/man3/ XHTML/glStencilOp.xml)。你使用'glStencilFunc'来做实际的测试(即丢弃阴影部分),'glStencilOP' _first_来真正地定义模板缓冲区中的内容。 – Damon

+0

您可能希望使用GL_REPLACE模板操作,使用尽可能便宜的着色器(禁用光照/纹理!),然后使用GL_EQUAL模板函数。如果您在绘制驾驶舱时使用z缓冲,则深度失败的GL_KEEP也可能是一个选项(可能会节省一些带宽)。 – Damon