Почему при отбраковке удаляются грани этого куба, которые не закрыты? - PullRequest
2 голосов
/ 24 августа 2010

Следующий код является модифицированной версией квадратного примера XCode для iPhone, чтобы нарисовать куб. Но когда я использую отбраковку, куб отрисовывается с отсутствующими лицами. Может кто-нибудь сказать мне, что я делаю не так?

#import "ES1Renderer.h"

@implementation ES1Renderer

// Create an OpenGL ES 1.1 context
- (id)init
{
    if ((self = [super init]))
    {
        context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES1];

        if (!context || ![EAGLContext setCurrentContext:context])
        {
            [self release];
            return nil;
        }

        // 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);
        glEnable(GL_CULL_FACE);
        /*glEnable(GL_LIGHTING);
        glEnable(GL_LIGHT0);
        const GLfloat light0Ambient[] = {0.05, 0.05, 0.05, 1.0};
        glLightfv(GL_LIGHT0, GL_AMBIENT, light0Ambient);
        const GLfloat light0Diffuse[] = {0.5, 0.5, 0.5, 1.0};
        glLightfv(GL_LIGHT0, GL_DIFFUSE, light0Diffuse);
        const GLfloat light0Specular[] = {0.7, 0.7, 0.7, 1.0};
        glLightfv(GL_LIGHT0, GL_SPECULAR, light0Specular);
        const GLfloat light0Position[] = {0.0, 0.0, 1.0, 0.0}; 
        glLightfv(GL_LIGHT0, GL_POSITION, light0Position);
        const GLfloat light0Direction[] = {0.0, 0.0, -1.0};
        glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, light0Direction);
        glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, 100.0); */
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        glOrthof(-1.0f, 1.0f, -1.5f, 1.5f, -1.0f, 1.0f);
        glScalef(0.5f, 0.5f, 0.5f);
        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();

    }

    return self;
}

- (void)render
{
    // Replace the implementation of this method to do your own custom drawing

    static const GLfloat squareVertices[] = {
        -0.5f,  -0.5f,   -0.5f, // 0
         0.5f,  -0.5f,   -0.5f, // 1

        -0.5f,   0.5f,   -0.5f, // 2
         0.5f,   0.5f,   -0.5f, // 3

        -0.5f,  -0.5f,    0.5f, // 4
         0.5f,  -0.5f,    0.5f, // 5

        -0.5f,   0.5f,    0.5f, // 6
         0.5f,   0.5f,    0.5f, // 7
    };

    static const GLubyte squareColors[] = {
        255, 0, 0, 255,
        0, 255, 0, 255,
        0, 0, 255, 255,
        255, 255, 255, 255,

        255, 0, 0, 255,
        0, 255, 0, 255,
        0, 0, 255, 255,
        255, 255, 255, 255,
    };

    static const GLubyte triangles [] = {
        0, 1, 2, // front
        1, 3, 2,
        2, 3, 6, // top
        3, 7, 6,
        6, 4, 5, // back
        5, 7, 6,
        4, 0, 1, // bottom
        1, 5, 4,
        4, 0, 2, // left
        2, 6, 4,
        1, 3, 5, // right
        3, 7, 5,
    };

  //  static float transY = 0.0f;

    // This application only creates a single context which is already set current at this point.
    // This call is redundant, but needed if dealing with multiple contexts.
    [EAGLContext setCurrentContext:context];

    // This application only creates a single default framebuffer which is already bound at this point.
    // This call is redundant, but needed if dealing with multiple framebuffers.
    glBindFramebufferOES(GL_FRAMEBUFFER_OES, defaultFramebuffer);
    glViewport(0, 0, backingWidth, backingHeight);


    glRotatef((GLfloat)1.0f, 0.0f, 0.0f, 1.0f);
   // transY++;

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glVertexPointer(3, GL_FLOAT, 0, squareVertices);
    glEnableClientState(GL_VERTEX_ARRAY);
    glColorPointer(4, GL_UNSIGNED_BYTE, 0, squareColors);
    glEnableClientState(GL_COLOR_ARRAY);

    //int n = ((int)[[NSDate date] timeIntervalSince1970])/2;
    glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_BYTE, triangles);


    // This application only creates a single color renderbuffer which is already bound at this point.
    // This call is redundant, but needed if dealing with multiple renderbuffers.
    glBindRenderbufferOES(GL_RENDERBUFFER_OES, colorRenderbuffer);
    [context presentRenderbuffer:GL_RENDERBUFFER_OES];
}

- (BOOL)resizeFromLayer:(CAEAGLLayer *)layer
{   
    // 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);

    if (glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES) != GL_FRAMEBUFFER_COMPLETE_OES)
    {
        NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatusOES(GL_FRAMEBUFFER_OES));
        return NO;
    }

    return YES;
}

- (void)dealloc
{
    // Tear down GL
    if (defaultFramebuffer)
    {
        glDeleteFramebuffersOES(1, &defaultFramebuffer);
        defaultFramebuffer = 0;
    }

    if (colorRenderbuffer)
    {
        glDeleteRenderbuffersOES(1, &colorRenderbuffer);
        colorRenderbuffer = 0;
    }

    // Tear down context
    if ([EAGLContext currentContext] == context)
        [EAGLContext setCurrentContext:nil];

    [context release];
    context = nil;

    [super dealloc];
}

@end

Ответы [ 2 ]

2 голосов
/ 24 августа 2010

посмотрите на первый нарисованный треугольник: его индексы 0,1,2.Попробуйте представить соответствующий треугольник в 3d (или нарисовать его).От центра мира вершины против часовой стрелки;с другой стороны грани они по часовой стрелке.

По умолчанию грани отбраковки граней повернуты по часовой стрелке.

Итак, у вас есть два варианта:

  • Изменить порядок индексов в треугольниках []: 2,1,0, ...
  • Изменить поведение по умолчанию: glCullFace (GL_FRONT);
1 голос
/ 24 августа 2010

Результатом glEnable(GL_CULL_FACE) является не отбор окклюзии, но отбор лица, то есть вы не делаете ничего плохого, все работает, как ожидалось.Для получения дополнительной информации см. http://www.opengl.org/resources/faq/technical/clipping.htm.

Чтобы включить выборку с обратной стороны, вам дополнительно необходимо добавить glCullFace(GL_BACK), см. Запись в Википедии (http://en.wikipedia.org/wiki/Back-face_culling) для получения дополнительной информации.

В качестве отступления: отбор окклюзии в OpenGL обычно выполняется с использованием буфера Z.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...