使用gluPerspective和gluLookAt的奇怪行为

时间:2016-04-24 15:33:30

标签: cocoa opengl perspective depth-buffer

对于一个项目,我需要实现一个NSOpenGLView。我发现了一些资源(教程,苹果文档...)能够启动,但是当我尝试使用gluPerspective和GluLookAt时,我有一些奇怪的行为(我的立方体的顶点是troncated,并且面在彼此之上绘制为如果没有深度缓冲区)。这是我的OpenGLView(NSOpenGLView类)的实现。

Nota 1:我需要我的应用程序与OSX 10.6兼容,这意味着我必须使用OpenGL 2.1。

Nota 2:我无法使用Interface Builder。我需要以编程方式初始化NSOpenGLView。

更新:gluPerspective zNear和zFar,以及gluLookAt眼睛参数已被修改以纠正troncated顶点的问题。但是,面部不能正确绘制的问题仍然存在。以下是图片说明:

Capture01 Capture02

更新2:最后,我通过阅读标题为“#34; OpenGL GL_DEPTH_TEST无法正常工作"”的问题找到了答案。解决方案是:如果要在没有Interface Builder的情况下创建NSOpenGLView,则必须以编程方式设置pixelFormat。我为那些遇到同样问题的人纠正了我的代码。

OpenGLView.m

#import "OpenGLView.h"

@interface OpenGLView ()
{
    NSTimer *updateTimer;
    float cubeRotationAngle;
}
@end

@implementation OpenGLView

-(id)initWithFrame:(NSRect)contentRect pixelFormat:(NSOpenGLPixelFormat *)format
{
    if(self = [super initWithFrame:(NSRect)contentRect  pixelFormat:format])
    {
        [self setFrame:contentRect];

        updateTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0/30.0 target:self selector:@selector(redraw) userInfo:nil repeats:YES] retain];
    [[NSRunLoop currentRunLoop] addTimer:updateTimer forMode:NSRunLoopCommonModes];
    }

    return self;
}

- (void)prepareOpenGL
{
    [[self openGLContext] makeCurrentContext];
}

- (void)drawRect:(NSRect)rect
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, 1.0, 1.0, 10.0);
    glEnable(GL_DEPTH_TEST);

    glClearColor(1, 1, 1, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    GLdouble eyeX = 2.0;
    GLdouble eyeY = 2.0;
    GLdouble eyeZ = 2.0;

    GLdouble targetX = 0.0;
    GLdouble targetY = 0.0;
    GLdouble targetZ = 0.0;

    GLdouble verticalVectorX = 0.0;
    GLdouble verticalVectorY = 0.0;
    GLdouble verticalVectorZ = 1.0;

    gluLookAt(eyeX, eyeY, eyeZ, targetX, targetY, targetZ, verticalVectorX, verticalVectorY, verticalVectorZ);

    cubeRotationAngle = cubeRotationAngle + 0.5;
    glRotatef(cubeRotationAngle, 2.0, 0.5, 0.5);

    float size = 0.4;

    glBegin(GL_QUADS);
    {
        //Blue face
        glColor3f(0, 0, 1);
        glVertex3f(-1*size,  1*size, -1*size);
        glVertex3f( 1*size,  1*size, -1*size);
        glVertex3f( 1*size, -1*size, -1*size);
        glVertex3f(-1*size, -1*size, -1*size);

        //Red face
        glColor3f(1, 0, 0);
        glVertex3f(-1*size, -1*size, -1*size);
        glVertex3f( 1*size, -1*size, -1*size);
        glVertex3f( 1*size, -1*size,  1*size);
        glVertex3f(-1*size, -1*size,  1*size);

        //Green face
        glColor3f(0, 1, 0);
        glVertex3f(-1*size,  1*size,  1*size);
        glVertex3f( 1*size,  1*size,  1*size);
        glVertex3f( 1*size, -1*size,  1*size);
        glVertex3f(-1*size, -1*size,  1*size);

        //Yellow face
        glColor3f(1, 1, 0);
        glVertex3f(-1*size,  1*size,  1*size);
        glVertex3f(-1*size,  1*size, -1*size);
        glVertex3f(-1*size, -1*size, -1*size);
        glVertex3f(-1*size, -1*size,  1*size);

        //Pink face 
        glColor3f(1, 0, 1);
        glVertex3f(-1*size,  1*size,  1*size);
        glVertex3f( 1*size,  1*size,  1*size);
        glVertex3f( 1*size,  1*size, -1*size);
        glVertex3f(-1*size,  1*size, -1*size);

        //light blue face
        glColor3f(0, 1, 1);
        glVertex3f( 1*size,  1*size, -1*size);
        glVertex3f( 1*size,  1*size,  1*size);
        glVertex3f( 1*size, -1*size,  1*size);
        glVertex3f( 1*size, -1*size, -1*size);
    }
    glEnd();
    glPopMatrix();

    glFlush();
}

- (void)redraw
{
    [self setNeedsDisplay:YES];
}

然后你必须像这样实例化OpenGLView:

NSOpenGLPixelFormatAttribute attrs[] = {NSOpenGLPFADepthSize, 32, 0};

NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];

openGLView = [[OpenGLView alloc] initWithFrame:NSMakeRect(20, 20, 760, 560) pixelFormat:format];

1 个答案:

答案 0 :(得分:0)

您的gluPerspective电话无效,因此,只会产生错误并保持当前矩阵不变。 nearfar参数都必须,并且它们也不能相等(因此您的注释值无效)。

这些值定义了近距离和远距离剪裁平面与投影中心的符号距离,因此负值将指代摄像机后面的背后的,这不会有任何意义(和对于与相机平面相交的图元,也会出现一些与剪辑相关的问题。)