OpenGL ES 渲染立體圖形

来源:https://www.cnblogs.com/lybSkill/archive/2018/12/05/10069233.html
-Advertisement-
Play Games

一、理解 頂點數據存儲在申請的緩衝區中,其由數據匯流排傳遞給著色器(如果是片元著色器,還須將頂點轉換成片元),再由著色器最終渲染到塗層上; 二、思路 1.設置塗層; 2.創建上下文; 3.清空緩存區; 4.創建渲染緩存區和幀緩存區; 5.開始繪製; 三、核心代碼 //最終渲染 四、效果 GitHub ...


一、理解

頂點數據存儲在申請的緩衝區中,其由數據匯流排傳遞給著色器(如果是片元著色器,還須將頂點轉換成片元),再由著色器最終渲染到塗層上;

二、思路

1.設置塗層;

 2.創建上下文;

 3.清空緩存區;

 4.創建渲染緩存區和幀緩存區;

 5.開始繪製;

三、核心代碼

//最終渲染

- (void)renderLayer
{
    //設置視窗背景顏色
    glClearColor(0.0, 0.0, 0.0, 1.0);
    //清空顏色緩存
    glClear(GL_COLOR_BUFFER_BIT);
    //設置視口大小
    CGFloat scale = [[UIScreen mainScreen] scale];
    glViewport(self.frame.origin.x*scale, self.frame.origin.y*scale, self.frame.size.width*scale, self.frame.size.height*scale);
    
    //讀取頂點和片元著色器程式
    NSString *vertFile = [[NSBundle mainBundle] pathForResource:@"shaderv" ofType:@"glsl"];
    NSString *fragFile = [[NSBundle mainBundle] pathForResource:@"shaderf" ofType:@"glsl"];
    NSLog(@"vertFile:%@", vertFile);
    NSLog(@"fragFile:%@", fragFile);
    
    //判斷myProgram是否存在,存在則清空
    if (self.myProgram) {
        glDeleteProgram(self.myProgram);
        self.myProgram = 0;
    }
    
    //載入著色器到myProgram中
    self.myProgram = [self loadShader:vertFile frag:fragFile];
    
    //創建鏈接
    glLinkProgram(self.myProgram);
    GLint linkSuccess;
    
    //獲取鏈接狀態
    glGetProgramiv(self.myProgram, GL_LINK_STATUS, &linkSuccess);
    
    //判斷鏈接是否成功
    if (linkSuccess == GL_FALSE) {
        //獲取失敗信息
        GLchar message[256];
        glGetProgramInfoLog(self.myProgram, sizeof(message), 0, &message[0]);
        //c字元串轉換成oc字元串
        NSString *messageString = [NSString stringWithUTF8String:message];
        NSLog(@"error:%@", messageString);
        return;
    } else {
        //使用myProgram
        glUseProgram(self.myProgram);
    }
    
    //創建繪製索引數組
    GLuint indices[] = {
        0, 3, 2,
        0, 1, 3,
        0, 2, 4,
        0, 4, 1,
        2, 3, 4,
        1, 4, 3
    };
    
    //判斷頂點緩存區是否為空,為空則申請一個緩存區標誌符
    if (self.myVertices == 0) {
        glGenBuffers(1, &_myVertices);
    }
    
    //----------處理頂點坐標---------
    
    /*頂點數據
     1.前3個坐標值(x、y、z),後3個顏色值(RGB);
     2.有先後順序,否則繪製形狀完全不同
     */
    GLfloat attrArr[] =
    {
        -0.5f, 0.5f, 0.0f,      1.0f, 0.0f, 1.0f, //左上
        0.5f, 0.5f, 0.0f,       1.0f, 0.0f, 1.0f, //右上
        -0.5f, -0.5f, 0.0f,     1.0f, 1.0f, 1.0f, //左下
        0.5f, -0.5f, 0.0f,      1.0f, 1.0f, 1.0f, //右下
        0.0f, 0.0f, 1.0f,       0.0f, 1.0f, 0.0f, //頂點
    };
    
    //將_myVertices綁定到GL_ARRAY_BUFFER標誌符上
    glBindBuffer(GL_ARRAY_BUFFER, _myVertices);
    //把頂點坐標數據從CPU複製到GPU上
    glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_DYNAMIC_DRAW);
    
    //將頂點坐標數據通過myProgram傳遞到頂點著色器程式的position
    
    //獲取頂點屬性入口
    GLuint position = glGetAttribLocation(self.myProgram, "position");
    /*傳遞數據
     1.一行6個數據,前3個為坐標,後3個為顏色;
     2.NULL開始位置:預設為0,指向數組首地址;
     */
    glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, NULL);
    //設置合適的格式從緩存區中讀取數據
    glEnableVertexAttribArray(position);
    
    //處理頂點顏色數據:傳遞到頂點著色器的positionColor
    GLuint positionColor = glGetAttribLocation(self.myProgram, "positionColor");
    glVertexAttribPointer(positionColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, (float *)NULL +3);
    glEnableVertexAttribArray(positionColor);
    
    //在myProgram中找到透視投影矩陣和模型視圖矩陣
    GLuint projectionMatrixSlot = glGetUniformLocation(self.myProgram, "projectionMatrix");
    GLuint modelViewMatrixSlot = glGetUniformLocation(self.myProgram, "modelViewMatrix");
    
    //創建透視投影矩陣並初始化
    float width = self.frame.size.width;
    float height = self.frame.size.height;
    KSMatrix4 _projectionMatrix;
    ksMatrixLoadIdentity(&_projectionMatrix);
    float aspect = width/height;
    ksPerspective(&_projectionMatrix, 30.0, aspect, 5.0f, 20.0f);
    
    //設置glsl裡面的投影矩陣
    glUniformMatrix4fv(projectionMatrixSlot, 1, GL_FALSE, (GLfloat *)&_projectionMatrix.m[0][0]);
    
    //開啟剔除功能
    glEnable(GL_CULL_FACE);
    
    //創建平移矩陣:Z軸平移-10
    KSMatrix4 _modelViewMatrix;
    ksMatrixLoadIdentity(&_modelViewMatrix);
    ksTranslate(&_modelViewMatrix, 0.0, 0.0, -10.0);
    
    //創建旋轉矩陣
    KSMatrix4 _rotationMatrix;
    ksMatrixLoadIdentity(&_rotationMatrix);
    ksRotate(&_rotationMatrix, xDegree, 1.0, 0.0, 0.0);
    ksRotate(&_rotationMatrix, yDegree, 0.0, 1.0, 0.0);
    ksRotate(&_rotationMatrix, zDegree, 0.0, 0.0, 1.0);
    
    //將平移矩陣和旋轉矩陣相乘,結果放到模型視圖矩陣中
    ksMatrixMultiply(&_modelViewMatrix, &_rotationMatrix, &_modelViewMatrix);
    
    //設置glsl裡面的模型視圖矩陣
    glUniformMatrix4fv(modelViewMatrixSlot, 1, GL_FALSE, (GLfloat *)&_modelViewMatrix.m[0][0]);
    
    //設置繪製參數:片元、個數、索引數組
    glDrawElements(GL_TRIANGLES, sizeof(indices)/sizeof(indices[0]), GL_UNSIGNED_INT, indices);
    
    //由頂點著色器將緩存區中的數據渲染到顯示塗層上
    [self.myContext presentRenderbuffer:GL_RENDERBUFFER];
}

四、效果

 

以上是採用GLSL自定義著色器繪製,下麵是採用GLKit框架並添加紋理來繪製

//核心代碼

- (void)renderLayer
{
    //頂點數據:前3個坐標(x、y、z),中間三個顏色(RGB),最後2個坐標(紋理)
    GLfloat attrArr [] = {
        -0.5, 0.5, 0.0,   0.0, 0.0, 0.5,   0.0, 1.0,
        0.5, 0.5, 0.0,    0.0, 0.5, 0.0,   1.0, 1.0,
        -0.5, -0.5, 0.0,  0.5, 0.0, 0.0,   0.0, 0.0,
        0.5, -0.5, 0.0,   0.0, 0.0, 0.5,   1.0, 0.0,
        0.0, 0.0, 1.0,     1.0, 1.0, 1.0,   0.5, 0.5
    };
    
    //繪圖索引
    GLuint indices[] =
    {
        0, 3, 2,
        0, 1, 3,
        0, 2, 4,
        0, 4, 1,
        2, 3, 4,
        1, 4, 3,
    };
    
    //頂點個數
    self.count = sizeof(indices)/sizeof(GLuint);
    
    //頂點數據存入緩存區:CPU->GPU
    GLuint buffer;
    glGenBuffers(1, &buffer);
    glBindBuffer(GL_ARRAY_BUFFER, buffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_STATIC_DRAW);
    
    //索引數據存入緩存區:CPU->GPU
    GLuint index;
    glGenBuffers(1, &index);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
    
    //傳遞頂點數據到著色器指定位置
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, NULL);
    
    //頂點顏色數據
    glEnableVertexAttribArray(GLKVertexAttribColor);
    glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, (GLfloat *)NULL + 3);
    
    //頂點紋理數據
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, (GLfloat *)NULL + 6);
    
    //載入紋理
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"cTest" ofType:@"jpg"];
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@"1", GLKTextureLoaderOriginBottomLeft, nil];
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
    
    self.mEffect = [[GLKBaseEffect alloc] init];
    self.mEffect.texture2d0.enabled = GL_TRUE;
    self.mEffect.texture2d0.name = textureInfo.name;
    
    //創建透視投影矩陣
    CGSize size = self.view.bounds.size;
    float aspect = fabs(size.width/size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1, 10.0);
    //設置等比縮放
    projectionMatrix = GLKMatrix4Scale(projectionMatrix, 1.0, 1.0, 1.0);
    
    self.mEffect.transform.projectionMatrix = projectionMatrix;
    
    //設置平移:Z軸負方向平移2.0
    GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0, 0.0, -2.0);
    self.mEffect.transform.modelviewMatrix = modelViewMatrix;
    
    //設置定時器
    double seconds = 0.1;
    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, seconds*NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(timer, ^{
        self.xDegree += 0.1*self.XB;
        self.yDegree += 0.1*self.YB;
        self.zDegree += 0.1*self.ZB;
    });
    dispatch_resume(timer);
}

 

效果:

 

GitHub


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 下麵是我從網上摘取的一段話:(視頻下載) (全部書籍)i1974年,在IBM公司聖約瑟研究實驗室研製的大型關係資料庫管理 系統SYSTEM中,使用SEQUEL語言(由BOYCE 和CHAMBERLIN 提出),後來在SEQUEL 的基礎上發展了SQL語言。 SQL語言是一種互動式查詢語言,允許用戶直 ...
  • 什麼是DBMS,什麼是資料庫?(視頻下載) (全部書籍)馬克-to-win:DBMS (database management system 資料庫管理系統)像mysql,oracle,sql server之類,首先沒什麼神秘的,都只是某個公司編的一個軟體而已,比如mysql是MySQL AB公司編 ...
  • 接下來你可以學習Linux,java和linux是學習大數據的基礎,學不分先後。Linux因為大數據相關軟體都是在Linux上運行的,所以Linux要學習的扎實一些,學好Linux對你快速掌握大數據相關技術會有很大的幫助,能讓你更好的理解hadoop、hive、hbase、spark等大數據軟體的運 ...
  • 今天使用navicat向MySQL中插入中文時,報錯: 在我自己資料庫設計之初,沒有設計好字元編碼格式的問題。 使用如下語句解決: ...
  • Redis五大數據類型 補充:常用命令 Ping ping下redis Dbsize 查看當前資料庫的key的數量 Select 1 切換到下標為1的資料庫中 Flushdb 清空當前庫key Flushall 清空全部庫key Redis鍵的操作(常用): 查看當前資料庫的所有key: Keys ...
  • 提示: 由於企業裡面做Redis開發,99%都是Linux版的運用和安裝, 幾乎不會涉及到Windows版,windows安裝只是為了學習而已了。 Windows版安裝 (1) 到https://github.com/dmajkic/redis/downloads 下去下載windows版本下的re ...
  • Redis是什麼? 是完全開源免費的,用C語言編寫的,遵守BSD協議,是一個高性能的(key/value)分散式記憶體資料庫,基於記憶體運行,並支持持久化的NoSQL資料庫,是當前最熱門的NoSql資料庫之一,也被人們稱為數據結構伺服器。 redis.io 是 redis 的官網 Redis 與其他 k ...
  • 報錯一: Attempted to transition from state `RESPONDER_INACTIVE_PRESS_IN` to `RESPONDER_ACTIVE_LONG_PRESS_IN`, which is not supported. This is most likely ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...