7.多种光源-如何在Shader中判断光源类型
7.1 知识点
重要知识回顾
在Shader光源开发中,我们需要了解一些基本的预处理指令和渲染路径的概念。
预处理指令
- Shader中也有预处理指令,类似于C#中的预处理指令。通过预处理指令,我们可以在编译时对代码进行条件编译,包含或排除特定的代码块。
前向渲染路径中的光照计算
Base Pass(基础渲染通道):
- 主要用于处理影响该物体的高质量光源,通常是平行光。
- 还包括逐顶点计算的中等质量光源和逐顶点计算的低质量光源(例如SH计算)。
Additional Pass(附加渲染通道):
- 主要用于处理除平行光以外的其他高质量光源。
- 每个高质量光源都会调用一次这个通道进行计算。
注意:处理多种光源的示例我们都在前向渲染中处理
前向渲染路径中我们主要关注处理什么内容?
在前向渲染路径中,渲染过程通常包含两个Pass:
Base Pass(基础渲染通道)
- 每个片元只会计算一次。
- 主要用于处理一个逐像素的平行光源,这通常是场景中最亮的光源,Unity会自动为我们分配该光源对应的变量。
- 其他的中等质量光源(逐顶点处理)和低质量光源(如SH处理)会由Unity自动处理,无需开发者干预。
Additional Pass(附加渲染通道)
- 主要用于处理除最亮平行光之外的其他高质量光源(包括平行光、点光源和聚光灯)。
- 每个高质量光源会调用一次该Pass进行计算。
- 因此,在Additional Pass中,我们通常需要根据光源类型来判断并处理不同的渲染逻辑。
如何在Shader中判断光源类型
在Unity的Shader开发中,我们通常通过一些宏来判断光源类型。这些宏的作用是让我们可以在编译时选择性地编译不同的代码块。
Unity提供的光源类型宏:
_DIRECTIONAL_LIGHT
: 用于平行光(Directional Light)。_POINT_LIGHT
: 用于点光源(Point Light)。_SPOT_LIGHT
: 用于聚光灯(Spot Light)。
使用宏进行条件编译
这些宏可以与条件编译指令一起使用,帮助我们在编写Shader时根据不同的光源类型执行不同的逻辑。
例如,在Shader中使用这些宏进行条件编译:
#if defined(_DIRECTIONAL_LIGHT)
// 平行光的计算逻辑
#elif defined(_POINT_LIGHT)
// 点光源的计算逻辑
#elif defined(_SPOT_LIGHT)
// 聚光灯的计算逻辑
#else
// 其他光源的计算逻辑
#endif
Shader变体(Shader Variants)
通过使用条件编译指令,Unity会根据不同的配置选项生成多个着色器变体。虽然这些变体共享相同的核心代码,但会根据条件编译的选择包含不同的代码块。
- Shader variants 是根据条件编译指令(如
#if
,#elif
,#else
,#endif
)生成的多个Shader版本。 - 不同的Shader变体可以根据不同的光源类型或者其他条件编译出来,因此可以在运行时选择最合适的Shader变体以提高渲染效率。
7.2 知识点代码
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Lesson07_多种光源_如何在Shader中判断光源类型 : MonoBehaviour
{
void Start()
{
#region 注意
// 注意:处理多种光源的示例我们都在前向渲染中处理
#endregion
#region 重要知识回顾
//1.预处理指令
// Shader中也存在预处理指令
// 可以通过选修课回顾下C#中的预处理指令
// 它的使用和Shader当中类似
//2.前向渲染路径在哪里进行光照计算
// Base Pass(基础渲染通道):
// 主要用于处理影响该物体的一个高质量光源(平行光)、所有中(逐顶点处理)低质量(SH处理)光源 等
// Additional Pass(附加渲染通道):
// 主要用于处理影响该物体的除平行光以外的其它高质量光源(每个高质量光源都会调用)
#endregion
#region 知识点一 前向渲染路径中我们主要关注处理什么内容?
//两个Pass
//1.Base Pass(基础渲染通道,每个片元只会计算一次):
// 只需要处理一个逐像素平行光源(一般场景中最亮会自动赋值对应变量)
// 其他的中(逐顶点)、低质量(SH)光源Unity会帮助我们处理
//2.Additional Pass(附加渲染通道):
// 除了最亮的平行光、其他高质量的光源(可能是平行光、点光源、聚光灯)都会调用一次该Pass进行计算
//因此我们一般需要在Additional Pass中判断光源类型来分别处理部分逻辑
#endregion
#region 知识点二 如何在Shader中判断光源类型
//Unity中提供了三个重要的宏
//分别是:
//_DIRECTIONAL_LIGHT:平行光
//_POINT_LIGHT:点光源
//_SPOT_LIGHT:聚光灯
//宏在这里的作用:
//可以用于在编译时根据条件判断来包含或排除不同的代码块,实现条件编译
//我们可以使用这些宏配合Unity Shader中的条件编译预处理指令
//用于在编译时根据一定的条件选择性地包含或排除代码块
//#if defined(_DIRECTIONAL_LIGHT)
// 平行光逻辑
//#elif defined (_POINT_LIGHT)
// 点光源逻辑
//#elif defined (_SPOT_LIGHT)
// 聚光灯逻辑
//#else
// 其他逻辑
//#endif
//Unity底层会根据该条件编译指令
//生成成多个 Shader Variants(着色器变体)
//这些 Variants 变体共享相同的核心代码
//但根据条件编译的选择会包含不同的代码块
//Shader variants 的基本概念是在编写 shader 时,
//通过条件编译指令(#if, #elif, #else, #endif)
//根据不同的配置选项生成多个版本的 shader。
//这些不同版本的 shader 称为 shader variants。
#endregion
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com