视频特效学习02- OpenGL渲染基础

学习目标:
  • 1.OpenGL渲染架构(掌握)
    1. OpenGL数据传递的3种方式(理解)
    1. OpenGL提供的着色器(掌握)
    1. 正投影/透视投影API的使用(掌握)
    1. OpenGL上常见图元(会用)
    1. 在存储着色器的情况下渲染图形并能通过键盘控制Demo(实践)

1.OpenGL渲染架构

  • 渲染架构图


    OpenGL渲染架构.png
      1. Client(客户端):Application中的代码和OpenGL API存储在CPU中,由应用程序执行,主系统内存中的驱动程序将数据不断的传递给Serve。
      1. Serve(服务端):操作GPU绘制图形的部分。在Serve端,顶点着色器处理client传递过来的数据,然后将图形进行光栅化,再由片元着色器填充颜色,完成图形的渲染。client与serve是独立异步执行的,它们分属于不同的硬件或者软件块。
      1. GPU渲染流程名词解释:
      • Vertex Shader(顶点着色器):client从Attribibutes、Uniforms、Texture Data3个通道将数据传递给顶点着色器。顶点着色器只处理Attribibutes、Uniforms数据,不处理Texture Data数据。顶点着色器处理传入顶点的数据,包括顶点位置、顶点颜色、光照等,每个顶点都会执行一次。
      • Fragment Shader(片元着色器):Attribibutes无法直接传递给片元着色器,是从顶点着色器传递过来的,Uniforms、Texture Data可以直接传递给片元着色器,片元着色器计算每一个像素点的颜色并填充。
      • Primitive Assembly(基元装配):将图形光栅化处理,将顶点链接起来组成点、线、三角形三种不同的图元,然后对超出屏幕的部分进行裁剪,这是对图形进行裁剪、透视分隔、视口变换、光栅化等操作。
      • Position Vertex:顶点位置
      • ins(输入):将数据拷贝到着色器中。
      • outs(输出):将数据由一个阶段传递到另一个阶段,开发者无法干预其过程。
      • Render渲染:渲染图形

2.OpenGL数据传递的3种方式

通道:Attributes、Uniforms、Texture Data
OpenGL API向GPU传递数据有三个通道,分别是Attributes属性、Uniforms和Texture Data纹理数据,根据场景合理的使用对应的管道

  • Attribibutes(属性):属性传递的是不断发生改变的数据,传入的数据包括顶点坐标、颜色值、纹理坐标、位移、光照法线等,属性可以是整型、浮点型、布尔、4维向量等。Attribibuty只能传递到顶点着色器,不能直接传递到片元着色器,可通过GLSL代码间接传递。
    属性总是以4维向量的形式进行内部存储,顶点坐标是(x,y,z),占3个分量;属性会从本地client内存中复制存储在图形硬件中的一个缓冲区上,这些属性只能提供给顶点着色器使用。

  • Uniforms:传递的是统一数据,如旋转矩阵、变换矩阵等。图形旋转实现是每一个顶点乘以旋转矩阵,确定旋转角度后旋转矩阵不在发生变化,这个旋转矩阵就可以通过Uniform传递,传递的数据类型有整型、浮点型、布尔、4维向量等。最常见的应用是在顶点渲染中设置变换矩阵。uniform值可以直接传递到顶点着色器和片元着色器。uniform变量还可以是标量类型、矢量类型、uniform矩阵。

  • Texture Data(纹理数据):传递图片,渲染图形时的线框填充、颜色填充、纹理填充、像素填充等对图片的处理,在顶点着色器、片元着色器中都可以对纹理数据进行采样和筛选。
    滤镜的实现就是在读取颜色的时候对像素点颜色的处理,可以读取多张纹理使用颜色混合对像素进行填充
    典型的应用场景:片段着色器对一个纹理值进行采样,然后在一个三角形表面应用渲染纹理数据。

tips:不能为了达到目的而使用Uniform值传递颜色值到片元着色器,颜色值只能从Attributes值间接传递到片元着色器。
视频解码渲染使用到的颜色空间是YUV颜色值,需要将YUV乘以转换矩阵转换成RGBA来填充颜色以正确地渲染到屏幕上,这时的旋转矩阵可以通过Uniform传递到片元着色器。

3.OpenGL提供的着色器

固定存储着色器:早期的OpenGL版本封装的,帮助开发者完成图形渲染的程序块。

  • 单元着色器

    • 函数名称:GLShaderManager::UseStockShader(GLT_SHADER_IDENTITY,GLFloat vColor[4])。
    • 参数: 参数1:存储着色器种类-单元着色器;参数2:颜色。
    • 使用场景:绘制OpenGL默认坐标系(-1,1)下图形。图形所有片段会由一种颜色填充。
  • 平面着色器:

    • 函数名称: GLShaderManager::UseStockShader(GLT_SHADER_FLAT,GLFloat mvp[16],GLFloat vColor[4])。
    • 参数: 参数1:存储着色器种类-平面着色器;参数2:允许变化的4*4矩阵;参数3:颜色。
    • 使用场景:在绘制图形时, 可以应⽤变换(模型/投影变换)。
  • 上色着色器:

    • 函数名称:GLShaderManager::UseStockShader(GLT_SHADER_SHADER,mvp[16])
    • 参数: 参数1: 存储着⾊器种类-平面着⾊;参数2:允许变化的4*4矩阵。
    • 使用场景:在绘制图形时, 可以应用变换(模型/投影变换) ,颜⾊将会平滑地插入到顶点之间,称为平滑着色。
  • 默认光源着色器:

    • 函数名称: GLShaderManager::UseStockShader(GLT_SHADER_DEFAULT_LIGHT,GLFloat mvMatrix[16], GLFloat pMatrix[16], GLFloat vColor[4]) 。
    • 参数: 参数1: 存储着⾊器种类-默认光源着⾊器 ;参数2: 模型视图44矩阵;参数3: 投影44矩阵;参数4: 颜⾊值 。
    • 使用场景:在绘制图形时,可以应用变换(模型/投影变换),并且这种着⾊器会使绘制的图形产⽣阴影和光照的效果. 。
  • 点光源着色器:

    • 函数名称: GLShaderManager::UseStockShader(GLT_SHADER_POINT_LIGHT_DIEF,GLFloat mvMatrix[16], GLFloat pMatrix[16],GLFloat vLightPos[3], GLFloat vColor[4])
    • 参数: 参数1: 存储着⾊器种类-点光源着⾊器 ;参数2: 模型视图44矩阵;参数3: 投影44矩阵;参数4:点光源位置;参数5: 颜⾊值。
    • 使用场景:在绘制图形时, 可以应⽤变换(模型/投影变换) ,并且这种着⾊器会使绘制的图形产⽣阴影和光照的效果。它与默认光源着⾊器⾮常类似,区别只是光源位置可能是特定的。
  • 纹理替换矩阵着色器:

    • 函数名称:GLShaderManager::UseStockShader(GLT_SHADER_TEXTURE_REPLACE,GLFloat mvMatrix[16],GLint nTextureUnit)
    • 参数: 参数1: 存储着⾊器种类-纹理替换矩阵着色器 ;参数2: 模型视图4*4矩阵;参数3:纹理单元。
    • 使用场景:在绘制图形时,可以应用变换(模型/投影变换),这种着⾊器通过给定的模型视图投影矩阵。使用纹理单元来进⾏颜⾊填充。其中每个像素点的颜⾊都是从纹理中获取。
  • 纹理调整着色器:

    • 函数名称: GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_MODULATE,GLfloat mvMatrix[16],GLfloat vColor[4],GLint nTextureUnit);
    • 参数: 参数1: 存储着⾊器种类-纹理调整着色器;参数2: 模型视图4*4矩阵;参数3:颜色;参数4:纹理单元。
    • 使用场景: 在绘制图形时,可以应用变换(模型/投影变换),这种着⾊器通过给定的模型视图矩阵。 着⾊器将一个基本色乘以一个取自纹理单元nTextureUnit 的纹理.将颜色与纹理进行颜色混合后才填充到片段中。
  • 纹理光源着色器:

    • 函数名称:GLShaderManager::UserStockShader(GLT_SHADER_TEXTURE_POINT_LIGHT_DIEF,GLfloat mvMatrix[16],GLfloat pMatrix[16],GLfloat vLightPos[3],GLfloat vBaseColor[4],GLint nTextureUnit)
    • 参数: 参数1: 存储着色器种类-纹理光源着色器;参数2: 模型视图4 * 4矩阵;参数3: 投影4*4矩阵;参数4: 点光源位置;参数5: 颜⾊值(⼏何图形的基本色) ;参数6: 纹理理单元 。
    • 使用场景:在绘制图形时,可以应⽤变换(模型/投影变换)。这种着色器通过给定的模型视图投影矩阵。 着⾊器将⼀个纹理通过漫反射照明计算进⾏调整(相乘)。

4.正投影/透视投影API的使用

  • 正投影:用于平面图形的渲染。使用GLFrumstum::SetOrthgraphic(GLFloat xMin,GLFloat xMax,GLFloat yMin,GLFloat yMax,GLFloat zMin,GLFloat zMax)函数设置正投影矩阵。这些参数是用来设置投影区间大小。单纯的设置正投影没有意义,设置的目的是为了获得投影矩阵。
  • 透视投影:用于3D图形,可以控制图形趋于人的眼睛看到的一样。使用GLFrumstum::SetPerspective(float fFov,float fAspect,float fNear,float fFar)。参数:fFov:垂直方向上的视觉角度 fAspect:纵横比 fNear:近裁剪面距离 fFar:远裁剪面距离 纵横比 = 宽(w)/高(h)。

5.OpenGL上常见图元

  • 7种基本图元


    OpenGL基本图元.png
  • 效果图


    OpenGL基本图元效果图.png
  • OpenGL 点/线 设置方式:

    • 1.最简单也是最常用的 由于OpenGL是状态机,所以使用后记得恢复为原始状态
       glPointSize(4.0f);
      
    • 2.通过使用程序大小模式来设置点大小
       GLfloat size[2] = {2.0f, 4.0f};
       GLflat step = 1.0f;
       glGetFloatv(GL_POINT_SIZE_RANGGE ,sizes);
       glGetFloatv(GL_POINT_GRAULARITY ,&step);
      
    • 3.在顶点着色器或几何着色器中设置点大小 使用GLSL写
      //gl_PointSize是着色器的内建变量可以在着色器源码直接写
       gl_PointSize = 5.0;
      
    • 4.设置线段宽度
      glLineWidth(2.5f);
      
  • OpenGL 三角形:

    • 概念:对于OpenGl光栅化最受欢迎的是三角形。3个顶点就能构成一个三角形。三角形类型来自于顶点。

    • 三角形环绕方式:按照顺序与方向结合来指定顶点的方式成为环绕。默认情况下,具有逆时针方向的多边形为正面。

      OpenGL三角形环绕.png

      \color{#4285f4}{绘制第一个三角形时,线条是按照V0-V1,再到V2,最后回到V0,绘制成一个闭合三角形。图中左侧为正面,右侧为反面。}

    • 三角形带:对于很多表面或者形状而言,我们需要绘制几个相连的三角形,使用GL_TRIANGLE_STRIP图元绘制一串相连三角形,提高效率。共用的是一条边。


      OpenGL三角形带画图过程.png

    优点:

    • 1.用前3个顶点指定第一个三角形之后,对于接下来的每一个三角形,只需要载指定1个顶点。绘制大量三角形时,采用这种方法可以节省大量的程序代码和数据存储空间。
    • 2.提高运算性能和节省带宽。更少的顶点意味着数据从内存传输到图形卡的速度更快,并且顶点着色器需要处理的次数也更少了。
  • 三角形扇:对于很多表面或者形状而言,我们需要绘制几个相连的三角形,使用GL_TRIANGLE_FAN图元绘制一组围绕一个中心点相连的三角形。共用的是一个点。


    OpenGL三角形扇画图过程.png

GLBatch,是GLTools中包含的一个简单容器类。

// 开始数据复制
// 参数1:图元
// 参数2:顶点数
// 参数3:一组或者两组纹理坐标(可选)
void GLBatch::Begain(GLeunm primitice, GLuint nVerts, GLuint nTexttureUnints = 0);

// 复制顶点数据(一个由3分量x,y,z顶点组成的数组)
void GLBatch::CopyVertexData3f(GLfloat *vVerts);

// 复制表面法线数据
void GLBatch::CopyNormalDataf(GLfloat *vNorms);

// 复制颜色数据
void GLBatch:CopyColorData4f(GLfloat *vColors);

// 复制纹理坐标数据
void GLBatch:CopyTextCoorData2f(GLFloat *vTextCoords,GLuint uiTextureLayer);

// 结束数据复制
void GLBatch::End(void);

//绘制图形
void GLBatch::Draw(void);
  • 在存储着色器的情况下渲染图形并能通过键盘控制Demo

你可能感兴趣的:(视频特效学习02- OpenGL渲染基础)