OpenGL基础概念(学习记录)

96
Frank_何益明
0.4 2018.11.26 17:06* 字数 1541

各平台渲染标准:

win32 : OpenGL ,DirectX

android: Skia/Canvas  (安卓SDK,2d) , OpenGL ES +NDK

mac/ios :Quartz2D,OpenGL ES 

Linux: OpenGL

wp7:DirectX

win8/wp8 : DirectX

游戏引擎基于的渲染标准:

HTML5: Canvas/WebGL 

Unity3D:OpenGL

Cocos2d-x:OpenGL ES/DirectX/Canvas(Html5版本)

一、OpenGL初识

1、什么是OpenGL?⼀一般认为OpenGL是⼀一个图形渲染库,然⽽而并不不是,OpenGL只是 包含了一系列操作图形、图像的函数的规范。严格规定了每个函数如何执行,以及它 们的输出值,而具体每个函数是如何实现的,是由显卡开发商自行决定的。 作为用户不会感受到功能上的差异。

2、代码风格OpenGL自身是一个巨大的状态机,OpenGL定义了很多状态设置函

数,通过设置函数参数的不同选项,达到不同的渲染效果。

// 创建对象

unsigned int objectId = 0;

glGenObject(1, &objectId);

// 绑定对象至上下文

glBindObject(GL_WINDOW_TARGET, objectId);

// 设置当前绑定到 GL_WINDOW_TARGET 的对象的一些选项

glSetObjectOption(GL_WINDOW_TARGET,GL_OPTION_WINDOW_WIDTH, 800);

glSetObjectOption(GL_WINDOW_TARGET,GL_OPTION_WINDOW_HEIGHT, 600);

// 将上下文对象设回默认

glBindObject(GL_WINDOW_TARGET, 0);

3、GLFW库

     跟系统相关的操作,如创建显示窗口、处理用户输入、创建OpengGL上下文,不同的操作系统是不一样的,所以OpenGL让开发者根据不同的平台自己去处理。这些都有人会写好了, GLUT、SDL、SFML、GLFM这些库刚好提供了一个窗口和上下文用来渲染。

     GLFW是一个专门针对OpenGL的C语言库,允许用户创建上下文、定义窗口参数以及用户输入。

4、GLAD

      OpenGL的函数的具体实现是由驱动开发商针对特定显卡实现的。开发者在调用每一个函数时需要运行时获取函数地址将其保存在一个函数指针中供以后使用,如下: 

// 定义函数原型

typedef void (*GL_GENBUFFERS) (GLsizei, GLuint*);

// 找到正确的函数并赋值给函数指针

GL_GENBUFFERS glGenBuffers=(GL_GENBUFFERS)wglGetProcAddress(“glGenBuffers”);

// 现在函数可以被正常调用了

GLuint buffer;

glGenBuffers(1, &buffer);

这个操作使代码复杂而且繁琐。 GLAD是一个开源的库,帮我们实现了运行时查询OpenGL函数实现的这个动作。GLAD使用了一个在线服务(https://glad.dav1d.de/),我们设置不同OpenGL版本的会得到相对应的库。加载这个库, 我们就是可以直接使用如上glGenBuffers函数,而无需写动态查询地址的代码。

二、OpenGL基础概念


    1、图形渲染管线

         图像渲染管线指的是一堆原始图形数据途经一个输送管道,期间经过各种变化处理最终出现在屏幕的过程。下图是图形渲染管线的每个阶段的抽象展示。蓝色部分我们可以注入自定义的着色器。



2、顶点输入

•  顶点数组对象:Vertex Array Object,VAO

• 顶点缓冲对象:Vertex Buffer Object,VBO

GPU内存中存储大量顶点的对象。使用这些对象可以一性发送大批数据到显卡上供点着色器访问。

float vertices[] = {

    -0.5f, -0.5f, 0.0f,

    0.5f, -0.5f, 0.0f,

    0.0f,  0.5f, 0.0f

};

//获取一个顶点缓冲对象

unsigned int VBO,VAO;

glGenBuffers(1, &VBO);

glGenVertexArrays(1, &VAO);

//绑定缓冲对象

glBindVertexArray(VAO);

glBindBuffer(GL_ARRAY_BUFFER, VBO); 

//将顶点数据复制到缓冲内存中

glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

//设置着色器获取顶点数据的指针

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);


OpenGL的坐标x、y、z轴的坐标范围是(-1.0,1.0)

3、顶点着色器

       渲染管线的每一个阶段运行着自己的小程序,快速处理图像数据,这些小程序就叫做着色器。

       GLSL: OpenGl着色器是用OpenGL着色器语言(OpenGL Shading Language)写成的。

      顶点着色器:主要目的是将一种3D坐标转换为另外一种3D坐标。同时允许我们对顶点属性进行一些基本处理。下面为一个简单GLSL顶点着色器的源代码: 

#version 330 core

layout (location = 0) in vec3 aPos;

void main()

{

   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);

}

3、片段着色器

     片段着色器所做的事计算像素最后的颜色输出。输出由RGBA4个分量组成,每个值的范围是0.0-1.0之间。 

#version 330 core

out vec4 FragColor;

void main()

{

    FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);

}

4、着色器程序

      我们需要对着色器源码进行编译,并链接到一个着色器程序上,然后就可以使用着色器进行渲染了。 

//编译顶点着色器

    unsigned int vertexShader;

    vertexShader = glCreateShader(GL_VERTEX_SHADER);

    glShaderSource(vertexShader,1,&vertexShaderSource,NULL);

    glCompileShader(vertexShader);

      //编译片段着色器

    unsigned int fragmentShader1;

    fragmentShader1 =  glCreateShader(GL_FRAGMENT_SHADER);

    glShaderSource(fragmentShader1,1,&fragmentShaderSource1,NULL);

    glCompileShader(fragmentShader1);

上面的vertexShaderSource,fragmentShaderSource1可以定义为着色器代码的字符串格式。

链接着色器程序,获取一个着色器程序对象 

//着色器程序

    unsigned int shaderProgram1;

    shaderProgram1  = glCreateProgram();

    glAttachShader(shaderProgram1,vertexShader);

    glAttachShader(shaderProgram1,fragmentShader1);

    glLinkProgram(shaderProgram1);

 设置渲染参数,进行渲染 

//设置好需要输入的顶点

glBindVertexArray(VAO);

//设置好着色器程序

glUseProgram(shaderProgram1);

//画三角形

glDrawArrays(GL_TRIANGLES, 0, 3);

5、GLM库

      GLM是OpenGL Mathematics的缩写,它是一个只有头文件的库。 是一个数学库,能够满足变换所需要的矩阵运算。

6、 纹理(Texture)

   纹理通常是一个2D图片(也有3D的),用来丰富物体的细节。 纹理中包含了大量的数据,并通过一定的方式给到着色器。通过测试、混合等后期处理,可以渲染出炫酷的效果。

附:教程地址  https://learnopengl-cn.github.io/intro/ 

OpenGL
Web note ad 1