1.光照模型的物理意义
我们先看一下漫反射的定义
漫反射颜色值 = (光源的rgb*定义的漫反射强度rgb)*max(0,dot(基于世界坐标系的模型法线,光源在世界空间坐标系下的位置))
先解释一下:
(光源的rgb*定义的漫反射强度rgb)
意味着:光源的rgb,和强度rgb的一种单存的颜色叠加。
其实到这一步,我们看到的渲染的模型的颜色就已经和光照挂钩了。我们可以这样写
saturate函数是一个饱和度计算函数,如果dot(objectNormal,lightPos)<0就会返回0,否则返回dot(objectNormal,lightPos);
那么最后一项,dot(objectNormal,lightPos),意味着什么?
我们可以将它视为一种强度变化。
黄色是光向量,指向光源,红色是模型在世界的法线。
这个一乘下来就相当于于什么呢,相当于光在法线上的投影。也就是光照在它身上应该显示多强的颜色。
_WorldSpaceLightPos0.xyz指的就是光向量。
所以,投影的话,最好还是normal一下,两个的长度都是1,投影的意义才会标准,当然,不加normal目前我没看到什么太大的问题。
2. 高光反射模型
反射的高光色= (叠加色:自发光颜色*光源颜色)*pow(归1化(反射光在视线方向的投影),高光强度)
叠加色很容易理解
//来自于CG函数库的_LightColor0.rgb
float3 lightColor = _LightColor0.rgb;
//自定义的_Color
float3 emmisiveColor = _Color.rgb;
float3 overLayColor = float3((lightColor.r*colorPower.r), (lightColor.g*colorPower.g)
, (lightColor.b*colorPower.b));
pow函数,就是一个求次方函数
归1化(观察角度在反射光的投影) ->max(0,dot(reflectLightDir,viewDir))
2.1reflectLightDir 的计算:
fixed3 reflectDir = normalize(reflect(-worldlight,worldnormal));
画一张图
入射光其实等于反向的
2.2viewDir的计算
viewDir = 观察摄像机的位置 - 顶点在世界坐标的位置
fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - mul(unity_ObjectToWorld,v.vertex).xyz);
看下实验吧:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "Unlit/Mesh7"
{
Properties
{
_Color("Color",Color) = (1,1,1,1)
_MainTex("Texture", 2D) = "white" {}
_Gloss("Gloss",Range(0,10)) = 1
}
SubShader
{
Tags {"LightModel" = "ForwardBase" }
LOD 100
Pass
{
//ZWrite Off
//Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vertex
#pragma fragment fragment
// make fog work
// #pragma multi_compile_fog
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct fromCpu
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : POSITION;
float4 color: COLOR0;
float3 normal:TEXCOORD1;
float3 wPos :TEXCOORD2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
fixed _Gloss;
half4 c1;
v2f vertex(fromCpu v)
{
v2f o;
float3 objectNormal = UnityObjectToWorldNormal(v.normal);
float3 lightDir = _WorldSpaceLightPos0.xyz;
objectNormal = normalize(objectNormal);
lightDir = normalize(lightDir);
//来自于CG函数库的_LightColor0.rgb
float3 lightColor = _LightColor0.rgb;
//自定义的_Color
float3 emmisiveColor = _Color.rgb;
float3 overlayColor = float3((lightColor.r*_Color.r), (lightColor.g*_Color.g)
, (lightColor.b*_Color.b));
float3 reflectDir = reflect(-lightDir, objectNormal);
reflectDir = normalize(reflectDir);
float3 cameraPos = _WorldSpaceCameraPos.xyz;
float3 viewDir = cameraPos - v.vertex.xyz;
viewDir = normalize(viewDir);
//高光反射公式
float3 glossColor = overlayColor * pow(saturate(dot(viewDir, reflectDir)), _Gloss);
o.normal = UnityObjectToWorldNormal(v.normal);
o.vertex = UnityObjectToClipPos(v.vertex);
o.color.rgb = glossColor;
o.color.rgb += UNITY_LIGHTMODEL_AMBIENT.xyz;
return o;
}
fixed4 fragment(v2f i) : SV_Target
{
return i.color;
}
ENDCG
}
}
}
看下效果:
这个效果感觉不够丝滑,看它那个光斑一块一块的,我决定放在片元着色器上去计算
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// Upgrade NOTE: replaced '_Object2World' with 'unity_ObjectToWorld'
Shader "Unlit/Shader8"
{
Properties
{
_Color("Color",Color) = (1,1,1,1)
_MainTex("Texture", 2D) = "white" {}
_Gloss("Gloss",Range(0,10)) = 1
}
SubShader
{
Tags {"LightModel" = "ForwardBase" }
LOD 100
Pass
{
//ZWrite Off
//Blend SrcAlpha OneMinusSrcAlpha
CGPROGRAM
#pragma vertex vertex
#pragma fragment fragment
// make fog work
// #pragma multi_compile_fog
#include "UnityCG.cginc"
#include "Lighting.cginc"
struct fromCpu
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal:NORMAL;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : POSITION;
float4 color: COLOR0;
float3 normal:TEXCOORD1;
float3 wPos :TEXCOORD2;
};
sampler2D _MainTex;
float4 _MainTex_ST;
fixed4 _Color;
fixed _Gloss;
half4 c1;
v2f vertex(fromCpu v)
{
v2f o;
float3 objectNormal = UnityObjectToWorldNormal(v.normal);
objectNormal = normalize(objectNormal);
o.normal = objectNormal;
o.vertex = UnityObjectToClipPos(v.vertex);
o.color.rgb = UNITY_LIGHTMODEL_AMBIENT.xyz;
return o;
}
fixed4 fragment(v2f i) : SV_Target
{
//光向量,指向光
float3 lightDir = _WorldSpaceLightPos0.xyz;
lightDir = normalize(lightDir);
//光色
float3 lightColor = _LightColor0.rgb;
//自发光
float3 emmisiveColor = _Color.rgb;
//叠加光
float3 overlayColor = float3((lightColor.r*emmisiveColor.r), (lightColor.g*emmisiveColor.g)
, (lightColor.b*emmisiveColor.b));
//反射光
float3 reflectDir = reflect(-lightDir, i.normal);
reflectDir = normalize(reflectDir);
//摄像机位置
float3 cameraPos = _WorldSpaceCameraPos.xyz;
//观察向量
float3 viewDir = cameraPos - i.vertex.xyz;
viewDir = normalize(viewDir);
//高光反射公式
float3 glossColor = overlayColor * pow(saturate(dot(viewDir, reflectDir)), _Gloss);
i.color.rgb += glossColor;
return i.color;
}
ENDCG
}
}
}
众享丝滑~