Unity中URP下获取每一个额外灯数据

本文详细介绍了在Unity引擎的UniversalRenderPipeline(URP)中,如何在SimpleLit着色器中获取额外灯的数量和数据,包括获取额外灯索引的方法以及不同平台上的处理策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

在上一篇文章中,我们知道了URP下是怎么获取额外灯数量的。

在这篇文章中,我们来了解一下怎么获取每一盏额外灯的数据。
在这里插入图片描述


一、我们先来看一下 SimpleLit 中的调用

  • SimpleLit中调用了 GetAdditionalLight
    在这里插入图片描述
  • 该函数有三个重载,我们分别称为1号、2号、3号重载,方便后面区分
    在这里插入图片描述
  • 3号调用了2号
    在这里插入图片描述

读源码后,可知,Unity在获取额外灯信息前。获取了额外灯索引。
所以,我们也分成两步来分析:获取额外灯索引、获取索引对应的额外灯信息。


二、获取额外灯索引

这里我们主要只是看一下,在Shader种,并不会去做修改。

  • 正常情况下,我们通过 GetPerObjectLightIndex 函数获取额外灯索引
    在这里插入图片描述
  • GetPerObjectLightIndex:主要分为3种情况。
    在这里插入图片描述

1、非移动平台

在这里插入图片描述

2、非GLES平台

在这里插入图片描述

3、大多数平台

在这里插入图片描述


三、获取额外灯数据

  • 获取额外灯的数据,使用了 GetAdditionalPerObjectLight 函数
    在这里插入图片描述
  • 这是该函数的主要内容,我们接下来,分析一下该函数干了什么
// Fills a light struct given a perObjectLightIndex
Light GetAdditionalPerObjectLight(int perObjectLightIndex, float3 positionWS)
{
    // Abstraction over Light input constants
#if USE_STRUCTURED_BUFFER_FOR_LIGHT_DATA
    float4 lightPositionWS = _AdditionalLightsBuffer[perObjectLightIndex].position;
    half3 color = _AdditionalLightsBuffer[perObjectLightIndex].color.rgb;
    half4 distanceAndSpotAttenuation = _AdditionalLightsBuffer[perObjectLightIndex].attenuation;
    half4 spotDirection = _AdditionalLightsBuffer[perObjectLightIndex].spotDirection;
    uint lightLayerMask = _AdditionalLightsBuffer[perObjectLightIndex].layerMask;
#else
    float4 lightPositionWS = _AdditionalLightsPosition[perObjectLightIndex];
    half3 color = _AdditionalLightsColor[perObjectLightIndex].rgb;
    half4 distanceAndSpotAttenuation = _AdditionalLightsAttenuation[perObjectLightIndex];
    half4 spotDirection = _AdditionalLightsSpotDir[perObjectLightIndex];
    uint lightLayerMask = asuint(_AdditionalLightsLayerMasks[perObjectLightIndex]);
#endif

    // Directional lights store direction in lightPosition.xyz and have .w set to 0.0.
    // This way the following code will work for both directional and punctual lights.
    float3 lightVector = lightPositionWS.xyz - positionWS * lightPositionWS.w;
    float distanceSqr = max(dot(lightVector, lightVector), HALF_MIN);

    half3 lightDirection = half3(lightVector * rsqrt(distanceSqr));
    // full-float precision required on some platforms
    float attenuation = DistanceAttenuation(distanceSqr, distanceAndSpotAttenuation.xy) * AngleAttenuation(spotDirection.xyz, lightDirection, distanceAndSpotAttenuation.zw);

    Light light;
    light.direction = lightDirection;
    light.distanceAttenuation = attenuation;
    light.shadowAttenuation = 1.0; // This value can later be overridden in GetAdditionalLight(uint i, float3 positionWS, half4 shadowMask)
    light.color = color;
    light.layerMask = lightLayerMask;

    return light;
}
  • 按照是否是移动平台,根据之前的计算的索引 获取到了额外光的主要数据
    在这里插入图片描述

lightPositionWS:额外灯在世界空间下的坐标
color:额外灯颜色
distanceAndSpotAttenuation:距离衰减
spotDirection:距离衰减方向


有了这写数据,就可以计算额外灯的方向、距离衰减和角度衰减了。
我们在之后的文章中,来分析额外灯方向、距离衰减和角度衰减是怎么计算的。

### Unity URP 渲染管线中的曲面细分与置换贴图 #### 曲面细分在URP中的应用 在Unity的通用渲染管线(Universal Render Pipeline, URP)中,曲面细分技术可以显著提升模型表面细节的表现力。通过Hull Shader阶段,能够动态增加几何体上的顶点数量,使得原本简单的多边形网格变得更加平滑细腻。 对于三角形面片而言,在Hull Shader函数内部定义了一个结构`PatchTess`用来存储边缘以及内部分割系数[^3]: ```csharp struct PatchTess { float edgeFactor[3] : SV_TESSFACTOR; float insideFactor : SV_INSIDETESSFACTOR; }; ``` 这些参数决定了该面片被细分为多少个小三角形。具体来说,`edgeFactor`数组里的三个元素分别对应三条边各自要划分成几份;而`insideFactor`则影响中心区域内的分割密度。当设置较大的数值时,意味着更精细复杂的形状将会呈现出来。 为了使上述逻辑生效于URP项目里,需确保所使用的Shader支持并启用了硬件级别的tessellation特性,并且正确配置Material Inspector下的相应选项以允许执行这一过程。 #### 置换贴图的工作原理及其集成到URP的方法 置换映射是一种高级纹理映射形式,它不仅改变物体的颜色外观还会影响其实际三维形态。借助高度场数据,可以在像素级别上调整法线方向甚至位移整个片段的位置,进而创造出逼真的凹凸效果而不必额外添加大量静态几何信息。 要在URP环境中实现这样的功能,通常会涉及到自定义Surface Input或编写特定类型的Unlit/Lit Shaders来解析来自RGB通道携带的高度差值。下面是一个简化版的例子展示如何读取一张灰度图像作为输入源来进行基本的垂直偏移操作: ```hlsl // HLSL代码片段 sampler2D _DisplacementMap; // 置换贴图采样器声明 float _Strength; // 控制强度变量 void surf(Input IN, inout SurfaceOutputStandard o){ fixed4 dispTex = tex2D(_DisplacementMap, IN.uv_MainTex); float displacement = (dispTex.r * 2.0f - 1.0f) * _Strength; // 应用Y轴正向拉伸变形 o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap)); o.Position += o.Normal * displacement; } ``` 这段脚本首先获取了指定UV坐标处对应的灰色亮度等级,接着乘以用户设定的比例因子完成最终位置坐标的计算。值得注意的是,这里假设法线已经过预处理处于世界空间下,因此可以直接沿此方向施加变化量达到预期目的。 综上所述,虽然URP本身并不直接提供内置工具去便捷地开启这两项特效,但凭借强大的可编程接口完全可以根据需求灵活定制满足条件的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

楠溪泽岸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值