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

这篇具有很好参考价值的文章主要介绍了Unity SRP 管线【第四讲:URP 阴影】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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);

Unity SRP 管线【第四讲:URP 阴影】,Unity,unity,游戏引擎,URP,Unity主光源阴影渲染

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文章来源地址https://www.toymoban.com/news/detail-773031.html

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

到了这里,关于Unity SRP 管线【第四讲:URP 阴影】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Unity URP 小知识】SRP如何提升了性能

    渲染过程,一般都是先设置各类状态(设置如何清除各种显卡中的帧缓冲,设置使用的Shader程序,设置要绘制的顶点数据(以及Shader中的顶点数据如何对应到这些顶点数据),设置要使用的Uniform变量,设置面剔除,设置深度缓冲、模板缓冲,Blend混合等等),然后调用DrawCa

    2024年02月12日
    浏览(37)
  • Unity升级到URP渲染管线,

    首先 需要安装URP的包 安装后 然后打开ProjectSettings 替换 上一步创建 URP的配置文件 这个时候有些材质就会变成洋红色 选择RenderPipelineConverter 等待转换完成即可,

    2024年02月15日
    浏览(39)
  • Unity URP渲染管线与内置渲染管线的性能差别

    首先,我们来了解一下Unity的内置渲染管线。内置渲染管线是Unity较早版本中使用的默认渲染管线,它使用的是传统的图形渲染技术。内置渲染管线提供了一系列的渲染功能,如阴影、反射、抗锯齿等。但是,由于其较为庞大且复杂的设计,它的性能相对较低。在高质量图形效

    2024年02月08日
    浏览(28)
  • Unity内置渲染管线升级URP教程

    URP全称为Universal Render Pipeline(通用渲染管线),可以提供更加灵活的渲染方案,通过添加Render Feature实现各种渲染效果。并且可以针对移动平台进行专门的优化,同时还提供了SRPBatcher提高渲染效率。Unity的一些工具,比如ShaderGraph,也是必须在URP管线下才可以使用,可以说许多方

    2024年02月16日
    浏览(39)
  • Unity URP下阴影锯齿

            在Unity开发的URP项目中出现阴影有明显锯齿。如下图所示:         并且在主光源的Shadow Type已经是Soft Shadows模式了。         阴影出现锯齿说明阴影质量不高,所以要先找到URP Asset文件进行阴影质量参数的设置。 1.打开PlayerSetting找到 Graphics(也可以Quality),然

    2024年01月23日
    浏览(49)
  • Unity Shader从内置渲染管线迁移到URP

    Unity 在URP中将shader更新为了HLSL语言,使用build-in shader 无法直接在URP中使用 这里讲一下关于shader的更新方法 参考 From Built-in to URP Tags 添加 \\\"RenderPipeline\\\" = \\\"UniversalPipeline\\\" CGPROGRAM ENDCG 改变为 HLSLPROGRAM ENDHLSL #include \\\"UnityCG.cginc\\\" 更改为 #include \\\"Packages/com.unity.render-pipelines.universal/Sh

    2024年02月05日
    浏览(32)
  • unity build-in 渲染管线升级urp渲染 shader篇

            由于工作原因需要对项目进行升级,从build-in渲染管线升级到urp渲染管线,我自己对应的unity版本是2018.版本升级到2021.3.2版本,由于最近几年unity版本升级比较快,个体版本差异有所不同,如遇与版本不一致问题敬请谅解。以下是根据官网等系列网站整理的内容

    2023年04月16日
    浏览(44)
  • Unity PS5开发 天坑篇 之 URP管线与HDRP管线部署流程以及出包介绍04

    目录 一, URP管线、HDRP管线下的Unity项目部署 1. PS5开发论坛关于Unity可支持的版本说明: 2. URP管线下的项目与部署 2.1 Build PS5 URP Project 2.2 运行画面 3. HDRP管线下的项目与部署 3.1 附上可以运行的画面: 4. PS5打包方式介绍 4.1 PC串流调试模式: Build Type: PC Hosted  4.2 增量包模式: BuildT

    2024年04月22日
    浏览(27)
  • 【Unity URP渲染管线下设置灯光数量上限_灯光不显示问题案例分享】

    1.我的这个项目是在URP渲染管线下,我在场景里创建了六个点灯,转动物体的时候,发现灯显示不全,会一闪一闪的出现。 2.在RenderPipelineAsset配置文件中查看灯光数量上限,首先在EditProject Setting 3.在Project Setting里选Quality,在Rendering找到UniversalRP Asset 4.选中UniversalRP Asset文件

    2024年02月16日
    浏览(36)
  • Unity技美35——再URP管线环境下,配置post后期效果插件(post processing)

    前两年在我的unity文章第10篇写过,后效滤镜的使用,那时候大部分项目用的还是unity的基础管线,stander管线。 但是现在随着unity的发展,大部分项目都用了URO管线,甚至很多PC端用的都是高效果的HDRP管线,这就导致以前的方法配置post后效,画面中没有效果。因此专门写一个

    2024年02月02日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包