现代OpenGL教程(九):基础光照——材质(ImGui+OpenGL3.3)

前言:该系列教程主要参考自网站www.opengl-tutorial.orglearnopengl.com/,基于开源GUI框架imgui v1.61实现,imgui自带的例子里面直接集成了glfw+gl3w环境,本系列教程将gl3w换成了glew,glew具体环境配置可参考:OpenGL环境配置教程:VS2012 + GLEW + GLFW + GLM

教程目录(持续更新中):
现代OpenGL教程(一):绘制三角形(ImGui+OpenGL3.3)
现代OpenGL教程(二):矩阵变换(ImGui+OpenGL3.3)
现代OpenGL教程(三):绘制彩色立方体(ImGui+OpenGL3.3)
现代OpenGL教程(四):立方体纹理贴图(ImGui+OpenGL3.3)
现代OpenGL教程(五):obj模型加载(ImGui+OpenGL3.3)
现代OpenGL教程(六):鼠标和键盘(ImGui+OpenGL3.3)
现代OpenGL教程(七):基础光照——颜色(ImGui+OpenGL3.3)
现代OpenGL教程(八):基础光照——Phong光照模型(ImGui+OpenGL3.3)
现代OpenGL教程(九):基础光照——材质(ImGui+OpenGL3.3)


本节概要

本节教程在上一节(现代OpenGL教程(八):基础光照——Phong光照模型(ImGui+OpenGL3.3)的基础上,重构了部分片段着色器的代码,并模拟了多种材质。本节完整代码下载地址:https://github.com/maijiaquan/blog-code/tree/master/opengl-material

运行效果如下:


往期回顾

前一节的教程中,我们知道OpenGL如何表达颜色:

  • 物体颜色objColor:吸收光线后,反射出来的光的颜色
  • 物体颜色 × \times × 光源颜色 能够模拟反射现象

上一节的教程中,我们知道了Phong光照模型的原理:

  • 环境光分量:ambient = lightColor
  • 漫反射光分量:diffuse = lightColor * diff,其中,diff为光线和法线夹角 θ \theta θ的余弦值
  • 镜面光分量:specular = lightColor * spec,其中spec为视线和反射光线夹角的余弦值的反光度次幂
  • 片段的颜色fragColor = objColor * (ambient + diffuse + specular)

将片段颜色计算公式的括号展开,则有:

  • 环境光颜色值:ambientColor = objColor * ambient
  • 漫反射光颜色值:diffuseColor = objColor * diffuse
  • 镜面光颜色值:specularColor = objColor * specular
  • 片段的颜色fragColor = ambientColor + diffuseColor + specularColor

设置物体的材质

为了更精细地描绘物体材质,我们不再使用单一的物体颜色objColor来描述物体的材质,而是用4个材质向量来描述:

  • material.ambient:设置了在环境光照下物体反射的颜色,通常就是物体的颜色
  • material.diffuse:设置了在漫反射光照下物体反射的颜色
  • material.specular:设置了在镜面光照下物体反射的颜色
  • material.shininess:其实就是反光度,但一般不同的材质反光度不一样,所以也把反光度作为材质的属性

在片段着色器中,将material定义成结构体,可以更方便地管理这4个材质向量:

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

片段颜色输出的公式变成:

  • 环境光颜色值:ambientColor = material.ambient * ambient
  • 漫反射光颜色值:diffuseColor = material.diffuse * diffuse
  • 镜面光颜色值:specularColor = material.specular * specular
  • 片段的颜色fragColor = ambientColor + diffuseColor + specularColor

ambient,diffusespecular展开,上述公式变成:

  • 环境光颜色值:ambientColor = material.ambient * lightColor
  • 漫反射光颜色值:diffuseColor = material.diffuse * lightColor * diff
  • 镜面光颜色值:specularColor = material.specular * lightColor * spec
  • 片段的颜色fragColor = ambientColor + diffuseColor + specularColor

转换成片段着色器代码:

void main()
{    
    // 1.ambient
    vec3 ambientColor = lightColor * material.ambient;

    // 2.diffuse 
    vec3 norm = normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);
    float diff =  max(dot(norm, lightDir), 0.0);
    vec3 diffuseColor = lightColor * diff * material.diffuse;

    // 3.specular
    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);  
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specularColor = lightColor * spec * material.specular;  

    vec3 result = ambientColor + diffuseColor + specularColor;
    FragColor = vec4(result, 1.0);
}

网站 http://www.barradeau.com/nicoptere/dump/materials.html 列出了常用的一些材质属性,根据这些属性绘制出来的材质效果如下:

本节完整代码下载地址:https://github.com/maijiaquan/blog-code/tree/master/opengl-material


参考资料:
材质 - LearnOpenGL CN

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值