教程
OpenGLES入门教程1-Tutorial01-GLKit
OpenGLES入门教程2-Tutorial02-shader入门
OpenGLES入门教程3-Tutorial03-三维变换
OpenGLES入门教程4-Tutorial04-GLKit进阶
这一次是进阶教程。
代码参考自这本书
OpenGL ES应用开发实践指南 iOS卷
效果展示
核心思路
通过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的是远平面)
总结
这次的代码改自第五章第六个样例,可以学习作者的代码风格,功能分工。
附上源码