教程
OpenGL ES入門(mén)教程1-Tutorial01-GLKit
OpenGL ES入門(mén)教程2-Tutorial02-shader入門(mén)
OpenGL ES入門(mén)教程3-Tutorial03-三維變換
這次我們用GLKit,更簡(jiǎn)單的實(shí)現(xiàn)圖形變換合搅、紋理貼圖樟插、著色睬关、深度測(cè)試(代碼在這)。
OpenGL ES系列教程在這里曙寡。
OpenGL ES系列教程的代碼地址 - 你的star和fork是我的源動(dòng)力绿店,你的意見(jiàn)能讓我走得更遠(yuǎn)。
效果展示
核心思路
使用GLKit來(lái)進(jìn)行圖形變換拖吼、紋理貼圖加載、深度測(cè)試这吻,用GLKBaseEffect來(lái)管理紋理貼圖和進(jìn)行著色吊档。
具體細(xì)節(jié)
1、頂點(diǎn)屬性
typedef NS_ENUM(GLint, GLKVertexAttrib)
{
GLKVertexAttribPosition,
GLKVertexAttribNormal,
GLKVertexAttribColor,
GLKVertexAttribTexCoord0,
GLKVertexAttribTexCoord1
} NS_ENUM_AVAILABLE(10_8, 5_0);
GLKEffects用到的頂點(diǎn)屬性已經(jīng)定義好唾糯,使用時(shí)直接用枚舉量賦值籍铁。如下圖涡上,直接對(duì)頂點(diǎn)的位置趾断、顏色拒名、紋理坐標(biāo)進(jìn)行賦值。
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 8, (GLfloat *)NULL);
//頂點(diǎn)顏色
glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 3, GL_FLOAT, GL_FALSE, 4 * 8, (GLfloat *)NULL + 3);
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 4 * 8, (GLfloat *)NULL + 6);
2芋酌、紋理
在自定義shader中使用紋理增显,需要用CoreGraphics把圖像轉(zhuǎn)換成bitmapdata,再申請(qǐng)紋理內(nèi)存脐帝,把圖像數(shù)據(jù)傳進(jìn)去同云,最后還要釋放bitmapdata。
在GLKit中堵腹,僅僅需要如下三行代碼炸站,就可以完成紋理的加載。
//紋理
NSString* filePath = [[NSBundle mainBundle] pathForResource:@"for_test" ofType:@"png"];
NSDictionary* options = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft, nil];
GLKTextureInfo* textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
GLKTextureLoaderOriginBottomLeft
參數(shù)是避免紋理上下顛倒疚顷,原因是紋理坐標(biāo)系和世界坐標(biāo)系的原點(diǎn)不同旱易。
最后創(chuàng)建著色器,啟用紋理腿堤,把剛剛創(chuàng)建的textureInfo的name賦值給著色器阀坏。
//著色器
self.mEffect = [[GLKBaseEffect alloc] init];
self.mEffect.texture2d0.enabled = GL_TRUE;
self.mEffect.texture2d0.name = textureInfo.name;
3、圖形變換
在OpenGL ES里面笆檀,圖形變換的表現(xiàn)形式就是矩陣操作忌堂,GLKit也提供了很多矩陣操作函數(shù)。
//初始的投影
CGSize size = self.view.bounds.size;
float aspect = fabs(size.width / size.height);
GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(90.0), aspect, 0.1f, 10.f);
projectionMatrix = GLKMatrix4Scale(projectionMatrix, 1.0f, 1.0f, 1.0f);
self.mEffect.transform.projectionMatrix = projectionMatrix;
GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);
self.mEffect.transform.modelviewMatrix = modelViewMatrix;
GLKMatrix4MakePerspective
是透視投影變換
GLKMatrix4Translate
是平移變換
/**
* 場(chǎng)景數(shù)據(jù)變化
*/
- (void)update {
GLKMatrix4 modelViewMatrix = GLKMatrix4Translate(GLKMatrix4Identity, 0.0f, 0.0f, -2.0f);
modelViewMatrix = GLKMatrix4RotateX(modelViewMatrix, self.mDegreeX);
modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, self.mDegreeY);
modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, self.mDegreeZ);
self.mEffect.transform.modelviewMatrix = modelViewMatrix;
}
在場(chǎng)景變換函數(shù)里面酗洒,GLKMatrix4RotateY
是繞Y軸旋轉(zhuǎn)士修,其他的分分別是繞X、Z軸旋轉(zhuǎn)樱衷。
4棋嘲、深度測(cè)試
在前面的教程介紹過(guò),開(kāi)啟深度測(cè)試需要分配深度測(cè)試的緩沖區(qū)箫老,并掛載到相應(yīng)的幀緩沖區(qū)封字。
在GLKit代碼中,深度測(cè)試的開(kāi)啟十分簡(jiǎn)單耍鬓。
在新建上下文時(shí)調(diào)用glEnable(GL_DEPTH_TEST);
開(kāi)啟深度測(cè)試阔籽。
//新建OpenGL ES 上下文
self.mContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
GLKView* view = (GLKView *)self.view;
view.context = self.mContext;
view.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
[EAGLContext setCurrentContext:self.mContext];
glEnable(GL_DEPTH_TEST);
在渲染場(chǎng)景時(shí),glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClear參數(shù)加入GL_DEPTH_BUFFER_BIT
即可牲蜀。
/**
* 渲染場(chǎng)景代碼
*/
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
[self.mEffect prepareToDraw];
glDrawElements(GL_TRIANGLES, self.mCount, GL_UNSIGNED_INT, 0);
}
總結(jié)
OpenGL ES的入門(mén)已經(jīng)差不多笆制,后面還有很多很多知識(shí),需要時(shí)再學(xué)習(xí)即可涣达。
總結(jié)這幾篇教程花了一個(gè)星期左右在辆。
學(xué)習(xí)過(guò)程中有幾部分最難受:
- 第一部分是OpenGL ES的頂點(diǎn)屬性证薇、紋理貼圖,對(duì)頂點(diǎn)到圖形的過(guò)程不理解匆篓,對(duì)OpenGL ES的數(shù)據(jù)緩存機(jī)制不了解浑度,無(wú)知容易使人知難而退;
- 第二部分是shader和glsl鸦概,glsl無(wú)法調(diào)試箩张、編譯信息不會(huì)查看、語(yǔ)法不懂等等窗市,一個(gè)1.0 + 1都會(huì)報(bào)錯(cuò)先慷,自己卻莫名其妙,只能通過(guò)二分注釋代碼來(lái)定位問(wèn)題咨察,特別讓人泄氣论熙;
- 第三部分是OpenGL ES的三維圖形變換和光照等,這部分更多的是數(shù)學(xué)知識(shí)和物理知識(shí)摄狱,代碼一般都很簡(jiǎn)單脓诡;這部分比前面的都難,但是因?yàn)橹滥睦锶笔Ф叮m然不懂誉券,但是不慌,只是有點(diǎn)難受刊愚。
最后的感想踊跟,計(jì)算機(jī)圖形學(xué)和線(xiàn)性代數(shù)畢竟是基礎(chǔ),自己多花點(diǎn)時(shí)間學(xué)習(xí)鸥诽,培養(yǎng)為核心競(jìng)爭(zhēng)力非常不錯(cuò)商玫。