本文接上文的Unity Shader零基础入门1:纯色物体

Unity Shader零基础入门1:纯色物体_qq_21315789的博客-CSDN博客

先讲几个知识点:

float、half和fixed类型的区别:
在子着色器中float可用half、fixed代替(比如用fixed3代替float3)
float为32位存储,half 为16位(大约可存储正负6万之间的数),fixed 11位(存储-2到2的数)。比如颜色只需要4个0~1的数来表示,一般用fixed4,这样可以比用float4节约资源。后面这个数字代表几维,比如float为一维,float3为3维。

属性的格式与类型:

上一课没有用到属性,这一课需要用到了。属性中新建变量的格式:

变量名("显示变量名",类型)=初始值

比如:_Diffuse("Diffuse Color",Color)=(1,1,1,1)

_Diffuse是变量名,新变量通常都加"_"防止和关键字冲突。Diffuse Color是在工程面板中显示的名称。Color是一个类型。(1,1,1,1)是初始值,代表白色。属性中的多维初始值只需要加括号。属性中的语句结束时没有";"。

属性中的常见类型举例:

_Color("_Color",Color)=(1,1,1,1) //颜色
_Vector("Vector",Vector)=(1,2,3,4) //矢量
_Int("Int",Int)=3434 //整型
_Float("Float",Float)=5.5 //浮点数,数字后不用加f
_Range("Range",Range(1,11))=1 //有范围限制的Float。范围自定义。这里定成了1~11。
_2D("Texture",2D)=""{} //图片。可赋值为"颜色"{}如"white"{}。当赋值了"white"{}后,如果没有再给图片赋值,那读取时取到的就只有白色。而如果给图片赋值了就能取到图片颜色。

属性中的变量,可以在工程面板中赋值。

属性中定义的变量,在SubShader中的pass块中不能直接使用,而是要再次定义才能使用。且两边用到的类型名并不完全相同。对属性中的变量在pass中可用如下方法重新定义:

fixed4 _Color;//SubShader里没有Color类型,需要用其它类型定义颜色。因为颜色只需要用到0-1的数,所以用fixed4。属性中结尾无需分号,这里需要。
float4 _Vector; //用float4 定义 Vector
float _Int; //int也定义为float
float _Range;//Range型也定义为float
sampler2D _2D; //图片类型在这里定义为sampler2D类型

标准光照模型:

在标准光照模型里面,我们把进入摄像机的光分为下面四个部分:

自发光、高光反射、漫反射、环境光。

环境光用来模拟间接光照,比如光照到物体时会反射给附件的物体。

颜色的融合与叠加:

当需要融合两个颜色时,直接用"*"将两个颜色的值相乘。新颜色会受到旧的两个颜色的影响,但亮度一般不增加。当需要叠加两个颜色时,将两个颜色的值相加,同时亮度会增加。

漫反射的计算:

当物体的某个区域被照射时,如果该区域正对着光,那么接收的光就多,亮度就高。而如果是侧向的光,那么亮度就低。就好像正午时最明亮一样。

所以我们使用cos (光源方向和法线的夹角)来控制漫反射的亮度(三角函数原理这里不多讲)。对向量的cos运算直接使用点乘即可。即dot(光源方向,法线)。

但如果光源在模型的另一面,cos (光源方向和法线的夹角)会变为负数。我们不需要背面为负数,只需要背面为黑(0),所以我们用一个max函数保证最小值为0:max(0,cos (光源方向和法线的夹角))。

同时漫反射的颜色一般与光线颜色有关,所以再乘照射物体的直射光颜色而得到漫反射颜色。我们自己也可以添加一个颜色用以影响漫反射颜色,所以漫反射为:

直射光颜色 * max(0,cos (光源方向和法线的夹角))*设置的颜色。

半兰伯特光照模型:

上面这个漫反射的计算方法有一个缺点为模型的背面完全是黑色的,因为max(0,cos (光源方向和法线的夹角))在背面只能得到0。如果希望背面是逐渐变深的灰色,可以将max(0,cos (光源方向和法线的夹角))改为cos (光源方向和法线的夹角)*0.5+0.5,这样在背面时就是0.5~0。

高光的计算:

通过指数(pow)来计算高光。

高光颜色=直射光颜色*pow(max(0,cosθ),高光的参数x),θ是反射光方向和视野方向的夹角。由于max(0,cosθ)不大于1,x越大,导致得到的值越小。高光越不明显。视野方向指反光点指向相机的方向。
反射光方向= normalize(reflect(入射光方向,法线方向))。通过_WorldSpaceLightPos0.xyz可得到光源方向,即由物体指向光源的方向。然后再乘负号得到光源指向物体的方向。

开始制作shader:

先新建一个shader。在工程面板中Create-Shader-Standard Surface Shader创建一个shader文件并重命名。

双击打开shader文件后删除原内容,改为如下内容:

Shader "Tutorial/02Specular" {Properties{//漫反射的颜色_DiffuseColor("Diffuse Color",Color)=(1,1,1,1)//_Gloss用于控制高光的程度,数字越小高光越明显、范围越大_Gloss("Gloss",Range(8,200))=10//高光颜色_SpecularColor("Specular Color",Color)=(1,1,1,1)}SubShader{pass{//CGPROGRAM上面的 Tags{ "LightMode"="ForwardBase" } 和下面的#include "Lighting.cginc" 两句是为了引入和能在之后使用unity内置的一些光照变量Tags{ "LightMode"="ForwardBase" }CGPROGRAM#include "Lighting.cginc"//属性中的变量在pass中需要重新定义才能使用。颜色为0-1,一般使用fixed4即可。fixed4 _DiffuseColor;//pass中没有Range型,且因为_Gloss不会很大,所以定义为half。half _Gloss;fixed4 _SpecularColor;//声明顶点函数名为vert#pragma vertex vert//声明片元函数名为frag#pragma fragment frag //这里定义了结构体方便存储和传输数据。//a2v的含义是application to vertex,也就是从系统传输内容给顶点函数用。struct a2v{//将模型空间下的法线向量赋值给normal。方向一般用三维向量。float3 normal:NORMAL;//将模型空间下的顶点坐标赋值给vertex。坐标一般用四维向量。//存储坐标其实只用到前3维,第4维是转换时用到的。float4 vertex:POSITION;float3 tan:TANGENT;};//v2f表示vertex to fragment,即由顶点函数传递给片元函数。该结构体将作为顶点函数的返回值//作为顶点函数返回值的结构体,其中的每一个量都必须被语义解释。struct v2f{//将position作为剪切空间中的顶点坐标。//这个值是顶点函数的返回值中一定要包含的,但可以是直接返回,也可以放在结构体中。//SV 表示system value,系统值。float4 position:SV_POSITION;//建立了一个存储和传递颜色用的变量。//颜色的最后一维是阿尔法值,所以也可以用三维向量存储一个没阿尔法值的颜色。fixed3 color:COLOR; };//顶点函数,参数为a2v类型,返回值为v2f类型v2f vert(a2v v){v2f f;//将模型空间下的顶点坐标转换到剪切空间并存储到f.positionf.position= mul(UNITY_MATRIX_MVP,v.vertex);//使用UNITY_LIGHTMODEL_AMBIENT即可得到环境光。.rgb表示取不包含阿尔法值(透明度)的前3位颜色值。//可以看到我们这里对颜色的计算主要用3维向量,因为这里不需要阿尔法值。fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.rgb;//取得环境光//将模型空间下的法线转换到世界空间。//用unity_ObjectToWorld 可得到从模型空间转换到世界空间需要的矩阵。unity_WorldToObject则是从世界空间转换到模型空间需要的矩阵。//normalize()表示转换为模为1的单位向量。因为已经是不超过1的单位向量,所以用fixed3即可储存。//将一个普通向量从模型空间转换到世界空间,使用mul(unity_ObjectToWorld,向量),但对法线却要用mul(法线,(float3x3)unity_WorldToObject),看起来仿佛是与普通向量相反//这里的x非常难打,还存在看起来一样但不完全一样的乘号,建议直接复制。fixed3 normalDir=normalize(mul(v.normal,(float3x3)unity_WorldToObject));//第一个直射光的位置(被照射点接收到的光的方向)。.xyz表示取坐标向量的前3维。fixed3 lightDir=normalize( _WorldSpaceLightPos0.xyz);//计算漫反射颜色。_LightColor0用于得到光线颜色。_DiffuseColor是之前在属性中定义的。fixed3 difuse= _LightColor0.rgb*max(dot(normalDir,lightDir),0)*_DiffuseColor.rgb;//得到反射光方向fixed3 reflectDir= normalize(reflect(-lightDir,normalDir));//视野方向。_WorldSpaceCameraPos.xyz用于得到相机位置。//mul(unity_ObjectToWorld,v.vertex).xyz则为世界空间下的顶点坐标。//通过相机位置减顶点位置,得到近似的视野方向。fixed3 viewDir= normalize(_WorldSpaceCameraPos.xyz-mul(unity_ObjectToWorld,v.vertex).xyz);//计算高光颜色。_SpecularColor也是在属性中定义的。fixed3 specular=_LightColor0.rgb*pow(max(0,dot(reflectDir,viewDir)),_Gloss)*_SpecularColor.rgb;//将漫反射、环境光、高光叠加作为显示的颜色f.color=difuse+ambient+specular;//将这个结构体作为返回值return f;}//片元函数//:SV_TARGET用于解释片元函数的返回值。这个返回值就是最终显示的颜色。float4 frag(v2f f):SV_TARGET{//片元函数的返回值需要是一个4维向量,所以后面补个1作为阿尔法值。return fixed4(f.color,1);}ENDCG}}Fallback "VertexLit"
}

之后新建一个胶囊体,为其添加一个新建的材质,然后就可以为其更换新写的shader:

然后就得到了一个能显示环境光、漫反射、和高光的胶囊体:

并且可以通过修改属性中添加的这几个变量修改漫反射颜色、高光系数、高光颜色:

如果需要修改环境光,在Window-Ambient Source-Color修改:

效果:

Unity Shader零基础入门2:环境光、漫反射、高光相关推荐

  1. 【Unity】零基础入门教程整理

    中文教程 学院派 夏村散人韩老师带你打基础 刘铁猛<C#语言入门详解>全集,最扎实的C#入门 活泼派 M_Studio作品 Unity教程 入门第一款游戏制作教程合集 用途很广的对话系统教 ...

  2. Unity C#零基础入门笔记(一)Paws3D笔记

    计算机语言: 计算机语言按发展分为三种: 机器语言 汇编语言 高级语言 机器语言就是机器码,是能够被计算机直接理解的语言.更通俗地讲就是010101这样的二进制指令.和硬件密切相关,编写苦难. 两个主 ...

  3. 零基础入门 Unity 之 UGUI 详解专栏 | 寻找C站宝藏

    零基础入门 Unity 之 UGUI 详解专栏 | 寻找C站宝藏 六大推荐理由 理由一:系统 理由二:详细 理由三:专业 理由四:图解 理由五:深度 理由六:实例 一键直达:<UGUI 控件详解 ...

  4. 有关我零基础入门Opengl并想开发七巧板小程序交作业这档子事

    有关我零基础入门Opengl并想开发七巧板小程序交作业这档子事 隔壁笔记链接:入手OpenGL 隔壁技术实现链接:部分思路实现 背景故事 c++课程老师给布置作业,"小作业",使用 ...

  5. 着色器编程_unity中的基础纹理,使用Unity Shader实现基础纹理的渲染效果

    学习通过使用Unity Shader实现基础纹理的渲染效果 目录 学习通过使用Unity Shader实现基础纹理的渲染效果 问1:详细描述一下漫反射纹理.高度纹理.法线纹理.渐变纹理和遮罩纹理? 问 ...

  6. [六点]Pygame零基础入门:极简开发框架

    [六点]Pygame零基础入门:极简开发框架 参考 Pygame官方文档 嵩天教授的Python游戏开发教程 前言 在入门游戏开发时,pygame框架可以快速协助开发小型游戏.轻松而愉快的开始是从玩游 ...

  7. python 二进制流转图片_Python零基础入门到精通-5.1节:Python程序的执行过程

    教程引言: 系统地讲解计算机基础知识,Python的基础知识, 高级知识,web开发框架,爬虫开发,数据结构与算法,nginx, 系统架构.一步步地帮助你从入门到就业. 5.1.1 在命令行中执行Py ...

  8. 【JAVA零基础入门系列】Day2 Java集成开发环境IDEA

    [JAVA零基础入门系列](已完结)导航目录 Day1 开发环境搭建 Day2 Java集成开发环境IDEA Day3 Java基本数据类型 Day4 变量与常量 Day5 Java中的运算符 Day ...

  9. 零基础入门jQuery视频教程

    零基础入门jQuery最新版开发.NET富客户端应用(选择器.DOM操作.事件和动画.Ajax应用.插件.Mobile) 课程分类:.NET+Jquery 适合人群:初级 课时数量:35课时 用到技术 ...

  10. 【组队学习】【24期】零基础入门语音识别(食物声音识别)

    零基础入门语音识别(食物声音识别) 开源内容: https://github.com/datawhalechina/team-learning-nlp/tree/master/FoodVoiceRec ...

最新文章

  1. 目标检测新技能!引入知识图谱:Reasoning-RCNN
  2. 染色[SDOI2011]
  3. bootstrap ui
  4. 中文微博客的热门锐推用户榜
  5. 网站常见攻击与防御汇总
  6. 6675温度波动大_温度和压力对压缩空气干燥机性能的影响
  7. Android ramdisk.img system.img userdata.img 介绍与使用
  8. redis基本命令list
  9. jQuery ajax - getScript() 方法
  10. 用wubi在一个独立分区硬件装ubuntu12.04产生的无法识别U盘的解决办法
  11. 通过 Go 语言来实现 DDD 分层设计,美滋滋!
  12. 前端学习(2926):vue改变样式2
  13. input只能输入数字_Python基础第一个案例:猜数字游戏,这个都写不出,那就放弃吧...
  14. Ranger-AdminServer安装
  15. 去掉softmax后Transformer会更好吗?复旦华为诺亚提出SOFT:轻松搞定线性近似
  16. inline-block和float
  17. ORA-12162错误解决
  18. Excel如何将多个sheet导出到PDF?
  19. 开机广告页面2017流行样式 dialogTheme的popuwindow版本
  20. 关于iOS中UITableView下拉距离短刷新没事,下拉距离长就会崩溃的问题解决方案

热门文章

  1. 学习笔记:中国大学MOOC《计算机程序设计C++》第3周单元测试
  2. 百度编辑器UEditor图片上传尺寸大小设置
  3. JMeter中文使用手册
  4. 3.接口测试用例书写
  5. 数据结构分类及八种常见数据结构
  6. word打不开html,word打不开怎么办?word文档打不开怎么办?
  7. top在linux的命令,Linux命令详解之–top命令 | Linux大学
  8. 概率论与数理统计学习笔记——第7讲——连续型随机变量(2.5.4指数分布及其与泊松分布的关系)
  9. python电子病历,如何在电子病历上安装软件包
  10. android 自动跳转市场,js判断设备,跳转app应用、android市场或者AppStore