unity URP实现PBR shader

unity URP实现PBR shader

之前到处找资料参考,复制粘贴了一个文章unity渲染管线及升级URP出来,实际操作的时候却发现作用较小。

今天重新写一个URP实现PBR的文章,就基于前边写的基于物理渲染-unity实现PBR shader + 多光源 + 半透明物体和阴影的基础补充吧。

一,整体结构

  • 第一行的shader命名和Properties部分不用变。
  1. Tag处增加"RenderPipeline"=“UniversalPipeline”,表示这个是urp的shader,改用"LightMode"="UniversalForward"表示渲染pass。
  2. CGINCLUDE、CGPROGRAM、ENDCG中的CG都改成HLSL–>如HLSLPROGRAM。
  3. 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"
  1. Properties中出现的属性需要用CBUFFER声明下:
//声明纹理和cubemap
TEXTURE2D(_MainTex);SAMPLER(sampler_MainTex);
TEXTURECUBE(_Cubemap);SAMPLER(sampler_Cubemap);
//声明其他变量等
CBUFFER_START(UnityPerMaterial)
half4 _Color;
float4 _MainTex_ST;
CBUFFER_END
  1. 声明宏
#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                 
  1. 结构体,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;
};
  1. URP自带的ShadowCaster:
UsePass "Universal Render Pipeline/Lit/ShadowCaster"
  1. FallBack
FallBack "Packages/com.unity.render-pipelines.universal/FallbackError"

二,PBR部分

  1. 获取相关变量、主光源光照等
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
  1. 直接光漫反射
float3 Albedo = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv).rgb;
half3 Kd = OneMinusReflectivityMetallic(Matelness);
half3 diffCol = Kd * Albedo * lightradiance;
  1. 直接光镜面反射----和内置管线一样
  2. 多光源直接光照
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));//内置球谐光照计算相应的采样数据
  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;

猜你喜欢

转载自blog.csdn.net/yx314636922/article/details/125067616