前言
光学中,我们是用辐射度来量化光。
光照按照不同的散射方向分为:漫反射(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. Javascript和BHO的相互调用简介

    v:* { } o:* { } w:* { } .shape { }p.MsoNormal,li.MsoNormal,div.MsoNormal { margin: 0cm; margin-botto ...

  2. iOS雷达图 iOS RadarChart实现

    实现效果 刚拿到设计稿的时候大概看了一眼,当时心里想着放张背景图,然后计算下相应点的坐标,在最上面画一层就OK了,其实一开始实现的时候也确实是这么做的,然后我就日了狗了,发现设计稿上多层五边形的间隔不 ...

  3. Netfilter的使用和实现

    本文主要内容:Netfilter的原理和实现浅析,以及示例模块. 内核版本:2.6.37 Author:zhangskd @ csdn blog 概述 Netfilter为多种网络协议(IPv4.IP ...

  4. linux下显示不规则图片窗口

    测试环境是ubuntu15.04,使用的图形库是gtk+. 图片格式采用的是X11的xpm格式,首先从网上找一个背景透明的png图片,然后用图形转换工具(比如gimp)转换为xpm格式. 程序代码如下 ...

  5. 最新App Store审核10大被拒理由

    最近,苹果在官网给出了截至2015年2月份应用被拒绝的十大理由,其中50%以上的应用被拒绝都是因为这10个原因,其中7个理由和2014年相同,其中排名前三的原因分别是:需要补充更多信息.存在明显的bu ...

  6. The 14th tip of DB Query Analyzer

      The 14th tip of DB Query Analyzer Ma Genfeng (Guangdong Unitoll Services incorporated, Guangzhou 5 ...

  7. 解读Raft(四 成员变更)

    将成员变更纳入到算法中是Raft易于应用到实践中的关键,相对于Paxos,它给出了明确的变更过程(实践的基础,任何现实的系统中都会遇到因为硬件故障等原因引起的节点变更的操作). 显然,我们可以通过sh ...

  8. InnoDB的4个特性

    innodb 的四个特性 insert buffer innodb使用insert buffer"欺骗"数据库:对于为非唯一索引,辅助索引的修改操作并非实时更新索引的叶子页,而是把 ...

  9. [更新]单线程的JS引擎与 Event Loop

    先来思考一个问题,JS 是单线程的还是多线程的?如果是单线程,为什么JavaScript能让AJAX异步发送和回调请求,还有setTimeout也看起来像是多线程的?还有non-blocking IO ...

  10. Fiddler抓包使用教程-Android应用抓包

    转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/74439165 本文出自[赵彦军的博客] Fiddler 也可以支持对手机应用进行 ...