前言
光学中,我们是用辐射度来量化光。
光照按照不同的散射方向分为:漫反射(diffuse)和高光反射(specular)。高光反射描述物体是如何反射光线的,漫反射则表示有多少光线会被折射、吸收和散射出表面。根据入射光线的数量和方向,我们可以计算出射光线的数量和方向,通常使用出射度描述它。辐射度和出射度之间是线性关系的,它们之间的比值就是材质的漫反射和高光反射属性。
BRDF模型
早期的游戏引擎一般只有一个光照模型,BRDF模型,即标准光照模型(Bidirectional Reflectance Distribution Function),又称Phong模型。
它的基本方法是,把进入到摄像机内的光线分为4部分,每部分使用一种方法来计算它的贡献度。
  • 自发光  描述当给定一个方向时,一个表面本身会向该方向发射多少辐射量。注意,如果没有使用全局光照,这些自发光的表面并不会照亮周围的物体,只是他本体看起来更亮而已。
  • 高光反射(金属之类的)  描述当光线从光源照射到模型表面时,该表面会在完全镜面反射方向散射多少辐射量。
  • 漫反射  该表面会向四周散射多少辐射量
  • 环境光  描述其他所有的间接光照(就是其他物体的发射的光线)。
兰伯特定律
发射光线的强度与表面法线和光源方向之间的夹角余弦值成正比。
 
漫发射的计算公式
   C = (c * m) * max( 0 , n * l )。
小写c为光源颜色,m为漫反射颜色,n是表面法线,l是指向光源的单位矢量。需要注意应该防止发现和光源点乘的结果为负值(避免物体被从后面来的光源照亮),所以用max函数限制其为正数。
 
高光反射的计算公式
  • r = 2(n * l)n - l
  • C = (c * m) * (max(0,v * r)) ^ gloss
n,l代表意义与漫反射公式相同,r为光的反射方向矢量,m为高光反射颜色, v 为 视角方向矢量,gloss为材质的光泽度,gloss越大亮点就越小。
 
 
Blinn模型的高光反射计算公式
  与上述Phong模型不同的是,Blinn模型引入了一个新矢量h,通过对 v 和 l的取平均后再归一化得到:h = ( v + l ) / | v + l |。
  公式为:C = ( c * m) * (max( 0, n * h ))^gloss
 
逐像素与逐顶点光照
 在片元着色器中计算,称为逐像素光照。在顶点着色器中计算,称为逐顶点光照(高罗德着色)。逐顶点光照是在每个顶点上计算光照,然后在渲染图元内部进行线性插值,最后输出成像素颜色。由于顶点数目小于像素数目,所以其计算量小于逐像素光照,因此在阴影交界处会出现锯齿,精细度不如逐像素光照。
 
Unity的环境光和自发光
环境光可以通过Shader的内置变量UNITY_LIGHTMODEL_AMBIENT访问
自发光只需要在片元着色器输出最后的颜色之前,把材质的自发光颜色添加到输出颜色上就行。
 
漫反射和高光反射的Shader实现
漫反射光照模型(逐顶点)
Shader "Unity Shader Book/Chapter6/Diffuse Vertex-Level"
{
Properties
{
_Diffuse("Diffuse",Color) = (1.0,1.0,1.0,1.0)
}
SubShader
{
Tags { "LightMode"="ForwardBase" } Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse;
struct appdata
{
float4 vertex : POSITION; //顶点在模型空间的坐标
float3 normal : NORMAL; //法线
} ; struct v2f
{
fixed3 color : COLOR; //输出颜色
float4 pos : SV_POSITION; //输出位置
} ; v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex); //模型空间转换到裁剪空间 fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; //环境光 fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject)); //法线方向n fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz); //光源位置 fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLight)); //公式计算 o.color = ambient + diffuse; return o;
} fixed4 frag (v2f i) : SV_Target
{
return fixed4(i.color,1.0);
}
ENDCG
}
}
}
高光反射模型(逐顶点)
Shader "Unity Shader Book/Chapter6/SpecularVertexLevel"
{
Properties
{
_Diffuse("Diffuse",Color) = (1.0,1.0,1.0,1.0)
_Specular("Specular",Color) = (1.0,1.0,1.0,1.0)
_Gloss("Gloss",Range(8.0,256)) = 20 //size of specular area
}
SubShader
{
Tags { "LightMode"="ForwardBase" } //Be careful ,The light direction will be opposite without this Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag #include "Lighting.cginc" fixed4 _Diffuse;
fixed4 _Specular;
float _Gloss;
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
} ; struct v2f
{
float3 color: COLOR;
float4 pos : SV_POSITION;
} ; v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
//equal to "o.pos = mul(UNITY_MATRIX_MVP,v.vertex);" fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz; fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));
// or use UnityObjectToWorldNormal(v.normal)
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz); fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir)); fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal)); //反射方向矢量r fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld,v.vertex).xyz); //视线方向 fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectDir,viewDir)),_Gloss); //公式计算 o.color = ambient + diffuse + specular; return o;
} fixed4 frag (v2f i) : SV_Target
{
return fixed4(i.color,1.0);
}
ENDCG
}
}
}

  

Unity3D学习(六):《Unity Shader入门精要》——Unity的基础光照的更多相关文章

  1. Unity Shader入门精要学习笔记 - 第4章 学习 Shader 所需的数学基础

    摘录自 冯乐乐的<Unity Shader入门精要> 笛卡尔坐标系 1)二维笛卡尔坐标系 在游戏制作中,我们使用的数学绝大部分都是计算位置.距离.角度等变量.而这些计算大部分都是在笛卡尔坐 ...

  2. Unity Shader入门精要读书笔记(一)序章

    本系列的博文是笔者读<Unity Shader入门精要>的读书笔记,这本书的章节框架是: 第一章:着手准备. 第二章:GPU流水线. 第三章:Shader基本语法. 第四章:Shader数 ...

  3. Unity Shader入门精要之 screen post-processing effect

    本篇记录了学习Unity Shader入门精要的屏幕后处理的一些知识点. OnRenderImage(RenderTexture src, RenderTexture dest) 以上函数是Unity ...

  4. Unity Shader入门精要学习笔记 - 第15章 使用噪声

    转载自 冯乐乐的 <Unity Shader 入门精要> 消融效果 消融效果常见于游戏中的角色死亡.地图烧毁等效果.这这些效果中,消融往往从不同的区域开始,并向看似随机的方向扩张,最后整个 ...

  5. Unity Shader入门精要学习笔记 - 第14章非真实感渲染

    转载自 冯乐乐的 <Unity Shader 入门精要> 尽管游戏渲染一般都是以照相写实主义作为主要目标,但也有许多游戏使用了非真实感渲染(NPR)的方法来渲染游戏画面.非真实感渲染的一个 ...

  6. Unity Shader入门精要学习笔记 - 第11章 让画面动起来

    转自 冯乐乐的 <Unity Shader入门精要> Unity Shader 中的内置变量 动画效果往往都是把时间添加到一些变量的计算中,以便在时间变化时画面也可以随之变化.Unity ...

  7. Unity Shader入门精要学习笔记 - 第10章 高级纹理

    转载自 冯乐乐的 <Unity Shader入门精要> 立方体纹理 在图形学中,立方体纹理是环境映射的一种实现方法.环境映射可以模拟物体周围的环境,而使用了环境映射的物体可以看起来像镀了层 ...

  8. Unity Shader入门精要学习笔记 - 第9章 更复杂的光照

    转载自 冯乐乐的<Unity Shader入门精要> Unity 的渲染路径 在Unity里,渲染路径决定了光照是如何应该到Unity Shader 中的.因此,如果要和光源打交道,我们需 ...

  9. Unity Shader入门精要学习笔记 - 第8章 透明效果

    转载自 冯乐乐的 <Unity Shader入门精要> 透明是游戏中经常要使用的一种效果.在实时渲染中要实现透明效果,通常会在渲染模型时控制它的透明通道.当开启透明混合后,当一个物体被渲染 ...

  10. 【我的书】《Unity Shader入门精要》出版上市

    重要的事 先说重要的事,就是我的书籍<Unity Shader入门精要>在经过无数次跳票后,终于出版上市了(泪目-)! 购买传送门: 亚马逊 当当 京东 截止到我写这篇文章的时候,京东是没 ...

随机推荐

  1. 03_TortoiseGit冲突和补丁演示,补丁冲突

     1 下载TortoiseGit,下载地址: http://tortoisegit.soft32.com/free-download/ 2 创建一个GIT仓库 3 创建克隆,创建两个用于克隆的仓库 ...

  2. How to Simulate the Price Order or Price Line Function using API QP_PREQ_PUB.PRICE_REQUEST Includes

    How to Simulate the Price Order or Price Line Function using API QP_PREQ_PUB.PRICE_REQUEST Includes ...

  3. Android开发技巧——自定义控件之组合控件

    Android开发技巧--自定义控件之组合控件 我准备在接下来一段时间,写一系列有关Android自定义控件的博客,包括如何进行各种自定义,并分享一下我所知道的其中的技巧,注意点等. 还是那句老话,尽 ...

  4. ruby利用Zip Gem写一个简单的压缩和解压的小工具

    在UNIX下的我们怎么会沦落到用ruby写压缩和解压工具呢?直接上shell啊!但是请允许本猫这次可耻的用ruby来玩玩吧!其实ruby GEM中有很多压缩解压包,我选的是Zip,也许是因为名字符合K ...

  5. ruby写一个文件内容相似性比较的代码

    1.相似度定义 我们定义,则,我们设,则,|C|=s,则相似度p=,p(0,1) 2.相似度检测算法设计 算法设计: 定义4个字符为一个字符串,将T1,T2分割成若干字符串,若剩余字符不足4个,则以空 ...

  6. Android开发 PopupWindow弹窗调用第三方地图(百度,高德)实现导航功能

    博客描述:后台返回地点的经纬度在地图上进行描点,点击导航弹出PopupWindow进行选择地图操作,如果手机中没有安装地图,提示没有,否则传值调起地图进行导航操作 看一下实现的效果,没图说再多都白搭 ...

  7. 布局display属性(一)--【Flex】

    一.Flex 布局是什么? Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性. 任何一个容器都可以指定为 Flex 布局. .box ...

  8. 移动web前端开发时注意事项(转)

    在智能手机横行的时代,作为一个web前端,不会编写移动web界面,的确是件悲催的事情.当公司准备做一个微信的微网站时,作为一个多年经验的web前端码农,我迷茫了,真心不知道从何下手. 接下来就是搜一堆 ...

  9. 别跟我谈EF抵抗并发,敢问你到底会不会用EntityFramework

    前言 一直以来写的博文都是比较温婉型的博文,今天这篇博文算是一篇批判性博文,有问题欢迎探讨,如标题,你到底会不会用EntityFramework啊. 你到底会不会用EntityFramework啊 面 ...

  10. 我对IoC/DI的理解

    IoC IoC: Inversion of Control,控制反转, 控制权从应用程序转移到框架(如IoC容器),是框架共有特性 1.为什么需要IoC容器 1.1.应用程序主动控制对象的实例化及依赖 ...