从0开始的OpenGL学习(二)-渲染三角形

本文主要解决一个问题:

如何渲染一个三角形?

本章中,会有大量的新名词和解释,大量的函数出现,建议找个安静的地方慢慢啃这块骨头。

首先,先从直觉上来想想要渲染一个三角形我们需要做些什么?大概需要这三个步骤:

  • 1、定义三个顶点。
  • 2、将三个顶点的边两两相连。
  • 3、将内部的区域涂成一种或几种颜色。

我们就从这几个方面来画出我们的三角形。

一、顶点

在OpenGL中,所有的顶点都是三维空间内的顶点,不过这不是问题,我们可以把深度定义为0来保证其在一个平面上。于是,我们定义三个点:(-0.5, 0.5, 0.0),(0.5, -0.5, 0.0),(0.0, 0.5, 0.0),由于在OpenGL中所有的顶点都会被规范化(将顶点的位置变换到-1到1之间),我们就直接定义规范化后的点,方便处理。我们的代码就像这个样子(编程是一种手写编码的过程,不是Ctrl+C、Ctrl+V的过程,手写一遍代码还是非常必要的):

顶点数组

我们有了顶点数组,如何让OpenGL知道呢?这里有个新东西,叫顶点缓存对象(Vertex Buffer Object,简称VBO),表示存储在GPU显存中的大量顶点数据。我们可以通过这个对象,一次性向GPU发送大量的数据,而不是一次次地从CPU中发送数据到GPU,这是个很慢的过程。

1、使用VBO

唯一ID:OpenGL中有太多的东西,我们需要一个唯一的ID,就像身份证一样来标识出哪个是哪个。这个ID不能我们自己来定,只能告诉OpenGL说,我需要一个唯一ID,你给我一个吧。然后,OpenGL就会给你一个没用过的唯一ID,这个过程是由glGenBuffers来实现的。


生成唯一ID

指明缓存对象类型:OpenGL中有很多缓存对象,虽然它给了我们一个ID,但不知道这个ID是用来表示什么缓存对象的。我们要明确告诉它,这是一个顶点缓存对象。绑定的作用,是将原来有的东西替换成我们新的东西,这样,接下来对GL_ARRAY_BUFFER的操作都是对我们新东西的操作了。

指定为顶点缓存对象

将顶点数据传到VBO:

顶点数据复制到VBO
  • 参数1:我们的顶点数据需要拷贝到的地方。(之前我们绑定的VBO)
  • 参数2:数组的大小
  • 参数3:数组的地址
  • 参数4:指定显卡要采用什么方式来管理我们的数据,GL_STATIC_DRAW表示这些数据不会经常改变。

2、顶点着色器

从OpenGL 3.3开始,OpenGL的渲染方式就从固定功能管线转向了可编程功能管线。而可编程的意思,就是可以通过许许多多的着色器来实现多种多样的效果,这些效果要比固定的效果好的多。顶点着色器就是这些许许多多的着色器中的一种。
先放出一段代码(GLSL语言编写,语法与C极为类似):

顶点着色器代码
  • 第一行:指明了使用OpenGL的版本以及运行模式(版本号3.3,核心模式)
  • 第二行:指明了需要从上一个步骤中获取一个vec3类型的位置数据,数据位置在输入数据的0偏移位置(类似于输入了一块数据,我们要的数据在头部)
  • 第七行(main函数内部):将顶点的位置直接赋值成输入的位置,gl_Position是一个内置的变量,用来表示顶点位置的。
2.1编译着色器

代码自然是要编译链接之后才能执行的,这里我们先说编译,链接的部分等讲完片元着色器再一起说,先不用纠结。
首先,创建一个着色器对象,返回值是这个对象的唯一ID

创建着色器对象

然后,我们将源码附加到着色器对象上并且编译这个着色器对象

附加源代码并且编译着色器对象

3、片元着色器

同样,先放出代码


片元着色器代码

类似的,我们输出一个颜色供片元使用,这个颜色是橙色。一个片元,包含了OpenGL用来渲染一个像素的所有信息。

3.1编译着色器

我们同样需要创建一个着色器对象,然后将源码附加到着色器对象上,然后编译。代码如下:

片元着色器源码

4、着色器程序对象

着色器程序对象是最终将所有着色器连接起来的对象。把所有的着色器对象和这个着色器程序对象连接起来之后,我们就能使用这个着色器程序对象了。
将着色器都连接到程序对象上时,OpenGL会将上一个阶段的输出连接到下一个阶段的输入上。
我们需要三步来使用着色器程序对象,现在已经很熟悉了。创建、附加、链接。

链接着色器代码

5、使用着色器程序对象

代码很简单,只有一行

使用着色器对象

6、清理着色器

将已经附加过的着色器都清除掉,我们现在不需要它们了(过河拆桥???)。

清理着色器

7、指明顶点属性

顶点着色器给了我们极大的便利性,我们可以输入想要输入的任何属性格式。因此,我们也就要告诉OpenGL我们顶点的格式是什么样子的。我们定义的顶点格式如下:

顶点格式(图片资源来源于learningopengl.com)

可以看到一些重要信息,我们的起始顶点的偏移为0,每个位置分量占用4字节的空间,一个顶点占用12字节空间。

于是,我们调用glVertexAttribPointer函数来指定顶点格式。

指明顶点格式代码
  • 参数1:指明我们想要配置的顶点属性。类似编号的东西,之前我们设置了location = 0,就是我们在这里用到的0.
  • 参数2:顶点属性的大小。我们用到的顶点是一个vec3的结果,所以大小为3.
  • 参数3:数据的类型。我们使用的是float类型
  • 参数4:指明数据是否要被规范化。这里我们设置成FALSE,不用规范化,因为我们已经规范化好了。
  • 参数5:表示属性的跨度。正如之前我们分析的,我们的跨度是12,就是3倍的float类型。
  • 参数6:指明了数据的起始偏移量。这里转成了一个void*指针类型比较奇怪,我们以后再聊。

我们获取的顶点属性是由VBO决定的,而glVertexAttribPointer操作的是当前绑定到GL_ARRAY_BUFFER上的VBO,所以,我们当前操作的就是我们之前生成并绑定的那个VBO。

glEnableVertexAttribArray(0)是用来让顶点属性生效的,参数0就是我们之前配置的那个顶点属性的位置。

二、绘制三角形
OpenGL中并没有将我们上面设想的两步单独弄出来,只需要指明要画的是三角形,而且是实体三角形,这两步就能自动完成了。
所以,当我们做完上面那么多步骤之后,我们只需要调用一行代码就可以了。

绘制三角形

到这里,似乎我们要做的事情都已经做完,只要编译运行代码就能看到我们想要的三角形了。然而,事实并不像我们想象的那样。运行的代码还是一片青灰色,根本看不到三角形的影子。加了一个VAO进去之后,就能显示出三角形来了。看看教程,原来这个VAO已经是OpenGL渲染管线中不可缺少的一部分了。所以,我们要郑重其事地来了解一下VAO。

三、VAO

全称是顶点数组对象(Vertex Array Object),作用是来保存对顶点属性的调用。这样,当我们需要这些顶点属性的时候,只需要简单地绑定VAO,不需要再设置一遍顶点属性就可以进行绘制了。(是不是觉得没有必要调用,我不想保存,只想显示。所以笔者才尝试不用VAO看看能不能显示出三角形,结果是,没戏,只能乖乖的用它。)

VAO会保存两种东西:

  • 其一、对glEnableVertexAttribArray或者是DisableVertexAttribArray的调用。
  • 其二、使用glVertexAttribPointer设置的顶点属性以及与顶点属性相关连的VBO。

生成VAO并绑定的代码如下:

unsigned int VAO;
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);

将这段代码添加到生成VBO的代码之后就可以编译运行了。
嗯,不出所料,我们的三角形显示出来了。

显示结果

最后,源码可以参考这里,强烈建议自己手输一遍代码,不自己写一遍还算是程序员么?

总结

图片资源来源于(www.learningopengl.com)

这是一张顶点处理的流程图,我们所做的工作就是处理其中的一些阶段。今天我们处理的是顶点着色和片元着色,之后在学光照和纹理的时候我们依旧是处理这些着色,可见这两个阶段是多么重要。

下一篇
目录
上一篇

参考资料:

www.learningopengl.com(推荐学习)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容