1

我有一个使用 OpenGL ES 完成的 3D iPhone 游戏。

这是一个很大的世界,但是我需要近距离绘制一些微小的第一人称视角位,因此我无法减小 glFrustumf() 进一步扩展的深度范围(zNear 与 zFar)。

当表面相遇以进行 Z 战斗时,我将它们稍微分开以防止它们闪烁。在有用和需要的情况下,我还让相机的距离决定了我调整它们的距离。

大部分都可以,但是有些东西的透视会受到分离的影响,并且使分离变小会导致闪烁。我很想把表面涂得更近。

有什么办法可以提高深度缓冲精度,这样表面就可以在没有更窄深度范围的情况下靠得更近?

如果没有,有没有其他方法可以解决这个问题?

我仍在应用程序中使用 OpenGL ES 1.1,但如果值得,我愿意升级。

谢谢你的帮助。


这是我创建深度缓冲区的方法...

在初始化方法中:

// Create default framebuffer object. The backing will be allocated for the current layer in -resizeFromLayer
glGenFramebuffersOES(1, &defaultFramebuffer);
glGenRenderbuffersOES(1, &colorRenderbuffer);
glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER_OES, colorRenderbuffer);

//Added depth buffer
glGenRenderbuffersOES(1, &depthRenderbuffer);
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glFramebufferRenderbufferOES(GL_FRAMEBUFFER_OES, GL_DEPTH_ATTACHMENT_OES, GL_RENDERBUFFER_OES, depthRenderbuffer);

在 resizeFromLayer 方法中:

// Allocate color buffer backing based on the current layer size
glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER_OES fromDrawable:layer];
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_WIDTH_OES, &backingWidth);
glGetRenderbufferParameterivOES(GL_RENDERBUFFER_OES, GL_RENDERBUFFER_HEIGHT_OES, &backingHeight);

//Added depth buffer
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);

这是我创建截锥体的方法...

const GLfloat  zNear = 2.2;
const GLfloat  zFar = 30000;
const GLfloat  fieldOfView = 60.0;
GLfloat size = zNear * tanf(degreesToRadian(fieldOfView) / 2.0);

if (LANDSCAPE) { //for landscape clip & aspect ratio.
    //parameters are: left, right, bottom, top, near, far
    glFrustumf(-size/(backingWidth/backingHeight),
               size/(backingWidth/backingHeight),
               -size, size,
               zNear, zFar);
}
4

3 回答 3

0

显然 OpenGL ES 1.x 不支持 32 位深度缓冲区。

此外,iOS 似乎不支持 16 位深度缓冲区,所以使用GL_DEPTH_COMPONENT16_OES只是表现为 24 位,这就是为什么我在使用时没有看到任何改进的原因GL_DEPTH_COMPONENT24_OES

GL_DEPTH_BITS我在尝试将深度缓冲区设置为 16 位后通过检查确认了这一点:

glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES, GL_DEPTH_COMPONENT16_OES, backingWidth, backingHeight);

GLint depthBufferBits;
glGetIntegerv(GL_DEPTH_BITS, &depthBufferBits );
NSLog(@"Depth buffer bits: %d", depthBufferBits );

输出:

Depth buffer bits: 24

哦,好吧,至少现在我知道了。希望这对其他人有帮助。

于 2013-01-29T20:59:33.817 回答
0

标准答案围绕使用glPolygonOffset. 这样做是在与缓冲区中已有的值进行比较之前,为多边形深度值添加一个偏移量。偏移量的计算考虑了屏幕深度和角度,因此它与您的世界的大小无关,并且不会影响要绘制的像素的身份。

问题是决定何时使用它。例如,如果您的场景是许多离散对象,没有统一的广泛数据结构(例如四叉树或 BSP 树),那么您可能必须使用桶系统之类的东西来发现对象非常接近(相对到他们的距离)并给更近的地方一个碰撞。如果问题是单个网格的内部问题,并且您没有更高级别的结构,那么显然问题会更复杂。

另一方面,如果您的场景完全或绝大多数是静态的,那么像 BSP 树这样的结构甚至可以在不需要深度缓冲区的情况下完成大部分绘图,这可能是一个优势。在绝望的最后,您可以使用深度书写从前到后渲染,但不进行比较,然后将移动的对象作为额外的层;在实践中,这会给你大量的透支(尽管 PVS 解决方案会有所帮助)与现代早期深度剔除的前后对比——尤其是在像 PowerVR 这样的基于延迟切片的渲染器上——所以这又不是一个容易的胜利。

作为一个单独的想法,有什么方法可以简化遥远的几何?

于 2013-01-29T21:35:38.210 回答
0

对我有用的是调整远近值。远近值之间的差异定义了深度缓冲区的精确程度。举个例子。假设您有 10000 的远距离和 500 的近距离。总深度为:9500 使用 16 位 DepthBuffer,您有 65536 种可能的深度组合。(根据 GPU 和 OpenGl 实现,这个值是用不同的几何图形计算的)然后每个空间单位大约有 65536/9500 ~= 7 个可能的深度。然后您将获得 1/7 ~= .14 的深度精度。如果您的对象之间的距离为 0.14 或更小,您可能会遇到 z-fighting。在现实生活中,这更复杂,但想法是一样的。

也许您的远值太长而您不需要它。增加近值也有助于在更靠近相机的物体(更可见的物体)中进行 z-fighting。

于 2013-05-09T21:47:30.557 回答