26.高级纹理-立方体纹理-反射-反射基础实现
26.1 知识点
实现反射基础效果
CG 中提供了内置函数 texCUBE
用于进行立方体纹理采样。
- 函数形式:
texCUBE(立方体纹理, 反射方向向量)
- 工作原理:利用反射方向向量,从立方体中心向纹理发射向量,得到相交点并进行采样。
实现反射效果
主要步骤
属性声明
- 声明两个关键属性:
- 立方体纹理
- 反射率(范围:0~1)
- 声明两个关键属性:
顶点着色器
- 关键步骤:
- 顶点坐标转裁剪坐标
- 顶点法线转世界坐标
- 顶点坐标转世界坐标
- 计算世界空间下的视角方向
- 视角反向逆向得到反射方向
- 关键步骤:
片元着色器
- 关键步骤:
- 利用
texCUBE
函数进行立方体纹理采样 - 结合反射程度返回最终颜色
- 利用
- 关键步骤:
新建 Shader
Shader "Unlit/Lesson26_ReflectBase"
{
Properties {}
SubShader
{
Pass {}
}
}
声明两个属性:立方体纹理和反射率
Properties
{
// 立方体纹理
_Cube("Cubemap", Cube) = "" {}
// 反射率
_Reflectivity("Reflectivity", Range(0,1)) = 1
}
声明渲染标签、预编译指令、内置库和对应属性
SubShader
{
Tags
{
"RenderType"="Opaque" // 设置渲染类型为不透明(Opaque)
"Queue"="Geometry" // 设置渲染队列为Geometry,通常用于普通几何物体
}
Pass
{
// 设置LightMode标签,指定光照模式为ForwardBase
Tags
{
"LightMode"="ForwardBase" // 指定使用正向渲染中的基本光照模式
}
CGPROGRAM
#pragma vertex vert // 指定顶点着色器函数为vert
#pragma fragment frag // 指定片元着色器函数为frag
// 包含Unity内置的CG库和光照相关的库
#include "UnityCG.cginc"
#include "Lighting.cginc"
// 立方体纹理属性
samplerCUBE _Cube;
// 反射率属性
float _Reflectivity;
ENDCG
}
}
声明结构体,包括裁剪空间下顶点坐标和世界空间下的反射向量
struct v2f
{
float4 pos:SV_POSITION; //裁剪空间下的顶点坐标
//世界空间下的反射向量
//我们将把反射向量的计算放在顶点着色器函数中 节约性能 表现效果也不会太差 肉眼几乎分辨不出来
float3 worldRefl:TEXCOORD0;
};
说明:反射向量的计算放在顶点着色器中以节约性能,视觉效果几乎无差别。
顶点函数中主要进行顶点坐标转换和计算反射光向量
v2f vert(appdata_base appdata_base)
{
v2f v2f;
//顶点坐标转换
v2f.pos = UnityObjectToClipPos(appdata_base.vertex);
//计算反射光向量
//1.计算世界空间下法线向量
float3 worldNormal = UnityObjectToWorldNormal(appdata_base.normal);
//2.世界空间下的顶点坐标
fixed3 worldPos = mul(unity_ObjectToWorld, appdata_base.vertex).xyz;
//3.计算视角方向 内部是用摄像机位置 - 世界坐标位置 计算反射向量时要取反
fixed3 worldViewDir = UnityWorldSpaceViewDir(worldPos);
//4.计算反射向量
v2f.worldRefl = reflect(-worldViewDir, worldNormal);
return v2f;
}
片元函数对立方体纹理利用对应的反射向量进行采样,用采样颜色 * 反射率 决定最终的颜色效果
fixed4 frag(v2f v2f):SV_TARGET
{
//对立方体纹理利用对应的反射向量进行采样
fixed4 cubemapColor = texCUBE(_Cube, v2f.worldRefl);
//用采样颜色 * 反射率 决定最终的颜色效果
return cubemapColor * _Reflectivity;
}
使用小工具重新生成一下cuemap,创建材质赋值,可以看到镜面效果
26.2 知识点代码
Lesson26_高级纹理_立方体纹理_反射_反射基础实现.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson26_高级纹理_立方体纹理_反射_反射基础实现 : MonoBehaviour
{
void Start()
{
#region 知识点一 实现反射基础效果使用的立方体纹理采样函数
//立方体纹理采样函数
// CG中提供了内置函数 texCUBE 用于进行立方体纹理采样
// texCUBE(立方体纹理,反射方向向量) 便可以得到在立方体纹理中的采样结果
// 原理就是利用反射方向向量,在立方体中心往纹理发射向量,得到相交点进行采样
#endregion
#region 知识点二 实现反射效果
//1.属性声明
// 我们将声明2个关键属性
// 1-1:立方体纹理
// 1-2:反射率(0~1)之间
//2.顶点着色器
// 关键步骤:
// 2-1:顶点坐标转裁剪坐标
// 2-2:顶点法线转世界坐标
// 2-3:顶点坐标转世界坐标
// 2-4:世界空间下 视角方向计算
// 2-5:视角反向逆向得到反射方向
//3.片元着色器
// 关键步骤:
// 3-1:立方体纹理采样(利用texCUBE函数)
// 3-2:结合反射程度返回最终颜色
#endregion
}
}
Lesson26_ReflectBase.shader
Shader "Unlit/Lesson26_ReflectBase"
{
Properties
{
//立方体纹理
_Cube("Cubemap", Cube) = ""{}
//反射率
_Reflectivity("Reflectivity", Range(0,1)) = 1
}
SubShader
{
Tags
{
"RenderType"="Opaque" // 设置渲染类型为不透明(Opaque)
"Queue"="Geometry" // 设置渲染队列为Geometry,通常用于普通几何物体
}
Pass
{
// 设置LightMode标签,指定光照模式为ForwardBase
Tags
{
"LightMode"="ForwardBase" // 指定使用正向渲染中的基本光照模式
}
CGPROGRAM
#pragma vertex vert // 指定顶点着色器函数为vert
#pragma fragment frag // 指定片元着色器函数为frag
// 包含Unity内置的CG库和光照相关的库
#include "UnityCG.cginc"
#include "Lighting.cginc"
// 立方体纹理属性
samplerCUBE _Cube;
// 反射率属性
float _Reflectivity;
struct v2f
{
float4 pos:SV_POSITION; //裁剪空间下的顶点坐标
//世界空间下的反射向量
//我们将把反射向量的计算放在顶点着色器函数中 节约性能 表现效果也不会太差 肉眼几乎分辨不出来
float3 worldRefl:TEXCOORD0;
};
v2f vert(appdata_base appdata_base)
{
v2f v2f;
//顶点坐标转换
v2f.pos = UnityObjectToClipPos(appdata_base.vertex);
//计算反射光向量
//1.计算世界空间下法线向量
float3 worldNormal = UnityObjectToWorldNormal(appdata_base.normal);
//2.世界空间下的顶点坐标
fixed3 worldPos = mul(unity_ObjectToWorld, appdata_base.vertex).xyz;
//3.计算视角方向 内部是用摄像机位置 - 世界坐标位置 计算反射向量时要取反
fixed3 worldViewDir = UnityWorldSpaceViewDir(worldPos);
//4.计算反射向量
v2f.worldRefl = reflect(-worldViewDir, worldNormal);
return v2f;
}
fixed4 frag(v2f v2f):SV_TARGET
{
//对立方体纹理利用对应的反射向量进行采样
fixed4 cubemapColor = texCUBE(_Cube, v2f.worldRefl);
//用采样颜色 * 反射率 决定最终的颜色效果
return cubemapColor * _Reflectivity;
}
ENDCG
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com