【unity】URP的shader开发中支持多光源,_ADDITIONAL_LIGHTS_VERTEX 和 _ADDITIONAL_LIGHTS 区别

这篇具有很好参考价值的文章主要介绍了【unity】URP的shader开发中支持多光源,_ADDITIONAL_LIGHTS_VERTEX 和 _ADDITIONAL_LIGHTS 区别。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

项目里有一个其他同事实现的shader,美术那边希望能支持多个光源, 我一看代码里面, frag 函数里已经实现了
 


				#ifdef _ADDITIONAL_LIGHTS
					uint pixelLightCount = GetAdditionalLightsCount();
					for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
					{
						Light light = GetAdditionalLight(lightIndex, i.posWorld.xyz);
						half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
						lightColor += LightingLambert(attenuatedLightColor, light.direction, normalDirection);
					}
				#endif

代码也加了:

            #pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS

材质里加了这个keyword还是没起作用,   若宏控制注了有效。  一开始没搞明白……
想到很可能这个关键字是系统本身控制的, 搜索了一下"_ADDITIONAL_LIGHTS",找到ForwardLights.cs里 确实控制了 _ADDITIONAL_LIGHTS 和 _ADDITIONAL_LIGHTS_VERTEX的开关,且2个只能存在一个(所以 multi_compile 是配置在一起的)
【unity】URP的shader开发中支持多光源,_ADDITIONAL_LIGHTS_VERTEX 和 _ADDITIONAL_LIGHTS 区别
最后发现是 UniversalRenderPipelineAsset 这个自定义配置里Additional Lights的配置:

【unity】URP的shader开发中支持多光源,_ADDITIONAL_LIGHTS_VERTEX 和 _ADDITIONAL_LIGHTS 区别

 perVertex (开 _ADDITIONAL_LIGHTS_VERTEX宏)表示 在顶点着色器 计算时,就取其他光源数据计算 光照值, 这样顶点数少 但像素绘制比较多(片元着色器执行次数更多)的情况,就能节省不少计算。

perPixel (开 _ADDITIONAL_LIGHTS) 表示  在片元着色器计算时,对其他光源做采样计算每个光照值 然后叠加。 (光源越多循环次数越多 性能影响也越大。)


一般来说使用 _ADDITIONAL_LIGHTS_VERTEX,可能要优化一些,但是有局限性,平行光还好,针对点光源,面片比较大的模型就很奇怪了,    这次就遇到这个问题,尝试地表接受一个点光源试试发现没作用,还以为代码没写好…………, 最后发现是它面太大了,顶点离点光源太远了 没计算进去……,如果点光跑到顶点附近 则还是有效果的, 但这个面片就整体发亮很奇怪。  

所以一般点光源 直接用lightmap烘培,运行时不要开,除非有特殊需求, 要么就是放到片元着色器里计算其他光。



自己写shader时如何让其支持  _ADDITIONAL_LIGHTS_VERTEX 或 _ADDITIONAL_LIGHTS呢?
可以参考simplelit.shader等 示例
_ADDITIONAL_LIGHTS比较简单
Fragment初始函数里在主光源后加

SimpleLitForwardPass.hlsl 调用的Lighting.hlsl 里的函数, 看 #ifdef _ADDITIONAL_LIGHTS 部分

half4 UniversalFragmentBlinnPhong(InputData inputData, half3 diffuse, half4 specularGloss, half smoothness, half3 emission, half alpha)
{
    Light mainLight = GetMainLight(inputData.shadowCoord);
    MixRealtimeAndBakedGI(mainLight, inputData.normalWS, inputData.bakedGI, half4(0, 0, 0, 0));

    half3 attenuatedLightColor = mainLight.color * (mainLight.distanceAttenuation * mainLight.shadowAttenuation);
    half3 diffuseColor = inputData.bakedGI + LightingLambert(attenuatedLightColor, mainLight.direction, inputData.normalWS);
#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
    half3 specularColor = LightingSpecular(attenuatedLightColor, mainLight.direction, inputData.normalWS, inputData.viewDirectionWS, specularGloss, smoothness);
#else 
    half3 specularColor = 0;
#endif

#ifdef _ADDITIONAL_LIGHTS
    uint pixelLightCount = GetAdditionalLightsCount();
    for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
    {
        Light light = GetAdditionalLight(lightIndex, inputData.positionWS);
        half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
        diffuseColor += LightingLambert(attenuatedLightColor, light.direction, inputData.normalWS);
#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
        specularColor += LightingSpecular(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, specularGloss, smoothness);
#endif
    }
#endif

#ifdef _ADDITIONAL_LIGHTS_VERTEX
    diffuseColor += inputData.vertexLighting;
#endif

    half3 finalColor = diffuseColor * diffuse + emission;

#if defined(_SPECGLOSSMAP) || defined(_SPECULAR_COLOR)
    finalColor += specularColor;
#endif

    return half4(finalColor, alpha);
}

如果shader用的 BRDFData 数据结构的 类似这样加
 


#ifdef _ADDITIONAL_LIGHTS
    uint pixelLightCount = GetAdditionalLightsCount();
    for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
    {
        Light light = GetAdditionalLight(lightIndex, inputData.positionWS);
        color += LightingPhysicallyBased(brdfData, light, inputData.normalWS, inputData.viewDirectionWS);
    }
#endif

#ifdef _ADDITIONAL_LIGHTS_VERTEX
    color += inputData.vertexLighting * brdfData.diffuse;
#endif

我们自己实现的一个shader:
 


				float4 shadowCoord = TransformWorldToShadowCoord(i.posWorld.xyz);
				Light mainLight = GetMainLight(shadowCoord);
				float NDotL = dot(normalDirection, mainLight.direction);
				//float halfLambert = saturate(NDotL * 0.5 + 0.5);
				float Lambert = saturate(NDotL);

				//half3 gi = SampleSH(normalDirection);
				half3 attenuatedLightColor = mainLight.color * (mainLight.distanceAttenuation * mainLight.shadowAttenuation);
				half3 lightColor = Lambert * attenuatedLightColor;

                half3 bakedGI = SAMPLE_GI(i.lightmapUV, i.vertexSH, normalDirection);
                MixRealtimeAndBakedGI(mainLight, normalDirection, bakedGI, half4(0, 0, 0, 0));
                lightColor += bakedGI;

				#ifdef _ADDITIONAL_LIGHTS
					uint pixelLightCount = GetAdditionalLightsCount();
					for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
					{
						Light light = GetAdditionalLight(lightIndex, i.posWorld.xyz);
						half3 attenuatedLightColor = light.color * (light.distanceAttenuation * light.shadowAttenuation);
						lightColor += LightingLambert(attenuatedLightColor, light.direction, normalDirection);
					}
				#endif


#ifdef _ADDITIONAL_LIGHTS_VERTEX
                half3 vertexLighting = i.fogFactorAndVertexLight.yzw;
                lightColor += vertexLighting;
#endif

要支持 _ADDITIONAL_LIGHTS_VERTEX , (片元着色器代码 上面有示例了,不贴了)
主要是顶点着色器里的计算 和 怎么传递给片元着色器:
一般需要 结构体 v2f (或者叫 VertexOutput  或者叫 Varyings,反正是自己定义的)

定义一个 
    half4 fogFactorAndVertexLight   : TEXCOORD6; // x: fogFactor, yzw: vertex light
这个是把 unity自带fog的值一起传递了
当然单独加一个也是可以的

#if defined(_ADDITIONAL_LIGHTS_VERTEX) 
    float3 vertexLight                : TEXCOORD7;
#endif
【unity】URP的shader开发中支持多光源,_ADDITIONAL_LIGHTS_VERTEX 和 _ADDITIONAL_LIGHTS 区别

顶点着色器 vert函数里 要加代码
 


#ifdef _ADDITIONAL_LIGHTS_VERTEX
    half3 vertexLight = VertexLighting(vertexInput.positionWS, normalInput.normalWS);
#endif

和fogFactor拼在一起
output.fogFactorAndVertexLight = half4(fogFactor, vertexLight);
传给 片元着色器,   片元着色器计算时 再分别取 它们的值

另一个例子(不和 fogFactor, 单独传递):文章来源地址https://www.toymoban.com/news/detail-501598.html

#if defined(_ADDITIONAL_LIGHTS_VERTEX) 
    //Pass to fragment shader to apply in Lighting function
    output.vertexLight.rgb = VertexLighting(vertexData.positionWS, vertexData.normalWS);
#endif

到了这里,关于【unity】URP的shader开发中支持多光源,_ADDITIONAL_LIGHTS_VERTEX 和 _ADDITIONAL_LIGHTS 区别的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Unity Spine 3.8 (URP) 踩坑(Shader报错修改)

    今天搜索spine优化,看到一篇文章项目导入多个Spine动画 合批 降低DrawCall -- UWA问答 | 游戏开发者互动问答社区 | 侑虎科技 提供了新思路,打算尝试一下URP。但美术使用的spine版本是3.8,项目用的Unity2021.3.11f1c2,直接导入spine URP包,shader报错:half4 不能转成 SurfaceData2D;遂改下

    2024年02月12日
    浏览(48)
  • unity URP 利用particle system制作简单的shader交互

    首先这里制作了一个简单交互,使用shader grapgh,根据计算距离和变化数值的差实现交互后的扩散,同时计算消散遮罩让它逐渐谈去。 将他赋予材质物体,根据脚本传入位置和逐渐变化的大小后,呈现这样的效果。 但是,shader graph这样的工具,在做这种效果非常快的同时,也

    2024年02月07日
    浏览(44)
  • Unity URP Shader “Redefinition of _Time“ error

    强烈建议先尝试阅读本文之后自行解决:https://zhuanlan.zhihu.com/p/360566324 我这里记录一下我的思路: 首先检查URP升级是否正确,主要看Asset是否设置,ShaderGraph表现是否正常 尝试排除是否是未定义宏导致的问题,主要是对比ShaderGraph自动生成的代码 确认自己的代码是否使用了

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

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

    2023年04月16日
    浏览(59)
  • 《Unity的URP项目中使用自定义shader导致材质消失的解决办法》

            在Unity中使用URP时,会有需求使用自定义的一些shader来实现特殊效果,这时如果我们直接使用新建材质与无光照着色器(Unlit shader),可能会发生一个对于新手而言意料之外的问题—— 物体!消失了!         打开你正在使用的的 通用渲染器(Universal Rendere

    2024年02月06日
    浏览(80)
  • Unity Shader 学习笔记(4)URP渲染管线带阴影PBR-Shader模板 -- 新增可自定义阴影颜色

    材质面板截图 功能实现(URP渲染管线下): 1、进一步优化Shader结构和算法; 2、包含PBR材质; 3、投射和接收阴影,并升级 支持自定义阴影颜色 ; 4、支持点光源照射(但不支持点光源阴影)。 通用渲染截图 自定义阴影颜色截图 完整代码: 写在最后: 1、在我的上一篇文

    2024年02月12日
    浏览(49)
  • 【Unity Shader Graph URP渲染管线下的自定义半透明效果_半透明案例分享】

    URP的渲染管线下 在项目设置里找到“Graphic” 找到URP Asset文件 索引到Renderer List文件——“ForwardRenderer” 在这个“ForwardRenderer”文件里找到“Add Renderer Feature” 添加一个渲染对象,类似下图:Render Object (Experimental) 如图设置,将“Event”设置成 AfterRenderingSkybox ,然后“Layer M

    2024年02月09日
    浏览(59)
  • Unity中URP下的添加雾效支持

    我们使用之前的棋盘格作为测试Shader来添加雾效。 Unity中 URP 下的棋盘格Shader #pragma multi_compile_fog float fogCoord : TEXCOORD2; o.fogCoord = ComputeFogFactor(o.vertexCS.z); col.rgb = MixFog(col,i.fogCoord);

    2024年04月25日
    浏览(34)
  • Unity中URP下实现深度贴花(雾效支持和BRP适配)

    在上一篇文章中,我们实现了贴花的效果。但是,细节效果需要优化。 Unity中URP下实现深度贴花 我们在这篇文章中,来优化一下贴花Shader的细节。 原雾效使用方法是只支持不透明对象的。 但是,我们的贴画是半透明的。所以,需要对其进行调整。 col.rgb = MixFog(col.rgb,i.fogCo

    2024年01月16日
    浏览(55)
  • Unity 圆角矩形Shader实现(支持长方形)(只写两行)

    相信很多小伙伴都会遇到做 圆角矩形 的需求,网上的shader还不明白是怎么实现的,甚至还有一部分是错误的,本文讲从原理到代码讲解 圆角矩形shader 的实现 想要实现一个圆角矩形,常见的是抽象成一个数学模型,如下图紫色区域,就是我们应该保留的区域,为了更准确的

    2024年02月04日
    浏览(49)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包