GLKView 渲染一张图片

1、OpenGL ES 公共的相初始化

 

// 1、初始化上下文
    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
    
    if(!context) {
        NSLog(@"context 创建失败");
    }
    
    //2、设置当前上下文
    [EAGLContext setCurrentContext:context];
    
    //3、获取GLView
    GLKView *view = (GLKView *)self.view;
    view.context = context;
    
    // 渲染缓冲区
    view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    
    //4、设置背景颜色
    glClearColor(0.3, 0.4, 0.7, 1);

2、加载顶点/纹理相关数据

(1)设置顶点和纹理坐标

(2)开辟顶点缓冲区

(3)顶点数组的数据copy到顶点缓冲区(内存-> 显存),顶点缓冲区 是存在显存中的数据

(4)默认情况下,出于性能考虑,所有定点着色器的属性(Attribute)变量都是关闭的,所以即使使用glBufferData,

(5)设置OpenGL ES读取顶点缓冲区数据的方式

(6)处理纹理坐标-打开纹理坐标通道
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0)

(7)OpenGL ES读取纹理数据的方式

// 设置定点数据
-(void)setUpVertexData
{
    // 定点数据,纹理坐标,都放在一个数组
    // 前面x、y、z(顶点坐标)中心点是(0,0)
    // s、t 纹理坐标  左下角是 (0 0)
    GLfloat vertexData[] = {
        0.5,-0.5, 0.0f,   1.0f,0.0f, //右下
        0.5,0.5, -0.0f,   1.0f,1.0f, //右上
        -0.5,0.5, 0.0f,   0.0f,1.0f, //左上
        
        0.5,-0.5, 0.0f,   1.0f,0.0f, //右下
        -0.5,0.5, 0.0f,   0.0f,1.0f, //左上
        -0.5,-0.5, 0.0f,   0.0f,0.0f, //左下
    };
    
    //2、开辟顶点缓冲区(显存),将顶点数组的数据copy到顶点缓冲区,为了让gpu可以调用得到
    //(1)创建顶点缓存区标识符ID,相当于顶点缓冲区指针
    GLuint bufferID;
    glGenBuffers(1, &bufferID);
    //(2)绑定缓冲区(明确缓冲区的作用 GL_ARRAY_BUFFER 代表存储的是数组)
    glBindBuffer(GL_ARRAY_BUFFER  , &bufferID);
    /**
     3、顶点数组的数据copy到顶点缓冲区(内存-> 显存),顶点缓冲区 是存在显存中的数据
     GL_ARRAY_BUFFER : 明确作用,说明顶点缓冲区是数组缓冲区
     sizeof(vertexData) 说明缓冲区大小
     &vertexData : 指定数据在哪里,把数组内存首地址传递进去
     GL_STATIC_DRAW : 绘制方式为静态绘制
     */
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), &vertexData, GL_STATIC_DRAW);
    
    /**
     * 4、默认情况下,出于性能考虑,所有定点着色器的属性(Attribute)变量都是关闭的,所以即使使用glBufferData,
     * 也没法讲顶点数据从内存拷贝到顶点缓存区中,用了glEnableVertexAttribArray,打开通道,制定访问属性,
     * 才能让定点着色器能够访问到从CPU复制到GPU的数据
     * GLKVertexAttribPosition,  顶点
     * GLKVertexAttribNormal,  法线
     * GLKVertexAttribColor,  颜色值
     * GLKVertexAttribTexCoord0,  纹理1
     * GLKVertexAttribTexCoord  纹理2
     */
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    
    // 5、OpenGL ES读取顶点缓冲区数据的方式
    /**
     glVertexAttribPointer(GLuint indx, <#GLint size#>, <#GLenum type#>, <#GLboolean normalized#>, <#GLsizei stride#>, <#const GLvoid *ptr#>)
     参数1 GLuint indx  所以指定的顶点属性索引值 GLKVertexAttribPosition ...
     参数2 size 每次读取的步长(如position 由3个x、y、z组成,如颜色值由四个 r g b a 组成, 纹理是2个组成: s、t),这个例子是每次读取3个
     参数3 type 数据类型 glfloat
     参数4 normalized 归一化 GL_FALSE
     参数5 stride 偏移量 ,连续顶点属性之间的偏移,,初始值为0
     参数6: ptr 顶点数组读取的首地址,初始值为0
     */
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 5,  0);
    
    // 6、处理纹理坐标-打开纹理坐标通道
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    
    // 7、OpenGL ES读取纹理数据的方式
    //参数6: ptr 纹理数组读取的首地址,从3开始
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 5, (GLfloat *)NULL + 3);
    
}

3、设置纹理相关

// 设置纹理
-(void)setUpTextture
{
    //1获取纹理图片路径
    NSString *filePaht = [[NSBundle mainBundle] pathForResource:@"123456" ofType:@"PNG"];
    // 2、设置纹理相关参数,解决纹理翻转在GLKit里的方法
    //纹理的原点:左下角(0,0);
    //view的原点:左上角(0,0);
    NSDictionary *optioss = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft,nil];
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePaht options:optioss error:nil];
    
    //3、GLBaseEffect 完成着色器工作 ,GLBaseEffect 可以包括三个光照,两个纹理
    cEffect = [[GLKBaseEffect alloc] init];
    cEffect.texture2d0.enabled = GL_TRUE;
    cEffect.texture2d0.name = textureInfo.name;
}

4、 绘制视图内容

// 绘制视图内容
/**
    GLKView 对象使OpenGL ES上下文成为当前上下文,并将其framebuffer绑定为OpenGL ES 呈现命令的目标,然后,委托方法绘制视图的内容
 */
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    //1、清理颜色缓冲区
    glClear(GL_COLOR_BUFFER_BIT);
    
    //2、准备绘制
    [cEffect prepareToDraw];
    
    //3、开始绘制
    //GL_TRIANGLES 图元类型:三角形
    //0 从第0个顶点开始
    //6 6个顶点
    glDrawArrays(GL_TRIANGLES, 0, 6);
}

最后效果图

完整代码:

//
//  ViewController.m
//  GLKitTest01
//
//  Created by kemuchao on 2022/9/3.
//

#import "ViewController.h"
#import <OpenglES/ES3/gl.h>
#import <OpenglES/ES3/glext.h>

@interface ViewController ()
{
    // 管理OpenGL ES 状态
    EAGLContext *context;
    GLKBaseEffect *cEffect;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 1、OpenGL ES 公共的相初始化
    [self setUpConfig];
    
    // 2、加载顶点/纹理相关数据
    [self setUpVertexData];
    
    // 设置纹理相关
    [self setUpTextture];
    
}

// 设置纹理
-(void)setUpTextture
{
    //1获取纹理图片路径
    NSString *filePaht = [[NSBundle mainBundle] pathForResource:@"123456" ofType:@"PNG"];
    // 2、设置纹理相关参数,解决纹理翻转在GLKit里的方法
    //纹理的原点:左下角(0,0);
    //view的原点:左上角(0,0);
    NSDictionary *optioss = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft,nil];
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePaht options:optioss error:nil];
    
    //3、GLBaseEffect 完成着色器工作 ,GLBaseEffect 可以包括三个光照,两个纹理
    cEffect = [[GLKBaseEffect alloc] init];
    cEffect.texture2d0.enabled = GL_TRUE;
    cEffect.texture2d0.name = textureInfo.name;
}

// 设置定点数据
-(void)setUpVertexData
{
    // 定点数据,纹理坐标,都放在一个数组
    // 前面x、y、z(顶点坐标)中心点是(0,0)
    // s、t 纹理坐标  左下角是 (0 0)
    GLfloat vertexData[] = {
        0.5,-0.5, 0.0f,   1.0f,0.0f, //右下
        0.5,0.5, -0.0f,   1.0f,1.0f, //右上
        -0.5,0.5, 0.0f,   0.0f,1.0f, //左上
        
        0.5,-0.5, 0.0f,   1.0f,0.0f, //右下
        -0.5,0.5, 0.0f,   0.0f,1.0f, //左上
        -0.5,-0.5, 0.0f,   0.0f,0.0f, //左下
    };
    
    //2、开辟顶点缓冲区(显存),将顶点数组的数据copy到顶点缓冲区,为了让gpu可以调用得到
    //(1)创建顶点缓存区标识符ID,相当于顶点缓冲区指针
    GLuint bufferID;
    glGenBuffers(1, &bufferID);
    //(2)绑定缓冲区(明确缓冲区的作用 GL_ARRAY_BUFFER 代表存储的是数组)
    glBindBuffer(GL_ARRAY_BUFFER  , &bufferID);
    /**
     3、顶点数组的数据copy到顶点缓冲区(内存-> 显存),顶点缓冲区 是存在显存中的数据
     GL_ARRAY_BUFFER : 明确作用,说明顶点缓冲区是数组缓冲区
     sizeof(vertexData) 说明缓冲区大小
     &vertexData : 指定数据在哪里,把数组内存首地址传递进去
     GL_STATIC_DRAW : 绘制方式为静态绘制
     */
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), &vertexData, GL_STATIC_DRAW);
    
    /**
     * 4、默认情况下,出于性能考虑,所有定点着色器的属性(Attribute)变量都是关闭的,所以即使使用glBufferData,
     * 也没法讲顶点数据从内存拷贝到顶点缓存区中,用了glEnableVertexAttribArray,打开通道,制定访问属性,
     * 才能让定点着色器能够访问到从CPU复制到GPU的数据
     * GLKVertexAttribPosition,  顶点
     * GLKVertexAttribNormal,  法线
     * GLKVertexAttribColor,  颜色值
     * GLKVertexAttribTexCoord0,  纹理1
     * GLKVertexAttribTexCoord  纹理2
     */
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    
    // 5、OpenGL ES读取顶点缓冲区数据的方式
    /**
     glVertexAttribPointer(GLuint indx, <#GLint size#>, <#GLenum type#>, <#GLboolean normalized#>, <#GLsizei stride#>, <#const GLvoid *ptr#>)
     参数1 GLuint indx  所以指定的顶点属性索引值 GLKVertexAttribPosition ...
     参数2 size 每次读取的步长(如position 由3个x、y、z组成,如颜色值由四个 r g b a 组成, 纹理是2个组成: s、t),这个例子是每次读取3个
     参数3 type 数据类型 glfloat
     参数4 normalized 归一化 GL_FALSE
     参数5 stride 偏移量 ,连续顶点属性之间的偏移,,初始值为0
     参数6: ptr 顶点数组读取的首地址,初始值为0
     */
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 5,  0);
    
    // 6、处理纹理坐标-打开纹理坐标通道
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    
    // 7、OpenGL ES读取纹理数据的方式
    //参数6: ptr 纹理数组读取的首地址,从3开始
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GL_FLOAT) * 5, (GLfloat *)NULL + 3);
    
}

// 设置基本配置
-(void)setUpConfig
{
    // 1、初始化上下文
    context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
    
    if(!context) {
        NSLog(@"context 创建失败");
    }
    
    //2、设置当前上下文
    [EAGLContext setCurrentContext:context];
    
    //3、获取GLView
    GLKView *view = (GLKView *)self.view;
    view.context = context;
    
    // 渲染缓冲区
    view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    
    //4、设置背景颜色
    glClearColor(0.3, 0.4, 0.7, 1);
}


// 绘制视图内容
/**
    GLKView 对象使OpenGL ES上下文成为当前上下文,并将其framebuffer绑定为OpenGL ES 呈现命令的目标,然后,委托方法绘制视图的内容
 */
-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
    //1、清理颜色缓冲区
    glClear(GL_COLOR_BUFFER_BIT);
    
    //2、准备绘制
    [cEffect prepareToDraw];
    
    //3、开始绘制
    //GL_TRIANGLES 图元类型:三角形
    //0 从第0个顶点开始
    //6 6个顶点
    glDrawArrays(GL_TRIANGLES, 0, 6);
}


@end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值