OpenGL-ch2

关于VBO和顶点数据,两者还是有点区别的

顶点数据是发送给GPU并存储在其存储(aka显存)中的数据,一份数据只需要一份就够,不需要副本,否则是对空间资源的极大浪费

VBO:顶点缓冲对象,是GPU读取顶点数据的平台/载体(实际读取的是顶点属性指针,迭代读取),一份顶点数据可以绑定在不同VBO上,意味着顶点数据对应VBO的关系可以是一对多的

2.为什么教程里不把法向量转换为世界空间坐标再计算?

1).法向量是个方向向量,不代表位置

2).法向量没有齐次坐标(w分量),平移对法向量不起任何作用,只能对其应用缩放和旋转

3).如果模型矩阵对顶点进行了不对等缩放(分量缩放倍率不一致),将其乘以法向量会导致法向量不再垂直于平面:

OpenGL-ch2_第1张图片

补救的办法是使用正视矩阵(Normal Matrix),后面可能会提及

vecn与颜色混合

不管是着色器还是GLM中的向量(vecn,n为分量个数),都不遵循传统矩阵相乘规则,他们遵循‘plain’数字运算规则:

vec1+vec2=(vec1.x+vec2.x,vec1.y+vec2.y,vec1.z+vec2.z)

vec1*vec2=(vec1.x*vec2.x,vec1.y*vec2.y,vec1.z*vec2.z)

(分量相加相乘)

在需要用到颜色混合时常用一个颜色向量加上另一个颜色向量,举个例子:

vec3 red(1.0f,0.0f,0.0f)vec3 green(0.0f,1.0f,0.0f)混合(相加):

结果为(1.0f,1.0f,0.0f)为黄色

而在反射光时常用光的颜色向量乘以物体的颜色向量,得到的结果就是反射出的颜色向量(实际入眼的颜色)

glm::vec3 lightColor(0.0f, 1.0f, 0.0f);

glm::vec3 toyColor(1.0f, 0.5f, 0.31f);

glm::vec3 result = lightColor * toyColor; // = (0.0f, 0.5f, 0.0f);

这里物体在绿光照射下,只反射部分绿光

(事实上,不负责的讲,物品的RGB3个分量每个分量的大小代表了对对应光的吸收程度,0.0为最高(完全吸收)1.0为最低(完全不吸收),这在逻辑上有点难理解,可以令物品的"本质颜色"为在白光(1,1,1)下的反射光的颜色作为基准)

什么是材质?(按照教程中的说法)

材质是物体颜色(objectColor)的“细分实践”,具体的来说,材质由以下几个部分组成:

OpenGL-ch2_第2张图片

直白的说,materialAmbientmaterialDiffuse等,定义了全局、漫反射、镜面反射的“颜色”

对比之前的代码:

(只需要注意ambient*objectColor就行了)

我们发现material.materialAmbient*lightColor=lightColor*objectColor(忽略强度)

material.materialAmbient=objectColor(在这里的作用)

在这里,不论是objectColor还是materialAmbient,都起到了定义全局反射时的“物品颜色”:

OpenGL-ch2_第3张图片

(materialAmbient=(0,0,1)时的情况)

OpenGL-ch2_第4张图片

(materialAmbient=(0,1,0)时的情况)

同理,materialDiffuse定义了在漫反射时“物品的颜色”:

OpenGL-ch2_第5张图片

(materialDiffuse=1,0,0时的情况)

所以一般来说,materialAmbientmaterialDiffuse是同一个颜色

那么,为什么用材质而不是直接定义objectColor?用材质提供给我们更强大、细致的控制物品颜色的手段,能够实现更复杂的光照下的颜色

在正式进入多光源之前

其实在投光物那里就实现了多光源,先解释一个基本问题,然后再介绍多光源的实现方法

(1).到底光照效果是如何实现的(以白光为例)?

首先要进行一个思维上的转换:即概念-实现,或者可以说是3D-2D的转换,我们已经知道最终显示在屏幕上的都是一个个带有RGB值的像素(片段),当我们在设计光照时,我们总是在想:"这个光照达成的反射效果或者镜面效果如何如何(冯氏光照模型)",在下意识中,我们总是将"光线"实例化,但实际上光线是没有被真正实例化的,我们充其量获得了光源的位置向量,或者方向向量(方向光)。光源是具象的,具体的(至少知道顶点坐标),光线是抽象的,甚至在物理学中对光线都没有实际意义上的定义,这只是人用于帮助理解光照现象本质的而杜撰出来的模型。

那那些效果是个怎么回事?在前面第3部分介绍了vecn跟光混合与反射的关系,两个颜色向量相加=混合,两个颜色相乘=反射(不负责的),现在这么想,在物体上的有一部分要实现镜面反射,也就是说,物体这一部分要比其它部分更"亮"一些(更白一些,直白的说),反映到2D屏幕上时,在经过光栅化后,屏幕中的这一块的片段的颜色值要相比其他部分更高一些(更接近纯白色),要高多少?这就是我们的工作了,我们要在一系列的运算中最终得出这个参数,然后令这个参数与镜面反射光(vec3)相乘,得到最后应该输出的颜色结果。

要注意两件事:1.这里的相乘不是指"反射",而是这个参数是一个float,将其与反射光的vec3相乘,我们就可以对反射光的RGB3个分量修改,比如我们对(0.5f,0,0)乘以2.0f,那么结果的红色就要比先前更亮一些。2.在做这些任务时我们已经进入片段着色器阶段了,也即是说,我们已经完成了3D-2D的转换,所有的操作都是针对2D屏幕的片段的,而不是3D空间中"真实物体"

(2).多光源如何实现

理解了上文之后我们来讨论一下多光源的实现细节,对于单光源来说,在我们分别计算了全局、漫反射、镜面3种光照后,我们应该得到了3个vec3颜色,这3个vec3颜色分别对应这3种光照下某片段应该呈现的颜色,然后我们简单的将这个3个vec3混合,就很轻松的得到了片段在这3种光照下的真实颜色。

对多光源也一样,但由于不同种类的光源其计算各3个vec3的方式不一样(聚光需要判定切光角,点光需要光源位置,方向光需要光线方向向量),这就需要针对每个不同的光源分别计算其对应的3vec3,然后在最后统一混合(全部相加),这就得到了在多光源下片段的颜色(每个光源都是一个因素,记住这一点)

你可能感兴趣的:(OpenGL)