OpenGL ES(五) GLKit+立方體貼圖+旋轉(zhuǎn)(另一種方式)

上一章产舞,我們使用純粹的頂點(diǎn)數(shù)據(jù)來(lái)做立方體貼圖旋轉(zhuǎn)琳钉,本章我們換一種思路。

效果

先定義一個(gè)結(jié)構(gòu)體

上一章我們用的是頂點(diǎn)數(shù)組戳表,這兒我們用結(jié)構(gòu)體桶至,把頂點(diǎn)坐標(biāo)和紋理坐標(biāo)區(qū)分開。

typedef struct {
    GLKVector3 positionCoodinate; // 頂點(diǎn)坐標(biāo)
    GLKMatrix2 textureCoodinate; // 紋理坐標(biāo)
    GLKVector3 normal; // 法線(光照)
} MyVertex;

相關(guān)屬性設(shè)置

image.png

配置基本信息

- (void)setupConfig{
    self.context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
    
    // 判斷是否創(chuàng)建成功
    if (!self.context) {
        NSLog(@"Create ES context failed");
        return;
    }
    
    // 設(shè)置當(dāng)前上下文
    [EAGLContext setCurrentContext:self.context];
    
    // GLKView
    CGRect frame = CGRectMake(20, 100, [UIScreen mainScreen].bounds.size.width - 20 * 2, [UIScreen mainScreen].bounds.size.height - 100 * 2);
    self.glkView = [[GLKView alloc] initWithFrame:frame context:self.context];
    self.glkView.delegate = self;
    self.glkView.context = self.context;
    
    self.glkView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
    self.glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
    [self.view addSubview:self.glkView];
    
    glClearColor(0.5, 0.5, 0.5, 1);
}

配置頂點(diǎn)數(shù)據(jù)

- (void)setupVertexData{
    // 開辟空間
    self.vetrexs = malloc(sizeof(MyVertex) * kCoodinateCount);
    
    // 前面
    self.vetrexs[0] = (MyVertex){{-0.5, 0.5, 0.5}, {0, 1}, {0, 0, 1}};
    self.vetrexs[1] = (MyVertex){{-0.5, -0.5, 0.5}, {0, 0}, {0, 0, 1}};
    self.vetrexs[2] = (MyVertex){{0.5, 0.5, 0.5}, {1, 1}, {0, 0, 1}};
    self.vetrexs[3] = (MyVertex){{-0.5, -0.5, 0.5}, {0, 0}, {0, 0, 1}};
    self.vetrexs[4] = (MyVertex){{0.5, 0.5, 0.5}, {1, 1}, {0, 0, 1}};
    self.vetrexs[5] = (MyVertex){{0.5, -0.5, 0.5}, {1, 0}, {0, 0, 1}};
    
    // 上面
    self.vetrexs[6] = (MyVertex){{0.5, 0.5, 0.5}, {1, 1}, {0, 1, 0}};
    self.vetrexs[7] = (MyVertex){{-0.5, 0.5, 0.5}, {0, 1}, {0, 1, 0}};
    self.vetrexs[8] = (MyVertex){{0.5, 0.5, -0.5}, {1, 0}, {0, 1, 0}};
    self.vetrexs[9] = (MyVertex){{-0.5, 0.5, 0.5}, {0, 1}, {0, 1, 0}};
    self.vetrexs[10] = (MyVertex){{0.5, 0.5, -0.5}, {1, 0}, {0, 1, 0}};
    self.vetrexs[11] = (MyVertex){{-0.5, 0.5, -0.5}, {0, 0}, {0, 1, 0}};
    
    // 下面
    self.vetrexs[12] = (MyVertex){{0.5, -0.5, 0.5}, {1, 1}, {0, -1, 0}};
    self.vetrexs[13] = (MyVertex){{-0.5, -0.5, 0.5}, {0, 1}, {0, -1, 0}};
    self.vetrexs[14] = (MyVertex){{0.5, -0.5, -0.5}, {1, 0}, {0, -1, 0}};
    self.vetrexs[15] = (MyVertex){{-0.5, -0.5, 0.5}, {0, 1}, {0, -1, 0}};
    self.vetrexs[16] = (MyVertex){{0.5, -0.5, -0.5}, {1, 0}, {0, -1, 0}};
    self.vetrexs[17] = (MyVertex){{-0.5, -0.5, -0.5}, {0, 0}, {0, -1, 0}};
    
    // 左面
    self.vetrexs[18] = (MyVertex){{-0.5, 0.5, 0.5}, {1, 1}, {-1, 0, 0}};
    self.vetrexs[19] = (MyVertex){{-0.5, -0.5, 0.5}, {0, 1}, {-1, 0, 0}};
    self.vetrexs[20] = (MyVertex){{-0.5, 0.5, -0.5}, {1, 0}, {-1, 0, 0}};
    self.vetrexs[21] = (MyVertex){{-0.5, -0.5, 0.5}, {0, 1}, {-1, 0, 0}};
    self.vetrexs[22] = (MyVertex){{-0.5, 0.5, -0.5}, {1, 0}, {-1, 0, 0}};
    self.vetrexs[23] = (MyVertex){{-0.5, -0.5, -0.5}, {0, 0}, {-1, 0, 0}};
    
    // 右面
    self.vetrexs[24] = (MyVertex){{0.5, 0.5, 0.5}, {1, 1}, {1, 0, 0}};
    self.vetrexs[25] = (MyVertex){{0.5, -0.5, 0.5}, {0, 1}, {1, 0, 0}};
    self.vetrexs[26] = (MyVertex){{0.5, 0.5, -0.5}, {1, 0}, {1, 0, 0}};
    self.vetrexs[27] = (MyVertex){{0.5, -0.5, 0.5}, {0, 1}, {1, 0, 0}};
    self.vetrexs[28] = (MyVertex){{0.5, 0.5, -0.5}, {1, 0}, {1, 0, 0}};
    self.vetrexs[29] = (MyVertex){{0.5, -0.5, -0.5}, {0, 0}, {1, 0, 0}};
    
    // 后面
    self.vetrexs[30] = (MyVertex){{-0.5, 0.5, -0.5}, {0, 1}, {0, 0, -1}};
    self.vetrexs[31] = (MyVertex){{-0.5, -0.5, -0.5}, {0, 0}, {0, 0, -1}};
    self.vetrexs[32] = (MyVertex){{0.5, 0.5, -0.5}, {1, 1}, {0, 0, -1}};
    self.vetrexs[33] = (MyVertex){{-0.5, -0.5, -0.5}, {0, 0}, {0, 0, -1}};
    self.vetrexs[34] = (MyVertex){{0.5, 0.5, -0.5}, {1, 1}, {0, 0, -1}};
    self.vetrexs[35] = (MyVertex){{0.5, -0.5, -0.5}, {1, 0}, {0, 0, -1}};
    
    
    glGenBuffers(1, &_bufferID); // 開辟1個(gè)頂點(diǎn)緩沖區(qū)匾旭,所以傳入1
    NSLog(@"bufferID:%d", _bufferID);
    // 綁定頂點(diǎn)緩沖區(qū)
    glBindBuffer(GL_ARRAY_BUFFER, _bufferID);
    // 緩沖區(qū)大小
    GLsizeiptr bufferSizeBytes = sizeof(MyVertex) * kCoodinateCount;
    // 將頂點(diǎn)數(shù)組的數(shù)據(jù)copy到頂點(diǎn)緩沖區(qū)中(GPU顯存中)
    glBufferData(GL_ARRAY_BUFFER, bufferSizeBytes, self.vetrexs, GL_STATIC_DRAW);
    
    
    // 打開讀取通道
    glEnableVertexAttribArray(GLKVertexAttribPosition); // 頂點(diǎn)坐標(biāo)數(shù)據(jù)
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(MyVertex)/*由于是結(jié)構(gòu)體镣屹,所以步長(zhǎng)就是結(jié)構(gòu)體大小*/, NULL + offsetof(MyVertex, positionCoodinate));
    
    
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0); // 紋理坐標(biāo)數(shù)據(jù)
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(MyVertex), NULL + offsetof(MyVertex, textureCoodinate));
    
    glEnableVertexAttribArray(GLKVertexAttribNormal); // 法線數(shù)據(jù)
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(MyVertex), NULL + offsetof(MyVertex, normal));
}

配置紋理

- (void)setupTexture{
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"png"];
    
    // 初始化紋理
    NSDictionary *options = @{GLKTextureLoaderOriginBottomLeft: @(1)}; // 紋理坐標(biāo)原點(diǎn)是左下角,但是圖片顯示原點(diǎn)應(yīng)該是左上角
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
    
    NSLog(@"textureInfo.name: %d", textureInfo.name);
    
    // 使用蘋果`GLKit`提供的`GLKBaseEffect`完成著色器工作(頂點(diǎn)/片元)
    self.baseEffect = [[GLKBaseEffect alloc] init];
    self.baseEffect.texture2d0.enabled = GL_TRUE;
    self.baseEffect.texture2d0.name = textureInfo.name;
    self.baseEffect.texture2d0.target = textureInfo.target;
    self.baseEffect.light0.enabled = YES; // 開啟光照效果
    self.baseEffect.light0.diffuseColor = GLKVector4Make(1, 1, 1, 1); // 開啟漫反射
    self.baseEffect.light0.position = GLKVector4Make(-0.5, -0.5, 5, 1); // 光源位置
    
    // 透視投影矩陣
    CGFloat aspect = fabs(self.glkView.bounds.size.width / self.glkView.bounds.size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0), aspect, 0.1, 100.0);
    self.baseEffect.transform.projectionMatrix = projectionMatrix;
}

添加定時(shí)器

- (void)addDisplayLink{
    self.angle = 0;
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateScene)];
    [self.displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

更新

- (void)updateScene{
    // 角度變化
    self.angle = self.angle + 2;
    // 修改`baseEffect.transform.modelviewMatrix`
    GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0, 0, -4.0);
    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, GLKMathDegreesToRadians(_angle), 0.3, 0.5, 0.7);
    self.baseEffect.transform.modelviewMatrix = modelViewMatrix;
    
    // 重新渲染
    [self.glkView display];
}

實(shí)現(xiàn)GLKViewDelegate代理

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
    // 開啟深度測(cè)試
    glEnable(GL_DEPTH_TEST);
    
    // 清除顏色緩沖區(qū)、深度緩沖區(qū)
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
    // 準(zhǔn)備繪制
    [self.baseEffect prepareToDraw];
    
    // 開始繪制
    glDrawArrays(GL_TRIANGLES, 0, kCoodinateCount); // 從第一個(gè)開始价涝,所以是0
}![![

](https://upload-images.jianshu.io/upload_images/3238726-be0e7960cd97485b.gif?imageMogr2/auto-orient/strip)
](https://upload-images.jianshu.io/upload_images/3238726-099805b126a459a0.gif?imageMogr2/auto-orient/strip)

ViewDidLoad調(diào)用相關(guān)方法

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor orangeColor];
    
    [self setupConfig];
    [self setupVertexData];
    [self setupTexture];
    [self addDisplayLink];
}

最后女蜈,不要忘了在dealloc里面做銷毀工作

- (void)dealloc{
    if ([EAGLContext currentContext] == self.glkView.context) {
        [EAGLContext setCurrentContext:nil];
    }
    
    if (self.vetrexs) {
        free(self.vetrexs);
        self.vetrexs = nil;
    }
    
    if (_bufferID) {
        glDeleteBuffers(1, &_bufferID);
        _bufferID = 0;
    }
    
    [self.displayLink invalidate];
}

Demo

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子伪窖,更是在濱河造成了極大的恐慌逸寓,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,039評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件覆山,死亡現(xiàn)場(chǎng)離奇詭異竹伸,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)簇宽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,426評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門勋篓,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人魏割,你說(shuō)我怎么就攤上這事譬嚣。” “怎么了见妒?”我有些...
    開封第一講書人閱讀 165,417評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)甸陌。 經(jīng)常有香客問(wèn)我须揣,道長(zhǎng),這世上最難降的妖魔是什么钱豁? 我笑而不...
    開封第一講書人閱讀 58,868評(píng)論 1 295
  • 正文 為了忘掉前任耻卡,我火速辦了婚禮,結(jié)果婚禮上牲尺,老公的妹妹穿的比我還像新娘卵酪。我一直安慰自己,他們只是感情好谤碳,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,892評(píng)論 6 392
  • 文/花漫 我一把揭開白布溃卡。 她就那樣靜靜地躺著,像睡著了一般蜒简。 火紅的嫁衣襯著肌膚如雪瘸羡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,692評(píng)論 1 305
  • 那天搓茬,我揣著相機(jī)與錄音犹赖,去河邊找鬼。 笑死卷仑,一個(gè)胖子當(dāng)著我的面吹牛峻村,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播锡凝,決...
    沈念sama閱讀 40,416評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開眼粘昨,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起雾棺,我...
    開封第一講書人閱讀 39,326評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤膊夹,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后捌浩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體放刨,經(jīng)...
    沈念sama閱讀 45,782評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,957評(píng)論 3 337
  • 正文 我和宋清朗相戀三年尸饺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了进统。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,102評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡浪听,死狀恐怖螟碎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情迹栓,我是刑警寧澤掉分,帶...
    沈念sama閱讀 35,790評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站克伊,受9級(jí)特大地震影響酥郭,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜愿吹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,442評(píng)論 3 331
  • 文/蒙蒙 一不从、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧犁跪,春花似錦椿息、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,996評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至枫耳,卻和暖如春倡勇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背嘉涌。 一陣腳步聲響...
    開封第一講書人閱讀 33,113評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工妻熊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人仑最。 一個(gè)月前我還...
    沈念sama閱讀 48,332評(píng)論 3 373
  • 正文 我出身青樓扔役,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親警医。 傳聞我的和親對(duì)象是個(gè)殘疾皇子亿胸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,044評(píng)論 2 355