7.如何在Shader中判断光源类型

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

×

喜欢就点赞,疼爱就打赏