颜色,基础光照,材质(二)

本篇blog讲一下关于材质的知识。


在前面中,我们通过设定几个光照分量以及物体本身的颜色,实现了物体的视觉输出(就是人眼看到的啦)。

设置材质:我们可以通过进一步地整合数据,来对物体的颜色进行更加严格的控制,既环境光照,漫反射光照,镜面光照三个分量,再加上反光度(为了方便理解,我们把这几个分量看成是物体本身的属性,也就是材质,同各个光照分量对应)。共四个分量,我们可以通过结构体来整合数据:

struct Material {
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
    float shininess;
};
uniform Material material;

在主程序,我们可以传入数据:

//in the main.cpp
void main()
{
    ...
    somethingShader.setVec3("material.ambient", 1.0f, 0.5f, 0.31f);
    somethingShader.setVec3("material.diffuse", 1,0f, 0.5f, 0.31f);
    somethingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f);
    somethingShader.setFloat("material.shininess", 32.0f);
    ...  
}

这里将物体的ambient和diffuse分量都设置为物体本来的颜色,而将specular设置为0.5是因为高光程度过高。接着,我们可以在片段着色器里面这么做:

//fragment shader
void main()
{
    vec3 ambient = light * material.ambient;
    ......
    ......
    vec3 result = ambient + diffuse + specular;
    FragColor = vec4(result, 1.0f);
}

这里和上一篇blog其实没有本质区别,上一篇blog我们是这么写的:

//fragment shader
void main()
{
    float ambientStrength = 0.1f;
    float ambient = light * ambientStrength;
    
    glm::vec3 result = ambient * coral;
    FragColor = vec4(result, 1.0f);
}

注:只看ambient部分,coral是物体的颜色,而material.ambient也是物体的颜色,两者都是将光源乘以物体本身颜色,要说有区别的话,就是原来的ambient实际上是光强度罢了(下面我们会将这个光强度也补齐)。

既然没有本质区别,那么我们为什么要这样做呢?答案是处于结构化的思维,并且我们可以直接在main.cpp函数中更改数据(而不用在fragment shader中去更改),同时我们可以更简单地让多个物体有多种不同的材质。


 

光的属性:在前面的blog中,我们还加入了强度这个东西,而引入它是因为光照强度的问题,不经过处理的话,物体的ambient, diffuse, specular会全力反射光,造成很亮眼的结果。因此这里,我们尝试创建单独的光照属性来影响每个单独的光照向量(请记住,本质上这和前面的strength没有任何区别,只是出于结构化的思维,以及可以直接在main.cpp函数中更改它。

这里我们创建一个和材质差不多的结构体:

struct Light {
    vec3 position;

    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};
uniform Light light;

传入数据:

lightingShader.setVec3("light.ambient",  0.2f, 0.2f, 0.2f);
lightingShader.setVec3("light.diffuse",  0.5f, 0.5f, 0.5f); // 将光照调暗了一些以搭配场景
lightingShader.setVec3("light.specular", 1.0f, 1.0f, 1.0f); 

然后更新着色器对应的代码:

vec3 ambient  = light.ambient * material.ambient;
vec3 diffuse  = light.diffuse * (diff * material.diffuse);
vec3 specular = light.specular * (spec * material.specular);
result = ambient + diffuse + specular;

这样子就完成了。

 

请记住,这种写法和前面的blog没有本质上的区别,只是出于结构化的思维,以及我们可以在main.cpp函数中自由地操纵数据。

 

posted @ 2019-10-11 14:48  jckcoenf  阅读(263)  评论(0编辑  收藏  举报