OPENGL学习笔记之十二

#OPENGL学习笔记之十二
2019/3/6

阅读材料来自learnopengl.com以及learnopengl-cn.github.io

在现实世界里,每个物体会对光产生不同的反应。每个物体对镜面高光也有不同的反应。有些物体反射光的时候不会有太多的散射(Scatter),因而产生一个较小的高光点,而有些物体则会散射很多,产生一个有着更大半径的高光点。我们考虑定义一个材质(Material)属性来模拟不同属性的物体。
我们考虑在glsl中引入结构体帮助我们简化代码:
材质颜色(Material Color):环境光照(Ambient Lighting)、漫反射光照(Diffuse Lighting)和镜面光照(Specular Lighting)。三个分量添加反光度(Shininess),我们就能够对物体的颜色输出有着精细的控制了。

//片段着色器中,冯氏光照模型的分量都定义一个颜色向量
#version 330 core
struct Material {
    vec3 ambient;//在环境光照下这个物体反射得是什么颜色,通常这是和物体颜色相同的颜色
    vec3 diffuse;//在漫反射光照下物体的颜色(和环境光照一样),漫反射颜色也要设置为我们需要的物体颜色
    vec3 specular;//镜面光照对物体的颜色影响(或者甚至可能反射一个物体特定的镜面高光颜色)
    float shininess;//影响镜面高光的散射/半径
}; 
uniform Material material;

面的图片展示了几种现实世界的材质对我们的立方体的影响:
不同材质的立方体

为一个物体赋予一款合适的材质是非常困难的,这需要大量实验和丰富的经验,所以由于不合适的材质而毁了物体的视觉质量是件经常发生的事。

材质系统

//在片段着色器中
void main()
{    
    // 环境光
    vec3 ambient = lightColor * material.ambient;//改成用结构体中的属性

    // 漫反射 
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = lightColor * (diff * material.diffuse);//改成用结构体中的属性

    // 镜面光
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);  
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = lightColor * (spec * material.specular);  //改成用结构体中的属性

    vec3 result = ambient + diffuse + specular;
    FragColor = vec4(result, 1.0);
}

//在主程序中
lightingShader.setVec3("material.ambient",  1.0f, 0.5f, 0.31f);//环境光设置成我们想要让物体所拥有的颜色
lightingShader.setVec3("material.diffuse",  1.0f, 0.5f, 0.31f);//漫反射分量我们想要让物体所拥有的颜色
lightingShader.setVec3("material.specular", 0.5f, 0.5f, 0.5f);//镜面分量设置为一个中等亮度的颜色
lightingShader.setFloat("material.shininess", 32.0f);

这里我们的程序告一段落,但是发现这个物体太亮了。物体过亮的原因是环境光、漫反射和镜面光这三个颜色对任何一个光源都会去全力反射。然而其实光源对环境光、漫反射和镜面光分量也具有着不同的强度。
我们为光照设置一个类似的结构体,其中的属性来影响每个单独的光照分量

struct Light {
    vec3 position;

    vec3 ambient;//通常会设置为一个比较低的强度,因为我们不希望环境光颜色太过显眼
    vec3 diffuse;//通常设置为光所具有的颜色,通常是一个比较明亮的白色
    vec3 specular;//镜面光分量通常会保持为vec3(1.0),以最大强度发光
};
uniform Light light;

一个光源对它的ambient、diffuse和specular光照有着不同的强度。注意我们也将光源的位置添加到了结构体中。

//更新片段着色器
vec3 ambient  = light.ambient * material.ambient;
vec3 diffuse  = light.diffuse * (diff * material.diffuse);
vec3 specular = light.specular * (spec * material.specular);

//主程序中设置光照属性
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); 

这一节的内容就彻底完成了,跑完程序后我们会发现,光照的效果会穿过物体到达背面,因为我们的立方体暂时为中空透明的,这个问题相信在以后会有解决的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值