教程
OpenGLES入門教程1-Tutorial01-GLKit
OpenGLES入門教程2-Tutorial02-shader入門
OpenGLES入門教程3-Tutorial03-三維變換
OpenGLES入門教程4-Tutorial04-GLKit進階
這一次是進階教程。
代碼參考自這本書
OpenGL ES應用開發實踐指南 iOS卷
iOS.png
效果展示
地球和月亮
核心思路
通過AGLKVertexAttribArrayBuffer類管理頂點數組,sphere.h獲取地球和月亮的頂點、法線、紋理坐標,用矩陣棧操作矩陣,通過正視投影變換和透視投影變換進行投影。
具體細節
1、AGLKElementIndexArrayBuffer類
AGLKElementIndexArrayBuffer是頂點緩存管理類
GLsizeiptr 類型就是long
GLsizei 類型是int32_t
核心函數
- 創建頂點緩存數組
- (id)initWithAttribStride:(GLsizeiptr)aStride
numberOfVertices:(GLsizei)count
bytes:(const GLvoid *)dataPtr
usage:(GLenum)usage;
- 重新緩存頂點數組
- (void)reinitWithAttribStride:(GLsizeiptr)aStride
numberOfVertices:(GLsizei)count
bytes:(const GLvoid *)dataPtr;
- 分配頂點數據
通過glVertexAttribPointer
設置頂點數據
- (void)prepareToDrawWithAttrib:(GLuint)index
numberOfCoordinates:(GLint)count
attribOffset:(GLsizeiptr)offset
shouldEnable:(BOOL)shouldEnable
- 繪制
+ (void)drawPreparedArraysWithMode:(GLenum)mode
startVertexIndex:(GLint)first
numberOfVertices:(GLsizei)count;
2、sphere.h球體
球體的頂點坐標數組、法線數組、紋理坐標數組,直接使用即可。
3、矩陣棧
把矩陣MatrixA放入棧中緩存,然后對矩陣進行操作,得到新的矩陣MatrixB;
最后把矩陣出棧,可以得到原始矩陣MatrixA。
是對矩陣的緩存作用,在有矩陣有多個狀態時很方便。
具體看下面矩陣數值的變化:
//地球
- (void)drawEarth
{
self.baseEffect.texture2d0.name = self.earthTextureInfo.name;
self.baseEffect.texture2d0.target = self.earthTextureInfo.target;
/*
current matrix:
1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 -5.000000 1.000000
*/
GLKMatrixStackPush(self.modelviewMatrixStack);
GLKMatrixStackRotate(
self.modelviewMatrixStack,
GLKMathDegreesToRadians(SceneEarthAxialTiltDeg),
1.0, 0.0, 0.0);
/*
current matrix:
1.000000 0.000000 0.000000 0.000000
0.000000 0.917060 0.398749 0.000000
0.000000 -0.398749 0.917060 0.000000
0.000000 0.000000 -5.000000 1.000000
*/
GLKMatrixStackRotate(
self.modelviewMatrixStack,
GLKMathDegreesToRadians(self.earthRotationAngleDegrees),
0.0, 1.0, 0.0);
/*
current matrix:
0.994522 0.041681 -0.095859 0.000000
0.000000 0.917060 0.398749 0.000000
0.104528 -0.396565 0.912036 0.000000
0.000000 0.000000 -5.000000 1.000000
*/
self.baseEffect.transform.modelviewMatrix =
GLKMatrixStackGetMatrix4(self.modelviewMatrixStack);
[self.baseEffect prepareToDraw];
[AGLKVertexAttribArrayBuffer
drawPreparedArraysWithMode:GL_TRIANGLES
startVertexIndex:0
numberOfVertices:sphereNumVerts];
/*
current matrix:
0.994522 0.041681 -0.095859 0.000000
0.000000 0.917060 0.398749 0.000000
0.104528 -0.396565 0.912036 0.000000
0.000000 0.000000 -5.000000 1.000000
*/
GLKMatrixStackPop(self.modelviewMatrixStack);
/*
current matrix:
1.000000 0.000000 0.000000 0.000000
0.000000 1.000000 0.000000 0.000000
0.000000 0.000000 1.000000 0.000000
0.000000 0.000000 -5.000000 1.000000
*/
self.baseEffect.transform.modelviewMatrix =
GLKMatrixStackGetMatrix4(self.modelviewMatrixStack);
}
4、變換
GLKMatrix4MakeFrustum
是透視投影變換
GLKMatrix4MakeOrtho
是正視投影變換
if([aControl isOn])
{
self.baseEffect.transform.projectionMatrix =
GLKMatrix4MakeFrustum(
-1.0 * aspectRatio,
1.0 * aspectRatio,
-1.0,
1.0,
2.0,
120.0);
// self.baseEffect.transform.projectionMatrix =
// GLKMatrix4MakePerspective(1.0, aspectRatio, 1.0, 50.0);
}
else
{
self.baseEffect.transform.projectionMatrix =
GLKMatrix4MakeOrtho(
-1.0 * aspectRatio,
1.0 * aspectRatio,
-1.0,
1.0,
1.0,
120.0);
}
透視投影的六個參數如下圖
透視投影
投影是在近平面。(和視線焦點距離為near的是近平面,far的是遠平面)
珍藏圖-參悟投影變換的核心
總結
這次的代碼改自第五章第六個樣例,可以學習作者的代碼風格,功能分工。
附上源碼