iOS--OpenGL渲染

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上画图的过程总结,作为学习记录吧,也希望可以帮到刚接触这个的同学。

猜你喜欢

转载自blog.csdn.net/T20091/article/details/44466259