颜色,基础光照,材质。

本片blog主要是为了整理脑内一些混杂的知识。


  • 颜色:

大自然中的物体都有着自己独一无二的颜色,我们需要用电脑去模拟这种颜色(尽管是用有限的电脑颜色去模拟无限的自然界存在的颜色,但是你基本看不出来区别)。

严格地说,平时生活中我们看到的某一个物体的颜色并不是它本身的颜色,而是它所反射(reflected)出来的颜色:想象一下,你在黑暗中看到自己的手基本是黑乎乎的一片,这就是它在弱光条件下所反射出来的颜色。也就是说,在不同的光源条件下,物体会反射出不同的颜色(也就是物体不吸收的光)。这也就是我们需要去处理的东西。

首先我们先定义一个物体自身的颜色:

//珊瑚红
glm::vec3 coral(1.0f, 0.5f, 0.31f);

接着我们定义一下白色的光源(也就是太阳光),然后把光源与物体本身的颜色相乘,得到的值为这个物体所反射出来的光:

//定义光源
glm::vec3 light(1.0f, 1.0f, 1.0f);
//相乘:反射出来的光
glm::vec3 result = coral * light;  

由此我们可以定义物体的颜色为物体从一个光源反射各个颜色分量的大小。自然而然,换个别的光源,反射出来的光也就变了:

glm::vec3 light2(0.51f, 0.23f, 0.87f);
glm::vec3 result2 = coral * light2;

并且显然,如果我们在OpenGL中要显示出物体的颜色的话,需要将颜色值结果赋值给FragColor。


  • 基础光照:现实世界的光很复杂,想要全部模拟出来基本不可能,因此我们会使用一些简化的光照模型,其中一个叫做冯氏光照模型(Phong Lighting Model)。冯氏光照模型由三个分量组成:环境 (ambient), 漫反射(diffuse),镜面(specular)光照。
  1. 先说环境(ambient),我们知道即便在黑暗环境下,也或多或少地存在一些光亮(这里不说直接的光源,有时候光亮由其他物体反射光源形成),为了模拟这个,就出现了环境光照:
//fragment shader
void main()
{
    float ambientStrength = 0.1f;
    float ambient = light * ambientStrength;

    glm::vec3 result = ambient * coral;
    FragColor = vec4(result, 1.0f);
}

注:这里引入了ambientStrength,是考虑到环境光不像直接的光源那么强。在后面的材质篇章会提出新的解决方法:光源分量。

  2. 接下来是漫反射(diffuse),我们知道在不光滑的平面上会出现漫反射这一现象,我们也同样需要去模拟它,那么怎么模拟呢?很简单,计算出光线与平面法线向量(normal vector)的夹角大小就行了,夹角越大,说明片段距离光源越远,影响也就越小(而这个夹角的大小我们可以通过使用点乘向量来展现,因为 a x b = |a||b|cos α。

//fragment shader
//the data of normal vector and the fragment position(world position) come from vertex shader,// the source data is vertices array,and the light position come from uniform variable

void main()
{
    vec3 norm = glm::normalize(Normal);
    vec3 lightDir = normalize(lightPos - FragPos);

    float diff = max(dot(norm, lightDir), 0.0f);
    vec3 diffuse = diffuse * light;   vec3 result = diffuse * coral;   FragColor = vec4(result, 1.0f);}

注:这里的diff可以看作是同第一部分环境光强度差不多的东西,后面也可以通过光源的漫反射分量来改变。

我们使用的是标准化之后的向量来简化运算,因为我们并不需要除了方向之外的东西。

还有一个值得注意的地方,就是法线向量(normal vector),在进行点乘运算之前,我们需要将法向向量转化为世界坐标(其他的各种坐标运算也是在世界坐标进行的),那么我们是直接乘以一个简单的模型矩阵(model matrix)就好了吗?非也。首先法向向量只是一个方向向量,不能表示空间中的位置,因此我们必须保证位移不能影响到它,其次,如果有不等比缩放的问题,也会影响到法向向量。

为了应对上述的问题,我们需要使用一个专门定制的模型矩阵,称之为法向矩阵(Normal Vector),它定义为“模型矩阵左上角的逆矩阵的转置矩阵“,具体如何计算出来的参照这篇文章。我们可以在顶点着色器(你要在片段着色器中运算也Ok,不过会降低速度)中自己生成这个矩阵(当顶点个数多的时候,这个运算建议在cpu运行,也就是主程序中,因为开销比较大)

//aNormal is the normal vector in local space

Normal = mat3(transpose(inverse(model))) * aNormal;

  • 镜面光照:第三部分,也就是最后一部分,也称之为高光反射(heightlight reflection)。嗯,明天再写。

原文地址:https://www.cnblogs.com/zhlabcd/p/11650852.html

时间: 2024-10-13 03:23:04

颜色,基础光照,材质。的相关文章

【浅墨Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法&颜色、光照与材质

本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442 邮箱: [email protected] 本篇文章中,我们学习了Unity Shader的基本写法框架,以及学习了Shader中Properties(属性)的详细写法,光照.材质与颜色的具体写法.写了6个Shader作为本文S

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

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

颜色和基础光照

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

第五章 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

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

基础光照

一.冯氏光照模型 其主要结构由3个分量组成:环境(ambient).漫反射(diffuse).镜面(specular)光照.下边这张图展示了这些分量看起来的样子: 环境光照:即使在黑暗的环境下,世界上通常也仍然有一些光亮(月亮.远处的光),所以物体几乎永远不是完全黑暗的.为了模拟这种效果,我们会使用一个环境光照常量,它永远会给物体一些颜色. 漫反射光照:模拟光源对物体的方向性影响.它是冯氏光照模型中最显著的分量.物体的某一部分越是正对着光源,它就会越亮. 镜面光照:模拟有光泽物体上面出现的亮点.

转载 R语言颜色基础设置

原文链接:http://www.biostatistic.net/thread-5065-1-1.html R语言在画图形的时候,经常遇到颜色设定问题,用户可以根据color.rgb值和hsv值来设定不同的颜色.第一列是颜色,第二列是hsv,第三列是rgb<ignore_js_op> 在颜色设定时,最好是根据自己想要的颜色来设定.这样我们能做到心中有数.所有可以用下面方法来设定颜色,简单有效. library(grDevices);ramp <- colorRamp(c("re