使用OpenGL ES绘制三角形

时间:2012-12-01 19:31:52

标签: objective-c xcode opengl-es background coordinates

首先,对不起我的英语, 我的问题是:

我正在学习OpenGL ES的教程,我必须在屏幕中间画一个三角形。在他们显示的图像中,三角形没有触及屏幕的边缘(我认为这是因为顶点的z坐标)

他们告诉我们要做的顶点是那些坐标:

(0.0,1.0,-3.0) (1.0,0.0,-3.0) (-1.0,0.0,-3.0)

本教程不是最新版本,所以我用个人代码完成了它:

//
//  EAGLView.m
//  OpenGlintro
//
//  Created by Arnaud Miguet on 01/12/12.
//  Copyright (c) 2012 Tap‘n'Develop. All rights reserved.
//

#import "EAGLView.h"

@implementation EAGLView

+ (Class) layerClass {
    return [CAEAGLLayer class];
}

- (void)setupVBOs {

    GLuint vertexBuffer;
    glGenBuffers(1, &vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    GLuint indexBuffer;
    glGenBuffers(1, &indexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);

}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        CAEAGLLayer *EAGLLayer = (CAEAGLLayer *) super.layer;
        EAGLLayer.opaque = YES;

        context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];

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

        glEnable (GL_DEPTH_TEST);

        GLuint framebuffer , renderbuffer;

        glGenBuffers(1, &framebuffer);
        glGenBuffers(1, &renderbuffer);

        glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);

        [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:EAGLLayer];
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbuffer);
        glViewport(10, 0, CGRectGetWidth(frame), CGRectGetHeight(frame));
        [self compileShaders];
        [self setupVBOs];
        [self render];
    }
    return self;
}


- (void)render {
    glClearColor(0.7, 0.7, 0.7, 1.0);


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // 1
    glViewport(0, 0, self.frame.size.width, self.frame.size.height);

    // 2
    glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE,
                          sizeof(Vertex), 0);
    glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE,
                          sizeof(Vertex), (GLvoid*) (sizeof(float) * 3));

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

    [context presentRenderbuffer:GL_RENDERBUFFER];
}

- (GLuint)compileShader:(NSString*)shaderName withType:(GLenum)shaderType {

    // 1
    NSString* shaderPath = [[NSBundle mainBundle] pathForResource:shaderName
                                                           ofType:@"glsl"];
    NSError* error;
    NSString* shaderString = [NSString stringWithContentsOfFile:shaderPath
                                                       encoding:NSUTF8StringEncoding error:&error];
    if (!shaderString) {
        NSLog(@"Error loading shader: %@", error.localizedDescription);
        exit(1);
    }

    // 2
    GLuint shaderHandle = glCreateShader(shaderType);

    // 3
    const char * shaderStringUTF8 = [shaderString UTF8String];
    int shaderStringLength = [shaderString length];
    glShaderSource(shaderHandle, 1, &shaderStringUTF8, &shaderStringLength);

    // 4
    glCompileShader(shaderHandle);

    // 5
    GLint compileSuccess;
    glGetShaderiv(shaderHandle, GL_COMPILE_STATUS, &compileSuccess);
    if (compileSuccess == GL_FALSE) {
        GLchar messages[256];
        glGetShaderInfoLog(shaderHandle, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    }

    return shaderHandle;

}

- (void)compileShaders {

    // 1
    GLuint vertexShader = [self compileShader:@"SimpleVertex"
                                     withType:GL_VERTEX_SHADER];
    GLuint fragmentShader = [self compileShader:@"SimpleFragment"
                                       withType:GL_FRAGMENT_SHADER];

    // 2
    GLuint programHandle = glCreateProgram();
    glAttachShader(programHandle, vertexShader);
    glAttachShader(programHandle, fragmentShader);
    glLinkProgram(programHandle);

    // 3
    GLint linkSuccess;
    glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
    if (linkSuccess == GL_FALSE) {
        GLchar messages[256];
        glGetProgramInfoLog(programHandle, sizeof(messages), 0, &messages[0]);
        NSString *messageString = [NSString stringWithUTF8String:messages];
        NSLog(@"%@", messageString);
        exit(1);
    }

    // 4
    glUseProgram(programHandle);

    // 5
    _positionSlot = glGetAttribLocation(programHandle, "Position");
    _colorSlot = glGetAttribLocation(programHandle, "SourceColor");
    glEnableVertexAttribArray(_positionSlot);
    glEnableVertexAttribArray(_colorSlot);
}

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

const Vertex Vertices[] = {
    {{0.0, 1.0, -2}, {1, 0, 0, 1}},
    {{1.0, 0.0, -2}, {1, 0, 0, 1}},
    {{-1.0, 0.0, 0}, {1, 0, 0, 1}}
};

const GLubyte Indices[] = {
    0,1,2
};
/*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.
 - (void)drawRect:(CGRect)rect
 {
 // Drawing code
 }
 */

@end

但由于在z = -1坐标处绘制的背景,顶点不会出现......有人可以帮助我吗?我找不到任何解决办法...

1 个答案:

答案 0 :(得分:0)

乍一看,似乎你的渲染函数只在viewDidLoad中被调用一次。这应该在具有连续更新的方法中实现,例如drawRect。

OpenGL ES具有非常陡峭的学习曲线,在iOS中,您可以通过实施GLKit框架来帮助自己。它可以为您节省所有对不同类型缓冲区的调用,并为您处理大部分用于绘制/更新功能的样板代码。

本教程是一个非常好的起点: http://www.raywenderlich.com/5223/beginning-opengl-es-2-0-with-glkit-part-1