我们教程是这个https://learnopengl-cn.github.io/01%20Getting%20started/01%20OpenGL/
平时的实验也是从上面出的,但是我自认为上面翻译的极差,总是不知所云,但是代码还是有一定可读性的。
一个学期下来,零零散散的学了基本的图形绘图,纹理,摄像机,图形变换,光照之类的,现在需要写大程了,仔细阅读了代码,才发现对于我对于如何绘制一个场景终于有些了解。
现在总结如下,主要是一些定义以及需要干什么,也是我这学期学习的,没学到就没总结,具体的代码网站上都有抄。
1 绘图需要知道什么
绘图需要知道:
1.顶点,
2.颜色或者纹理,
3.观察的角度,
4.投影方式,
5.位置
如果给了这5个参数,基本就可以画出简单的立体场景了。所以我们的任务变成了如何给GPU传输这5个参数。
2 顶点
顶点是顶点着色器的输出决定的。每一个点都会调用一次顶点着色器,看它的输出是什么。因此绘制顶点必须给顶点着色器传递数据。
给顶点着色器传递数据,必须用到内存。内存是一个连续的数组。但是数组中一个点是几个属性必须确定。比如存储p1.x,p1.y,p1.z,p2.x,p2.y,p2.z,…也就是三个值代表一个点,这时候必须告诉gpu数组中的值如何解释。
用vao实现这个功能,比如一个点需要6个值来表示,前3个是位置,后3个是颜色r,g,b,那么需要用一个vao对这两个属性都解释一遍。
glEnableVertexAttribArray确定你现在想解释哪个属性,glVertexAttribPointer确定你到底怎么解释这个属性。
解释完成以后,就用一个vbo类型的变量把这些数据拷贝到内存里面。可以选择画的时候拷贝,也可以画之前拷贝,一个画的更快,一个会内存消耗更少。此时内存里面的数据自动对应上面解释的vao,因此只要保存了vao,比如叫做a的变量,下次绑定a,就自动获得了数据解释方式和内存中的数据。
ebo就是如果你不想按照内存,也就是vbo指向的点的顺序画,或者想一个点画很多次,就用这个指定绘制的顺序。在vao后设置,自动和vao关联。
总结一下:用vao设置一个点的几个属性,然后用vbo将点的数据拷贝进内存,然后用ebo指定绘制的顺序,那么就完成了点的设置,想要画的时候绑定对应的vao类型的变量即可。
当绘制的时候,顶点着色器获得一个点的若干个属性,然后把位置属性输出。把其他属性传递下去。layout(localtion=0)就是第0个属性,以此类推。
3 纹理和颜色
颜色是片段着色器的输出决定的,片段着色器获得顶点着色器传递下来的数据。然后输出一个vec4类型的变量,就是这个点的颜色。
纹理的本质也是颜色,纹理比较复杂:
首先,模型上有若干个点,然后纹理上也传递若干个点,绘制的时候,这些点的颜色就替换为纹理上的颜色。
纹理通过uniform的方式传递给片段着色器,uniform类似一个管道,可以直接从程序里传数据给着色器,一般顶点的位置是通过内存传递的,其他的属性主要是通过uniform的管道传递的。
因此,如果想用纹理,那么必须额外给片段着色器一些点,叫做Texcoord,表示纹理上和内存中的点对应的点。然后和传递进来的纹理一起调用texture就可以赋值了。
纹理是一个特殊的类型,其他的uniform可以在程序中直接赋值,这个叫做sampler2d,或者sampler开头的纹理类型变量必须通过openGL规定的纹理单元进行传输。首先,生成一个纹理,然后把它的绑定到一个纹理单元中(一个片段着色器有16个纹理单元,第一个单元默认激活,其他需要手动激活),然后把片段着色器中那个纹理变量的名称,比如是a的值,设定为0,就是a是第0个纹理单元的纹理的意思。
然后用a就可以表示程序里生成的那个纹理了。
有一个特殊的纹理,叫做samplerCube,这个纹理是贴在正方体上的,可以用来制作天空,让观察者在一个111的盒子中,然后先看到其他的物体,空隙由这个盒子填充。就是说盒子不会挡住其他物体,挡住的只是黑色的空白。
另外光照就是颜色乘上一个系数。系数主要是环境光+漫反射+镜面方式三个之和,环境光由物体和光照强度决定,漫反射,镜面反射由物体和光照强度,方向,颜色决定。公式在网上有。
4 观察角度
如何绘制立体场景,其实是靠投影,把一个3维的场景投影到屏幕上,因此需要确定观察矩阵。观察矩阵就是lookat,用视角向量减去位置向量很容易就能算出来,然后把投影矩阵传递进去,和顶点着色器的输出乘一下即可。
5 投影方式
有透视和另一个,把这个传进顶点着色器和输出乘一下即可。
6 位置
和观察角度类型,位置不同决定了三维场景投影的不同,因此传进去和输出乘一下即可。
总结
绘图需要的数据 | 传递的方式 |
---|---|
顶点坐标x,y.z | 内存->顶点着色器->输出 |
颜色r,g,b | 内存->顶点着色器->内存着色器->输出 |
纹理 | 纹理单元->片段着色器。片段着色器用uniform接受,修改输出 |
光照 | 片段着色器用unifom接受光强,位置,修改颜色输出 |
投影方式 | 顶点着色器用unifom接收mat4,修改坐标 |
观察矩阵 | 顶点着色器用uniform接收mat4,修改坐标 |