欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

OpenGL ES 渲染立体图形

程序员文章站 2022-05-07 19:09:44
一、理解 顶点数据存储在申请的缓冲区中,其由数据总线传递给着色器(如果是片元着色器,还须将顶点转换成片元),再由着色器最终渲染到涂层上; 二、思路 1.设置涂层; 2.创建上下文; 3.清空缓存区; 4.创建渲染缓存区和帧缓存区; 5.开始绘制; 三、核心代码 //最终渲染 四、效果 GitHub ......

一、理解

顶点数据存储在申请的缓冲区中,其由数据总线传递给着色器(如果是片元着色器,还须将顶点转换成片元),再由着色器最终渲染到涂层上;

二、思路

1.设置涂层;

 2.创建上下文;

 3.清空缓存区;

 4.创建渲染缓存区和帧缓存区;

 5.开始绘制;

三、核心代码

//最终渲染

- (void)renderlayer
{
    //设置窗口背景颜色
    glclearcolor(0.0, 0.0, 0.0, 1.0);
    //清空颜色缓存
    glclear(gl_color_buffer_bit);
    //设置视口大小
    cgfloat scale = [[uiscreen mainscreen] scale];
    glviewport(self.frame.origin.x*scale, self.frame.origin.y*scale, self.frame.size.width*scale, self.frame.size.height*scale);
    
    //读取顶点和片元着色器程序
    nsstring *vertfile = [[nsbundle mainbundle] pathforresource:@"shaderv" oftype:@"glsl"];
    nsstring *fragfile = [[nsbundle mainbundle] pathforresource:@"shaderf" oftype:@"glsl"];
    nslog(@"vertfile:%@", vertfile);
    nslog(@"fragfile:%@", fragfile);
    
    //判断myprogram是否存在,存在则清空
    if (self.myprogram) {
        gldeleteprogram(self.myprogram);
        self.myprogram = 0;
    }
    
    //加载着色器到myprogram中
    self.myprogram = [self loadshader:vertfile frag:fragfile];
    
    //创建链接
    gllinkprogram(self.myprogram);
    glint linksuccess;
    
    //获取链接状态
    glgetprogramiv(self.myprogram, gl_link_status, &linksuccess);
    
    //判断链接是否成功
    if (linksuccess == gl_false) {
        //获取失败信息
        glchar message[256];
        glgetprograminfolog(self.myprogram, sizeof(message), 0, &message[0]);
        //c字符串转换成oc字符串
        nsstring *messagestring = [nsstring stringwithutf8string:message];
        nslog(@"error:%@", messagestring);
        return;
    } else {
        //使用myprogram
        gluseprogram(self.myprogram);
    }
    
    //创建绘制索引数组
    gluint indices[] = {
        0, 3, 2,
        0, 1, 3,
        0, 2, 4,
        0, 4, 1,
        2, 3, 4,
        1, 4, 3
    };
    
    //判断顶点缓存区是否为空,为空则申请一个缓存区标志符
    if (self.myvertices == 0) {
        glgenbuffers(1, &_myvertices);
    }
    
    //----------处理顶点坐标---------
    
    /*顶点数据
     1.前3个坐标值(x、y、z),后3个颜色值(rgb);
     2.有先后顺序,否则绘制形状完全不同
     */
    glfloat attrarr[] =
    {
        -0.5f, 0.5f, 0.0f,      1.0f, 0.0f, 1.0f, //左上
        0.5f, 0.5f, 0.0f,       1.0f, 0.0f, 1.0f, //右上
        -0.5f, -0.5f, 0.0f,     1.0f, 1.0f, 1.0f, //左下
        0.5f, -0.5f, 0.0f,      1.0f, 1.0f, 1.0f, //右下
        0.0f, 0.0f, 1.0f,       0.0f, 1.0f, 0.0f, //顶点
    };
    
    //将_myvertices绑定到gl_array_buffer标志符上
    glbindbuffer(gl_array_buffer, _myvertices);
    //把顶点坐标数据从cpu复制到gpu上
    glbufferdata(gl_array_buffer, sizeof(attrarr), attrarr, gl_dynamic_draw);
    
    //将顶点坐标数据通过myprogram传递到顶点着色器程序的position
    
    //获取顶点属性入口
    gluint position = glgetattriblocation(self.myprogram, "position");
    /*传递数据
     1.一行6个数据,前3个为坐标,后3个为颜色;
     2.null开始位置:默认为0,指向数组首地址;
     */
    glvertexattribpointer(position, 3, gl_float, gl_false, sizeof(glfloat)*6, null);
    //设置合适的格式从缓存区中读取数据
    glenablevertexattribarray(position);
    
    //处理顶点颜色数据:传递到顶点着色器的positioncolor
    gluint positioncolor = glgetattriblocation(self.myprogram, "positioncolor");
    glvertexattribpointer(positioncolor, 3, gl_float, gl_false, sizeof(glfloat)*6, (float *)null +3);
    glenablevertexattribarray(positioncolor);
    
    //在myprogram中找到透视投影矩阵和模型视图矩阵
    gluint projectionmatrixslot = glgetuniformlocation(self.myprogram, "projectionmatrix");
    gluint modelviewmatrixslot = glgetuniformlocation(self.myprogram, "modelviewmatrix");
    
    //创建透视投影矩阵并初始化
    float width = self.frame.size.width;
    float height = self.frame.size.height;
    ksmatrix4 _projectionmatrix;
    ksmatrixloadidentity(&_projectionmatrix);
    float aspect = width/height;
    ksperspective(&_projectionmatrix, 30.0, aspect, 5.0f, 20.0f);
    
    //设置glsl里面的投影矩阵
    gluniformmatrix4fv(projectionmatrixslot, 1, gl_false, (glfloat *)&_projectionmatrix.m[0][0]);
    
    //开启剔除功能
    glenable(gl_cull_face);
    
    //创建平移矩阵:z轴平移-10
    ksmatrix4 _modelviewmatrix;
    ksmatrixloadidentity(&_modelviewmatrix);
    kstranslate(&_modelviewmatrix, 0.0, 0.0, -10.0);
    
    //创建旋转矩阵
    ksmatrix4 _rotationmatrix;
    ksmatrixloadidentity(&_rotationmatrix);
    ksrotate(&_rotationmatrix, xdegree, 1.0, 0.0, 0.0);
    ksrotate(&_rotationmatrix, ydegree, 0.0, 1.0, 0.0);
    ksrotate(&_rotationmatrix, zdegree, 0.0, 0.0, 1.0);
    
    //将平移矩阵和旋转矩阵相乘,结果放到模型视图矩阵中
    ksmatrixmultiply(&_modelviewmatrix, &_rotationmatrix, &_modelviewmatrix);
    
    //设置glsl里面的模型视图矩阵
    gluniformmatrix4fv(modelviewmatrixslot, 1, gl_false, (glfloat *)&_modelviewmatrix.m[0][0]);
    
    //设置绘制参数:片元、个数、索引数组
    gldrawelements(gl_triangles, sizeof(indices)/sizeof(indices[0]), gl_unsigned_int, indices);
    
    //由顶点着色器将缓存区中的数据渲染到显示涂层上
    [self.mycontext presentrenderbuffer:gl_renderbuffer];
}

四、效果

OpenGL ES 渲染立体图形

OpenGL ES 渲染立体图形

 

 

github