Unity 的基础光照
目录
前言
内容
BRDF 模型
兰伯特定律
漫发射的计算公式
高光反射的计算公式
Blinn 模型的高光反射计算公式
逐像素与逐顶点光照
Unity 的环境光和自发光
漫反射和高光反射的 Shader 实现
漫反射光照模型(逐顶点)
高光反射模型(逐顶点)
前言
光学中,我们是用辐射度来量化光。
光照按照不同的散射方向分为两种形式:漫反射(diffuse)和高光反射(specular)。
高光反射描述物体是如何反射光线的,漫反射则表示有多少光线会被折射、吸收和散射出表面。根据入射光线的数量和方向,我们可以计算出射光线的数量和方向,通常使用出射度描述它。辐射度和出射度之间是线性关系的,它们之间的比值就是材质的漫反射和高光反射属性。
接下来将会介绍Unity内的两种光照方式实现的原理以及代码实现:
内容
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)); //法线方向nfixed3 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 //镜面反射面积大小}SubShader{Tags { "LightMode"="ForwardBase" } //小心,如果没有这个光源会反向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);//等同于 "o.pos = mul(UNITY_MATRIX_MVP,v.vertex);"fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));//或使用 UnityObjectToWorldNormal(v.normal)fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));fixed3 reflectDir = normalize(reflect(-worldLightDir,worldNormal)); //反射方向矢量rfixed3 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}}
}
Unity 的基础光照相关推荐
- 《Unity 3D 游戏开发技术详解与典型案例》——1.1节Unity 3D基础知识概览
本节书摘来自异步社区<Unity 3D 游戏开发技术详解与典型案例>一书中的第1章,第1.1节Unity 3D基础知识概览,作者 吴亚峰 , 于复兴,更多章节内容可以访问云栖社区" ...
- Unity面试题加强版之二《unity编辑器基础》
Unity面试题加强版之二Unity编辑器基础 unity超全面试题,掌握轻轻松松拿Offer,码住学习 40.请描述游戏动画有几种,以及其原理. 主要有关节动画.单一网格模型动画(关键帧动画).骨骼 ...
- Unity引擎基础补充
Unity引擎基础补充 本博客将对之前的Unity脚本,3D数学基础博客内容做一定的补充.所以部分知识点可能并不全. 使用Unity的API,我们要清楚各个参数其代表的含义. 文章目录 Unity引擎 ...
- Unity Shader入门精要——第3章 Unity Shader基础
Unity Shader入门精要读书笔记系列 第1章 欢迎来到Shader的世界 第2章 渲染流水线 第3章 Unity Shader基础 文章目录 Unity Shader入门精要读书笔记系列 前言 ...
- 《 Unity Shader 入门精要》 第3章 Unity Shader 基础
第3章 Unity Shader 基础 3.1 Unity Shader 概述 材质与 Unity Shader 在 Unity 中我们通常需要将材质(Material) 和 Unity Shader ...
- Unity Mesh基础知识
Unity Mesh基础知识 什么是Mesh Mesh的组成部分 利用Mesh创建一个Cube 创建Cube 顶点坐标 渲染 转载链接 什么是Mesh Mesh是指的模型的网格,3D模型是由多 ...
- 蓝鸥Unity开发基础二——课时20 接口
蓝鸥Unity开发基础二--课时20 接口 一.接口 使用interface关键字定义接口 接口定义一组成员单不直接实现它们 二.实现接口 实现接口的任何类都必须实现其所有的成员方法 接口不能直接实例 ...
- OpenGL 基础光照ColorsBasic Lighting
OpenGL 基础光照ColorsBasic Lighting 基础光照ColorsBasic Lighting简介 环境光照 漫反射光照 法向量 计算漫反射光照 最后一件事 镜面光照 基础光照Col ...
- 【蓝鸥Unity开发基础三】课时14 刚体
[蓝鸥Unity开发基础三]课时14 刚体 一.刚体 物理引擎: 物理引擎能够真实的模拟物理效果 Unity中使用的是NVIDIA的PhysX物理引擎 在Unity中使用Rigidbody让游戏对象受 ...
最新文章
- 句法分析是什么?成分句法分析、依存句法分析又是什么?他们之间有什么区别?
- [业界资讯]腾讯QQ同时在线用户数突破8000万
- IT人员健康信号之颈椎病自疗
- python之33个关键字详解_Python解析、提取url关键字的实例详解
- 前端学习(970):fastclick插件使用
- 0pencv——图像腐蚀
- python抽荣耀水晶_教你2种免费拿荣耀水晶的方法,获奖概率让人惊喜,一般人我不告诉他...
- html5游戏制作入门系列教程(四)
- python两个数组合并、找出中位数_leetcode刷题记录-找出这两个有序数组的中位数(python版本)...
- 20145328 《信息安全系统设计基础》第2周学习总结
- 容器化技术之Docker入门
- 都说 Linux 是吃内存大户,可你知道具体是哪些进程吃掉了吗?
- Maven项目jar包依赖冲突的原因以及解决办法
- CouchBase简单介绍
- 计算机专业英语高等教育出版社2013版
- 推荐几个好的粉碎文件的软件?这3款软件让你彻底摆脱无法删除文件的烦恼
- 解决AndroidStudio报错问题:Missing essential plugin
- 【Three.js】十二、three.js摄像机控件
- python 状态空间模型_R语言状态空间模型:卡尔曼滤波器KFAS建模时间序列
- excel打开很慢_从海量Excel文件中快速高效地提取数据
热门文章
- win10配置python环境变量
- error: (-215:Assertion failed) size.width0 size.height0 in function 'cv::imshow'解决
- 科创板丨西部超导上半年实现营收6.69亿元 同比增长26.69%
- mybatis的selectKey的用法
- 年度最新!iOS如何申请苹果公司开发者账号流程详细图文介绍
- 2022年网络安全比赛--压缩包文件暴力破解中职组(超详细)
- Linux-3 常用工具
- 3大简历难题,你是否也曾遭遇?
- aws sqs java_AWS SQS Java.并非所有消息都从SQS队列中检索
- 测试用例设计方法(等价类、边界值等)