前言
光学中,我们是用辐射度来量化光。
光照按照不同的散射方向分为:漫反射(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. PO订单审批通过API

    DECLARE l_return_status VARCHAR2(1); l_exception_msg VARCHAR2(4000); BEGIN mo_global.set_policy_cont ...

  2. HBase 快照操作

    1.配置hbase-site.xml <property> <name>hbase.snapshot.enabled</name> <value>tru ...

  3. SpriteBuilder全屏弹出菜单的特殊效果

    但是等一下!这里可以有更多.对于全屏的弹出菜单,你可以在显示弹出全屏菜单时朦胧化背景的level视图. 通过修改SpriteBuilder中的color节点的Color属性(比如修改为black)和O ...

  4. C/C++中关键字static的用法及作用

    本文将主要从static在C和C++共有的作用及C++特有的作用两个方面进行解析. 在C和C++中共有的作用 隐藏(对变量.函数均可) 当同时编译多个文件时,所有未加static前缀的全局变量或全局函 ...

  5. Android特效专辑(十)——点击水波纹效果实现,逻辑清晰实现简单

    Android特效专辑(十)--点击水波纹效果实现,逻辑清晰实现简单 这次做的东西呢,和上篇有点类似,就是用比较简单的逻辑思路去实现一些比较好玩的特效,最近也是比较忙,所以博客更新的速度还得看时间去推 ...

  6. Globalization Guide for Oracle Applications Release 12

    Section 1: Overview Section 2: Installing Section 3: Configuring Section 4: Maintaining Section 5: U ...

  7. C语言可变参实现参数累加返回

    C语言可变参的作用真的是非常大,自从发表了可变参如何实现printf,fprintf,sprintf的文章以来,便有不少博友私信问我实现的机制,我也解释了相关的知识点.今天,我们借着这个机会,再来举一 ...

  8. 存储引擎-Buffered tree

    Buffered-tree 也称为COLA,即cache-oblivious,可以不需要知道具体内存大小和一个块的大小,使用一套逻辑进行处理,因此内存大小可知,内存可能被临时占用去做其它事情. Buf ...

  9. Mac OS X 简单的方法知道何时来电了

    最近本猫所在的小区时常停电,往往半夜或是凌晨才来电啊!早上起来本猫在想如何知道确切的来电时间,但又不费事的方法呢. 方法一是用手机录音器录音,因为来电后门禁会发出"滴"的一声,所以 ...

  10. C# 设置Word文档背景(纯色/渐变/图片背景)

    Word是我们日常生活.学习和工作中必不可少的文档处理工具.精致美观的文档能给人带来阅读时视觉上的美感.在本篇文章中,将介绍如何使用组件Free Spire.Doc for .NET(社区版)给Wor ...