光照
文章目录
不同的光照shader,同条件下会有不一样的结果
vertex_difuse
unity光照对比顶点光照
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZgsBjJ9c-1681797878882)(image-20230306121657737.png)]
因为使用顶点做插值,所以可以看到比较严重的锯齿
Shader "Unlit/基础光照实现/vertex_difuse"
{
Properties
{
_Diffuse("漫反射颜色",Color)=(1,1,1,1)
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
fixed3 color:COLOR;
};
fixed4 _Diffuse;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//在顶点着色器中计算漫反射光照
//unity中使用 UNITY_LIGHTMODEL_AMBIENT 来表示环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
//获取光的方向
//当世界只有一个平行光光源的时候可以使用 _WorldSpaceLightPos0 这个内置的变量来获取光照的方向
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
//世界中的法线信息
//可以使用 unity_ObjectToWorld 矩阵来将其变换到世界中
fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_ObjectToWorld));
//_LightColor0 世界只有一个平行光光源的时候 表示光源的颜色
//saturate函数的作用是将输入的参数数值限定在 0-1 之间
fixed3 diff = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLight));
o.color = diff + ambient;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return fixed4(i.color,1.0f);
}
ENDCG
}
}
}
vertex_difuse
按像素计算
效果很精美,没有锯齿,但是可以看到黑色区域非常黑
Shader "Unlit/基础光照实现/pixel_difuse"
{
Properties
{
_Diffuse("漫反射颜色",Color)=(1,1,1,1)
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 worldNormal:NORMAL;
};
fixed4 _Diffuse;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//世界中的法线信息
//可以使用 unity_ObjectToWorld 矩阵来将其变换到世界中
o.worldNormal = normalize(mul(v.normal,(float3x3)unity_ObjectToWorld));
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//unity中使用 UNITY_LIGHTMODEL_AMBIENT 来表示环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
//获取光的方向
//当世界只有一个平行光光源的时候可以使用 _WorldSpaceLightPos0 这个内置的变量来获取光照的方向
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
float3 worldNormal = normalize(i.worldNormal);
//_LightColor0 世界只有一个平行光光源的时候 表示光源的颜色
//saturate函数的作用是将输入的参数数值限定在 0-1 之间
fixed3 diff = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLight));
fixed3 color = diff + ambient;
return fixed4(color,1.0f);
}
ENDCG
}
}
}
Lamert_pixel_difuse
lamert算法改进了阴影的缺陷
Shader "Unlit/基础光照实现/Lamert_pixel_difuse"
{
Properties
{
_Diffuse("漫反射颜色",Color)=(1,1,1,1)
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 worldNormal:NORMAL;
};
fixed4 _Diffuse;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//世界中的法线信息
//可以使用 unity_ObjectToWorld 矩阵来将其变换到世界中
o.worldNormal = normalize(mul(v.normal,(float3x3)unity_ObjectToWorld));
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//unity中使用 UNITY_LIGHTMODEL_AMBIENT 来表示环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
//获取光的方向
//当世界只有一个平行光光源的时候可以使用 _WorldSpaceLightPos0 这个内置的变量来获取光照的方向
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
float3 worldNormal = normalize(i.worldNormal);
//兰伯特光照计算
//c_diffuse = (c_light * m_diffuse) * (a * (normal.dot(lightdir)) + b)
//半兰伯特公式
//c_diffuse = (c_light * m_diffuse) * (0.5 * (normal.dot(lightdir)) + 0.5)
fixed3 half_lambert = 0.5 * dot(worldNormal,worldLight) + 0.5;
//_LightColor0 世界只有一个平行光光源的时候 表示光源的颜色
//saturate函数的作用是将输入的参数数值限定在 0-1 之间
fixed3 diff = _LightColor0.rgb * _Diffuse.rgb * half_lambert;
fixed3 color = diff + ambient;
return fixed4(color,1.0f);
}
ENDCG
}
}
}
Specular_Lamert_pixel_difuse
lamert算法+高光(镜面反射)算法后的表现
可以看到这样的高光整体效果不是很自然
Shader "Unlit/基础光照实现/Specular_Lamert_pixel_difuse"
{
Properties
{
_Diffuse("漫反射颜色",Color)=(1,1,1,1)
_Specular("镜面反射系数",Color)=(1,1,1,1)
_Power("高光指数",Range(1.0,512.0))=20.0
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 worldNormal:TEXCOORD0;
float3 worldPos:TEXCOORD1;
};
fixed4 _Diffuse;
fixed4 _Specular;
float _Power;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//世界中的法线信息
//可以使用 unity_ObjectToWorld 矩阵来将其变换到世界中
o.worldNormal = normalize(mul(v.normal,(float3x3)unity_ObjectToWorld));
o.worldPos = mul(v.vertex,(float3x3)unity_ObjectToWorld);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//unity中使用 UNITY_LIGHTMODEL_AMBIENT 来表示环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
//获取光的方向
//当世界只有一个平行光光源的时候可以使用 _WorldSpaceLightPos0 这个内置的变量来获取光照的方向
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
float3 worldNormal = normalize(i.worldNormal);
//兰伯特光照计算
//c_diffuse = (c_light * m_diffuse) * (a * (normal.dot(lightdir)) + b)
//半兰伯特公式
//c_diffuse = (c_light * m_diffuse) * (0.5 * (normal.dot(lightdir)) + 0.5)
fixed3 half_lambert = 0.5 * dot(worldNormal,worldLight) + 0.5;
//_LightColor0 世界只有一个平行光光源的时候 表示光源的颜色
//saturate函数的作用是将输入的参数数值限定在 0-1 之间
fixed3 diff = _LightColor0.rgb * _Diffuse.rgb * half_lambert;
//计算镜面反射
//Unity中给出了计算反射方向的函数 r = reflect(i,n)
/*
r:表示反射的方向
i:表示的是入射的方向
n:表示的是法线方向
*/
fixed3 reflectdir = normalize(reflect(-worldLight,worldNormal));
//观察方向
//_WorldSpaceCameraPos 表示的是当前世界中摄像机的位置
fixed3 viewdir = normalize( _WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectdir,viewdir)),_Power);
fixed3 color = diff + ambient + specular;
return fixed4(color,1.0f);
}
ENDCG
}
}
}
BlinPhong_Specular_Lamert_pixel_difuse
对于折射的角度做了一些处理步骤
Shader "Unlit/基础光照实现/BlinPhong_Specular_Lamert_pixel_difuse"
{
Properties
{
_Diffuse("漫反射颜色",Color)=(1,1,1,1)
_Specular("镜面反射系数",Color)=(1,1,1,1)
_Power("高光指数",Range(1.0,512.0))=20.0
}
SubShader
{
Pass
{
Tags { "LightMode"="ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
float3 worldNormal:TEXCOORD0;
float3 worldPos:TEXCOORD1;
};
fixed4 _Diffuse;
fixed4 _Specular;
float _Power;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
//世界中的法线信息
//可以使用 unity_ObjectToWorld 矩阵来将其变换到世界中
o.worldNormal = normalize(mul(v.normal,(float3x3)unity_ObjectToWorld));
o.worldPos = mul(v.vertex,(float3x3)unity_ObjectToWorld);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
//unity中使用 UNITY_LIGHTMODEL_AMBIENT 来表示环境光
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;
//获取光的方向
//当世界只有一个平行光光源的时候可以使用 _WorldSpaceLightPos0 这个内置的变量来获取光照的方向
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz);
float3 worldNormal = normalize(i.worldNormal);
//兰伯特光照计算
//c_diffuse = (c_light * m_diffuse) * (a * (normal.dot(lightdir)) + b)
//半兰伯特公式
//c_diffuse = (c_light * m_diffuse) * (0.5 * (normal.dot(lightdir)) + 0.5)
fixed3 half_lambert = 0.5 * dot(worldNormal,worldLight) + 0.5;
//_LightColor0 世界只有一个平行光光源的时候 表示光源的颜色
//saturate函数的作用是将输入的参数数值限定在 0-1 之间
fixed3 diff = _LightColor0.rgb * _Diffuse.rgb * half_lambert;
//计算镜面反射
//Unity中给出了计算反射方向的函数 r = reflect(i,n)
/*
r:表示反射的方向
i:表示的是入射的方向
n:表示的是法线方向
*/
//fixed3 reflectdir = normalize(reflect(-worldLight,worldNormal));
//观察方向
//_WorldSpaceCameraPos 表示的是当前世界中摄像机的位置
fixed3 viewdir = normalize( _WorldSpaceCameraPos.xyz - i.worldPos.xyz);
fixed3 halfdir = normalize(worldLight + viewdir);
//fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(reflectdir,viewdir)),_Power);
fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(saturate(dot(worldNormal,halfdir)),_Power);
fixed3 color = diff + ambient + specular;
return fixed4(color,1.0f);
}
ENDCG
}
}
}