引子:移動端開發(fā)經(jīng)過這么多年的開發(fā),已經(jīng)越來越成熟了桂对,而且由于網(wǎng)頁端技術(shù)的野蠻發(fā)展甩卓,移動端開發(fā)已經(jīng)越來越式微啦。在這個(gè)環(huán)境下深耕iOS原生和努力掌握大前端技術(shù)棧對于iOS開發(fā)者來說越發(fā)的重要蕉斜∮馐粒基于圖形和視頻技術(shù)的流行趨勢,掌握圖形和視頻的渲染技術(shù)棧也顯得越發(fā)重要宅此。本篇介紹如果在Xcode搭建Open GL 工程机错。
該篇文章簡單的搭建一個(gè)在MAC的OpenGL工程,以及對代碼進(jìn)行解釋
-
新建macOS工程 Xcode --> File --> New --> Project
選擇macOS ---> Application ---> App
-
添加OpenGL.framework和GLUT.framework兩個(gè)系統(tǒng)庫
在General下的Frameworks,Libraries,and Embedded Content下父腕,或者Build Phases下的Link Binary With Libraries下添加OpenGL.framework和GLUT.framework兩個(gè)系統(tǒng)庫
-
導(dǎo)入GLTools弱匪、libGTools.a等文件這里已經(jīng)整理好了。直接把include侣诵、libGTools.a文件拖入工程
文件地址:https://pan.baidu.com/s/1cM8ryabz_hfiqGCJIws5ig 提取碼:tqch
刪除程序入口文件:AppDelegate.h痢法、AppDelegate.m、Main.storyboard杜顺、main.m财搁、viewController.h、viewController.m
-
新建程序入口文件main.cpp
新建c++文件main.cpp作為程序入口文件躬络,不創(chuàng)建header file文件
編寫main.cpp文件繪制一個(gè)圖形
main.cpp文件如下:
#include <stdio.h>
#include "GLTools.h"
/*
GLTool.h頭文件包含了大部分GLTool中類似C語言的獨(dú)立函數(shù)
*/
#include <GLUT/GLUT.h>
/*
在Mac 系統(tǒng)下尖奔,`#include<glut/glut.h>`
在Windows 和 Linux上,我們使用freeglut的靜態(tài)庫版本并且需要添加一個(gè)宏
*/
#include "GLShaderManager.h"
/*
`#include<GLShaderManager.h>` 移入了GLTool 著色器管理器(shader Mananger)類穷当。沒有著色器提茁,我們就不能在OpenGL(核心框架)進(jìn)行著色。著色器管理器不僅允許我們創(chuàng)建并管理著色器馁菜,還提供一組“存儲著色器”茴扁,他們能夠進(jìn)行一些初步?基本的渲染操作。
*/
GLBatch triangleBatch;// 簡單的批次容器汪疮,是GLTools的一個(gè)簡單的容器類峭火。
GLShaderManager shaderManager;// 定義一個(gè)著色管理器
/// 窗口大小改變時(shí)接受新的寬度和高度,其中(0智嚷,0)代表窗口的左下角坐標(biāo)卖丸,w、h代表像素
void changeSize(int w, int h) {
glViewport(0, 0, w, h);
}
/// 做初始花設(shè)置
void setupRC(){
/// 設(shè)置背景顏色
glClearColor(1.f, 1.f, 1.f, 1.f);
/// 初始化著色管理器
shaderManager.InitializeStockShaders();
/// 設(shè)置三角形,其中數(shù)組vVert包含所有3個(gè)頂點(diǎn)的x,y,笛卡爾坐標(biāo)對盏道。
GLfloat vVerts[] = {
-1.f, -1.f, 0.f,
0.5f, 0.f, 0.f,
-0.6f, 0.5f, 0.f
};
/// 批次處理
triangleBatch.Begin(GL_TRIANGLES, 3);
triangleBatch.CopyVertexData3f(vVerts);
triangleBatch.End();
}
/// 開始渲染
void renderScene(void) {
/// 清除一個(gè)或一組特定的緩沖區(qū)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
/// 設(shè)置一組浮點(diǎn)數(shù)表示紅色
GLfloat vRed[] = {1.f, 0.f, 0.f, 1.f};
/// 傳遞到存儲著色器稍浆,即GLT_SHADER_IDENTITY著色器撰茎,這個(gè)著色器只是使用指定顏色以默認(rèn)笛卡爾坐標(biāo)系在屏幕上渲染集合圖形
shaderManager.UseStockShader(GLT_SHADER_IDENTITY, vRed);
/// 提交著色器
triangleBatch.Draw();
/// 將在后臺緩沖區(qū)進(jìn)行渲染沽一,然后再結(jié)束時(shí)交換到前臺
glutSwapBuffers();
}
int main(int argc, char * argv[]) {
/// 設(shè)置當(dāng)前工作目錄,針對MAC OS X,防止在Windows上錯(cuò)誤蹋绽。在Windows中是沒必要的悼嫉。因?yàn)閣indows下默認(rèn)的工作目錄就是與程序可執(zhí)行目錄相同净宵。但是在Mac OS中工作目錄被更改為應(yīng)用程序捆綁中的/Resource文件夾溉箕。
gltSetWorkingDirectory(argv[0]);
/// 初始化GLUT庫,GLUT庫的api在macOS 10.9 已被棄孤钦,但不影響使用
glutInit(&argc, argv);
/// 初始化雙緩存窗口 GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL 分別是:雙緩存窗口歧斟、RGBA顏色模式、深度測試偏形、模板緩沖區(qū)
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
/// GLUT窗口静袖,設(shè)置窗口大小
glutInitWindowSize(800, 800);
/// 設(shè)置窗口標(biāo)題
glutCreateWindow("Triangle");
/// 注冊回調(diào)
glutReshapeFunc(changeSize);// 注冊重塑函數(shù)
glutDisplayFunc(renderScene);// 注冊顯示函數(shù)
/// 驅(qū)動程序的初始化無問題,初始化GLEW庫俊扭,確保OpenGL API對程序完全可用队橙。
GLenum err = glewInit();
if (GLEW_OK != err) {
fprintf(stderr, "glew error: %s\n",glewGetErrorString(err));
return 1;
}
/// 調(diào)用setupRC,設(shè)置渲染環(huán)境
setupRC();
/// 進(jìn)入GLUT事件處理循環(huán)萨惑,讓所有的與“事件”有關(guān)的函數(shù)調(diào)用無限循環(huán)捐康,這里讓整個(gè)繪圖循環(huán)進(jìn)行。它將調(diào)用必要的任何已注冊的回調(diào)
glutMainLoop();
return 0;
}
程序入口main函數(shù)代碼解讀:
- gltSetWorkingDirectory(argv[0])
設(shè)置當(dāng)前工作目錄庸蔼,針對MAC OS X解总,防止在Windows上錯(cuò)誤。在Windows中是沒必要的姐仅。因?yàn)閣indows下默認(rèn)的工作目錄就是與程序可執(zhí)行目錄相同花枫。但是在Mac OS中工作目錄被更改為應(yīng)用程序捆綁中的/Resource文件夾。 - glutInit(&argc, argv)
初始化(OpenGL Utility Toolkit)掏膏,GLUT是一個(gè)很方便的輔助庫劳翰,而且與平臺無關(guān)。GLUT的功能包括窗口和菜單的創(chuàng)建和管理馒疹,事件處理以及提供了很多繪制3D圖形的方法等等佳簸。雖然GLUT庫的api在macOS 10.9 已被棄用但是作為窗口工具在學(xué)習(xí)OpenGL卻是比較方便的 - glutInitDisplayMode(unsigned int mode)
設(shè)置顯示模式的類型mode的類型值可指定單個(gè)或多個(gè)值的組合,在本程序我們選擇GLUT_DOUBLE颖变、GLUT_RGBA生均、GLUT_DEPTH、GLUT_STENCIL
值 | 對應(yīng)宏定義 | 意義 |
---|---|---|
GLUT_RGB | 0x0000 | 指定RGB顏色模式的窗口 |
GLUT_RGBA | 0x0000 | 指定RGBA顏色模式的窗口 |
GLUT_INDEX | 0x0001 | 指定顏色索引模式的窗口 |
GLUT_SINGLE | 0x0000 | 指定單緩存窗口 |
GLUT_DOUBLE | 0x0002 | 指定雙緩存窗口 |
GLUT_ACCUM | 0x0004 | 窗口使用累加緩存 |
GLUT_ALPHA | 0x0008 | 窗口的顏色分量包含 alpha 值 |
GLUT_DEPTH | 0x0010 | 窗口使用深度緩存 |
GLUT_STENCIL | 0x0020 | 窗口使用模板緩存 |
GLUT_MULTISAMPLE | 0x0080 | 指定支持多樣本功能的窗口 |
GLUT_STEREO | 0x0100 | 指定立體窗口 |
GLUT_LUMINANCE | 0x0200 | 窗口使用亮度顏色模型 |
- 窗口參數(shù)設(shè)置:
glutInitWindowSize(800, 800)用來設(shè)置窗口大小
glutCreateWindow("Triangle")設(shè)置窗口的名字 - 注冊回調(diào)函數(shù):
glutReshapeFunc(void (func)(int width, int height));// glutReshapeFunc函數(shù)在調(diào)整窗口大小時(shí)被調(diào)用
glutDisplayFunc(void (func)(void));// glut調(diào)用glutDisplayFunc函數(shù)進(jìn)行渲染 - glewInit()初始化GLEW
(OpenGL Extension Wrangler Library)是用來管理OpenGL的函數(shù)指針的悼做,所以在調(diào)用任何OpenGL的函數(shù)之前我們需要初始化GLEW疯特。初始化失敗就退出程序哗魂。 - setupRC()
在該函數(shù)中進(jìn)行預(yù)加載紋理肛走,建立幾何圖形,渲染器等工作 - glutMainLoop()
進(jìn)入GLUT事件處理循環(huán)录别,讓所有的與“事件”有關(guān)的函數(shù)調(diào)用無限循環(huán)朽色,這里讓整個(gè)繪圖循環(huán)進(jìn)行邻吞。它將調(diào)用必要的任何已注冊的回調(diào)
setupRC函數(shù)解讀:
- glClearColor (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)在顏色緩沖被清空后調(diào)用設(shè)置色值和透明度。
- GLShaderManager:
存儲著色器由GLTools的C++類GLShaderManager管理葫男。
GLShaderManager shaderManager;
shaderManager.InitializeStockShaders();初始化存儲著色管理器 - vVerts:
vVerts中存儲頂點(diǎn)坐標(biāo)抱冷,因?yàn)椴捎玫氖堑芽栕鴺?biāo)系,所以是三個(gè)參數(shù)表示為一個(gè)點(diǎn)梢褐,三個(gè)三處依次為(x,y,z) -
GLBatch:
GLBatch是GL的一個(gè)批次類旺遮,可以簡單的理解為GL的批次處理腳本類。
GLBatch的Begin(GLenum primitive, GLuint nVerts, GLuint nTextureUnits = 0);函數(shù)三個(gè)參數(shù)分別為幾何圖元類型盈咳,頂點(diǎn)坐標(biāo)個(gè)數(shù)和紋理參數(shù)耿眉。其中紋理參數(shù)可為空。該工程我們選擇GL_TRIANGLES鱼响。調(diào)用GLBatch的Begin函數(shù)開始預(yù)處理鸣剪,調(diào)用CopyVertexData3f函數(shù)復(fù)制頂點(diǎn)數(shù)據(jù),最后調(diào)用End函數(shù)結(jié)束
幾何圖元的參數(shù)一共有十種丈积,分別為:
GL_POINTS:點(diǎn)
GL_LINES:線段筐骇,二個(gè)點(diǎn)確定線段
GL_LINE_STRIP:第一個(gè)點(diǎn)依次連接的線段
GL_LINE_LOOP:和GL_LINE_STRIP相同,但首尾連接江滨,形成環(huán)狀
GL_POLYGON:多邊形
GL_QUADS:由四個(gè)點(diǎn)組成一個(gè)四邊形
GL_QUADS_STRIP:四邊形帶
GL_TRIANGLES:三角形铛纬,三個(gè)點(diǎn)確定
GL_TRIANGLE_STRIP:共用一個(gè)條帶上的頂點(diǎn)的一組三角形
GL_TRIANGLE_FAN:以一個(gè)原點(diǎn)為中心呈扇形排列,公共相鄰頂點(diǎn)的一組三角形
renderScene函數(shù)解讀
- glClear (GLbitfield mask)清除viewport的緩沖區(qū)牙寞,可以清空單個(gè)或多個(gè)緩沖區(qū)標(biāo)志為:
GL_COLOR_BUFFER_BIT: 當(dāng)前可寫的顏色緩沖
GL_DEPTH_BUFFER_BIT: 深度緩沖
GL_ACCUM_BUFFER_BIT: 累積緩沖
GL_STENCIL_BUFFER_BIT: 模板緩沖 - UseStockShader(GLT_STOCK_SHADER nShaderID, ...)存儲著色器的種類有很多種饺鹃,在該程序我們使用單位著色器GLT_SHADER_IDENTITY。存儲著色器的種類有:
單位(Identity)著色器---GLT_SHADER_IDENTITY
平面著色器---GLT_SHADER_FLAT
上色(Shaded)著色器---GLT_SHADER_SHADED
默認(rèn)光源著色器---GLT_SHADER_DEFAULT_LIGHT
點(diǎn)光源著色器---GLT_SHADER_DEFAULT_LIGHT
紋理替換矩陣著色器---GLT_SHADER_TEXTURE_REPLACE
紋理調(diào)整著色器---GLT_SHADER_TEXTURE_MODULATE
紋理光源著色器---GLT_SHADER_TEXTURE_POINT_LIGHT_DIFF等 - GLBatch 的 Draw()函數(shù)间雀。提交批次類進(jìn)行繪制
- glutSwapBuffers()悔详。函數(shù)表示雙緩存的后臺渲染完成后可以交換兩個(gè)緩沖區(qū)指針,這樣緩存區(qū)已經(jīng)渲染好的位圖就可以交替的出現(xiàn)在屏幕上了