漫反射
漫反射计算公式 : C diffuse = (C light · M diffuse ) max(0 , n · l )
C light :入射光线的强度和颜色
M diffuse : 材质的漫反射系数 物体本色
n : 法线单位向量
l : 光源单位向量
逐顶点漫反射代码 :
效果图:

复制代码
Shader "DiffuseVertex"
{
Properties
{
_Diffuse ("Diffuse",Color)=(1,1,1,1)
}
SubShader
{

Pass{
Tags{"LightMode" = "ForwardBase"}

CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "Lighting.cginc"

fixed4 _Diffuse;//获取反漫射颜色(既上面设置的物体自身颜色)

struct a2v{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f{
float4 pos : SV_POSITION;
fixed3 color : COLOR;
};
//逐顶点漫反射
v2f vert(a2v v){
v2f o;

o.pos = UnityObjectToClipPos(v.vertex);

fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;//环境光

//由于下方法线光线两个向量点乘必须处于 同一坐标系下 所以此处将此处的顶点转换到
//通过矩阵坐标空间转换 以及 单位转换 算出单位法线向量
//unity_WorldToObject 既 _World2Object 变换矩阵 可将模型空间转换到世界空间
//通过调换顺序已达到此矩阵的转置矩阵 注意 mul 乘法公式从左到右
//由于法线向量是个三维矢量 将变换矩阵通过 float3x3 转成3x3矩阵
fixed3 worldNormal = normalize(mul(v.normal,(float3x3)unity_WorldToObject));

// 取得光线的单位向量
fixed3 worldLight = normalize(_WorldSpaceLightPos0.xyz); // normalize 单位化 归一化

//通过点乘 获得 法线与光线的夹角 saturate 只截取[0,1]范围内 防止为负数 s
//光线的颜色*漫反射的颜色(物体本色)*光线与法线的夹角 光线照射的角度
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
}
}
FallBack "Diffuse"
}
复制代码

 


逐片元(像素)漫反射代码 :
效果图:

复制代码
Shader "DiffusePixel"
{
Properties
{
_Diffuse ("Diffuse",Color)=(1,1,1,1)
}
SubShader
{

Pass{
Tags{"LightMode" = "ForwardBase"}

CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "Lighting.cginc"

fixed4 _Diffuse;//获取反漫射颜色(既上面设置的物体自身颜色)

struct a2v{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
};


v2f vert(a2v v){
v2f o;

//投影矩阵 将模型空间转换为裁切空间
o.pos = UnityObjectToClipPos(v.vertex);

//空间转换
o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);


//将世界空间下的法线传递给片元着色器
return o;
}

fixed4 frag(v2f i) : SV_Target{

fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;//环境光

//同逐顶点
fixed3 worldNormal = normalize(i.worldNormal);

//光线单位向量
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);

//漫反射计算主体
fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));

//颜色叠加计算出最后的颜色
fixed3 color = ambient + diffuse;

//返回
return fixed4(color,1.0);



}


ENDCG
}
}
FallBack "Diffuse"
}
复制代码

 


半兰伯特公式 像素漫反射:
效果图:

复制代码
Shader "HalfLambert"
{
Properties
{
_Diffuse ("Diffuse",Color)=(1,1,1,1)
}
SubShader
{

Pass{
Tags{"LightMode" = "ForwardBase"}

CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "Lighting.cginc"

fixed4 _Diffuse;//获取反漫射颜色(既上面设置的物体自身颜色)

struct a2v{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
};


v2f vert(a2v v){
v2f o;

//投影矩阵 将模型空间转换为裁切空间
o.pos = UnityObjectToClipPos(v.vertex);

//空间转换
o.worldNormal = mul(v.normal,(float3x3)unity_WorldToObject);


//将世界空间下的法线传递给片元着色器
return o;
}

fixed4 frag(v2f i) : SV_Target{

fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;//环境光

//同逐顶点
fixed3 worldNormal = normalize(i.worldNormal);

//光线单位向量
fixed3 worldLightDir = normalize(_WorldSpaceLightPos0.xyz);

//漫反射计算主体
//fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * saturate(dot(worldNormal,worldLightDir));
//利用半兰伯特公示计算 原理是将原来的max控制最低值的方法给取消
//取代为将值变为原来的一半 原[-1,1] 乘上0.5得 [-0.5,0.5] 最后加上0.5 得 [0,1] 因此称为半兰伯特
//通过这种方法 能够使背光面也会有光线明暗过渡 而不是如同一张纸一样呈现出一个颜色
fixed halfLambert = dot(worldNormal,worldLightDir) * 0.5 + 0.5;

fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * halfLambert;



//颜色叠加计算出最后的颜色
fixed3 color = ambient + diffuse;

//返回
return fixed4(color,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}
复制代码

三种类型的漫反射反射:

 

 

 

 

 
posted on   朱朱的奇妙冒险  阅读(146)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了



点击右上角即可分享
微信分享提示