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