之前到处找资料参考,复制粘贴了一个文章unity渲染管线及升级URP出来,实际操作的时候却发现作用较小。
今天重新写一个URP实现PBR的文章,就基于前边写的基于物理渲染-unity实现PBR shader + 多光源 + 半透明物体和阴影的基础补充吧。
一,整体结构
- 第一行的shader命名和Properties部分不用变。
- Tag处增加"RenderPipeline"=“UniversalPipeline”,表示这个是urp的shader,改用"LightMode"="UniversalForward"表示渲染pass。
- CGINCLUDE、CGPROGRAM、ENDCG中的CG都改成HLSL–>如HLSLPROGRAM。
- include中的cs文件都不用了,改用hlsl文件,常见使用如下,其他具体对应文件自己查下。
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
- Properties中出现的属性需要用CBUFFER声明下:
//声明纹理和cubemap
TEXTURE2D(_MainTex);SAMPLER(sampler_MainTex);
TEXTURECUBE(_Cubemap);SAMPLER(sampler_Cubemap);
//声明其他变量等
CBUFFER_START(UnityPerMaterial)
half4 _Color;
float4 _MainTex_ST;
CBUFFER_END
- 声明宏
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS //开启接受阴影
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE//使用TransformWorldToShadowCoord
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS//使用AdditionalLightRealtimeShadow计算add光源阴影
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS//精度?不确定
#pragma multi_compile _ _SHADOWS_SOFT
- 结构体,urp没有内置结构体了,自己构建的默认命名也有更改:
struct Attributes//a2v
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
};
struct Varings//v2f
{
float4 positionCS : SV_POSITION;
float3 positionWS : TEXCOORD0;
float2 uv : TEXCOORD1;
};
- URP自带的ShadowCaster:
UsePass "Universal Render Pipeline/Lit/ShadowCaster"
- FallBack
FallBack "Packages/com.unity.render-pipelines.universal/FallbackError"
二,PBR部分
- 获取相关变量、主光源光照等
float4 shadowCoord = TransformWorldToShadowCoord(IN.positionWS);//阴影接收
Light mainLight = GetMainLight(shadowCoord);
float3 lightDir = normalize(mainLight.direction);
half atten = mainLight.shadowAttenuation*mainLight.distanceAttenuation;
half3 lightradiance = mainLight.color * ndotl * atten;
float3 ViewDir = normalize(_WorldSpaceCameraPos.xyz-IN.positionWS);//GetCameraPositionWS()->_WorldSpaceCameraPos.xyz
- 直接光漫反射
float3 Albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv).rgb;
half3 Kd = OneMinusReflectivityMetallic(Matelness);
half3 diffCol = Kd * Albedo * lightradiance;
- 直接光镜面反射----和内置管线一样
- 多光源直接光照
int addLightsCount = GetAdditionalLightsCount();
for (uint lightIndex = 0; lightIndex < addLightsCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex, IN.positionWS,shadowCoord);//多光源阴影接收
……
half3 addlightradiance = light.color * addndotl * light.shadowAttenuation * light.distanceAttenuation;
diffCol += ……;
……
specCol += ……;
}
half3 Direct = diffCol + specCol;
另外想要副光源也能够产生阴影,需要勾选URP管线->Inspector->Additional Lights->Cast Shadows:
5. 间接光照漫反射,一处改动:
float3 irradiance = SampleSH(float4(worldNormal,1));//内置球谐光照计算相应的采样数据
- 间接光照镜面反射,三处改动:
float4 rgbm = SAMPLE_TEXTURECUBE_LOD(unity_SpecCube0, samplerunity_SpecCube0, reflectDir, mip);
float3 iblSpecular = DecodeHDREnvironment(rgbm,unity_SpecCube0_HDR);
half2 envBRDF = SAMPLE_TEXTURE2D(_BRDF, sampler_BRDF,half2(lerp(0, 0.99,ndotv),lerp(0, 0.99,Roughness))).rg;