OpenGLES(三)- GLKit: 多边形纹理、旋转
本文中会省略关于GLKit最基本的API的注释,如果需要详细注释可以看另一篇OpenGLES(二)- 纹理贴图
展示效果
- 在本案例中增加了固定光源,让物体更加逼真。
1. 上下文创建
不同于上文中的GLKView的创建方式。使用这种initWithFrame
方式可以不用依赖GLKViewController。
content = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3];
if(!content){return;}
[EAGLContext setCurrentContext:content];
//GLKView创建
glkView = [[GLKView alloc] initWithFrame:CGRectMake(0, 100, UIScreen.mainScreen.bounds.size.width, UIScreen.mainScreen.bounds.size.height) context:content];
//必须注册代理
glkView.delegate = self;
self.view = glkView;
glkView.drawableColorFormat = GLKViewDrawableColorFormatRGBA8888;
glkView.drawableDepthFormat = GLKViewDrawableDepthFormat24;
glClearColor(0.3, 0.1, 0.7, 1.0f);
//这里相当于翻转 z 轴,使正方形朝屏幕外
glDepthRangef(1, 0);
/*
//默认(0, 1)正方形朝屏幕内
glDepthRangef(0, 1);
*/
2.顶点创建
正方形6个面,每个面由2个三角形组成,所以一共需要36个顶点。
代码语言:javascript复制// 具体36个点的信息就不放出来了
vertexs = malloc(sizeof(HRVertex) * 36);
// 创建帧缓存区
GLuint bufferId;
glGenBuffers(1, &bufferId);
glBindBuffer(GL_ARRAY_BUFFER, bufferId);
glBufferData(GL_ARRAY_BUFFER, sizeof(HRVertex) * 36, vertexs, GL_STATIC_DRAW);
//将顶点、纹理坐标、法线传入顶点着色器
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(HRVertex), NULL offsetof(HRVertex, positionCoord));
glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(HRVertex), NULL offsetof(HRVertex, textureCoord));
glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(HRVertex), NULL offsetof(HRVertex, normal));
- 法线: 垂直于一个平面的向量,可以用于反射光线的计算。法线是通过计算两个向量的叉乘来得到。
- 向量A X 向量B = (AyBz-AzBy,AxBz-AzBx,AxBy-AyBx)
3. 效果器创建、纹理图片加载
代码语言:javascript复制 NSString *file = [[NSBundle mainBundle] pathForResource:@"cat" ofType:@"jpg"];
UIImage *image = [UIImage imageWithContentsOfFile:file];
NSDictionary *option = @{GLKTextureLoaderOriginBottomLeft: @(YES)};
GLKTextureInfo *info = [GLKTextureLoader textureWithCGImage:[image CGImage] options:option error:nil];
effect = [[GLKBaseEffect alloc] init];
effect.texture2d0.enabled = YES;
effect.texture2d0.name = info.name;
effect.texture2d0.target = info.target;
//创建光线
effect.light0.enabled = YES;
//反射光线颜色
effect.light0.diffuseColor = GLKVector4Make(1, 1, 1, 1);
//光源位置
effect.light0.position = GLKVector4Make(-0.5, 0.5, 5, 1);
- baseEffect中可以支持3个默认光源。
4. CADisplayLink创建
代码语言:javascript复制disLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)];
[disLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
-(void)update{
//1.计算旋转度数
angle = (angle 1) % 360;
//2.修改baseEffect.transform.modelviewMatrix,完成旋转的视图变换
effect.transform.modelviewMatrix = GLKMatrix4MakeRotation(GLKMathDegreesToRadians(angle), 0.3, 0.5, 0.7);
//3.重新渲染
[glkView display];
}
5. 代理
代码语言:javascript复制- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
[effect prepareToDraw];
glDrawArrays(GL_TRIANGLES, 0, 36);
}
6. dealloc(销毁)
代码语言:javascript复制- (void)dealloc
{
//displayLink 失效
[disLink invalidate];
disLink = nil;
//重置content
if ([EAGLContext currentContext] == [(GLKView *)self.view context] ) {
[EAGLContext setCurrentContext:nil];
}
//顶点数组重置
if(vertexs){
free(vertexs);
vertexs = nil;
}
}