基础概念OpenGLES(一)

作者: 仙人掌__ | 来源:发表于2019-06-08 12:05 被阅读0次

    opengl es是什么?

    • opengl 是一个跨平台(不同的GPU类型,如电脑端NVIDIA,Intel,AMD的显卡,手机端PowerVR(苹果系列), Adreno(高通,安卓系列)等等)、跨编程语言(各个编程语言java,C,OC,js等等都有opengl的接口)的图形图像处理接口,opengl本身只是一组api接口规范,具体的实现一般是由具体的显卡(GPU)设备生产商编码实现的,比如苹果手机是由apple实现的,Linux系统则是由各个显卡生产商通过驱动程序导入的。

    • opengl es是opengl的一个子集,是专门用来针对手机,平板电脑等嵌入式设备的图形图像处理接口,接口设计中不涉及上下文环境和窗口的管理,这由各个平台自行实现。比如ios就是EAGL;安卓就是EGL;

    tips:
    libSDL是一个跨平台的图形处理库,其中有包含对opengl es的标准接口的封装及各个平台上下文,窗口管理的封装。
    备注:opengl es 2.0 官方接口文档 https://www.khronos.org/registry/OpenGL-Refpages/es2.0/

    基础概念

    • 应用端:
      即我们自己的程序端,相对于opengl es,我们属于应用端
    • 图元:
      要渲染的几何物体,或者形状。比如要渲染一个正方形的图片,就是一个图元,要渲染两条直线,这两条直线也是图元
    • 纹理:
      通俗点,可以理解为一张图片,在opengl es中纹理就是图片的另外一种叫法
    • 纹素:
      纹理的基础单元,也就是像素
    • 顶点数组
      顶点指的是组成图元的各个顶点的坐标数据(在3D笛卡尔坐标中即x,y,z坐标),这些坐标数据可以一起存到一个内存数组中,这个数组就叫做顶点数组
    • 顶点缓冲区
      在显存中专门分配一块显存来存储这个顶点数组,这个显存就称为顶点缓冲区
    • 顶点着色器
      顶点着⾊器(简称为VS)是opengl es中⽤于计算图形顶点属性(包括顶点坐标归一化、顶点光照运算等等)的程序。顶点着色器是逐顶点运算的程序,也就是说每个顶点数据都会执行⼀次顶点着⾊器,当然这是并行的
    • 片元着色器
      片元着色器(简称为PS)用来决定要渲染图形的每个像素的颜色的程序,它也是并行计算的

    opengl es渲染管线

    渲染管线也就是opengl es的工作流程,这里是opengl es2.0以后的版本的渲染管线

    • 1、opengl es接收API的输入
      通过 API 设定顶点的信息(一般包括顶点坐标,纹理坐标,颜色,变换矩阵等等),一般由顶点着色器接收这些信息作为输入
    • 2、顶点着色器处理顶点坐标
      前一阶段的输入将在 VS 中进行运算,以得到最终的顶点坐标。
    • 3、图元装配
      将顶点着色器计算出的最终顶点坐标进行图元装配,构建出最终想要渲染的图形。所有要渲染的图形都可以由三个基本的图元(点、线、三角形)组成,比如正方形或者长方形,就可以由两个三角形组成,圆形可以由无数个三角形组成,只是三角形的数量越多,圆形看上去越圆润
    • 4、光栅化
      通过计算,将要渲染的图形上所有的像素点找到,并根据插值或者其他方式计算出其颜色等信息的过程
    • 5、片元着色器计算像素颜色
      光栅化得到了要渲染图形的所有像素的信息,这些信息作为片元着色器的输入,那么在片元着色器中将计算像素颜色
    • 6、像素处理
      片元着色器计算的像素颜色还不是最终要渲染的颜色,这一步骤还包括Alpha Test、Depth/Stencil Test、Blend、Dither等几个步骤,经过这几个步骤后得到的就是最终的渲染颜色

    备注:以上所有的操作都是并行处理

    opengl es的相关坐标系

    • opengl es的坐标系原点位于要渲染区域的中心点,向右和向上分别为x轴和y轴的正向轴,取值范围为(-1,1)
      如下为正确渲染一张图片为例传递顶点坐标
      static float verData1[8] = {
      -1.0f, -1.0f, // 左下角
      1.0f,-1.0f, // 右下角
      -1.0f,1.0f, // 左上角
      1.0f,1.0f, // 右上角
      };
      一般按照如上的顺序传递坐标,取值也可以是其它值,比如
      static float verData1[8] = {
      -0.5f, -0.5f, // 左下角
      0.5f,-0.5f, // 右下角
      -0.5f,0.5f, // 左上角
      0.5f,0.5f, // 右上角
      };
      表示取中间的1/2区域;实际上就是压缩效果
      static float verData1[8] = {
      -2.0f, -2.0f, // 左下角
      2.0f,-2.0f, // 右下角
      -2.0f,2.0f, // 左上角
      2.0f,2.0f, // 右上角
      };
      表示将原来的坐标系放大了一倍后在基于原始的进行截取

    • 纹理坐标系
      在opengl 中,通常将纹理中的像素根据纹理坐标系来进行编址,纹理坐标系的横轴成为S轴,纵轴成为T轴,垂直于ST轴的成为R轴,在2D纹理中,没有
      R轴,横轴和纵轴又称为UV轴,所以2D纹理坐标系又称为UV坐标系,UV轴的取值范围都是(0,1)。与OpenGL 坐标系不同的是,纹理坐标系的原点位于左
      上角
      如下为正确渲染一张图片为例传递纹理坐标:
      static float uvData[8] = {
      0.0f, 1.0f,// 左下角
      1.0f, 1.0f, // 右下角
      0.0f, 0.0f,// 左上角
      1.0f, 0.0f, // 右上角
      };
      纹理坐标系一般不要去改变它的值,传这个就好,(当然也可该,前提是知道内部的转换原理),如果要实现压缩和裁剪效果,改变几何坐标系方便一些。

    • 设定opengl es渲染区域
      glViewPort(x,y,w,h) 函数窗口创建的渲染区域
      它以左下角作为原点的坐标系
      此函数的意思就是,基于当前视图左下角作为原点的坐标系,选取一个左下角坐标为x,y,长宽为w,h的区域作为渲染的区域

    纹理映射

    • 1、缩放
      纹理的映射就是让物体的每个片元(每个颜色像素)都找到对应的纹理纹素点,在这个映射过程中,因为纹理和物体的不匹配,一般会出现两种情况
      第一种是拥有大量纹素的纹理被映射到只还有少量片元的物体中
      第二种是拥有少量纹素的纹理被映射到含有大量片元的物体中
      如下:
      glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR)
      glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR)
      GL_TEXTURE_MIN_FILTER:
      是多个纹素对应一个片元的解决方案。可以设置两个值,GL_NEAREST 和 GL_LINEAR ,这两个值分别对应了两种不同的解决方案。GL_LINEAR 会混合匹配的颜色来得到片元的颜色,产生的颜色可能是纹理中不存在的颜色。例如一个纹理是由交替的黑色和白色的纹素组成,那个线性取样会使最终的片元颜色为灰色。GL_NEAREST 会拾取与片元 U,V 坐标最相近的颜色。
      GL_TEXTURE_MAG_FILTER:
      是没有足够的纹素来映射片元的解决方案。可以设置的值同 GL_TEXTURE_MIN_FILTER 一样。GL_LINEAR 会告诉OpenGL ES 混合附近纹素的颜色来计算片元的颜色。GL_LINEAR会有一个放大纹理的效果,当没有足够的纹素来映射片元时,会让纹理模糊的出现在要渲染的图形上。
      GL_NEAREST 仅仅会拾取片元的 U ,V 位置接近的纹素的颜色,并放大纹理,会使其像素化的出现在要渲染的图形上。
      GL_LINEAR:
      线性插值,取最近的点的线性平均值 (性能消耗较大)
      mipmaps
      它也是一种纹理过滤算法,按我的理解它是以空间换时间的一种技巧,具体原理就是事先根据纹理生成长和宽逐渐除以2的小纹理,比如原始纹理大小128x128,
      采用此方法后,会生成64x64 32x32 16x16 8x8 4x4 2x2 1x1的一系列纹理,如果需要20x18的纹理,则取最近的32x32 16x16进行平均
      该方法很好的解决了如下问题:
      1、当纹理很大,但是屏幕区域很小,渲染出现的闪烁问题,因为根据最邻近插值和线性插值都无法很快计算出合理的像素
      它可以取的值如下:
      GL_NEAREST_MIPMAP_NEAREST 选择最近的mipmap层,然后再用最邻近过滤插值
      GL_LINEAR_MIPMAP_NEAREST 选择最近mipmap层,然后再用线性插值
      GL_NEAREST_MIPMAP_LINEAR 选择最近的2层mipmap用最邻近过滤插值
      GL_LINEAR_MIPMAP_LINEAR 选择最邻近的2层mipmap用线性插值
      使用如下函数生成mipmaps
      glGenerateMipmap(GLenum target);

    • 2、warp
      另外一种在映射时可能出现的情况是纹理的四个顶点坐标不是1.0时,将采用如下方式:
      glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_WARP_S,GL_REPEAT) S轴方向
      glTexParameter(GL_TEXTURE_2D,GL_TEXTURE_WARP_T,GL_REPEAT) T轴方向
      GL_REPEAT:纹理没有覆盖的部分重复之前的纹理,当纹理大小大于物体大小时,纹理采样会出错。
      GL_MIRRODED_REPEAT:将原来的纹理先颠倒再重复,当纹理大小大于物体大小时,纹理采样会出错。
      GL_CLAMP_TO_EDGE:延续结束时的纹理

    顶点着色器中顶点坐标的顺序规则

    open gl 中顶点坐标
    static float verData1[8] = {
    -1.0f,-1.0f, // 左下角
    1.0f,-1.0f, // 右下角
    -1.0f,1.0f, // 左上角
    1.0f,1.0f, // 右上角
    };
    对应的纹理坐标
    static float uvData[8] = {
    0.0f, 1.0f, // 左下角
    1.0f, 1.0f, // 右下角
    0.0f, 0.0f, // 左上角
    1.0f, 0.0f, // 右上角
    };
    对应的为glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 可以渲染出一张图片

    VBO

    GPU中专门开辟的一块内存用于存储图元的顶点数据,这样每次调用glDrawArrays()函数时,GLSL就是直接从GPU中获取
    顶点数据,而不是每次都有cpu拷贝到GPU(cpu拷贝到gpu肯定效率不如直接从GPU中取),这样对于顶点数据比较多时,
    可以加快效率;

    FBO

    帧缓冲,也就是通过glGenFramebuffers()函数生成的对象,它主要用于存储opengl es最终的渲染结果。

    离屏渲染

    当需要对纹理进行多次渲染采样时(也就是对一个纹理进行多个着色器程序去处理),而这些渲染采样中间过程是不需要
    展示给用户看的,所以就可以额外创建一个FBO对象来专门做这个事情,这个FPO对象就成为为离屏渲染帧缓冲,这个
    过程叫做离屏渲染

    渲染缓冲区

    通过glGenRenderbuffers()生成的缓冲区,他用于将渲染的结果呈现到屏幕上,需要与FBO绑定

    opengl es api和EGL api

    opengl es api是用来进行图像渲染操作的,
    egl api是由各个操作系统实现的系统api,它主要的作用就是创建窗口,创建opengl 上下文环境等。可以由各自厂商自行定义,使用通用的EGL接口。
    如苹果就是EAGL,安卓就可以用EGL来自行管理,也可以用GLSurface系统创建opengl 环境

    相关文章

      网友评论

        本文标题:基础概念OpenGLES(一)

        本文链接:https://www.haomeiwen.com/subject/dlqixctx.html