2

我正在尝试在 iOS 上学习 OpenGL。我正在关注本教程。

http://www.raywenderlich.com/5235/beginning-opengl-es-2-0-with-glkit-part-2

我确定我仔细按照步骤操作,但是当我走到尽头时,只是在屏幕上看不到任何形状。

https://gist.github.com/seanhess/5356598

我确实看到背景颜色发生了变化,因此 OpenGL 正常工作。只是对 glDrawElements 的调用似乎没有做任何事情。

glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);

他有一些演示代码,但它与您在教程中编写的代码不同,我想在粘贴之前了解为什么这不起作用。

GLKBaseEffect 应该在哪里绘制?我不明白我们是如何实际使用它的。

4

1 回答 1

5

以下似乎是错误的,因为所有顶点都是相同的:

// these are not TRIANGLES, they are vertices
const Vertex Vertices[]  = {
    {{1, -1, 0}, {1, 0, 0, 1}},
    {{1, -1, 0}, {1, 0, 0, 1}},
    {{1, -1, 0}, {1, 0, 0, 1}},
    {{1, -1, 0}, {1, 0, 0, 1}},
};

即使其他一切都是正确的,您的三角形也会退化,因为所有顶点都是重合的。当您固定坐标时,请确保索引以逆时针方式引用顶点,或者,对于您的第一次实验,更好的是,调用

glDisable(GL_CULL_FACE);

在绘图之前。您可以尝试像这样选择顶点:

// these are not TRIANGLES, they are vertices
const Vertex Vertices[]  = {
    {{-.9, -.9, 0}, {1, 0, 0, 1}},
    {{.9, -.9, 0}, {1, 0, 0, 1}},
    {{-.9, .9, 0}, {1, 0, 0, 1}},
    {{.9, .9, 0}, {1, 0, 0, 1}},
};

// These are the trianges. Just reference the vertices
const GLubyte Indices[] = {
    0, 1, 2,
    2, 1, 3
};

编辑

尝试评论更新的第二部分:

/*
// Set the projection matrix of the effect. It defines the field of view
float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 40., 10.0);
self.effect.transform.projectionMatrix = projectionMatrix;

// Rotate about z axis
// the model view matrix is the transform applied to any geometry that the effect renders
GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0, 0, -6);
_rotation += 90 * self.timeSinceLastUpdate;
modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(_rotation), 0, 0, 1);
self.effect.transform.modelviewMatrix = modelViewMatrix;
 */

您定义的矩阵将您的对象置于最终图像之外。当您在屏幕上看不到任何内容时,您首先应该检查的是转换矩阵。在您的情况下,问题在于透视转换:

GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 40., 10.0);

您平移和旋转的对象必须位于此调用的第 3 和第 4 个参数之间的距离才能被绘制,实际上第 3 个参数是所谓的平面的距离,并且必须小于第 4 个参数,远平面。对于这两个参数,一个安全的赌注通常是 1 和 100。

GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 1.0, 100.0);

编辑 2

以下是工作版本。

//
//  HelloGLKitViewController.m
//  OpenGL2Tutorial
//
//  Created by Sean Hess on 4/10/13.
//  Copyright (c) 2013 Sean Hess. All rights reserved.
//

#import "HelloGLKitViewController.h"

typedef struct {
    float Position[3];
    float Color[4];
} Vertex;

// these are not TRIANGLES, they are vertices
const Vertex Vertices[]  = {
    {{-.9, -.9, 0}, {1, 0, 0, 1}},
    {{.9, -.9, 0}, {1, 0, 0, 1}},
    {{-.9, .9, 0}, {1, 0, 0, 1}},
    {{.9, .9, 0}, {1, 0, 0, 1}},
};

// These are the trianges. Just reference the vertices
const GLubyte Indices[] = {
    0, 1, 2,
    2, 1, 3
};


@interface HelloGLKitViewController () {
    GLuint _vertexBuffer;
    GLuint _indexBuffer;
    float _rotation;
    float _currentRed;
    BOOL _increasing;
}

@property (nonatomic, strong) EAGLContext * context;
@property (nonatomic, strong) GLKBaseEffect * effect;
@end

@implementation HelloGLKitViewController

// I think this method just fills the objective-c stuff with the information from my c structs
- (void)setupGL {
    [EAGLContext setCurrentContext:self.context];
    self.effect = [GLKBaseEffect new];

    glGenBuffers(1, &_vertexBuffer); // supposed to be an array of buffers, doing that trick again
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer); // when I say "GL_ARRAY_BUFFER" I mean _vertexBuffer
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
}

- (void)tearDownGL {
    [EAGLContext setCurrentContext:self.context];
    glDeleteBuffers(1, &_vertexBuffer);
    glDeleteBuffers(1, &_indexBuffer);
    self.effect = nil;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    if (!self.context) NSLog(@"FAiled to create ES Context");
    GLKView * view = (GLKView *)self.view;
    view.context = self.context;

    // will automatically pause when interrupted
    self.pauseOnWillResignActive = YES;

    [self setupGL];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
    [self tearDownGL];
}

#pragma mark - GLKViewDelegate

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

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

    // have to call after you change any properties in the effect, before drrawing
    [self.effect prepareToDraw];

    // We don't have to do this again, since we did it above in setupGL
    // They're already bound to GL_ARRAY_BUFFER and GL_ELEMENT_ARRAYBUFFER
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);

    // remember my vertex array contains Vertex(s)
    // so we're telling it how to read it
    // position is 3 floats, the offset is based on that offsetof function
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) offsetof(Vertex, Position));

    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) offsetof(Vertex, Color));

    // 1. pretty much always use triangles
    // 2. the number of vertices to render. tricky way to do .length on array
    // 3. the data type
    // 4. seems like should be pointer to indices. We're using VBOs, so it's already set to the GL_ELEMENT_ARRAY_BUFFER. So give it 0.
    glDrawElements(GL_TRIANGLES, sizeof(Indices)/sizeof(Indices[0]), GL_UNSIGNED_BYTE, 0);

}

- (void)update {
    if (_increasing) {
        _currentRed += 1.0 * self.timeSinceLastUpdate;
    } else {
        _currentRed -= 1.0 * self.timeSinceLastUpdate;
    }
    if (_currentRed >= 1.0) {
        _currentRed = 1.0;
        _increasing = NO;
    }
    if (_currentRed <= 0.0) {
        _currentRed = 0.0;
        _increasing = YES;
    }


    // Set the projection matrix of the effect. It defines the field of view
    float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 1.0, 100.0);
    self.effect.transform.projectionMatrix = projectionMatrix;


    // Rotate about z axis
    // the model view matrix is the transform applied to any geometry that the effect renders
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0, 0, -6);
    _rotation += 90 * self.timeSinceLastUpdate;
    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(_rotation), 0, 0, 1);
    self.effect.transform.modelviewMatrix = modelViewMatrix;

}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    self.paused = !self.paused;

    NSLog(@"timeSinceLastUpdate: %f", self.timeSinceLastUpdate);
    NSLog(@"timeSinceLastDraw: %f", self.timeSinceLastDraw);
    NSLog(@"timeSinceFirstResume: %f", self.timeSinceFirstResume);
    NSLog(@"timeSinceLastResume: %f", self.timeSinceLastResume);
}


@end
于 2013-04-10T17:33:17.957 回答