Unity3D学习笔记(三十六):Shader着色器(3)- 光照
逐顶点漫反射光照:是把光照计算放在顶点函数里,效果差(过渡区域),效率高
Shader "Lesson/VFVertDiffuse" {
Properties{
_DiffuseColor("漫反射颜色", Color) = (,,,)
}
SubShader{
Pass
{
//设置正确的光照渲染模式,前项渲染里的基础
Tags { "LightMode" = "ForwardBase" }
//定义Cg的开始和结束
CGPROGRAM
#pragma vertex vert//定义顶点函数名字
#pragma fragment frag//定义片元函数名字
#include "Lighting.cginc"//如果想要使用提供一些灯光变量和方法,需要引入文件 //漫反射光 = 光照颜色和强度 * 漫反射颜色 * max(0, dot(法线方向, 光照方向))
//漫反射颜色:从属性面板获取 _DiffuseColor
//光照颜色:系统提供的,_LightColor0
//法线方向:世界空间下的:需要把模型空间下的法线转换到世界空间下 worldNormal
fixed4 _DiffuseColor;//重定义属性变量 struct m2v
{
//需要获取顶点坐标和法线向量
float4 vex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
//把光照计算放在顶点函数中
//所以需要把计算之后的漫反射光Color传递到片元函数中
float4 position : SV_POSITION;
fixed4 color : COLOR0;
};
//实现定点和片元函数
v2f vert(m2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vex);//转换顶点坐标
float3 worldNormal = normalize(mul(UNITY_MATRIX_M, v.normal));//normalize归一化向量
float3 worldPosition = mul(UNITY_MATRIX_M, v.vex);//先获取世界空间下的顶点坐标
float3 lightDir = normalize(UnityWorldSpaceLightDir(worldPosition));//UnityWorldSpaceLightDir,获取光照方向
fixed3 color = _LightColor0.xyz * _DiffuseColor.xyz * max(, dot(worldNormal, lightDir));//漫反射颜色,光照不影响透明度,所以是.xyz没有w
f.color = fixed4(color, );
return f;
}
fixed4 frag(v2f f) : SV_Target
{
return f.color;
}
ENDCG
}
}
FallBack "Diffuse"
}
逐像素漫反射光照:是把光照计算放在片元函数里,效果好,效率低
Shader "Lesson/VFFragDiffuse" {
Properties{
_DiffuseColor("漫反射颜色", Color) = (,,,)
}
SubShader{
Pass
{
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
fixed4 _DiffuseColor; struct m2v
{
float4 vex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 position : SV_POSITION;
float3 worldNormal : COLOR0;//把世界空间下的法线传递过去
float3 worldPosition : COLOR1;//世界空间下的顶点坐标
};
v2f vert(m2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vex);
f.worldNormal = normalize(mul(UNITY_MATRIX_M, v.normal));//转换法线向量,变成世界空间下的
f.worldPosition = mul(UNITY_MATRIX_M, v.vex);
return f;
}
fixed4 frag(v2f f) : SV_Target
{
float3 lightDir = normalize(UnityWorldSpaceLightDir(f.worldPosition));
fixed3 color = _LightColor0.xyz * _DiffuseColor.xyz * max(, dot(f.worldNormal, lightDir));
return fixed4(color, );
}
ENDCG
}
}
FallBack "Diffuse"
}
Pass
{
//设置正确的光照渲染模式,前项渲染里的基础
Tags { "LightMode" = "ForwardBase" }
}
fixed3 color = _LightColor0.xyz * _DiffuseColor.xyz * (dot(f.worldNormal, lightDir) * 0.5 + 0.5);
Shader "Lesson/VFVertSpecular" {
Properties{
_DiffuseColor("漫反射颜色", Color) = (,,,)
_SpecularColor("高光颜色", Color) = (,,,)
_Gloss("高光系数", Range(, )) = 0.2
}
SubShader{
Pass
{
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc" fixed4 _DiffuseColor;
fixed4 _SpecularColor;
float _Gloss; struct m2v
{
float4 vex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 position : SV_POSITION;
fixed4 color : COLOR0;
};
v2f vert(m2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vex);
//高光(Specular) = 光照颜色和强度 * 高光颜色 * pow(max(0, dot(v, r)), 高光系数)
//V:顶点到相机的方向 UnityWorldSpaceViewDir(worldPosition)
//R:反射光的方向 reflect(-lightDir, worldNormal)
//光照颜色和强度 _LightColor0
//高光颜色 _SpecularColor
//高光系数 _Gloss
//世界空间下的法线
float3 worldNormal = normalize(mul(UNITY_MATRIX_M, v.normal));
//世界空间下的顶点坐标
float3 worldPosition = mul(UNITY_MATRIX_M, v.vex);
//顶点到光源的方向
float3 lightDir = normalize(UnityWorldSpaceLightDir(worldPosition));
//顶点到相机的方向
float3 cameraDir = normalize(UnityWorldSpaceViewDir(worldPosition));
//反射光的方向
float3 refDir = reflect(-lightDir, worldNormal);
//漫反射 半兰伯特
fixed3 diffuse = _LightColor0.xyz * _DiffuseColor.xyz * (dot(worldNormal, lightDir) * 0.5 + 0.5);
//高光
fixed3 specular = _LightColor0.xyz * _SpecularColor.xyz * pow(max(, dot(cameraDir, refDir)), _Gloss);
f.color = fixed4(diffuse + specular, );
return f;
}
fixed4 frag(v2f f) : SV_Target
{
return f.color;
}
ENDCG
}
}
FallBack "Diffuse"
}
实现漫反射,高光,自发光、贴图纹理混合影响的Shader
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Lesson/VFFragSpecular" {
Properties{
_MainTex("纹理", 2D) = "white"{}
_DiffuseColor("漫反射颜色", Color) = (,,,)
_SpecularColor("高光颜色", Color) = (,,,)
_Emission("自发光颜色", Color) = (0.05,0.05,0.05,)
_Gloss("高光系数", Range(, )) = 1.05
}
SubShader{
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM #pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc" //重定义
fixed4 _DiffuseColor;
fixed4 _SpecularColor;
fixed4 _Emission;
float _Gloss;
sampler2D _MainTex; struct m2v
{
float4 vex : POSITION;
float3 normal : NORMAL;
float2 uv : TEXCOORD0;
}; struct v2f
{
//转换之后的坐标
float4 position : SV_POSITION;
//世界空间下法线向量
float3 worldNormal : COLOR0;
//世界空间下的顶点坐标
float3 worldPosition : COLOR1;
//uv
float2 uv : TEXCOORD0;
};
v2f vert(m2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vex);
f.worldNormal = normalize(mul(UNITY_MATRIX_M, v.normal));
f.worldPosition = mul(UNITY_MATRIX_M, v.vex);
f.uv = v.uv;
return f;
} fixed4 frag(v2f f) : SV_Target
{
/*高光(Specular) = 光照颜色和强度 * 高光颜色 * pow(max(0, dot(v, r)), 高光系数)
V: 顶点到相机的方向 UnityWorldSpaceViewDir(世界空间下的顶点坐标)
R:反射光的方向 reflect(从光源指向顶点的方向, 世界空间下的法线方向)
*/ //顶点到相机的方法
float3 cameraDir = normalize(UnityWorldSpaceViewDir(f.worldPosition));
//光照方向 从顶点指向光源方法
float3 lightDir = normalize(UnityWorldSpaceLightDir(f.worldPosition));
//反射光方向 -lightDir 从光源指向顶点方法
float3 refDir = reflect(-lightDir, f.worldNormal);
//漫反射 半兰伯特
fixed3 diffuse = _LightColor0.xyz * _DiffuseColor.xyz * (dot(f.worldNormal,lightDir) * 0.5 + 0.5);
//高光
fixed3 specular = _LightColor0.xyz * _SpecularColor.xyz * pow(max(, dot(cameraDir, refDir)), _Gloss);
//自发光 _Emission
//环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
//光的颜色
fixed3 lightColor = diffuse + specular + _Emission + ambient;
//根据UV获取纹理的颜色
fixed4 texColor = tex2D(_MainTex, f.uv);
texColor.xyz = texColor.xyz * lightColor;
return texColor;
}
ENDCG
}
}
FallBack "Diffuse"
}
多光情况
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Lesson/VFMoreLightDiffuse" {
Properties{
_DiffuseColor("漫反射颜色", Color) = (,,,)
}
SubShader{
Pass
{
Tags{ "LightMode" = "ForwardBase" }
CGPROGRAM #pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc" //重定义
fixed4 _DiffuseColor; struct m2v
{
float4 vex : POSITION;
float3 normal: NORMAL;
}; struct v2f
{
float4 position : SV_POSITION;
fixed4 color : COLOR0;
}; v2f vert(m2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vex); //世界空间下的法线
float3 worldNormal = normalize(mul(UNITY_MATRIX_M, v.normal));
//光照方向
float3 lightDir = normalize(UnityWorldSpaceLightDir(mul(UNITY_MATRIX_M, v.vex))); fixed3 diffuse = _LightColor0.xyz * _DiffuseColor.xyz * max(, dot(worldNormal, lightDir)); f.color = fixed4(diffuse, );
return f;
} fixed4 frag(v2f f) : SV_Target
{
return f.color;
}
ENDCG
}
Pass
{
Blend One One//把点光源(新)和太阳光(旧)混合
Tags{ "LightMode" = "ForwardAdd" }//最多添加4盏光源
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc" //重定义
fixed4 _DiffuseColor;
struct m2v
{
float4 vex : POSITION;
float3 normal: NORMAL;
};
struct v2f
{
float4 position : SV_POSITION;
fixed4 color : COLOR0;
};
v2f vert(m2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vex);
//世界空间下的法线
float3 worldNormal = normalize(mul(UNITY_MATRIX_M, v.normal));
//光照方向
float3 lightDir = normalize(UnityWorldSpaceLightDir(mul(UNITY_MATRIX_M, v.vex)));
fixed3 diffuse = _LightColor0.xyz * _DiffuseColor.xyz * max(, dot(worldNormal, lightDir));
f.color = fixed4(diffuse, );
return f;
}
fixed4 frag(v2f f) : SV_Target
{
return f.color;
}
ENDCG
}
}
FallBack "Diffuse"
}
补充内容
补充:在障碍物后面显示轮廓阴影
Shader "Lesson/PlayerBody" {
Properties {
_Color ("Color", Color) = (,,,)
_OcculusionColor ("被挡住以后的颜色", Color) = (,,,)
}
SubShader {
Tags { "Queue"="Geometry+200" }
Pass
{
ZTest Greater
Color[_OcculusionColor]
}
Pass
{
ZTest Less
Color[_Color]
}
}
FallBack "Diffuse"
}
补充:物体多个材质球渲染,unity mobile shader:解决眼镜和身体的遮挡关系
Shader "Lesson/Glass" {
Properties {
_Color ("Color", Color) = (,,,)
_OcculusionColor ("被挡住以后的颜色", Color) = (,,,)
}
SubShader {
Tags { "Queue"="Geometry+100" }
Pass
{
ZTest Greater
ZWrite off
Color[_OcculusionColor]
}
Pass
{
ZTest Less
Color[_Color]
}
}
FallBack "Diffuse"
}
边缘发光
// Upgrade NOTE: replaced '_World2Object' with 'unity_WorldToObject'
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader"Lesson/OutLine1"
{
Properties
{
_MainTex("main tex",2D) = "black"{}
_RimColor("rim color",Color) = (,,,)//边缘颜色
_RimPower("rim power",range(,)) = //边缘强度
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include"UnityCG.cginc"
struct v2f
{
float4 vertex:POSITION;
float4 uv:TEXCOORD0;
float4 NdotV:COLOR;
};
sampler2D _MainTex;
float4 _RimColor;
float _RimPower;
v2f vert(appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = v.texcoord;
float3 V = WorldSpaceViewDir(v.vertex);
V = mul(unity_WorldToObject,V);//视方向从世界到模型坐标系的转换
o.NdotV.x = saturate(dot(v.normal,normalize(V)));//必须在同一坐标系才能正确做点乘运算
return o;
}
half4 frag(v2f IN) :COLOR
{
half4 c = tex2D(_MainTex,IN.uv);
//用视方向和法线方向做点乘,越边缘的地方,法线和视方向越接近90度,点乘越接近0.
//用(1- 上面点乘的结果)*颜色,来反映边缘颜色情况
c.rgb += pow(( - IN.NdotV.x) ,_RimPower)* _RimColor.rgb;
return c;
}
ENDCG
}
}
FallBack"Diffuse"
}
Shader "Lesson/OutLine2"
{
Properties
{
_MainTex("main tex",2D) = ""{}
_Factor("factor",Range(,0.1)) = 0.01//描边粗细因子
_OutLineColor("outline color",Color) = (,,,)//描边颜色
}
SubShader
{
Pass
{
Cull Front //剔除前面
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" struct v2f
{
float4 vertex :POSITION;
}; float _Factor;
half4 _OutLineColor; v2f vert(appdata_full v)
{
v2f o;
//v.vertex.xyz += v.normal * _Factor;
//o.vertex = mul(UNITY_MATRIX_MVP,v.vertex); //变换到视坐标空间下,再对顶点沿法线方向进行扩展
float4 view_vertex = mul(UNITY_MATRIX_MV,v.vertex);
float3 view_normal = mul(UNITY_MATRIX_IT_MV,v.normal);
view_vertex.xyz += normalize(view_normal) * _Factor; //记得normalize
o.vertex = mul(UNITY_MATRIX_P,view_vertex);
return o;
} half4 frag(v2f IN) :COLOR
{
//return half4(0,0,0,1);
return _OutLineColor;
}
ENDCG
}
Pass
{
Cull Back //剔除后面
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" struct v2f
{
float4 vertex :POSITION;
float4 uv:TEXCOORD0;
}; sampler2D _MainTex; v2f vert(appdata_full v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP,v.vertex);
o.uv = v.texcoord;
return o;
} half4 frag(v2f IN) :COLOR
{
//return half4(1,1,1,1);
half4 c = tex2D(_MainTex,IN.uv);
return c;
}
ENDCG
}
}
FallBack "Diffuse"
}
Shader "Lesson/OutLine3"
{
Properties
{
_MainTex("main tex", 2D) = ""{ }
_OutLineColor("outline color",Color) = (,,,)//描边颜色
}
SubShader
{
//描边
pass
{
Cull Front
Offset -,- //深度偏移
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" sampler2D _MainTex;
half4 _OutLineColor; struct v2f
{
float4 pos : SV_POSITION;
}; v2f vert(appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
return o;
} float4 frag(v2f i) : COLOR
{
return _OutLineColor;
}
ENDCG
}
//正常渲染物体
pass
{
//Cull Back
//Offset 5,-1
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc" sampler2D _MainTex;
float4 _MainTex_ST; struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
}; v2f vert(appdata_base v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP,v.vertex);
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
} float4 frag(v2f i) : COLOR
{
float4 c = tex2D(_MainTex,i.uv);
return c;
}
ENDCG
}
}
}
Unity3D学习笔记(三十六):Shader着色器(3)- 光照的更多相关文章
- Unity3D学习笔记(十六):Animator新动画
新动画系统: 给模型选择动画类型 普通动画:Generic 人形动画:Humanoid 建立动画控制器 - 在Project右击 - 选择Create-AnimatorContorller 将对应动画 ...
- 【Unity 3D】学习笔记三十六:物理引擎——刚体
物理引擎就是游戏中模拟真是的物理效果.如两个物体发生碰撞,物体自由落体等.在unity中使用的是NVIDIA的physX,它渲染的游戏画面很逼真. 刚体 刚体是一个很很中要的组件. 默认情况下,新创的 ...
- PHP学习笔记三十六【try 二】
<?php //定义一个顶级异常处理器 要定义在最上面 function my_exception($e) { echo "我是顶级异常处理:".$e->getMess ...
- Nodejs学习笔记(十六)--- Pomelo介绍&入门
目录 前言&介绍 安装Pomelo 创建项目并启动 创建项目 项目结构说明 启动 测试连接 聊天服务器 新建gate和chat服务器 配置master.json 配置servers.json ...
- Nodejs学习笔记(十六)—Pomelo介绍&入门
前言&介绍 Pomelo:一个快速.可扩展.Node.js分布式游戏服务器框架 从三四年前接触Node.js开始就接触到了Pomelo,从Pomelo最初的版本到现在,总的来说网易出品还算不错 ...
- angular学习笔记(三十)-指令(10)-require和controller
本篇介绍指令的最后两个属性,require和controller 当一个指令需要和父元素指令进行通信的时候,它们就会用到这两个属性,什么意思还是要看栗子: html: <outer‐direct ...
- angular学习笔记(三十)-指令(7)-compile和link(2)
继续上一篇:angular学习笔记(三十)-指令(7)-compile和link(1) 上一篇讲了compile函数的基本概念,接下来详细讲解compile和link的执行顺序. 看一段三个指令嵌套的 ...
- angular学习笔记(三十)-指令(7)-compile和link(1)
这篇主要讲解指令中的compile,以及它和link的微妙的关系. link函数在之前已经讲过了,而compile函数,它和link函数是不能共存的,如果定义了compile属性又定义link属性,那 ...
- angular学习笔记(三十)-指令(6)-transclude()方法(又称linker()方法)-模拟ng-repeat指令
在angular学习笔记(三十)-指令(4)-transclude文章的末尾提到了,如果在指令中需要反复使用被嵌套的那一坨,需要使用transclude()方法. 在angular学习笔记(三十)-指 ...
- angular学习笔记(三十)-指令(5)-link
这篇主要介绍angular指令中的link属性: link:function(scope,iEle,iAttrs,ctrl,linker){ .... } link属性值为一个函数,这个函数有五个参数 ...
随机推荐
- 【Hadoop学习之五】win7+Eclipse+hadoop3搭建本机开发环境
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 hadoop-3.1.1 拓扑: 知识准备: 1.eclip ...
- JVM调优总结 -Xms
转载自:http://unixboy.iteye.com/blog/174173/ 设置eclipse : -Xms256M -Xmx512M -XX:PermSize=256m -XX:MaxPer ...
- 英文名为什么最好不用joe?JOE英文名的寓意是什么?
英文名为什么最好不用joe?JOE英文名的寓意是什么? Joe 的意思是乔,人名.意为,上帝还会赐予 Joe 乔(男子名, 对不相识者非正式的称呼; Joseph的昵称)(=GIJoe)[美俚]美国兵 ...
- vue去掉严格开发,即去掉vue-cli安装时的eslint
vue去掉严格开发,即去掉vue-cli安装时的eslint : 1.vue-cli书写规范(主要是js规范) a.逗号.冒号后面要加空格 b.不能使用双引号,一律使用单引号 webpack的语法检查 ...
- Step6:SQL Server 数据变更时间戳(timestamp)在复制中的运用
一.本文所涉及的内容(Contents) 本文所涉及的内容(Contents) 背景(Contexts) 方案(Solution) 方案一(Solution One) 方案二(Solution Two ...
- if语法
语法一: if 条件: 条件成立时执行的子代码块 age_of_girl=31 if age_of_girl > 30: print('阿姨好') 语法二:if + else if 条件 ...
- python-selenium,关于页面滑动的操作
//移动到元素element对象的“顶端”与当前窗口的“顶部”对齐 ((JavascriptExecutor) driver).executeScript("arguments[0].scr ...
- Docker学习笔记之运行和管理容器
0x00 概述 容器是基于容器技术所建立和运行的轻量级应用运行环境,它是 Docker 封装和管理应用程序或微服务的“集装箱”.在 Docker 中,容器算是最核心的部分了,掌握容器的操作也是 Doc ...
- Golang切片的三种简单使用方式及区别
概念 切片(slice)是建立在数组之上的更方便,更灵活,更强大的数据结构.切片并不存储任何元素而只是对现有数组的引用. 三种方式及细节案例 ①定义一个切片,然后让切片去引用一个已经创建好的数组 pa ...
- python2.7安装mysql-python
环境:python2.7.14+mysql-python-1.2.3.win-amd64-py2.7.exe 安装版本许参照解释器版本,有64和32位之分,如果安装错误版本,则运行时会报错:Impor ...