为了在2D屏幕上出现3D,我们需要在对象上做投影变换。如下图:
这里有一个near平面和far平面,显示的对象在这个之间。离near近的会缩小而变得小,离far近的会放大而变的大。
打开SimpleVertex.glsl,做如下修改:
// Add right before the main
uniform mat4 Projection;
// Modify gl_Position line as follows
gl_Position = Projection * Position;
增加一个uniform关键字的变量 Projection。
注意Projection类型是mat4,mat4表示4*4的矩阵。
这里有一个Cocos3D Math Library files 库。
增加新变量到OpenGLView.h
GLuint _projectionUniform;
OpenGLView.m做些改变
// Add to top of file
#import "CC3GLMatrix.h"
// Add to bottom of compileShaders
_projectionUniform = glGetUniformLocation(programHandle, "Projection");
// Add to render, right before the call to glViewport
CC3GLMatrix *projection = [CC3GLMatrix matrix];
float h = 4.0f * self.frame.size.height / self.frame.size.width;
[projection populateFromFrustumLeft:-2 andRight:2 andBottom:-h/2 andTop:h/2 andNear:4 andFar:10];
glUniformMatrix4fv(_projectionUniform, 1, 0, projection.glMatrix);
// Modify vertices so they are within projection near/far planes
const Vertex Vertices[] = {
{{1, -1, -7}, {1, 0, 0, 1}},
{{1, 1, -7}, {0, 1, 0, 1}},
{{-1, 1, -7}, {0, 0, 1, 1}},
{{-1, -1, -7}, {0, 0, 0, 1}}
};
这里最重要的是导入数学库,并且调用glGetUniformLocation得到需要设置着色器输入变量的句柄。
然后,我们使用数学库创建了一个投影矩阵。
编译和运行程序,你将发现正方形想这个样子!
增加变换和旋转
在SimpleVertex.glsl中增加下面的改变
/ Add right after the Projection uniform
uniform mat4 Modelview;
// Modify the gl_Position line
gl_Position = Projection * Modelview * Position;
你应该很好的理解这个现在!增加另一个输入矩阵,应用这个modeview矩阵给位置。
增加新的实例变量给OpenGLView.h
|
// Add to end of compileShaders
_modelViewUniform = glGetUniformLocation(programHandle, "Modelview");
// Add to render, right before call to glViewport
CC3GLMatrix *modelView = [CC3GLMatrix matrix];
[modelView populateFromTranslation:CC3VectorMake(sin(CACurrentMediaTime()), 0, -7)];
glUniformMatrix4fv(_modelViewUniform, 1, 0, modelView.glMatrix);
// Revert vertices back to z-value 0
const Vertex Vertices[] = {
{{1, -1, 0}, {1, 0, 0, 1}},
{{1, 1, 0}, {0, 1, 0, 1}},
{{-1, 1, 0}, {0, 0, 1, 1}},
{{-1, -1, 0}, {0, 0, 0, 1}}
};
渲染和CADisplayLink
理想的是我们能同步用OpenGL渲染的频率。
// Add new method before init
- (void)setupDisplayLink {
CADisplayLink* displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render:)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
}
// Modify render method to take a parameter
- (void)render:(CADisplayLink*)displayLink {
// Remove call to render in initWithFrame and replace it with the following
[self setupDisplayLink];
CADisplayLink将在每一帧调用你的渲染方法。