什么是Opengles?
OpenGL ES(OpenGL for Embedded Systems)是 OpenGL 三维图形API的子集,针对手机、PDA和游戏主机等嵌入式设备而设计,各显卡制造商和系统制造商来实现这组 API。
Opengles与EGL的联系
EGL是OpenGL ES渲染API和本地窗口系统之间的一个中间接口层,它主要有系统制造商实现。EGL提供如下机制:
- 与设备的原生窗口系统通信
- 查询绘图表面的可用类型和配置
- 创建绘图表面
- 在OpenGL ES和其他图形渲染API之前同步渲染
- 管理纹理贴图等渲染资源
Opengles的基本使用流程
- 设置上下文
-(void)setupGLContext{
//初始化渲染上下文,管理所有绘制的状态,命令及资源信息
_eaglContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
//设置为当前上下文
if(![EAGLContext setCurrentContext:_eaglContext]){
NSLog(@"opengl setcontext failure");
}
}
- 创建CAEAGLLayer
- 直接创建CAEAGLLayer
_eaglLayer = [CAEAGLLayer layer];
_eaglLayer.frame = CGRectMake(0, 0, 320, 320);//self.view.frame;
_eaglLayer.opaque = YES;
[self.view.layer addSublayer:_eaglLayer];
- 重写View的layerClass方法
+ (Class)layerClass{
return [CAEAGLLayer class];
}
3、创建framebuffer、renderBuffer及关联
RenderBuffer是一块存储图像数据的内存区域,包括颜色附件,深度附件,模板附件。
FrameBuffer是一个聚合结构,相当于一个结构体,里面有颜色,深度附件,模板附件等,需要关联其他渲染缓冲区(RenderBuffer或纹理)。
-(void)setupRenderAndFrameBuffer{
glGenRenderbuffers(1, &_colorRenderBuffer);
//设置为当前renderBuffer
glBindRenderbuffer(GL_RENDERBUFFER, _colorRenderBuffer);
//renderbuffer 分配存储空间
if(!([_eaglContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:_eaglLayer])){
NSLog(@"renderbufferstorage failure");
}
int _backingWidth;
int _backingHeight;
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &_backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &_backingHeight);
NSLog(@"GL_RENDERBUFFER_WIDTH:%d GL_RENDERBUFFER_HEIGHT:%d", _backingWidth, _backingHeight);
//FBO用于管理colorRenderBUffer,离屏渲染
glGenFramebuffers(1, &_frameBuffer);
glBindFramebuffer(GL_FRAMEBUFFER, _frameBuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, _colorRenderBuffer);
}
- 创建顶点着色器及片源着色器
着色器是用GLSL语法编写的。
顶点着色器
attribute vec4 Position;
void main(void){
gl_Position = Position;
}
片元着色器
precision mediump float;
void main(void){
gl_FragColor = vec4(1.0,0.0,0.0,1.0);
}
5、构建program及编译shader
-(void)compileShaders{
//生成一个定点着色器对象
GLuint vertexShader = [self compileShader:@"SimpleVextex" withType:GL_VERTEX_SHADER];
//生产一个片元着色器对象
GLuint fragmentShader = [self compileShader:@"SimpleFragment" withType:GL_FRAGMENT_SHADER];
GLuint programHandle = glCreateProgram();
glAttachShader(programHandle, vertexShader);
glAttachShader(programHandle, fragmentShader);
glLinkProgram(programHandle);
//着色器对象链接到程序对象后,删除找色器对象
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
GLint linkSuccess;
glGetProgramiv(programHandle, GL_LINK_STATUS, &linkSuccess);
if(linkSuccess == GL_FALSE){
GLchar message[256];
NSString *messageString = [NSString stringWithUTF8String:message];
NSLog(@"着色器程序:%@", messageString);
exit(1);
}
glUseProgram(programHandle);
self.position = glGetAttribLocation(programHandle, "Position");
}
-(GLuint)compileShader:(NSString*)shaderName withType:(GLenum)shaderType{
NSString *shaderPath = [[NSBundle mainBundle] pathForResource:shaderName ofType:@"glsl"];
NSError *error;
NSString *shaderString = [NSString stringWithContentsOfFile:shaderPath encoding:NSUTF8StringEncoding error:&error];
GLuint shader = glCreateShader(shaderType);
const char* shaderStringUTF8 = [shaderString UTF8String];
int shaderStringLength = (int)shaderString.length;
glShaderSource(shader, 1, &shaderStringUTF8, &shaderStringLength);
glCompileShader(shader);
GLint compileZSuccess;
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileZSuccess);
if(compileZSuccess == GL_FALSE){
GLchar message[256];
NSString *messageString = [NSString stringWithUTF8String:message];
NSLog(@"生成着色器对象:%@", messageString);
exit(1);
}
return shader;
}
6、设置视窗大小
glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
int width = _eaglLayer.frame.size.width;
int height = _eaglLayer.frame.size.height;
glViewport(0, 0, width, height);
7、绘制
定义顶点数组,存入顶点缓冲区对象中,然后传入顶点数据,最后绘制。
-(void)renderUsingIndexVBO{
const GLfloat vertices[] ={
0.5f, 0.5f, 0.0f,
0.5f, -0.5f, 0.0f,
-0.5f, -0.5f, 0.0f,
-0.5f, 0.5f, 0.0f
};
const GLubyte indices[] = {
0,1,3,
1,2,3
};
//创建定点缓冲区
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
//创建索引
GLuint indexBuffer;
glGenBuffers(1, &indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
//传递定点数据
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(0);
// glDrawArrays(GL_TRIANGLES, 0, 3);
//根据索引绘制
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, 0);
}
8、显示
if(![_eaglContext presentRenderbuffer:GL_RENDERBUFFER]){
NSLog(@"presentRenderbuffer failure");
}
基本流程介绍完毕,再调试中碰到错误,可以调用glError来调试具体的错误。
demo地址 提取码: is5u