基础光照

一、冯氏光照模型

其主要结构由3个分量组成:环境(ambient)、漫反射(diffuse)、镜面(specular)光照。下边这张图展示了这些分量看起来的样子:

环境光照:即使在黑暗的环境下,世界上通常也仍然有一些光亮(月亮、远处的光),所以物体几乎永远不是完全黑暗的。为了模拟这种效果,我们会使用一个环境光照常量,它永远会给物体一些颜色。

漫反射光照:模拟光源对物体的方向性影响。它是冯氏光照模型中最显著的分量。物体的某一部分越是正对着光源,它就会越亮。

镜面光照:模拟有光泽物体上面出现的亮点。

二、环境光照

把环境光照添加到场景里非常简单,用光的颜色乘以一个很小的常量环境因子,再乘以物体的颜色,然后将最终结果作为片段的颜色。

1 void main(){
2     float ambientStrength = 0.1;//一个很小的常量环境因子
3     vec3 ambient = ambientStrength * lightColor;
4
5     vec3 result = ambient * lightColor;
6     FragColor = vec4(result,1.0f);
7 }

运行结果:

立方体非常暗,但是应用了环境光,所以不是全黑。

三、漫反射光照

环境光照本身不能提供显著的结果,漫反射可以对物体产生显著的视觉效果。漫反射光照使物体上与光线方向越接近的片段能从光源处获得更多的亮度。

如果光线垂直于物体表面,那么这束光会对物体的影响最大化。为了测量光线和片段的角度,我们使用法向量(黄色箭头)。

注:为了只得到两个向量夹角的余弦值,我们使用单位向量,所以我们需要确保点乘的向量都要经过标准化。

计算漫反射光照需要什么?

1>法向量:一个垂直于顶点表面的向量

2>定向的光线:光源位置与片段位置的向量差。

四、法向量

我们把法向量加入到顶点数据中,更新立方体的顶点着色器

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;out vec3 normal;void main(){  gl_Position = projection * view * model * vec4(aPos,1.0f);  normal = aNormal;}

五、计算漫反射光照

1、在片段着色器中将光源位置设为uniform

2、我们在世界空间中进行所有的光照计算,因此我们需要一个在世界空间中的顶点位置。我们可以通过把顶点位置属性乘以模型矩阵(不是观察和投影矩阵)来把它变换到世界空间坐标。在顶点着色器中:

out vec3 FragPos;
out vec3 Normal;

void main()
{
    gl_Position = projection * view * model * vec4(aPos, 1.0);
    FragPos = vec3(model * vec4(aPos, 1.0));
    Normal = aNormal;
}

3、在片段着色器中添加光照计算

1>计算光照方向

1 vec3 normal = normalize(normal);
2 vec3 lightDir =  normalize(lightPos - FragPos);

计算光照时一定对向量进行单位化,只关心方向

2>计算漫反射分量

我们对normlightDir向量进行点乘,计算光源对当前片段实际的漫发射影响。结果值再乘以光的颜色,得到漫反射分量。两个向量之间的角度越大,漫反射分量就会越小:

1 float diff = max(dot(norm,lightDir),0);
2 vec3 diffuse = diff * lightColor;

如果两个向量之间的角度大于90度,点乘的结果就会变成负数,这样会导致漫反射分量变为负数。为此,我们使用max函数返回两个参数之间较大的参数,从而保证漫反射分量不会变成负数。因为负数的光照是没有定义的。

现在我们有了环境光分量和漫反射分量,我们把它们相加,然后把结果乘以物体的颜色,来获得片段最后的输出颜色。

1 vec3 result = (ambient + difuse) * objectColor;
2 FragColor = vec4(result,1.0);

六、镜面光照

也是根据光的方向向量和物体的法向量来决定的,但也依赖于观察方向

vec3 reflectDir = reflect(-lightDir, norm);

需要注意的是我们对lightDir向量进行了取反。reflect函数要求第一个向量是光源指向片段位置的向量,但是lightDir当前正好相反,是从片段指向光源(由先前我们计算lightDir向量时,减法的顺序决定)。为了保证我们得到正确的reflect向量,我们通过对lightDir向量取反来获得相反的方向。第二个参数要求是一个法向量,所以我们提供的是已标准化的norm向量。

我们先计算视线方向与反射方向的点乘(并确保它不是负值),然后取它的32次幂。这个32是高光的反光度(Shininess)。一个物体的反光度越高,反射光的能力越强,散射得越少,高光点就会越小。在下面的图片里,你会看到不同反光度的视觉效果影响:

我们不希望镜面成分过于显眼,所以我们把指数保持为32。

原文地址:https://www.cnblogs.com/keguniang/p/9969586.html

时间: 2024-10-10 10:09:15

基础光照的相关文章

OpenGL(十一) 可编程管线 基础光照 的实现

在OpenGL中创建 基础光照 ,主要的工作将模型中的法线信息和法线空间运算矩阵传入到shader中.另一方面,LightDir,ViewDir通常是在shader中从引擎参数获取的,为了简化光照模型的实现,这里我们可以在shader中写死.至于经典的 ambient+diffuse+specular 光照原理,不是本文的重点,就在shader中一笔带过了. 原理 通过函数 glm::mat4 normalMatrix = glm::inverseTranspose(s_shaderData.m

颜色,基础光照,材质。

本片blog主要是为了整理脑内一些混杂的知识. 颜色: 大自然中的物体都有着自己独一无二的颜色,我们需要用电脑去模拟这种颜色(尽管是用有限的电脑颜色去模拟无限的自然界存在的颜色,但是你基本看不出来区别). 严格地说,平时生活中我们看到的某一个物体的颜色并不是它本身的颜色,而是它所反射(reflected)出来的颜色:想象一下,你在黑暗中看到自己的手基本是黑乎乎的一片,这就是它在弱光条件下所反射出来的颜色.也就是说,在不同的光源条件下,物体会反射出不同的颜色(也就是物体不吸收的光).这也就是我们需

第五章 Unity中的基础光照(2)

目录 1. Unity中的环境光和自发光 2. 在UnityShader中实现漫反射光照模型 2.1 实践:逐顶点光照 2.2 实践:逐像素光照 2.3 半兰伯特模型 1. Unity中的环境光和自发光 在标准光照模型中,环境光和自发光的计算是最简单的. 在Unity中,场景中的环境光可以在Window->Lighting->Ambient Source/Ambient Intensity中控制,如下图所示.在Shader中,我们只需要通过Unity的内置变量UNITY_LIGHTMODEL_

Unity Shader入门精要学习笔记 - 第6章 开始 Unity 中的基础光照

转自冯乐乐的<Unity Shader入门精要> 通常来讲,我们要模拟真实的光照环境来生成一张图像,需要考虑3种物理现象. 首先,光线从光源中被发射出来. 然后,光线和场景中的一些物体相交:一些光线被物体吸收了,而另一些光线被散射到其他方向. 最后,摄像机吸收了一些光,产生了一张图像. 在光学中,我们使用辐照度来量化光.对于平行光来说,它的辐照度可通过计算在垂直于l的单位面积上单位时间内穿过的能量来得到.在计算光照模型时,我们需要知道一个物体表面的辐照度,而物体表面往往是和l不垂直的,我们可以

Unity Shader 之 基础光照

摄像机是如何看这个世界的 游戏中摄像机所看到的世界与我们现实中所看到的几乎是一样的. 首先,光线从光源中发射出来. 然后,光线和场景中的一些物体相交(散射,吸收). 最后,摄像机吸收了一些光,产生一张图像. 光线与物体相交的结果有两个:散射(scattering)和吸收(absorption) 散射:只改变光线的方向,但不改变光线的密度和颜色,有两种方向:内部与外部,对应折射与反射. 折射(refraction):散射到物体内部,用漫反射(diffuse)模型来计算. 反射(reflection

颜色和基础光照

一: 颜色 我们在现实生活中看到某一物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的(Reflected)颜色. 那些不能被物体所吸收(Absorb)的颜色(被拒绝的颜色)就是我们能够感知到的物体的颜色. 白色的阳光实际上是所有可见颜色的集合,物体吸收了其中的大部分颜色.它仅反射了代表物体颜色的部分,被反射颜色的组合就是我们所感知到的颜色. 当我们在OpenGL中创建一个光源时,我们希望给光源一个颜色.在上一段中我们有一个白色的太阳,所以我们也将光源设置为白色.当我们把光源的颜色与物体的颜

OpenSceneGraph基础:光照

效果: 接着前篇进行(http://blog.csdn.net/boksic/article/details/44002155),现在考虑光照效果 主程序 转载请注明http://blog.csdn.net/boksic 如有疑问欢迎留言 和之前基本唯一的变化就是把窗口部分的操作放在初始化函数initCanvas里进行. int main(int argc, const char* argv[]) { osg::Group *scene = startupScene(); osg::ref_pt

立方体贴图(Cubemap)

http://blog.csdn.net/asdjy123/article/details/51190643 点击打开链接 好东西保存方便查看 立方体贴图(Cubemap) 原文 Cubemaps 作者 JoeyDeVries 翻译 Django 校对 Geequlim 我们之前一直使用的是2D纹理,还有更多的纹理类型我们没有探索过,本教程中我们讨论的纹理类型是将多个纹理组合起来映射到一个单一纹理,它就是cubemap. 基本上说cubemap它包含6个2D纹理,这每个2D纹理是一个立方体(cu

Unreal SDK 游戏开发从入门到精通(UnrealScript语法、UI Scene界面、UDK独立开发游戏)

对这个课程有兴趣的朋友可以加我的QQ2059055336和我联系 课程内容简介 本系列讲座主要讲述如何利用UDK开发游戏程序. 本课程主要分为四个部分: 1.学习UnrealScript的基本语法, 为下面的学习打下良好的基础 2.系统学习UDK的主要模块, 熟悉并掌握游戏开发的各个系统 3.使用UDK独立开发游戏Demo, 体验和理解UDK对游戏开发流程的整合 课程大纲 第一章初步接触Unreal SDK 1.1 Unreal sdk简介aaa 1.2 UC语言的基本介绍 1.3 搭建UDK的