OpenGL(全写Open Graphics Library)是个定义了一个跨编程语言、跨平台的编程接口规格的专业的图形程序接口。
OpenGL可以直接把RGB/RGBA的数据直接写入纹理中,利用纹理在窗口上进行贴图。然而我们知道从解码得到的数据基本上都不是RGB的,而是yuv的像素格式,比较常见的有YV12、NV12等。yuv可以通过软件计算转成RGB格式,然后进行贴图,这是一种很低效率的方式。比较好的做法是,通过GLSL着色器在GPU上进行像素格式转换。
虽然OpenGL是跨平台的,但是显示窗口和OpenGL的绑定,这个是不提供的。在iOS上可以自己实现,也可以继承Apple封装好的GLKView,本文就是采用继承GLKView的方式进行绘图。
@interface ShowView : GLKView
@end
使用的时候可以直接将UIView的class选择为ShowView,当然也可以给UIView添加一个ShowView成为其subview。
-(id)initWithFrame:(CGRect)frame
{
m_bHasInit = false;
self = [super initWithFrame:frame];
if(self)
{
m_glSimpleProgram = 0;
m_pBuffer = NULL;
m_nWidth = 0;
m_nHeight = 0;
// Initialization code
if(self.context == NULL)
{
self.context = [[EAGLContext alloc]
initWithAPI:kEAGLRenderingAPIOpenGLES2];
}
// Make the new context current
[EAGLContext setCurrentContext:self.context];
// Create a base effect that provides standard OpenGL ES 2.0
// Shading Language programs and set constants to be used for
// all subsequent rendering
self.baseEffect = [[GLKBaseEffect alloc] init];
self.baseEffect.useConstantColor = GL_TRUE;
self.baseEffect.constantColor = GLKVector4Make(
1.0f, // Red
1.0f, // Green
1.0f, // Blue
1.0f);// Alpha
[self GlInitialize];
tex_y = glGetUniformLocation(m_glSimpleProgram, "SamplerY");
[self CheckGlError:"glGetUniformLocation"];
tex_u = glGetUniformLocation(m_glSimpleProgram, "SamplerU");
[self CheckGlError:"glGetUniformLocation"];
tex_v = glGetUniformLocation(m_glSimpleProgram, "SamplerV");
[self CheckGlError:"glGetUniformLocation"];
m_bHasInit = true;
}
else
{
printf("error\n");
}
return self;
}
创建并编译链接着色器程序。
OpenGL的初始化,编译指定的着色器程序,为后续的画图的上传纹理时能够GPU像素转换。
-(void)GlInitialize
{
if(m_bHasInit)
{
return;
}
m_pBuffer = NULL;
m_glSimpleProgram = [self BuildProgram:VERTEX_SHADER ShaderSource:FRAG_SHADER];
glUseProgram(m_glSimpleProgram);
}
画图函数
- (void)drawRect:(CGRect)rect
{
// Drawing code
[self.baseEffect prepareToDraw];
if(!m_bHasInit)
{
return;
}
glUseProgram(m_glSimpleProgram);
glBindAttribLocation(m_glSimpleProgram, ATTRIB_VERTEX, "vPosition");
[self CheckGlError:"glBindAttribLocation"];
glBindAttribLocation(m_glSimpleProgram, ATTRIB_TEXTURE, "a_texCoord");
[self CheckGlError:"glBindAttribLocation"];
glActiveTexture(GL_TEXTURE0);
glUniform1i(tex_y, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_LUMINANCE,
m_nWidth,
m_nHeight,
0,
GL_LUMINANCE,
GL_UNSIGNED_BYTE,
m_pBuffer);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE1);
glUniform1i(tex_u, 1);
glBindTexture(GL_TEXTURE_2D, 1);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_LUMINANCE,
m_nWidth / 2,
m_nHeight / 2,
0,
GL_LUMINANCE,
GL_UNSIGNED_BYTE,
m_pBuffer + m_nWidth * m_nHeight * 5 / 4);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glActiveTexture(GL_TEXTURE2);
glUniform1i(tex_v, 2);
glBindTexture(GL_TEXTURE_2D, 2);
glTexImage2D(GL_TEXTURE_2D,
0, GL_LUMINANCE,
m_nWidth / 2,
m_nHeight / 2,
0,
GL_LUMINANCE,
GL_UNSIGNED_BYTE,
m_pBuffer + m_nWidth * m_nHeight);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, squareVertices);
[self CheckGlError:"glVertexAttribPointer ATTRIB_VERTEX"];
glEnableVertexAttribArray(ATTRIB_VERTEX);
[self CheckGlError:"glEnableVertexAttribArray ATTRIB_VERTEX"];
glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, coordVertices);
[self CheckGlError:"glVertexAttribPointer ATTRIB_TEXTURE"];
glEnableVertexAttribArray(ATTRIB_TEXTURE);
[self CheckGlError:"glEnableVertexAttribArray ATTRIB_TEXTURE"];
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[self CheckGlError:"glDrawArrays"];
}
上面是自己在使用OpenGL在iOS上画图的过程总结,作为学习记录吧,也希望可以帮到刚接触这个的同学。