OpenGL学习笔记(四)-光照-材质-光照贴图

参考网址:LearnOpenGL 中文版
哔哩哔哩教程

第二章 光照

2.1 颜色

现实生活中人眼看到某一物体的颜色,是它所反射的颜色。如将白光照在红色的玩具上,玩具会吸收白光中除了红色以外的所有子颜色,不被吸收的红色光被反射到我们的眼中,让这个玩具看起来是红色的。
在这里插入图片描述
该颜色反射的定律运用在OpenGL时,给定光源颜色,把光源的颜色与物体的颜色值相乘,所得到的就是这个物体所反射的颜色。

glm::vec3 ambientColor(0.0f, 1.0f, 0.0f);
glm::vec3 objColor(1.0f, 0.5f, 0.31f);
glm::vec3 result = ambientColor * objColor; // = (0.0f, 0.5f, 0.0f);

将环境光和物体光设为uniform变量

uniform vec3 objColor;
uniform vec3 ambientColor;void main() 										
{										FragColor=vec4(objColor*ambientColor,1.0)* mix(texture(TextureA, TexCoord),texture(TextureB, TexCoord),0.2);//从外部输入的纹理图像ourTexture中,使用纹理坐标TexCoord进行采样			
}

在这里插入图片描述

2.2 基础光照

2.2.1 冯氏光照模型

冯氏光照模型的主要结构由3个分量组成:环境(Ambient)、漫反射(Diffuse)和镜面(Specular)光照。
在这里插入图片描述
2.2.2 环境光照

即使在黑暗的情况下,世界上也仍然有一些光亮。为模拟这种情况,使用一个很小的环境光照常量,添加到物体的最终颜色中。即便场景中没有直接的光源,也能看起来存在有一些发散的光。
环境光照分量ambient:光的颜色lightColor乘以一个常量环境因子ambientStrength

float ambientStrength=0.5;
vec3 ambient=ambientStrength*lightColor;

2.2.3 漫反射光照

漫反射光照使物体上与光线方向越接近的片段能从光源处获得更多的亮度。如果光线垂直于物体表面,这束光对物体的影响会最大化(更亮)。为了测量光线和片段的角度,使用片段法向量与光线方向向量的点乘计算。两个单位向量的点乘结果为一个标量,夹角越小,点乘结果越倾向于1,光对片段颜色的影响就应该越大。
在这里插入图片描述
1、片段法向量:把法线数据手工添加到顶点数据中,并更新顶点属性指针吗,就可以在顶点着色器中输入片段法向量。

  • 如何将法向量变换到世界坐标系:法向量只是一个方向向量,没有w分量,位移不会影响到法向量。因此,将法向量乘以模型矩阵中的旋转部分,只实施缩放和旋转变换,变换到世界坐标系中。
  • 当模型矩阵执行了不等比缩放,顶点的改变会导致法向量不再垂直于表面,通过法线矩阵可移除对法向量错误缩放的影响。
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;Normal= mat3(transpose(inverse(modelMat))) * aNormal;	
...

2、光线方向:通过光源的位置向量和片段的位置向量计算。

  • 光源的位置是一个静态变量,在片段着色器中把它声明为uniform vec3 lightPos

  • 片段位置位于世界坐标系中,可以通过把顶点位置属性乘以模型矩阵来把它变换到世界空间坐标。Frapos=vec3(modelMat*vec4(aPos, 1.0))

  • 光的方向向量是光源位置向量与片段位置向量之间的向量差。

    vec3 lightDir=normalize(lightPos-Frapos);
    vec3 norm=normalize(Normal);
    

3、漫反射光照:对norm和lightDir向量进行点乘,计算光源对当前片段实际的漫发射影响。结果值再乘以光的颜色,得到漫反射分量。两个向量之间的角度越大,漫反射分量就会越小。如果两个向量之间的角度大于90度,点乘的结果就会变成负数,将这些结果设为0。

float diff=max(dot(lightDir,norm),0.0);	
vec3 diffuse=diff*lightColor;

2.2.4 镜面光照

镜面光照依据光的方向向量、物体的法向量和观察方向决定。镜面光照是基于光的反射特性。如果从反射向量方向上观察表面所反射的光,镜面光照都会达到最大化。
在这里插入图片描述

1、 计算反射向量和视线方向的角度差,如果夹角越小,那么镜面光的影响就会越大。当我们去看光被物体所反射的那个方向的时候,会看到一个高光。

2、 把摄像机位置坐标viewPos传给片段着色器,使用摄像机位置viewPos和片段的位置Frapos来计算观察向量viewDir(视线方向)。利用reflect函数计算沿着法线轴的反射向量reflectDirreflect函数要求第一个向量是从光源指向片段位置的向量,对lightDir向量进行了取反。

uniform vec3 viewPos;vec3 viewDir=normalize(viewPos-Frapos);
vec3 reflectDir=reflect(-lightDir,norm);

3、定义一个镜面强度变量specularStrength,给镜面高光一个中等亮度颜色。

4、计算视线方向与反射方向的点乘,然后取它的32次幂。这个32是高光的反光度(Shininess)。一个物体的反光度越高,反射光的能力越强,散射得越少,高光点就会越小(这与幂函数的特性有关)。
在这里插入图片描述

float spec=pow(max(dot(viewDir,reflectDir),0.0),32);
vec3 specular=	specularStrength*spec*lightColor;

5、物体总的光照为三个分量之和

FragColor=vec4((ambient+diffuse+specular)*objColor,1.0);

在这里插入图片描述

2.3 材质

2.3.1 设置材质

1、在现实世界里,每个物体会对光产生不同的反应。如果想要模拟多种类型的物体,必须为每个物体定义一个材质属性。

  • 在上一节中,已知影响物体视觉输出的有:(1)光的颜色,光的强度;(2)环境光照,漫反射光照,镜面光照;(3)物体材质颜色。
  • 在本节中,用四个分量定义物体材质颜色:环境光反射率、漫反射率、镜面反射率和光泽度。通过为每个分量指定一个颜色,就能够精确控制材质颜色。
  • 材质可以理解为对光的反射特性。例如树叶看起来是绿色的,是因为树叶反射了绿色的光。剥离掉树叶这种物质,提取出树叶对光“处理”的特性,这就叫树叶材质
    在这里插入图片描述

2、在片段着色器中,创建一个结构体(Struct)来储存物体的材质属性。

  • ambient定义了在环境光照下这个物体反射的颜色,通常这是和物体颜色相同的颜色;
  • diffuse定义了在漫反射光照下物体的颜色,通常也要设置为我们需要的物体颜色;
  • specular定义了镜面光照对物体的颜色影响;
  • shininess影响镜面高光的散射/半径。
#version 330 core
struct Material {vec3 ambient;vec3 diffuse;vec3 specular;float shininess;
}; uniform Material material;
  • 上一节中,物体的视觉输出
void main()
{// 环境光vec3 ambient = ambientStrength * lightColor* objectColor;// 漫反射 vec3 diffuse = lightColor*(diff *objectColor) ;// 镜面光vec3 specular = specularStrength* lightColor * (spec* objectColor) ;  //物体vec3 result = ambient + diffuse + specular ;FragColor = vec4(result, 1.0);
} 
  • 将物体材质颜色改用三个分量表示,则片段着色器中物体视觉输出为
void main()
{    // 环境光vec3 ambient = ambientStrength * lightColor * material.ambient;// 漫反射 vec3 diffuse = lightColor * (diff * material.diffuse);// 镜面光vec3 specular = specularStrength*lightColor * (spec * material.specular);  //物体vec3 result = ambient + diffuse + specular;FragColor = vec4(result, 1.0);
}

3、在渲染主函数中,定义一个材质类,创建材质对象

Material(Shader *_shader, glm::vec3 _ambient, glm::vec3 _diffuse, glm::vec3 _specular, float _shiness);

利用材质类对象,对着色器中的材质变量进行赋值

//设置材质的反射率
myMaterial->shader->setVec3f("material.ambient", myMaterial->ambient);
myMaterial->shader->setVec3f("material.diffuse", myMaterial->diffuse);
myMaterial->shader->setVec3f("material.specular", myMaterial->specular);
myMaterial->shader->setFloat("material.shiness", myMaterial->shiness);

2.3.2 设置光照

光源对环境光、漫反射和镜面光分量也具有着不同的强度。上一节,通过使用一个强度值改变环境光和镜面光强度。本节中,需要为每个光照分量都指定一个强度向量。

1、创建光源结构体。环境光照通常会设置为一个比较低的强度,不希望环境光颜色太过显眼。光源的漫反射分量通常设置为光所具有的颜色,通常是一个比较明亮的白色。镜面光分量通常会保持为vec3(1.0),以最大强度发光。

struct Light {vec3 position;vec3 ambient;vec3 diffuse;vec3 specular;
};uniform Light light;

2、更新着色器

void main() 										
{		//环境光照vec3 ambient=light.ambient*material.ambient;//漫反射光照vec3 diffuse=light.diffuse*(diff*material.diffuse);//镜面光照vec3 specular=light.specular*(spec*material.specular);//物体FragColor=vec4(ambient+diffuse+specular,1.0);		
}

3、设置光照强度

//设置光源变量
myShader->setVec3f("light.position", glm::vec3(8.0f, 10.0f, 5.0f));
myShader->setVec3f("light.ambient",glm::vec3 (0.2f, 0.2f, 0.2f));
myShader->setVec3f("light.diffuse", glm::vec3(0.5f, 0.5f, 0.5f));
myShader->setVec3f("light.specular", glm::vec3(1.0f, 1.0f, 1.0f));

2.4 光照贴图

上一节中的那个材质系统它只是一个最简单的模型,所以引入漫反射和镜面光贴图(Map)。对物体的漫反射分量(以及间接地对环境光分量,它们几乎总是一样的)和镜面光分量有着更精确的控制。

2.4.1 漫反射贴图

1、目的:根据片段在物体上的位置来获取颜色,对物体的每个片段单独设置漫反射颜色。

2、实现:通过一个纹理(覆盖物体的图像),逐片段索引其独立的颜色值。在光照场景中被称为漫反射贴图(Diffuse Map),表现了物体所有的漫反射颜色的纹理图像。

3、将Material结构体中的vec3漫反射分量替换为sampler2D类型的漫反射贴图。

  • 由于环境光颜色在几乎所有情况下都等于漫反射颜色,移除了环境光材质颜色分量。

  • sampler2D是不透明类型(Opaque Type),不能实例化,只能通过uniform来定义它。Material结构体封装了不透明类型变量diffuse,因此只能使用uniform实例化这个结构体。

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

4、通过纹理采样器和纹理坐标,即可从纹理中采样片段的漫反射颜色值,通过该颜色值就可影响漫反射分量的大小,颜色值较大的地方,漫反射分量大。

vec3 ambient = light.ambient * vec3(texture(material.diffuse, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(material.diffuse, TexCoords));

5、在顶点数据中加入纹理坐标,更新属性指针,传入顶点坐标

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
...
out vec2 TexCoords;void main()
{...TexCoords = aTexCoords;
}

6、加载图像作为纹理,将纹理与纹理单元绑定,并将纹理单元赋值到material.diffuse这个uniform采样器中。

LoadImageToGPU("container2.png", GL_RGBA, GL_RGBA, 0);glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, myMaterial->diffuse);myMaterial->shader->setInt("material.diffuse", 0);

在这里插入图片描述
2.4.2 镜面光贴图

1、在上图中,木质箱子不应该有这么强的镜面高光的,可以将材质镜面光分量设置为vec3(0.0)来解决,但这也意味着钢制边框将不再能够显示镜面高光了。因此,希望可以让物体的某些部分以不同的强度显示镜面高光。

2、同样使用一个镜面高光的纹理贴图,根据纹理贴图的灰度值(或者颜色值),来定义物体每部分的镜面光强度。
在这里插入图片描述
3、镜面高光的强度可以通过图像每个像素的灰度值获取。镜面光贴图上的每个像素都可以由一个颜色向量来表示,在片段着色器中,取样对应的颜色分量并将它乘以光源的镜面强度。一个像素越「白」,乘积就会越大,物体的镜面光分量就会越亮。由于木头材质应该没有镜面高光,所以镜面高光贴图的整个木头部分全部都转换成了黑色。

4、在片段着色器中,设置镜面光贴图的采样器

struct Material {sampler2D diffuse;sampler2D specular;float     shininess;
};vec3 specular = light.specular * spec * vec3(texture(material.specular, TexCoords));

5、在主程序中,同样加载图像作为贴图

Material* myMaterial = new Material(myShader, LoadImageToGPU("container2.png", GL_RGBA, GL_RGBA, Shader::DIFFUSE),LoadImageToGPU("container2_specular.png", GL_RGBA, GL_RGBA, Shader::SPECULAR),32.0f );myMaterial->shader->setInt("material.specular", Shader::SPECULAR);//采样器与纹理单元绑定

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/354250.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

三维建模贴图技巧

作者:关宇 #一、概述 整个三维项目中建模制作为核心环节,决定了整个项目的框架基础。在制作的时候参考数据尤为重要决定了模型的精度。 一个完整的三维模型包括白模和贴图,白模决定了模型的外形结构,而贴图赋予色彩和细节。 个人…

提升树叶渲染性能

树的渲染的大部分消耗都是花在树叶上,为了是树叶看起来很茂密,美术一般会加很多叶子的三角形,但是三角形太多的话会让vs压力很大,因为树叶的动画都是在vs里完成的,因此大多游戏都采用的是Leaf Card也就是Billboard Lea…

【Unity Shader】树叶晃动效果原理及实现

1 树叶晃动原理 在模型空间下,对顶点进行X轴和Y轴上的偏移。 1.1 方法 通过计算顶点与Y轴单位向量的点积求得stage1。通过计算顶点与X轴单位向量的点积,加上时间分量_Time.y,求其正弦值stage2。将stage1/stage2与向量(0.001, 0, 0.001)相乘…

blender 2.8制作面片树叶的shading node设置

1. 创建Pricipled BSDF材质,并设置材质Settings的Blend Mode为Alpha Blend模式! 2. 在shading窗口内设置节点: 添加下列节点 Texture Coordinate Mapping Image Texture Image Texture Transparent BSDF Principled BSDF Mix Shader Material Output…

【UE4 Material 101学习笔记】 :Lec08/10/11/12 视差贴图的应用/布料着色/体积冰效果/树叶摇动

Lec08 视差贴图 原理 LearnOpenGL视差贴图 1. 使用高度图偏移UV 未使用高度贴图偏移UV时 使用之后,表面不平坦产生的阴影会更为明显一些。 当角度较大时,失真比较明显。 2. 视差遮蔽映射(Parallax Occlusion Mapping) 可弥…

UE风格化Day19-树叶材质

材质蓝图的基础技巧 补充一些材质蓝图的基础技巧,虽然比较基础,但是刚开始学的时候完全没有教程专门提到这个: 材质的管理一般分为:材质函数、材质、材质实例 首先网格体一般挂的材质就是用材质实例,当然也可以直接挂…

Quixel megascans模型材质贴图合集包

Quixel megascans是一个在线高分辨率扫描模型和贴图库,一致的PBR校准的表面,植被,和三维扫描模型,还包括用于管理的桌面应用、混合和输出你的扫描数据的程序。它的产品已经与游戏和电影工作室合作。 quixel megascans可以帮助您创…

自动化测试Junit

目录 Junit5注解TestDisabledBeforeAll、AfterAll、BeforeEach、AfterEach 参数化单参数多参数CSV获取参数方法获取参数 测试用例执行顺序断言 assert断言相等断言不相等断言为空断言不为空 测试套件 自动化测试项目1. 熟悉项目2. 针对核心流程设计手工测试用例3. 将手工测试用…

解释PBR纹理贴图(texture-maps)

纹理贴图,不管你是学习sp绘制纹理,还是利用渲染器创造艺术作品,接触到PBR流程,总要面对各种贴图。我在学习的时候,有时候搞得懂,有时候糊里糊涂,我想还是要做个笔记的,好记性不如烂笔…

PBR贴图基础知识

PBR贴图基础知识 一,基础知识二,PBR贴图类型传统次世代方式PBR次世代方式1,金属度粗糙度流程---Base ColorMetallicRoughness2,反射度光滑度流程---Diffuse/AlbedospecularGlossiness/Smoothness3,通用贴图类型法线贴图…

UE4 Material 101学习笔记——08-12 凹凸和视差贴图/纹理压缩/布料/体积冰/摇曳树叶

UE4 Material 101学习笔记——08-12 凹凸和视差贴图/纹理压缩/布料/体积冰/摇曳树叶 Lec08 凹凸和视差贴图 Bump Offset and Parallax Occlusion MappingLec09 纹理压缩与设置 Texture Compression and SettingsLec10 布料着色器 Cloth Shading10.1 了解布料10.2 布料shader Le…

技术美术个人笔记(十四)——Houdini程序化树木

前言:关于大地形美术资产制作部分的houdini程序化树木部分,原houdini内置有Labs Quick Basic Trees节点,以下步骤均基于此节点优化魔改; 效果预览: tip:其中树叶贴图及地形颜色变化通过在材质中对贴图采样…

CSS3+js绘制3D圣诞树

最近大家都在用代码写圣诞树,我也跟个风吧! 主要技术: 1.CSS3的3D变换 2.DOM动态添加节点 开发环境:vscode 目录 一.引入 二、基本知识 1.CSS3的3D变换 (1).空间直角坐标系 (2).transform详解 (3).transform-style 2.DOM节点…

unity透明通道加颜色_树叶透明贴图的制作原理及渲染!

对于很多刚开始接触渲染模块的同学来说,不知道透明贴图的制作原理,以及如何渲染出好的效果,今天结合案例给大家讲解一下,先打开我们需要的素材,如下图: 在制作之前我们先给树叶一个普通的blinn材质&#xf…

SpringBootWeb案例-2(上)

前面我们已经实现了员工信息的条件分页查询以及删除操作。 关于员工管理的功能,还有两个需要实现: 新增员工修改员工 首先我们先完成"新增员工"的功能开发,再完成"修改员工"的功能开发。而在"新增员工"中&…

微调样本质量胜于数量 LIMA: Less Is More for Alignment

1、总体介绍 大型语言模型的训练分为两个阶段:(1)从原始文本中进行无监督的预训练,以学习通用的表征;(2)大规模的指令学习和强化学习,以更好地适应最终任务和用户的偏好。 作者通过…

XP系统如何把文本转换成html,xp系统下将HTML文件设置为屏保的方法

关于XP系统的屏保设置,很多人脑子中肯定有个固定的样式,因为按照XP系统的传统来说,都是固定的按照图片来设置的,所以很多人就对屏保有了一定的硬性思维,就是只能是图片的形式。其实这样的想法是有所偏差的,…

linux6禁用屏幕保护程序,禁用屏幕保护程序(ScreenSaver Disabled)

禁用屏幕保护程序ScreenSaverDisabled是一款可以帮助用户朋友让自己的电脑不要总是被屏幕保护影响,有些设置隔三差五就会进入屏保状态,使用这款禁用屏幕保护程序ScreenSaverDisabled可以帮您解决这个烦恼。 相关软件软件大小版本说明下载地址 禁用屏幕保…

xp系统怎么定时锁定计算机,电脑怎么设置自动锁屏_XP系统电脑怎么设置自动锁屏...

摘要 腾兴网为您分享:XP系统电脑怎么设置自动锁屏,字体配置,智慧大学,掌上新华,小t智联等软件知识,以及mp3音乐裁剪器,小霸王,屏幕分屏软件,湖北网上税务局,照片印刷&…

汉字时钟屏保软件/汉字时钟电脑屏幕保护下载/汉字时钟屏保/windows屏保

软件名称:冷高轮时间汉字时钟屏保 软件语言:简体中文 软件类别:桌面工具 软件授权:免费软件 适用平台:WinXP, Win7, Win8, Win10, WinAll 电脑壁纸下载可在wallpaper engine或者upupoo上搜索全称“冷高轮时间‘ …