0基础尝试实现UnityURP渲染管线的AdditionalLit(点光源,聚光灯)非平行光的光照模型代码

Posted avi9111

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了0基础尝试实现UnityURP渲染管线的AdditionalLit(点光源,聚光灯)非平行光的光照模型代码相关的知识,希望对你有一定的参考价值。

目录

0基础其实最好

代码的本质

代码的入口

 代码分析

代码逻辑

代码实现

自行练习


0基础其实最好

其实不可能是0基础,但是0基础反而能习得上乘武功,就好像张三丰说的,忘了你爸吧

假如你现在开始看现在的Unity URP或Standard Shader

1-如果熟读乐乐姐的《入门精要》,那是2015年出版的,2013年开始写,写的那是一个优雅,而你再看现在Unity内部Shader,我保证你内伤。

2-如果你有多年程序经验,你会觉得看不明白的代码,肯定是好代码,但细心想想,这年头还看不明白的代码,本来只剩100年前的汇编语言,这个UniyShader排第二看不懂。

3-如果你会一点微积分,懂公式推理,熟悉微平面理论,我劝你放下,今天我们只谈买菜的功夫。

所以,先自宫,再往下看:

=================================================================

//关键代码
        uint pixelLightCount = GetAdditionalLightsCount();
        for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
        
            Light light = GetAdditionalLight(lightIndex, positionWS);


//踩坑之后,发现,还是自己写一个自定义渲染管线
//踩坑之后,发现,还是自己写一个自定义渲染管线
//踩坑之后,发现,还是自己写一个自定义渲染管线

代码的本质

天下武功,唯快不破;代码亦如此,就是一输入,然后一输出,别整那些花里胡哨的。

代码的入口

<找到Package目录下的Shader目录>

说说我是怎么发现这个入口的吧(反正自宫之后,现在大家都不懂Unity,不懂写代码,就一普通具备正常思维能力的人儿)

1.project 面板,右键,创建一个材质

2.材质面板,Shader选Universal RP ->Lit.shader

3.材质面板,上部(shader)右键->Edit Shader.

即可定位到 Lit Shader

 代码分析

<一大堆代码,都不用看,就一句代码有用:Lit.shader这个文件引用了XXXXPass.hlsl这个文件>

 600行代码,就这一句有用,《其他不用看》

代码逻辑

发现Spot lit 点光源的逻辑,就是在 LitForwradBase.hlsl 这文件

最终你会发现,是初始化了SurfaceData,然后把这个参数传给:

UniversalFragmentPBR()这个方法计算出最终的颜色

half4 LitPassFragment(Varyings input) : SV_Target
   
    //.............
     SurfaceData surfaceData;
    InitializeStandardLitSurfaceData(input.uv, surfaceData);

    InputData inputData;
    InitializeInputData(input, surfaceData.normalTS, inputData);

    half4 color = UniversalFragmentPBR(inputData, surfaceData);

代码实现(核心代码)

#ifdef _ADDITIONAL_LIGHTS
    uint pixelLightCount = GetAdditionalLightsCount();
    for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
    
        Light light = GetAdditionalLight(lightIndex, inputData.positionWS, shadowMask);
        #if defined(_SCREEN_SPACE_OCCLUSION)
            light.color *= aoFactor.directAmbientOcclusion;
        #endif
        color += LightingPhysicallyBased(brdfData, brdfDataClearCoat,
                                         light,
                                         inputData.normalWS, inputData.viewDirectionWS,
                                         surfaceData.clearCoatMask, specularHighlightsOff);
    
#endif

自行练习

<试了一晚上,发现还是得用官方得brdf结构体,好处就是所有光都帮你算好了,公式给你封装,2行代码,可支持点光源,聚光灯,和Area光,而且还是Urp管线下,不好的地方就是代码没法写,一个代码整的不可扩展,真的,程序是一个专业活,TA和美术就不要写代码了,重写又不是,重构又重构不了>

贴出所有代码吧

    #include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"    
        SurfaceData surfaceData;
        InitializeStandardLitSurfaceData(i.uv, surfaceData);
        half3 colorAdd = half3(0,0,0);
        uint pixelLightCount = GetAdditionalLightsCount();
        for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
        
            Light light = GetAdditionalLight(lightIndex, positionWS);
            //1.
            // float4 lightPositionWS = _AdditionalLightsPosition[lightIndex];
            // float3 lightVec = lightPositionWS - positionWS;
            // // 表面到光线的距离
            // float d = length(lightVec);
            // // 光的衰弱
            // float att = 1.0f / dot(0.1, float3(1.0f, d, d * d));
            //
            // colorAdd += light.color * att;

            //2.毫无根据,乱来的方法
            //colorAdd += IndirectColor * light.distanceAttenuation*30;

            //3.出处:           //  // https://zhuanlan.zhihu.com/p/368888374
           //  //range是光源的有效范围
           //  float4 lightPositionWS = _AdditionalLightsPosition[lightIndex];
           //  float3 lightPosition = lightPositionWS.xyz;
           //  //float range = lightPositionWS.w;//不是Matrix
           //  float3 lightVector = lightPosition - positionWS;
           //  //lightRangeSqr =  -1.0 * lightRangeSqr / 0.36;//http://www.kittehface.com/2020/05/light-universal-render-pipeline-to.html
           //  float range = 6;//搞了很久,没法搞到官方 urp 管线下的 lit range.......^@^&T^!!^*^!^!! 
           // float rangeSqr = range * range;
           //  float3 lightDir = normalize(lightVector);
           //  float distanceToLightSqr = dot(lightVector,lightVector);
           //  //距离衰减系数
           //  //float atten = _AdditionalLightsAttenuation[lightIndex];
           //  float atten = DistanceAtten(distanceToLightSqr,rangeSqr);//自定义方法
           //  //float atten = DistanceAttenuation(distanceToLightSqr,rangeSqr);//官方方法
           //  //高光项
           //  //half3 specular =  BlinnPhongSpecular(viewDir,normal,lightDir,property.shininess) * property.specularColor;
           //  //漫反射项
           //  //half3 diffuse = LambertDiffuse(normal,lightDir) * property.diffuseColor;
           //  colorAdd += IndirectColor*atten;

            
            //4.依赖light.distanceAttenuation,但好像没什么卵用
        // //    float3 lightVector =      lightPositionOrDirection.xyz - worldPos * lightPositionOrDirection.w;
        //     float3 lightDirection = normalize(lightVector);
        //     float diffuse = saturate(dot(N, lightDirection));
	       //
        //     float rangeFade = dot(lightVector, lightVector) * light.distanceAttenuation;
        //     rangeFade = saturate(1.0 - rangeFade * rangeFade);
        //     rangeFade *= rangeFade;
	       //
        //     float distanceSqr = max(dot(lightVector, lightVector), 0.00001);
        //     diffuse *= rangeFade / distanceSqr;
        //     colorAdd += IndirectColor*diffuse;

            //5.use BRDF Struct(暂时)
            BRDFData brdfData;
            BRDFData brdfDataClearCoat = (BRDFData)0;
            // NOTE: can modify alpha
            InitializeBRDFData(surfaceData.albedo, surfaceData.metallic, surfaceData.specular, surfaceData.smoothness, surfaceData.alpha, brdfData);

            bool specularHighlightsOff = false;
            colorAdd += LightingPhysicallyBased(brdfData, brdfDataClearCoat,
                                 light,
                                 N, V,
                                 surfaceData.clearCoatMask, specularHighlightsOff);
        

 

参考:

这位小哥讲URP“”实战“”,也讲的很清楚了

【Unity】Custom URP Shader(1)—— 让每个物体受不同强度的平行光照射 - 知乎

以上是关于0基础尝试实现UnityURP渲染管线的AdditionalLit(点光源,聚光灯)非平行光的光照模型代码的主要内容,如果未能解决你的问题,请参考以下文章

0基础UnityURP渲染管线人物渲染_皮肤_头发_眼睛_各向异性_SSS之实践

unityURP管线学习+后处理

OpenGL学习随笔-- OpenGL ES 2.0渲染管线

计算机图形学学习—— 基础篇:可编程渲染管线

深入URP之Shader篇1: URP Shader概述

渲染管线之深度测试与α融合—如何实现同时绘制不透明物体和透明物体