我们要明确 realtime 和 bake两种状态
Shader "Custom/A"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
[Noraml]_Normal("Normal", 2D) = "bump"{}
_SpecularScale("Specular scale",float) = 1
_SpecularStrength("Specular strength",float) = 1
}
SubShader
{
//renderPipleine决定shader使用那种管线模式
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalRenderPipeline"}
LOD 100
Pass
{
//LightMode——URP中已经对Pass进行了集中管理,如果我们没有在URPAsset里设置或
//RenderFeature方法中添加,自定义的pass将不会起作用
//https://blog.csdn.net/enk_2/article/details/109081930
name "Forward"
Tags{"LightMode" = "UniversalForward"}
HLSLPROGRAM
#pragma prefer_hlslcc gles
#pragma exclude_renderers d3d11_9x
#pragma target 2.0
//Mainlight受光 阴影相关
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile _ _SHADOWS_SOFT
//额外光照
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
//lightmap
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile_fog
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_instancing
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
TEXTURE2D(_Normal);
SAMPLER(sampler_MainTex);
//CBUFFER中的属性需要和properties中保持一致这样才可以正确SRP Batch,一般放除贴图以外的变量,不支持properties中不包含的传入属性
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
float _SpecularScale;
float _SpecularStrength;
CBUFFER_END
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float2 uv : TEXCOORD0;
float2 lightmapUV : TEXCOORD1;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 uv : TEXCOORD0;
//有lightmap定义lightmap 有顶点定义顶点
DECLARE_LIGHTMAP_OR_SH(lightmapUV, vertexSH, 1);
float4 positionWSAndFogfactor : TEXCOORD2;
float3 noramlWS : TEXCOORD3;
float3 tangetnWS : TEXCOORD4;
float3 bitangentWS:TEXCOORD5;
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
float4 shadowCoord : TEXCOORD7;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
UNITY_VERTEX_OUTPUT_STEREO
};
Varyings vert (Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
//vertex和normal的便捷方法,不需要自己繁琐的转换。
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
output.positionCS = vertexInput.positionCS;
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
output.positionWSAndFogfactor.xyz = vertexInput.positionWS;
output.normalWS = noramlInput.normalWS;
output.tangetnWS = normlaInput.tangentWS;
output.bitangentWS = normalInput.bitangentWS;
//绘制接受阴影
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
output.shadowCoord = TransformWorldToShadowCoord(vertexInput.positionWS);
#endif
//input lightmapUV; output lightmapUV;
OUTPUT_LIGHTMAP_UV(input.lightmapUV, unity_LightmapST, output.lightmapUV);
OUTPUT_SH(output.normalWS, output.vertexSH);//in normal out vertexSH
o.positionWSAndFogfactor.w = ComputeFogFactor(output.positionCS.z);
return output;
}
half4 frag (Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
Light mainLight;
#if defined(REQUIRES_VERTEX_SHADOW_COORD_INTERPOLATOR)
mainLight = GetMainLight(input.shadowCoord);
#else
mainLight = GetMainLight();
#endif
float fogFactor = input.positionWSAndFogfactor.w;
float3 positionWS = input.positionWSAndFogfactor.xyz;
float3x3 tangnetTransform = float3x3(input.tangentWS,
input.bitangentWS,
input.normalWS);
// sample the texture
half4 col = SAMPLE_TEXTURE2D(_MainTex,sampler_MainTex, input.uv);
float3 normal = UnpackNormal(SAMPLE_TEXTURE2D(_Normal, sampler_Normal, input.uv));
float3 worldNormal = mul(normal, tangnetTransform);
float NdotL = max(0, dot(worldNormal, mainLight.direcion));
float3 viewDir = normalize(_WorldSpaceCameraPos.xyz - positionWS);
float3 halfDir =normalize( mainLight.direction + viewDir);
float NdotH = max(0, dot(worldNormal, halfDir));
float spec = pow(NdotH, _SpecularScale) * _SpecularStrength;
half4 color = 1;
color.rgb = col.rgb * NdotL;
color.a = col.a;
half3 bakedGI = SAMPLE_GI(input.lightmapUV,input.vertexSH, worldNormal);
//实时光
float3 ambient = col.rgb * bakedGI;
color.rgb = color.rgb * mainLight.shadowAttenuation + ambient + spec;
//额外光照
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for (uint lightIndex = 0u; lightIndex < pixelLightCount; ++lightIndex)
{
Light addlight = GetAdditionalLight(lightIndex, positionWS);
color.rgb += col.rgb * (max(0, dot(addlight.direction, i.normalWS)) * addlight.color.rgb * addlight.distanceAttenuation * addlight.shadowAttenuation);
}
#endif
color.rgb = MixFog(color.rgb,fogfactor);
// apply fog
return color;
}
ENDHLSL
}
}
}