Opengles的基本认识

什么是Opengles?

OpenGL ES(OpenGL for Embedded Systems)是 OpenGL 三维图形API的子集,针对手机、PDA和游戏主机等嵌入式设备而设计,各显卡制造商和系统制造商来实现这组 API。

Opengles与EGL的联系

EGL是OpenGL ES渲染API和本地窗口系统之间的一个中间接口层,它主要有系统制造商实现。EGL提供如下机制:

  • 与设备的原生窗口系统通信
  • 查询绘图表面的可用类型和配置
  • 创建绘图表面
  • 在OpenGL ES和其他图形渲染API之前同步渲染
  • 管理纹理贴图等渲染资源
33333.jpg

Opengles的基本使用流程

  1. 设置上下文
-(void)setupGLContext{
    //初始化渲染上下文,管理所有绘制的状态,命令及资源信息
    _eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    //设置为当前上下文
    if(![EAGLContext setCurrentContext:_eaglContext]){
        NSLog(@"opengl setcontext failure");
    }
}
  1. 创建CAEAGLLayer
  • 直接创建CAEAGLLayer
    _eaglLayer = [CAEAGLLayer layer];
    _eaglLayer.frame = CGRectMake(0, 0, 320, 320);//self.view.frame;
    _eaglLayer.opaque = YES;
    [self.view.layer addSublayer:_eaglLayer];
  • 重写View的layerClass方法
+ (Class)layerClass{
    return [CAEAGLLayer class];
}

3、创建framebuffer、renderBuffer及关联
RenderBuffer是一块存储图像数据的内存区域,包括颜色附件,深度附件,模板附件。
FrameBuffer是一个聚合结构,相当于一个结构体,里面有颜色,深度附件,模板附件等,需要关联其他渲染缓冲区(RenderBuffer或纹理)。

-(void)setupRenderAndFrameBuffer{
    glGenRenderbuffers(1, &_colorRenderBuffer);
    //设置为当前renderBuffer
    glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
    //renderbuffer 分配存储空间
    if(!([_eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer])){
        NSLog(@"renderbufferstorage failure");
    }
    int _backingWidth;
    int _backingHeight;
    
    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth);

    glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
    NSLog(@"GL_RENDERBUFFER_WIDTH:%d GL_RENDERBUFFER_HEIGHT:%d", _backingWidth, _backingHeight);
    //FBO用于管理colorRenderBUffer,离屏渲染
    glGenFramebuffers(1, &_frameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);

}
  1. 创建顶点着色器及片源着色器
    着色器是用GLSL语法编写的。
    顶点着色器
attribute vec4 Position;
void main(void){
    gl_Position = Position;
}

片元着色器

precision mediump float;

void main(void){
    gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}

5、构建program及编译shader

-(void)compileShaders{
    //生成一个定点着色器对象
    GLuint vertexShader = [self compileShader:@"SimpleVextex" withType:GL_VERTEX_SHADER];
    //生产一个片元着色器对象
    GLuint fragmentShader = [self compileShader:@"SimpleFragment" withType:GL_FRAGMENT_SHADER];
    GLuint programHandle = glCreateProgram();
    glAttachShader(programHandle, vertexShader);
    glAttachShader(programHandle, fragmentShader);
    glLinkProgram(programHandle);
    //着色器对象链接到程序对象后,删除找色器对象
    glDeleteShader(vertexShader);
    glDeleteShader(fragmentShader);
    
    GLint linkSuccess;
    glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
    if(linkSuccess == GL_FALSE){
        GLchar message[256];
        NSString *messageString = [NSString stringWithUTF8String:message];
        NSLog(@"着色器程序:%@", messageString);
        exit(1);
    }
    
    glUseProgram(programHandle);
    self.position = glGetAttribLocation(programHandle, "Position");
}

-(GLuint)compileShader:(NSString*)shaderName withType:(GLenum)shaderType{
    NSString *shaderPath = [[NSBundle mainBundle] pathForResource:shaderName ofType:@"glsl"];
    NSError *error;
    NSString *shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:&error];
    
    GLuint shader = glCreateShader(shaderType);
    const char* shaderStringUTF8 = [shaderString UTF8String];
    int shaderStringLength = (int)shaderString.length;
    
    glShaderSource(shader, 1, &shaderStringUTF8, &shaderStringLength);
    glCompileShader(shader);
    
    GLint compileZSuccess;
    glGetShaderiv(shader, GL_COMPILE_STATUS, &compileZSuccess);
    if(compileZSuccess == GL_FALSE){
        GLchar message[256];
        NSString *messageString = [NSString stringWithUTF8String:message];
        NSLog(@"生成着色器对象:%@", messageString);
        exit(1);
    }
    return shader;
}

6、设置视窗大小

    glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);
    int width  = _eaglLayer.frame.size.width;
    int height = _eaglLayer.frame.size.height;
    glViewport(0, 0, width, height);

7、绘制
定义顶点数组,存入顶点缓冲区对象中,然后传入顶点数据,最后绘制。

-(void)renderUsingIndexVBO{
    const GLfloat vertices[] ={
        0.5f, 0.5f, 0.0f,
        0.5f, -0.5f, 0.0f,
        -0.5f, -0.5f, 0.0f,
        -0.5f, 0.5f, 0.0f
    };
    
    const GLubyte indices[] = {
        0,1,3,
        1,2,3
    };
    
    //创建定点缓冲区
    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);
    
    //传递定点数据
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);
//    glDrawArrays(GL_TRIANGLES, 0, 3);
    //根据索引绘制
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
}

8、显示

    if(![_eaglContext presentRenderbuffer:GL_RENDERBUFFER]){
        NSLog(@"presentRenderbuffer failure");
    }

基本流程介绍完毕,再调试中碰到错误,可以调用glError来调试具体的错误。
demo地址 提取码: is5u

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容