Unity SRP 管线【第四讲:URP 阴影】

news2024/12/25 9:33:10

URP 全文源码解析参照

引入

在UniversalRenderer.cs/ line 505行处
此处已经准备好了所有渲染数据(所有数据全部存储在了renderingData中)
我们只用renderingData中的数据初设置mainLightShadows

bool mainLightShadows = m_MainLightShadowCasterPass.Setup(ref renderingData);
bool additionalLightShadows = m_AdditionalLightsShadowCasterPass.Setup(ref renderingData);
bool transparentsNeedSettingsPass = m_TransparentSettingsPass.Setup(ref renderingData);

进入函数 m_MainLightShadowCasterPass.Setup(ref renderingData);

在这里插入图片描述

文章目录

  • URP 全文源码解析参照
  • 引入
  • MainLightShadowCasterPass.cs
    • 一、MainLightShadowCasterPass 创建
      • 参数:
        • 基类参数
        • 自定义参数
        • GPU ID参数
    • 二、MainLightShadowCasterPass 初始化
      • 1. 初始化数据(矩阵、cascade分割、切片)
      • 2. 一些条件判断,未通过的话将ShadowMap置为默认值
      • 3. 设置数据
            • (1)m_ShadowCasterCascadesCount
            • (2)RenderTexture 大小
            • (3)提取级联阴影的光照矩阵以及包围球
            • (4)获取新的临时阴影纹理
            • (5)存储renderingData中的阴影数据
      • 4. 绑定渲染目标和清除状态
      • 5. 执行 Execute
    • 三、Execute 阴影参数设置
  • GPU中的阴影数据

MainLightShadowCasterPass.cs

一、MainLightShadowCasterPass 创建

public MainLightShadowCasterPass(RenderPassEvent evt)

在UniversalRenderer管线创建的时候,我们已经做了创建

我们设置MainLightShadow在RenderingShadows(Event = 50)之前

// UniversalRenderer.cs
public UniversalRenderer(UniversalRendererData data) : base(data)
{
	...
	m_MainLightShadowCasterPass = new MainLightShadowCasterPass(RenderPassEvent.BeforeRenderingShadows);
	m_AdditionalLightsShadowCasterPass = new AdditionalLightsShadowCasterPass(RenderPassEvent.BeforeRenderingShadows);
	...
}

创建MainLightShadowCasterPass

参数:

基类参数
public RenderPassEvent renderPassEvent { get; set; }
int renderTargetWidth { get; set; }
int renderTargetHeight { get; set; }
自定义参数
const int k_MaxCascades = 4;
const int k_ShadowmapBufferBits = 16;
float m_CascadeBorder;                  // 边缘模糊度(0~1)
float m_MaxShadowDistanceSq;			// 最大阴影距离的平方
int m_ShadowCasterCascadesCount;		// 当前设置的Cascades数量

RenderTargetHandle m_MainLightShadowmap;           //临时阴影纹理Shader中的索引ID
internal RenderTexture m_MainLightShadowmapTexture;//实际临时阴影纹理,以及设置(深度为16位)

Matrix4x4[] m_MainLightShadowMatrices;// 阴影矩阵
ShadowSliceData[] m_CascadeSlices;    // 级联阴影切片数据,包含(
						//splitData、       级联阴影数据(由UNITY内置函数提供)
						//offsetX/Y、       级联阴影偏移
						//resolution        级联阴影分辨率
						//shadowTransform   级联阴影矩阵
Vector4[] m_CascadeSplitDistances;    // 包围球数据(xyz:位置,w:半径)
GPU ID参数
private static class MainLightShadowConstantBuffer
{
    public static int _WorldToShadow;
    public static int _ShadowParams;
    public static int _CascadeShadowSplitSpheres0;
    public static int _CascadeShadowSplitSpheres1;
    public static int _CascadeShadowSplitSpheres2;
    public static int _CascadeShadowSplitSpheres3;
    public static int _CascadeShadowSplitSphereRadii;
    public static int _ShadowOffset0;
    public static int _ShadowOffset1;
    public static int _ShadowOffset2;
    public static int _ShadowOffset3;
    public static int _ShadowmapSize;
}
MainLightShadowConstantBuffer._WorldToShadow = Shader.PropertyToID("_MainLightWorldToShadow");
MainLightShadowConstantBuffer._ShadowParams = Shader.PropertyToID("_MainLightShadowParams");
MainLightShadowConstantBuffer._CascadeShadowSplitSpheres0 = Shader.PropertyToID("_CascadeShadowSplitSpheres0");
MainLightShadowConstantBuffer._CascadeShadowSplitSpheres1 = Shader.PropertyToID("_CascadeShadowSplitSpheres1");
MainLightShadowConstantBuffer._CascadeShadowSplitSpheres2 = Shader.PropertyToID("_CascadeShadowSplitSpheres2");
MainLightShadowConstantBuffer._CascadeShadowSplitSpheres3 = Shader.PropertyToID("_CascadeShadowSplitSpheres3");
MainLightShadowConstantBuffer._CascadeShadowSplitSphereRadii = Shader.PropertyToID("_CascadeShadowSplitSphereRadii");
MainLightShadowConstantBuffer._ShadowOffset0 = Shader.PropertyToID("_MainLightShadowOffset0");
MainLightShadowConstantBuffer._ShadowOffset1 = Shader.PropertyToID("_MainLightShadowOffset1");
MainLightShadowConstantBuffer._ShadowOffset2 = Shader.PropertyToID("_MainLightShadowOffset2");
MainLightShadowConstantBuffer._ShadowOffset3 = Shader.PropertyToID("_MainLightShadowOffset3");
MainLightShadowConstantBuffer._ShadowmapSize = Shader.PropertyToID("_MainLightShadowmapSize");
m_MainLightShadowmap.Init("_MainLightShadowmapTexture");

二、MainLightShadowCasterPass 初始化

public bool Setup(ref RenderingData renderingData){}

1. 初始化数据(矩阵、cascade分割、切片)

Clear();

2. 一些条件判断,未通过的话将ShadowMap置为默认值

… 这里不作为重点

3. 设置数据

SetUp函数主要是将数据整理保存到类内参数中供类使用
其中设置的数据有:

(1)m_ShadowCasterCascadesCount

光源级联阴影数量

(2)RenderTexture 大小
renderTargetWidth;
renderTargetHeight;
(3)提取级联阴影的光照矩阵以及包围球
  1. Vector4[] m_CascadeSplitDistances[cascadeIndex] 包围球数据(xyz:位置,w:半径)
  2. ShadowSliceData[] m_CascadeSlices; 级联阴影切片数据
public struct ShadowSliceData
{
    public Matrix4x4 viewMatrix;
    public Matrix4x4 projectionMatrix;
    public Matrix4x4 shadowTransform;//projectionMatrix * viewMatrix
    public int offsetX;			     //ShadowAtlasMap行偏移
    public int offsetY;				 //ShadowAtlasMap列偏移
    public int resolution;			 //分辨率
    public ShadowSplitData splitData;//splitData包含筛选信息
}

提取函数

for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex)
{
    bool success = ShadowUtils.ExtractDirectionalLightMatrix(
    	ref renderingData.cullResults, 
    	ref renderingData.shadowData,
        shadowLightIndex, 
        cascadeIndex, 
        renderTargetWidth, 
        renderTargetHeight, 
        shadowResolution, 
        light.shadowNearPlane,
        out m_CascadeSplitDistances[cascadeIndex], 
        out m_CascadeSlices[cascadeIndex]);

    if (!success)
        return SetupForEmptyRendering(ref renderingData);
}
(4)获取新的临时阴影纹理
m_MainLightShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(renderTargetWidth, renderTargetHeight, k_ShadowmapBufferBits);
(5)存储renderingData中的阴影数据
m_MaxShadowDistanceSq = renderingData.cameraData.maxShadowDistance * renderingData.cameraData.maxShadowDistance;
m_CascadeBorder = renderingData.shadowData.mainLightShadowCascadeBorder;

4. 绑定渲染目标和清除状态

public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
{
    ConfigureTarget(new RenderTargetIdentifier(m_MainLightShadowmapTexture), m_MainLightShadowmapTexture.depthStencilFormat, renderTargetWidth, renderTargetHeight, 1, true);
    ConfigureClear(ClearFlag.All, Color.black);
}

5. 执行 Execute

public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
{
    if (m_CreateEmptyShadowmap)
    {
        SetEmptyMainLightCascadeShadowmap(ref context);
        return;
    }

    RenderMainLightCascadeShadowmap(ref context, ref renderingData.cullResults, ref renderingData.lightData, ref renderingData.shadowData);
}

三、Execute 阴影参数设置

RenderMainLightCascadeShadowmap(
			ref context, 
			ref renderingData.cullResults, 
			ref renderingData.lightData, 
			ref renderingData.shadowData);

参数设置多引用ShadowsUtils单例中的函数设置
进入函数RenderMainLightCascadeShadowmap

// settings 中为阴影所需要的数据
var settings = new ShadowDrawingSettings(cullResults, shadowLightIndex);
settings.useRenderingLayerMaskTest = UniversalRenderPipeline.asset.supportsLightLayers;

for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex)
{
    settings.splitData = m_CascadeSlices[cascadeIndex].splitData;

    // 偏移量
    Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, m_CascadeSlices[cascadeIndex].projectionMatrix, m_CascadeSlices[cascadeIndex].resolution);
    ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias);
    
    CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.CastingPunctualLightShadow, false);
    ShadowUtils.RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex],
        ref settings, m_CascadeSlices[cascadeIndex].projectionMatrix, m_CascadeSlices[cascadeIndex].viewMatrix);
}

shadowData.isKeywordSoftShadowsEnabled = shadowLight.light.shadows == LightShadows.Soft && shadowData.supportsSoftShadows;
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadows, shadowData.mainLightShadowCascadesCount == 1);
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadowCascades, shadowData.mainLightShadowCascadesCount > 1);
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, shadowData.isKeywordSoftShadowsEnabled);

SetupMainLightShadowReceiverConstants(cmd, shadowLight, shadowData.supportsSoftShadows);
  1. SetupShadowCasterConstantBuffer
// 阴影偏移
cmd.SetGlobalVector("_ShadowBias", shadowBias);

// 世界空间光照方向,用于支持阴影法线偏移(normal bias).
Vector3 lightDirection = -shadowLight.localToWorldMatrix.GetColumn(2);
cmd.SetGlobalVector("_LightDirection", new Vector4(lightDirection.x, lightDirection.y, lightDirection.z, 0.0f));

// 世界空间光源位置
Vector3 lightPosition = shadowLight.localToWorldMatrix.GetColumn(3);
cmd.SetGlobalVector("_LightPosition", new Vector4(lightPosition.x, lightPosition.y, lightPosition.z, 1.0f));
  1. 关闭精确光源阴影 PunctualLightShadow(点光源、方向光、聚光灯)
/*  "_CASTING_PUNCTUAL_LIGHT_SHADOW"  */
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.CastingPunctualLightShadow, false);
  1. 渲染cascade阴影
    设置默认全局偏移(这应该就是为什么,在unity中,将light的bias都设为0,但还是没有明显的摩尔纹)
cmd.SetGlobalDepthBias(1.0f, 2.5f); // these values match HDRP defaults 

设置Viewport、矩阵信息

cmd.SetViewport(new Rect(shadowSliceData.offsetX, shadowSliceData.offsetY, shadowSliceData.resolution, shadowSliceData.resolution));
cmd.SetViewProjectionMatrices(view, proj);

渲染阴影,禁用硬件剪刀矩阵(不知道是什么)

context.DrawShadows(ref settings);
cmd.DisableScissorRect();
  1. 是否开启主光源阴影、主光源级联阴影、主光源软阴影
/*"_MAIN_LIGHT_SHADOWS"*/
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadows, shadowData.mainLightShadowCascadesCount == 1);
/*"_MAIN_LIGHT_SHADOWS_CASCADE"*/
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadowCascades, shadowData.mainLightShadowCascadesCount > 1);
/*"_SHADOWS_SOFT"*/
CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, shadowData.isKeywordSoftShadowsEnabled);
  1. 设置阴影接收常量

    1. 阴影贴图 “_MainLightShadowmapTexture
    2. 光源矩阵 “_MainLightWorldToShadow”(级联矩阵为多个矩阵 Matrix4x4[])
    3. 阴影参数 “_MainLightShadowParams
      • x :阴影强度
      • y :是否软阴影(1为软,0为硬)
      • z :阴影衰减部分的衰减斜率
      • w:横坐标0处阴影开始衰减部分的纵坐标
    4. 级联阴影数据:
      四个级联的包围球数据(4 * Vector4) _CascadeShadowSplitSpheres0、1、2、3
      四个级联的半径的平方(1 * Vector4) _CascadeShadowSplitSphereRadii
    5. 软阴影:
      阴影像素偏移(左下、右下、左上、右上) _MainLightShadowOffset0/1/2/3
      阴影偏移量(偏移x,偏移y,shadowMap宽,shadowMap长 _MainLightShadowmapSize
  2. 在渲染结束后释放临时Texture

public override void OnCameraCleanup(CommandBuffer cmd)
{
    if (cmd == null)
        throw new ArgumentNullException("cmd");

    if (m_MainLightShadowmapTexture)
    {
        RenderTexture.ReleaseTemporary(m_MainLightShadowmapTexture);
        m_MainLightShadowmapTexture = null;
    }
}

GPU中的阴影数据

Shadows.hlsl

SCREENSPACE_TEXTURE(_ScreenSpaceShadowmapTexture);
SAMPLER(sampler_ScreenSpaceShadowmapTexture);

TEXTURE2D_SHADOW(_MainLightShadowmapTexture);
SAMPLER_CMP(sampler_MainLightShadowmapTexture);

TEXTURE2D_SHADOW(_AdditionalLightsShadowmapTexture);
SAMPLER_CMP(sampler_AdditionalLightsShadowmapTexture);

CBUFFER_START(MainLightShadows)
	// Last cascade is initialized with a no-op matrix. It always transforms
	// shadow coord to half3(0, 0, NEAR_PLANE). We use this trick to avoid
	// branching since ComputeCascadeIndex can return cascade index = MAX_SHADOW_CASCADES
	float4x4    _MainLightWorldToShadow[MAX_SHADOW_CASCADES + 1];
	float4      _CascadeShadowSplitSpheres0;
	float4      _CascadeShadowSplitSpheres1;
	float4      _CascadeShadowSplitSpheres2;
	float4      _CascadeShadowSplitSpheres3;
	float4      _CascadeShadowSplitSphereRadii;
	half4       _MainLightShadowOffset0;
	half4       _MainLightShadowOffset1;
	half4       _MainLightShadowOffset2;
	half4       _MainLightShadowOffset3;
	half4       _MainLightShadowParams;   // (x: shadowStrength, y: 1.0 if soft shadows, 0.0 otherwise, z: main light fade scale, w: main light fade bias)
	float4      _MainLightShadowmapSize;  // (xy: 1/width and 1/height, zw: width and height)
CBUFFER_END

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1320175.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

tamper编写

借鉴 sqlmap之tamper脚本编写_sqlmap tamper编写-CSDN博客 先看一个tamper的例子 栗子 escapequotes.py #!/usr/bin/env python""" Copyright (c) 2006-2023 sqlmap developers (https://sqlmap.org/) See the file LICENSE for copying permission "&…

Prometheus全面学习教程

一、Prometheus概述 1、Prometheus介绍 Prometheus 是一个开源的服务监控系统和时序数据库&#xff0c;其提供了通用的数据模型和快捷数据采集、存储和查询接口。它的核心组件Prometheus server会定期从静态配置的监控目标或者基于服务发现自动配置的自标中进行拉取数据&…

【期刊出版征稿】2024年艺术、教育和管理国际学术会议(ICAEM2024)

2024年艺术、教育和管理国际学术会议 2024 International Conference on Arts, Education and Management&#xff08;ICAEM2024&#xff09; 2024年艺术、教育和管理国际学术会议&#xff08;ICAEM2024&#xff09;将于2024年2月02-04日在马来西亚-吉隆坡召开。会议主题主要…

【TI毫米波雷达】上电时序、串口回环BUG及SOP模式不正常工作的解决方案(LP87524电源PMIC芯片的BUCK供电时序配置)

【TI毫米波雷达】雷达上电时序及SOP模式不正常工作的解决方案&#xff08;LP87524电源PMIC芯片的BUCK供电时序配置&#xff09; 文章目录 上电时序上电以后的雷达串口回环问题延迟上电时序LP87524电源PMIC芯片的BUCK供电时序LP87524电源PMIC芯片的BUCK默认供电输出附录&#x…

18.NAT

NAT IP v4 &#xff1a;32bit IP v6&#xff1a; 128bit 一个公网地址支持6000个用户使用上网 运营商只维护公网地址&#xff0c;会将私网地址丢弃 一般部署在路由器或防火墙上面 方法一 NAT配置 使用公网接口地址 在路由器的出口GE&#xff3f;0/0口进行配置 然后PC2…

简洁易懂的Yolov7本地训练自己的数据并onnx推理

YOLOV7 官方代码Yolov7 测试官方案例 1、下载下来先按照github教程下载yolov7.pt权重 2、pycharm&#xff08;或其他&#xff09;打开detect文件&#xff0c;修改权重路径和推理图片的路径&#xff0c;分别是 parser.add_argument(--weights, nargs, typestr, defaultyolov…

[LLM]nanoGPT---训练一个写唐诗的GPT

karpathy/nanoGPT: The simplest, fastest repository for training/finetuning medium-sized GPTs. (github.com) 原有模型使用的莎士比亚的戏剧数据集, 如果需要一个写唐诗机器人&#xff0c;需要使用唐诗的文本数据&#xff0c; 一个不错的唐诗&#xff0c;宋词数据的下载…

东南亚Shopee:东南亚领先的电商平台

Shopee是东南亚地区最著名的电商平台之一&#xff0c;成立于2015年。作为新加坡互联网公司Sea Group&#xff08;原名Garena&#xff09;的一部分&#xff0c;Shopee在东南亚市场拥有广泛的业务覆盖范围&#xff0c;包括新加坡、马来西亚、泰国、印度尼西亚、越南和菲律宾等国家…

源码编译 METIS 以及 GKlib 在Linux ubuntu上

1. GKlib 构建 $ git clone --recursive gitgithub.com:Kleenelan/GKlib.git $ cd GKlib/ $ make config ccgcc openmpset $ make $ make install源码构建了 GKlib 的 openmp 版本&#xff0c;以便充分使用多核的算力&#xff1b; make config ccgcc openmpset 的效果图&#…

QT-可拖拉绘图工具

QT-可拖拉绘图工具 一、演示效果二、关键程序三、下载链接 一、演示效果 二、关键程序 #include "diagramscene.h" #include "arrow.h"#include <QTextCursor> #include <QGraphicsSceneMouseEvent> #include <QDebug>QPen const Diagr…

Windows本地搭建开源企业管理套件Odoo并实现公网访问

文章目录 前言1. 下载安装Odoo&#xff1a;2. 实现公网访问Odoo本地系统&#xff1a;3. 固定域名访问Odoo本地系统 前言 Odoo是全球流行的开源企业管理套件&#xff0c;是一个一站式全功能ERP及电商平台。 开源性质&#xff1a;Odoo是一个开源的ERP软件&#xff0c;这意味着企…

当OneNote不同步时,你需要做些什么让其恢复在线

OneNote笔记本无法同步的原因有很多。由于OneNote使用OneDrive将笔记本存储在云中,因此可能会出现互联网连接问题,与多人联机处理笔记本时会出现延迟,以及从不同设备处理同一笔记本时会发生延迟。以下是OneNote不同步时的操作。 注意:本文中的说明适用于OneNote for Windo…

什么是工业互联网平台?

1.什么是工业互联网平台&#xff1f; 1.1 工业互联网平台的定义 工业互联网平台是一个连接设备与服务、数据与人的跨行业、跨领域的全新工业平台。工业互联网平台利用了互联网、物联网、大数据、AI等技术&#xff0c;集成各类工业设备&#xff0c;不断采集和分析数据&#xff…

百度地图添加坐标点,并返回坐标信息

1、创建地图容器 在mounted中初始化地图、鼠标绘制工具和添加鼠标监听事件 vue data中添加地图和绘制工具对象 2、添加初始化化地图方法 initMap(longitude, latitude) {let that thisthat.map new BMapGL.Map("container");// 创建地图实例if (longitude null ||…

功放诊断测试

1.切换trace显示时间模式&#xff0c;Toggle time mode 2.测seedkey 需要加载seednkey.dll 3.功能寻址和物理寻址切换

idea恢复默认出厂设置

idea恢复默认出厂设置 1、IDEA 2021 之后&#xff0c; 在顶部工具栏&#xff0c;选择 File | Manage IDE Settings | Restore Default Settings. 2、或者双击shift搜索Restore Default settings然后点击restore and restart

MySQL安装——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理

MySQLhttps://www.mysql.com/ 将下发的ds_db01.sql数据库文件放置mysql中 12、编写Scala代码&#xff0c;使用Spark将MySQL的ds_db01库中表user_info的全量数据抽取到Hive的ods库中表user_info。字段名称、类型不变&#xff0c;同时添加静态分区&#xff0c;分区字段为etl_da…

ubuntu18.04 64 位安装笔记——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务2:离线数据处理

进入VirtuakBox官网&#xff0c;网址链接&#xff1a;Oracle VM VirtualBoxhttps://www.virtualbox.org/ 网页连接&#xff1a;Ubuntu Virtual Machine Images for VirtualBox and VMwarehttps://www.osboxes.org/ubuntu/ 将下发的ds_db01.sql数据库文件放置mysql中 12、编写S…

代码随想录算法训练营Day5 | 242.有效的字母异位词、349.两个数组的交集、202.快乐数、1. 两数之和

LeetCode 242 有效的字母异位词 本题思路&#xff1a;我们只需要分别统计&#xff0c;字符串 s ,字符串 t 中每个字符的出现次数&#xff0c;分别用两个数组来存储&#xff0c;然后再循环遍历对比两个数组中相同位置出现的次数&#xff0c;如果有不同的则返回 false。 统计完之…

双非大数据

双非本秋招上岸总结 个人简介 学历&#xff1a;双非&#xff1b; 专业&#xff1a;软件工程&#xff1b; 求职岗位&#xff1a;大数据开发工程师&#xff1b; 状态&#xff1a;已上岸 翻车经历 学校以Java后端开发为主流&#xff0c;我从大二开始学习Java&#xff0c;直到大四…