10.光照模型-高光反射光照模型-Phong式高光反射模型-逐顶点光照
10.1 知识点
关键知识点回顾
公式
- 高光反射光照颜色 = 光源的颜色 * 材质高光反射颜色 * max(0, 标准化后观察方向向量· 标准化后的反射方向)幂
相关变量和函数
观察者的位置(摄像机的位置)_WorldSpaceCameraPos
相对于法向量的反射向量 方法:reflect(入射向量, 顶点法向量) 返回反射向量
指数幂 方法:pow(底数,指数) 返回计算结果
利用Phong式高光反射光照模型实现光照效果(逐顶点光照)
创建着色器并简化初始代码
Shader "Unlit/Lesson10_Phong_Specular_Vertex"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
v2f vert (appdata appdata)
{
}
fixed4 frag (v2f v2f) : SV_Target
{
}
ENDCG
}
}
}
属性声明(材质高光反射颜色、光泽度)
Properties
{
// 高光反射颜色
_SpecularColor("SpecularColor", Color) = (1,1,1,1)
// 光泽度
_SpecularNum("SpecularNum", Range(0, 20)) = 0.5
}
渲染标签Tags设置
将LightMode光照模式 设置为ForwardBase向前渲染(通常用于不透明物体的基本渲染)
// 设置我们的光照模式 ForwardBase这种向前渲染模式 主要是用来处理 不透明物体的 光照渲染的
Tags
{
"LightMode"="ForwardBase"
}
引用内置文件 UnityCG.cginc
和 Lighting.cginc
// 引用对应的内置文件,用于使用内置结构体和变量
#include "UnityCG.cginc"
#include "Lighting.cginc"
结构体声明
要传裁剪空间下的顶点坐标信息和对应顶点的漫反射光照颜色
// 顶点着色器传递给片元着色器的内容
struct v2f
{
// 裁剪空间下的顶点坐标信息
float4 pos:SV_POSITION;
// 对应顶点的漫反射光照颜色
fixed3 color:COLOR;
};
获得属性
// 对应属性中的颜色和光泽度
fixed4 _SpecularColor;
float _SpecularNum;
顶点着色器逻辑
在顶点函数中,获得需要的变量并套用基本公式实现逻辑
v2f vert(appdata_base appdata_base)
{
v2f v2f;
//1.将顶点坐标转换到裁剪空间当中
//UnityObjectToClipPos 把模型空间下的顶点转换到裁剪空间下
v2f.pos = UnityObjectToClipPos(appdata_base.vertex);
//2.计算颜色相关
//高光反射光照颜色 = 光源的颜色 * 材质高光反射颜色 * max(0, 标准化后观察方向向量· 标准化后的反射方向)幂
//光源的颜色 _LightColor.rgb
//材质高光反射颜色 _SpecularColor.rgb
//幂(光泽度) _SpecularNum
//2.1 标准化后观察方向向量
//将模型空间下的顶点位置 转换到 世界空间下
//由于没有提供直接转换的api 所以要使用内置矩阵运算进行转换
// UNITY_MATRIX_M : 从模型空间下 转到 世界空间下的转换矩阵
float3 worldPos = mul(UNITY_MATRIX_M, appdata_base.vertex);
//用观察者的位置(摄像机的位置)减去世界空间下顶点坐标 得到的就是视角方向
float3 viewDir = _WorldSpaceCameraPos.xyz - worldPos;
//单位化(归一化)
viewDir = normalize(viewDir);
//2.2 标准化后的反射方向
//世界空间下的光位置的方向向量
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
//世界空间下的法线向量
float3 normal = UnityObjectToWorldNormal(appdata_base.normal);
//reflect(入射向量,顶点法向量) 返回反射向量 反射光线向量
float3 reflectDir = reflect(-lightDir, normal);
//3.套公式
//高光反射光照颜色 = 光源的颜色 * 材质高光反射颜色 * max(0, 标准化后观察方向向量· 标准化后的反射方向)幂
fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(viewDir, reflectDir)), _SpecularNum);
//记录颜色 传递给片元着色器
v2f.color = color;
return v2f;
}
片元着色器
把计算好的光照的颜色传递出去
fixed4 frag(v2f v2f) : SV_Target
{
// 返回计算好的光照颜色,透明度为1
return fixed4(v2f.color.rgb, 1);
}
调整光泽度和颜色,查看效果并对比
通过调整材质的 SpecularColor
和 SpecularNum
,可以观察光泽度的变化以及光照的高光反射效果。
10.2 知识点代码
Lesson10_光照模型_高光反射光照模型_Phong式高光反射模型_逐顶点光照
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson10_光照模型_高光反射光照模型_Phong式高光反射模型_逐顶点光照 : MonoBehaviour
{
void Start()
{
#region 关键知识点回顾
//高光反射光照颜色 = 光源的颜色 * 材质高光反射颜色 * max(0, 标准化后观察方向向量· 标准化后的反射方向)幂
//1.观察者的位置(摄像机的位置)
// _WorldSpaceCameraPos
//2.相对于法向量的反射向量 方法
// reflect(入射向量,顶点法向量) 返回反射向量
//3.指数幂 方法
// pow(底数,指数) 返回计算结果
#endregion
#region 知识点 利用Phong式高光反射光照模型实现光照效果(逐顶点光照)
//关键步骤
//1.属性声明(材质高光反射颜色、光泽度)
//2.渲染标签Tags设置 将LightMode光照模式 设置为ForwardBase向前渲染(通常用于不透明物体的基本渲染)
//3.引用内置文件UnityCG.cginc和Lighting.cginc
//4.结构体声明
//5.基本公式实现逻辑
#endregion
}
}
Lesson10_Phong_Specular_Vertex.shader
Shader "Unlit/Lesson10_Phong_Specular_Vertex"
{
Properties
{
//高光反射颜色
_SpecularColor("SpecularColor", Color) = (1,1,1,1)
//光泽度
_SpecularNum("SpecularNum", Range(0, 20)) = 0.5
}
SubShader
{
//设置我们的光照模式 ForwardBase这种向前渲染模式 主要是用来处理 不透明物体的 光照渲染的
Tags
{
"LightMode"="ForwardBase"
}
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
//引用对应的内置文件
//主要是为了之后 的 比如内置结构体使用,内置变量使用
#include "UnityCG.cginc"
#include "Lighting.cginc"
//顶点着色器传递给片元着色器的内容
struct v2f
{
//裁剪空间下的顶点坐标信息
float4 pos:SV_POSITION;
//对应顶点的漫反射光照颜色
fixed3 color:COLOR;
};
//对应属性当中的颜色和光泽度
fixed4 _SpecularColor;
float _SpecularNum;
v2f vert(appdata_base appdata_base)
{
v2f v2f;
//1.将顶点坐标转换到裁剪空间当中
//UnityObjectToClipPos 把模型空间下的顶点转换到裁剪空间下
v2f.pos = UnityObjectToClipPos(appdata_base.vertex);
//2.计算颜色相关
//高光反射光照颜色 = 光源的颜色 * 材质高光反射颜色 * max(0, 标准化后观察方向向量· 标准化后的反射方向)幂
//光源的颜色 _LightColor.rgb
//材质高光反射颜色 _SpecularColor.rgb
//幂(光泽度) _SpecularNum
//2.1 标准化后观察方向向量
//将模型空间下的顶点位置 转换到 世界空间下
//由于没有提供直接转换的api 所以要使用内置矩阵运算进行转换
// UNITY_MATRIX_M : 从模型空间下 转到 世界空间下的转换矩阵
float3 worldPos = mul(UNITY_MATRIX_M, appdata_base.vertex);
//用观察者的位置(摄像机的位置)减去世界空间下顶点坐标 得到的就是视角方向
float3 viewDir = _WorldSpaceCameraPos.xyz - worldPos;
//单位化(归一化)
viewDir = normalize(viewDir);
//2.2 标准化后的反射方向
//世界空间下的光位置的方向向量
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
//世界空间下的法线向量
float3 normal = UnityObjectToWorldNormal(appdata_base.normal);
//reflect(入射向量,顶点法向量) 返回反射向量 反射光线向量
float3 reflectDir = reflect(-lightDir, normal);
//3.套公式
//高光反射光照颜色 = 光源的颜色 * 材质高光反射颜色 * max(0, 标准化后观察方向向量· 标准化后的反射方向)幂
fixed3 color = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(viewDir, reflectDir)), _SpecularNum);
//记录颜色 传递给片元着色器
v2f.color = color;
return v2f;
}
fixed4 frag(v2f v2f) : SV_Target
{
//把计算好的光照的颜色 传递出去就可以了
//返回v2f中的颜色 透明度传1
return fixed4(v2f.color.rgb, 1);
}
ENDCG
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com