BuildIn和URP在传参和语义上区别
- ------------------------------------------------------------------------------------------------------------------
- BuildIn管线CG和URP管线HLSL
- ------------------------------------------------------------------------------------------------------------------
- Unity内置源码:
- ------------------------------------------------------------------------------------------------------------------
- ------------------------------------------------------------------------------------------------------------------
- BuildIn管线下最简光照shader框架
- URP管线下最简光照shader框架
- URP管线下最简GUI 不透明Opaque shader框架
- URP管线下最简GUI 透明Transparent shader框架
- HDRP管线下最简Unlit shader框架
------------------------------------------------------------------------------------------------------------------
BuildIn管线CG和URP管线HLSL
- Tag和CGPROGRAM不赘述
- Tag和HLSLPROGRAM不赘述
CG光照宏定义
...
#pragma multi_compile_fwdbase
...
HLSL光照宏定义
...
//支持多个平行光,只支持一个平行光的阴影,主光源阴影,屏幕空间阴影,级联阴影
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
//软阴影
#pragma multi_compile_fragment _ _SHADOWS_SOFT
//支持多光源和多光源阴影的宏
//#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
//#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
//反射、环境遮蔽和烘焙相关宏定义
//#pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
//#pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
//#pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
//#pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
//#pragma multi_compile_fragment _ _LIGHT_LAYERS
//#pragma multi_compile_fragment _ _LIGHT_COOKIES
//#pragma multi_compile _ _CLUSTERED_RENDERING
...
CG包含文件
...
#include "UnityCG.cginc"
#include "AutoLight.cginc"
...
HLSL包含文件
...
//HLSL包含文件
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
...
Include文件/包含文件
包含文件核心 | 内置管线 | URP管线 |
---|---|---|
Content | Built-in | URP |
Core | Unity.cginc | Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl |
Light | AutoLight.cginc | Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl |
Shadows | AutoLight.cginc | Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl |
Surface shaders | Lighting.cginc | 无 |
CG纹理采样
...
sampler2D _MainTex;
float4 _MainTex_ST;
...
half4 col= tex2D(_MainTex, i.uv);
HLSL纹理采样
...
TEXTURE2D(_BaseMap); SAMPLER(sampler_BaseMap);
CBUFFER_START(UnityPerMaterial)//用“CBUFFER_START”包围起来,主要是做SRP Batcher性能优化。
float4 _BaseMap_ST;
CBUFFER_END
...
float4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
...
CG获取灯光信息
Shader "1"
{
Properties
{
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Tags{"LightMode" = "ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct appdata
{
...
};
struct v2f
{
...
};
...
float4 _LightColor0;
...
v2f vert (appdata v)
{
v2f o;
...
return o;
}
half4 frag (v2f i) : SV_Target
{
...
//主灯平行光
half3 light_dir = normalize(_WorldSpaceLightPos0.xyz);
half3 LightColor = _LightColor0.xyz;
...
}
ENDCG
}
Pass
{
Tags{"LightMode" = "ForwardAdd"}
Blend One One
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdadd
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct appdata
{
float4 vertex : POSITION;
};
struct v2f
{
float4 pos : SV_POSITION;
float3 pos_world : TEXCOORD2;
LIGHTING_COORDS(5, 6)
};
...
float4 _LightColor0;
...
v2f vert(appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.pos_world = mul(unity_ObjectToWorld, v.vertex).xyz;
TRANSFER_VERTEX_TO_FRAGMENT(o);
return o;
}
half4 frag(v2f i) : SV_Target
{
...
//点光源
half3 light_dir_point = normalize(_WorldSpaceLightPos0.xyz - i.pos_world);
half3 light_dir = normalize(_WorldSpaceLightPos0.xyz);
light_dir = lerp(light_dir, light_dir_point, _WorldSpaceLightPos0.w);
...
}
ENDCG
}
}
Fallback "Diffuse"
}
HLSL获取灯光信息
Shader "NewShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
...
Pass
{
Tags { "LightMode" = "UniversalForward" }
...
//支持多个平行光,只支持一个平行光的阴影,主光源阴影,屏幕空间阴影,级联阴影
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
//软阴影
#pragma multi_compile_fragment _ _SHADOWS_SOFT
//支持多光源和多光源阴影的宏
//#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
//#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
//反射、环境遮蔽和烘焙相关宏定义
//#pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
//#pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
//#pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
//#pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
//#pragma multi_compile_fragment _ _LIGHT_LAYERS
//#pragma multi_compile_fragment _ _LIGHT_COOKIES
//#pragma multi_compile _ _CLUSTERED_RENDERING
...
//HLSL包含文件
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
...
//HLSLPROGRAM
HLSLPROGRAM
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangentOS : TANGENT;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float2 uv : TEXCOORD0;
float2 uv : TEXCOORD0;
float3 positionWS : TEXCOORD1;
half3 normalWS : TEXCOORD2;
half4 tangentWS : TEXCOORD3; // xyz: tangent, w: sign
float4 shadowCoord : TEXCOORD4;
float4 positionCS : SV_POSITION;
UNITY_FOG_COORDS(5)
SHADOW_COORDS(6)//阴影
};
...
TEXTURE2D(_MainTex ); SAMPLER(sampler_MainTex );
CBUFFER_START(UnityPerMaterial)//用“CBUFFER_START”包围起来,主要是做性能优化。
float4 _MainTex _ST;
CBUFFER_END
...
Varyings LitPassVertex(Attributes input)
{
Varyings output = (Varyings)0;
UNITY_SETUP_INSTANCE_ID(input);
UNITY_TRANSFER_INSTANCE_ID(input, output);
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
output.uv = input.texcoord;
output.normalWS = normalInput.normalWS;
real sign = input.tangentOS.w * GetOddNegativeScale();
half4 tangentWS = half4(normalInput.tangentWS.xyz, sign);
output.tangentWS = tangentWS;
//half3 viewDirWS = GetWorldSpaceNormalizeViewDir(vertexInput.positionWS);
output.positionWS = vertexInput.positionWS;
output.shadowCoord = GetShadowCoord(vertexInput);
output.positionCS = vertexInput.positionCS;
UNITY_TRANSFER_FOG(o,o.vertex);
TRANSFER_SHADOW(o)//阴影
return o;
}
half4 LitPassFragment(Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
Light mainLight = GetMainLight(input.shadowCoord,input.positionWS,float4(1.0,1.0,1.0,1.0));
float3 lightDir = mainLight.direction;
half shadow = mainLight.shadowAttenuation;
//视线方向
half3 view_dir = normalize(_WorldSpaceCameraPos.xyz - i.pos_world);
//灯光方向
half3 light_dir = normalize(_WorldSpaceLightPos0.xyz);
//主光源颜色信息
half3 mainlight = _LightColor0.xyz;
//多光源
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for(uint lightIndex = 0; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex,input.positionWS,float4(1.0,1.0,1.0,1.0));
half NdotL_add = dot(normalDir, light.direction);
half half_lambert_add = (NdotL_add + 1.0) * 0.5;
float atten_add = lerp(1 , light.shadowAttenuation * light.distanceAttenuation , input.vertexColor.g);
half labmbert_term_add = half_lambert_add * ao * atten_add + diffuse_control;
toon_diffuse += saturate((labmbert_term_add * light.color - _ToonThesHold) * _ToonHardness);
}
#endif
//半角向量
half3 half_dir = normalize(light_dir + view_dir);
//NdotH
half NdotH = dot(normal_dir, half_dir);
// sample the texture
float4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDHLSL
}
}
}
CG Cast Shadows生成阴影
在shader中新增一个ShadowCaster的Pass,渲染物体的投影。
...
// Pass to render object as a shadow caster
Pass
{
//Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders
#include "UnityCG.cginc"
struct appdata
{
float4 vertex:POSITION;
half3 normal:NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
V2F_SHADOW_CASTER;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert( appdata_base v )
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag( v2f i ) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
...
- 添加"LightMode" = "ShadowCaster"的Pass。
- 添加宏定义 #pragma multi_compile_shadowcaster,使投影语义V2F_SHADOW_CASTER被定义。
- appdata中声明float4 vertex:POSITION;和half3 normal:NORMAL;这是生成阴影所需要的语义。
- v2f中添加V2F_SHADOW_CASTER;用于声明需要传送到片断的数据。
- 在顶点着色器中添加TRANSFER_SHADOW_CASTER_NORMALOFFSET(o),主要是计算阴影的偏移以解决不正确的Shadow Acne和Peter Panning现象。
- 在片断着色器中添加SHADOW_CASTER_FRAGMENT(i)
HLSL Cast Shadows生成阴影
新增两个pass,ShadowCaster和DepthOnly,生成阴影,
...
Pass
{
Name "ShadowCaster"
Tags{"LightMode" = "ShadowCaster"}
ZWrite On
ZTest LEqual
ColorMask 0
Cull[_Cull]
HLSLPROGRAM
#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma multi_compile _ DOTS_INSTANCING_ON
// -------------------------------------
// Universal Pipeline keywords
// This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
#pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
ENDHLSL
}
Pass
{
Name "DepthOnly"
Tags{"LightMode" = "DepthOnly"}
ZWrite On
ColorMask 0
Cull[_Cull]
HLSLPROGRAM
#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma multi_compile _ DOTS_INSTANCING_ON
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
ENDHLSL
}
...
CG Receive Shadows接收阴影
...
Shader "SHADOWS"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
// #pragma multi_compile DIRECTIONAL SHADOWS_SCREEN
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 worldPos : TEXCOORD1;
UNITY_SHADOW_COORDS(2)
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldPos = mul(unity_ObjectToWorld,v.vertex);
TRANSFER_SHADOW(o)//阴影
return o;
}
fixed4 frag (v2f i) : SV_Target
{
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos)
fixed4 col = tex2D(_MainTex, i.uv) * atten;
return col;
}
ENDCG
}
// Pass to render object as a shadow caster
Pass
{
//Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
CGPROGRAM
...
ENDCG
}
}
}
...
- 在v2f中添加UNITY_SHADOW_COORDS(idx),unity会自动声明一个叫_ShadowCoord的float4变量,用作阴影的采样坐标。
- 在顶点着色器中添加TRANSFER_SHADOW(o),用于将上面定义的_ShadowCoord纹理采样坐标变换到相应的屏幕空间纹理坐标,为采样阴影纹理使用。
- 在片断着色器中添加UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos),其中atten即存储了采样后的阴影。
- Receive Shadows接收阴影Pass和光照Pass是在一个Pass内计算。Shader中如果没有ShadowCaster的Pass,接收阴影会失效。
- 但如果只是让物体有阴影,添加一个ShadowCaster的Pass既可。
HLSL Receive Shadows接收阴影
在UniversalForwardPass下采样阴影,如图
...
Pass
{
Tags { "LightMode" = "UniversalForward" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
#pragma multi_compile_fragment _ _SHADOWS_SOFT
#pragma multi_compile _ _ADDITIONAL_LIGHTS
#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attritubes
{
float4 positionOS : POSITION;
...
};
struct Varyings
{
float4 positionCS : SV_POSITION;
...
float3 positionWS : TEXCOORD1;
float4 shadowCoord : TEXCOORD4;
};
...
Varyings vert (Attritubes input)
{
Varyings output = (Varyings)0;
VertexPositionInputs vertexInput = GetVertexPositionInputs(input.positionOS.xyz);
output.positionCS = vertexInput.positionCS;
output.positionWS = vertexInput.positionWS;
//output.positionWS = TransformObjectToWorld(input.positionOS.xyz);
output.shadowCoord = GetShadowCoord(vertexInput);
return output;
}
half4 frag (Varyings input) : SV_Target
{
...
Light mainLight = GetMainLight(input.shadowCoord,input.positionWS,float4(1.0,1.0,1.0,1.0));
float3 lightDir = mainLight.direction;
float shadow = mainLight.shadowAttenuation;
//float shadow = MainLightRealtimeShadow(input.shadowCoord);
...
}
ENDHLSL
}
...
------------------------------------------------------------------------------------------------------------------
Unity内置源码:
CG生成阴影ShadowCaster Pass
// Shadow rendering pass
Pass {
Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
ZWrite On ZTest LEqual
CGPROGRAM
#pragma target 3.5
// -------------------------------------
#pragma shader_feature_local _ _ALPHATEST_ON _ALPHABLEND_ON _ALPHAPREMULTIPLY_ON
#pragma shader_feature_local _METALLICGLOSSMAP
#pragma shader_feature_local _PARALLAXMAP
#pragma multi_compile_shadowcaster
#pragma multi_compile_instancing
#pragma vertex vertShadowCaster
#pragma fragment fragShadowCaster
#include "UnityStandardShadow.cginc"
ENDCG
}
UnityStandardShadow
“UnityStandardShadow.cginc”
// Unity built-in shader source. Copyright (c) 2016 Unity Technologies. MIT license (see license.txt)
#ifndef UNITY_STANDARD_SHADOW_INCLUDED
#define UNITY_STANDARD_SHADOW_INCLUDED
// NOTE: had to split shadow functions into separate file,
// otherwise compiler gives trouble with LIGHTING_COORDS macro (in UnityStandardCore.cginc)
#include "UnityCG.cginc"
#include "UnityShaderVariables.cginc"
#include "UnityStandardConfig.cginc"
#include "UnityStandardUtils.cginc"
#if (defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)) && defined(UNITY_USE_DITHER_MASK_FOR_ALPHABLENDED_SHADOWS)
#define UNITY_STANDARD_USE_DITHER_MASK 1
#endif
// Need to output UVs in shadow caster, since we need to sample texture and do clip/dithering based on it
#if defined(_ALPHATEST_ON) || defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)
#define UNITY_STANDARD_USE_SHADOW_UVS 1
#endif
// Has a non-empty shadow caster output struct (it's an error to have empty structs on some platforms...)
#if !defined(V2F_SHADOW_CASTER_NOPOS_IS_EMPTY) || defined(UNITY_STANDARD_USE_SHADOW_UVS)
#define UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT 1
#endif
#ifdef UNITY_STEREO_INSTANCING_ENABLED
#define UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT 1
#endif
half4 _Color;
half _Cutoff;
sampler2D _MainTex;
float4 _MainTex_ST;
#ifdef UNITY_STANDARD_USE_DITHER_MASK
sampler3D _DitherMaskLOD;
#endif
// Handle PremultipliedAlpha from Fade or Transparent shading mode
half4 _SpecColor;
half _Metallic;
#ifdef _SPECGLOSSMAP
sampler2D _SpecGlossMap;
#endif
#ifdef _METALLICGLOSSMAP
sampler2D _MetallicGlossMap;
#endif
#if defined(UNITY_STANDARD_USE_SHADOW_UVS) && defined(_PARALLAXMAP)
sampler2D _ParallaxMap;
half _Parallax;
#endif
half MetallicSetup_ShadowGetOneMinusReflectivity(half2 uv)
{
half metallicity = _Metallic;
#ifdef _METALLICGLOSSMAP
metallicity = tex2D(_MetallicGlossMap, uv).r;
#endif
return OneMinusReflectivityFromMetallic(metallicity);
}
half RoughnessSetup_ShadowGetOneMinusReflectivity(half2 uv)
{
half metallicity = _Metallic;
#ifdef _METALLICGLOSSMAP
metallicity = tex2D(_MetallicGlossMap, uv).r;
#endif
return OneMinusReflectivityFromMetallic(metallicity);
}
half SpecularSetup_ShadowGetOneMinusReflectivity(half2 uv)
{
half3 specColor = _SpecColor.rgb;
#ifdef _SPECGLOSSMAP
specColor = tex2D(_SpecGlossMap, uv).rgb;
#endif
return (1 - SpecularStrength(specColor));
}
// SHADOW_ONEMINUSREFLECTIVITY(): workaround to get one minus reflectivity based on UNITY_SETUP_BRDF_INPUT
#define SHADOW_JOIN2(a, b) a##b
#define SHADOW_JOIN(a, b) SHADOW_JOIN2(a,b)
#define SHADOW_ONEMINUSREFLECTIVITY SHADOW_JOIN(UNITY_SETUP_BRDF_INPUT, _ShadowGetOneMinusReflectivity)
struct VertexInput
{
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv0 : TEXCOORD0;
#if defined(UNITY_STANDARD_USE_SHADOW_UVS) && defined(_PARALLAXMAP)
half4 tangent : TANGENT;
#endif
UNITY_VERTEX_INPUT_INSTANCE_ID
};
#ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT
struct VertexOutputShadowCaster
{
V2F_SHADOW_CASTER_NOPOS
#if defined(UNITY_STANDARD_USE_SHADOW_UVS)
float2 tex : TEXCOORD1;
#if defined(_PARALLAXMAP)
half3 viewDirForParallax : TEXCOORD2;
#endif
#endif
};
#endif
#ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT
struct VertexOutputStereoShadowCaster
{
UNITY_VERTEX_OUTPUT_STEREO
};
#endif
// We have to do these dances of outputting SV_POSITION separately from the vertex shader,
// and inputting VPOS in the pixel shader, since they both map to "POSITION" semantic on
// some platforms, and then things don't go well.
void vertShadowCaster (VertexInput v
, out float4 opos : SV_POSITION
#ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT
, out VertexOutputShadowCaster o
#endif
#ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT
, out VertexOutputStereoShadowCaster os
#endif
)
{
UNITY_SETUP_INSTANCE_ID(v);
#ifdef UNITY_STANDARD_USE_STEREO_SHADOW_OUTPUT_STRUCT
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(os);
#endif
TRANSFER_SHADOW_CASTER_NOPOS(o,opos)
#if defined(UNITY_STANDARD_USE_SHADOW_UVS)
o.tex = TRANSFORM_TEX(v.uv0, _MainTex);
#ifdef _PARALLAXMAP
TANGENT_SPACE_ROTATION;
o.viewDirForParallax = mul (rotation, ObjSpaceViewDir(v.vertex));
#endif
#endif
}
half4 fragShadowCaster (UNITY_POSITION(vpos)
#ifdef UNITY_STANDARD_USE_SHADOW_OUTPUT_STRUCT
, VertexOutputShadowCaster i
#endif
) : SV_Target
{
#if defined(UNITY_STANDARD_USE_SHADOW_UVS)
#if defined(_PARALLAXMAP) && (SHADER_TARGET >= 30)
half3 viewDirForParallax = normalize(i.viewDirForParallax);
fixed h = tex2D (_ParallaxMap, i.tex.xy).g;
half2 offset = ParallaxOffset1Step (h, _Parallax, viewDirForParallax);
i.tex.xy += offset;
#endif
#if defined(_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A)
half alpha = _Color.a;
#else
half alpha = tex2D(_MainTex, i.tex.xy).a * _Color.a;
#endif
#if defined(_ALPHATEST_ON)
clip (alpha - _Cutoff);
#endif
#if defined(_ALPHABLEND_ON) || defined(_ALPHAPREMULTIPLY_ON)
#if defined(_ALPHAPREMULTIPLY_ON)
half outModifiedAlpha;
PreMultiplyAlpha(half3(0, 0, 0), alpha, SHADOW_ONEMINUSREFLECTIVITY(i.tex), outModifiedAlpha);
alpha = outModifiedAlpha;
#endif
#if defined(UNITY_STANDARD_USE_DITHER_MASK)
// Use dither mask for alpha blended shadows, based on pixel position xy
// and alpha level. Our dither texture is 4x4x16.
#ifdef LOD_FADE_CROSSFADE
#define _LOD_FADE_ON_ALPHA
alpha *= unity_LODFade.y;
#endif
half alphaRef = tex3D(_DitherMaskLOD, float3(vpos.xy*0.25,alpha*0.9375)).a;
clip (alphaRef - 0.01);
#else
clip (alpha - _Cutoff);
#endif
#endif
#endif // #if defined(UNITY_STANDARD_USE_SHADOW_UVS)
#ifdef LOD_FADE_CROSSFADE
#ifdef _LOD_FADE_ON_ALPHA
#undef _LOD_FADE_ON_ALPHA
#else
UnityApplyDitherCrossFade(vpos.xy);
#endif
#endif
SHADOW_CASTER_FRAGMENT(i)
}
#endif // UNITY_STANDARD_SHADOW_INCLUDED
HLSL阴影ShadowCaster Pass
Pass
{
Name "ShadowCaster"
Tags{"LightMode" = "ShadowCaster"}
ZWrite On
ZTest LEqual
ColorMask 0
Cull[_Cull]
HLSLPROGRAM
#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma multi_compile _ DOTS_INSTANCING_ON
// -------------------------------------
// Universal Pipeline keywords
// This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
#pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
ENDHLSL
}
ShadowCasterPass
Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl
#ifndef UNIVERSAL_SHADOW_CASTER_PASS_INCLUDED
#define UNIVERSAL_SHADOW_CASTER_PASS_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl"
// Shadow Casting Light geometric parameters. These variables are used when applying the shadow Normal Bias and are set by UnityEngine.Rendering.Universal.ShadowUtils.SetupShadowCasterConstantBuffer in com.unity.render-pipelines.universal/Runtime/ShadowUtils.cs
// For Directional lights, _LightDirection is used when applying shadow Normal Bias.
// For Spot lights and Point lights, _LightPosition is used to compute the actual light direction because it is different at each shadow caster geometry vertex.
float3 _LightDirection;
float3 _LightPosition;
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 texcoord : TEXCOORD0;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct Varyings
{
float2 uv : TEXCOORD0;
float4 positionCS : SV_POSITION;
};
float4 GetShadowPositionHClip(Attributes input)
{
float3 positionWS = TransformObjectToWorld(input.positionOS.xyz);
float3 normalWS = TransformObjectToWorldNormal(input.normalOS);
#if _CASTING_PUNCTUAL_LIGHT_SHADOW
float3 lightDirectionWS = normalize(_LightPosition - positionWS);
#else
float3 lightDirectionWS = _LightDirection;
#endif
float4 positionCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, lightDirectionWS));
#if UNITY_REVERSED_Z
positionCS.z = min(positionCS.z, UNITY_NEAR_CLIP_VALUE);
#else
positionCS.z = max(positionCS.z, UNITY_NEAR_CLIP_VALUE);
#endif
return positionCS;
}
Varyings ShadowPassVertex(Attributes input)
{
Varyings output;
UNITY_SETUP_INSTANCE_ID(input);
output.uv = TRANSFORM_TEX(input.texcoord, _BaseMap);
output.positionCS = GetShadowPositionHClip(input);
return output;
}
half4 ShadowPassFragment(Varyings input) : SV_TARGET
{
Alpha(SampleAlbedoAlpha(input.uv, TEXTURE2D_ARGS(_BaseMap, sampler_BaseMap)).a, _BaseColor, _Cutoff);
return 0;
}
#endif
HLSL屏幕空间阴影
Pass
{
Name "DepthOnly"
Tags{"LightMode" = "DepthOnly"}
ZWrite On
ColorMask 0
Cull[_Cull]
HLSLPROGRAM
#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma multi_compile _ DOTS_INSTANCING_ON
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
ENDHLSL
}
Shadows
Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl
half MainLightRealtimeShadow(float4 shadowCoord)
{
#if !defined(MAIN_LIGHT_CALCULATE_SHADOWS)
return half(1.0);
#elif defined(_MAIN_LIGHT_SHADOWS_SCREEN) && !defined(_SURFACE_TYPE_TRANSPARENT)
return SampleScreenSpaceShadowmap(shadowCoord);
#else
ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
half4 shadowParams = GetMainLightShadowParams();
return SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowCoord, shadowSamplingData, shadowParams, false);
#endif
}
URP屏幕空间阴影在这里添加
------------------------------------------------------------------------------------------------------------------
HLSL的SpaceTransforms合集
- 文件在工程这个位置:Packages/com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl
- 内有注释,挺详细的。主要是一些封装好的函数,可以将传入数据做空间转换。
代码如下:
#ifndef UNITY_SPACE_TRANSFORMS_INCLUDED
#define UNITY_SPACE_TRANSFORMS_INCLUDED
#if SHADER_API_MOBILE || SHADER_API_GLES || SHADER_API_GLES3
#pragma warning (disable : 3205) // conversion of larger type to smaller
#endif
// Caution: For HDRP, adding a function in this file requires adding the appropriate #define in PickingSpaceTransforms.hlsl
// Return the PreTranslated ObjectToWorld Matrix (i.e matrix with _WorldSpaceCameraPos apply to it if we use camera relative rendering)
float4x4 GetObjectToWorldMatrix()
{
return UNITY_MATRIX_M;
}
float4x4 GetWorldToObjectMatrix()
{
return UNITY_MATRIX_I_M;
}
float4x4 GetPrevObjectToWorldMatrix()
{
return UNITY_PREV_MATRIX_M;
}
float4x4 GetPrevWorldToObjectMatrix()
{
return UNITY_PREV_MATRIX_I_M;
}
float4x4 GetWorldToViewMatrix()
{
return UNITY_MATRIX_V;
}
// Transform to homogenous clip space
float4x4 GetWorldToHClipMatrix()
{
return UNITY_MATRIX_VP;
}
// Transform to homogenous clip space
float4x4 GetViewToHClipMatrix()
{
return UNITY_MATRIX_P;
}
// This function always return the absolute position in WS
float3 GetAbsolutePositionWS(float3 positionRWS)
{
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
positionRWS += _WorldSpaceCameraPos.xyz;
#endif
return positionRWS;
}
// This function return the camera relative position in WS
float3 GetCameraRelativePositionWS(float3 positionWS)
{
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
positionWS -= _WorldSpaceCameraPos.xyz;
#endif
return positionWS;
}
real GetOddNegativeScale()
{
// FIXME: We should be able to just return unity_WorldTransformParams.w, but it is not
// properly set at the moment, when doing ray-tracing; once this has been fixed in cpp,
// we can revert back to the former implementation.
return unity_WorldTransformParams.w >= 0.0 ? 1.0 : -1.0;
}
float3 TransformObjectToWorld(float3 positionOS)
{
#if defined(SHADER_STAGE_RAY_TRACING)
return mul(ObjectToWorld3x4(), float4(positionOS, 1.0)).xyz;
#else
return mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)).xyz;
#endif
}
float3 TransformWorldToObject(float3 positionWS)
{
#if defined(SHADER_STAGE_RAY_TRACING)
return mul(WorldToObject3x4(), float4(positionWS, 1.0)).xyz;
#else
return mul(GetWorldToObjectMatrix(), float4(positionWS, 1.0)).xyz;
#endif
}
float3 TransformWorldToView(float3 positionWS)
{
return mul(GetWorldToViewMatrix(), float4(positionWS, 1.0)).xyz;
}
// Transforms position from object space to homogenous space
float4 TransformObjectToHClip(float3 positionOS)
{
// More efficient than computing M*VP matrix product
return mul(GetWorldToHClipMatrix(), mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)));
}
// Tranforms position from world space to homogenous space
float4 TransformWorldToHClip(float3 positionWS)
{
return mul(GetWorldToHClipMatrix(), float4(positionWS, 1.0));
}
// Tranforms position from view space to homogenous space
float4 TransformWViewToHClip(float3 positionVS)
{
return mul(GetViewToHClipMatrix(), float4(positionVS, 1.0));
}
// Normalize to support uniform scaling
float3 TransformObjectToWorldDir(float3 dirOS, bool doNormalize = true)
{
#ifndef SHADER_STAGE_RAY_TRACING
float3 dirWS = mul((float3x3)GetObjectToWorldMatrix(), dirOS);
#else
float3 dirWS = mul((float3x3)ObjectToWorld3x4(), dirOS);
#endif
if (doNormalize)
return SafeNormalize(dirWS);
return dirWS;
}
// Normalize to support uniform scaling
float3 TransformWorldToObjectDir(float3 dirWS, bool doNormalize = true)
{
#ifndef SHADER_STAGE_RAY_TRACING
float3 dirOS = mul((float3x3)GetWorldToObjectMatrix(), dirWS);
#else
float3 dirOS = mul((float3x3)WorldToObject3x4(), dirWS);
#endif
if (doNormalize)
return normalize(dirOS);
return dirOS;
}
// Tranforms vector from world space to view space
real3 TransformWorldToViewDir(real3 dirWS, bool doNormalize = false)
{
float3 dirVS = mul((real3x3)GetWorldToViewMatrix(), dirWS).xyz;
if (doNormalize)
return normalize(dirVS);
return dirVS;
}
// Tranforms vector from world space to homogenous space
real3 TransformWorldToHClipDir(real3 directionWS, bool doNormalize = false)
{
float3 dirHCS = mul((real3x3)GetWorldToHClipMatrix(), directionWS).xyz;
if (doNormalize)
return normalize(dirHCS);
return dirHCS;
}
// Transforms normal from object to world space
float3 TransformObjectToWorldNormal(float3 normalOS, bool doNormalize = true)
{
#ifdef UNITY_ASSUME_UNIFORM_SCALING
return TransformObjectToWorldDir(normalOS, doNormalize);
#else
// Normal need to be multiply by inverse transpose
float3 normalWS = mul(normalOS, (float3x3)GetWorldToObjectMatrix());
if (doNormalize)
return SafeNormalize(normalWS);
return normalWS;
#endif
}
// Transforms normal from world to object space
float3 TransformWorldToObjectNormal(float3 normalWS, bool doNormalize = true)
{
#ifdef UNITY_ASSUME_UNIFORM_SCALING
return TransformWorldToObjectDir(normalWS, doNormalize);
#else
// Normal need to be multiply by inverse transpose
float3 normalOS = mul(normalWS, (float3x3)GetObjectToWorldMatrix());
if (doNormalize)
return SafeNormalize(normalOS);
return normalOS;
#endif
}
real3x3 CreateTangentToWorld(real3 normal, real3 tangent, real flipSign)
{
// For odd-negative scale transforms we need to flip the sign
real sgn = flipSign * GetOddNegativeScale();
real3 bitangent = cross(normal, tangent) * sgn;
return real3x3(tangent, bitangent, normal);
}
real3 TransformTangentToWorld(real3 dirTS, real3x3 tangentToWorld)
{
// Note matrix is in row major convention with left multiplication as it is build on the fly
return mul(dirTS, tangentToWorld);
}
// This function does the exact inverse of TransformTangentToWorld() and is
// also decribed within comments in mikktspace.h and it follows implicitly
// from the scalar triple product (google it).
real3 TransformWorldToTangent(real3 dirWS, real3x3 tangentToWorld)
{
// Note matrix is in row major convention with left multiplication as it is build on the fly
float3 row0 = tangentToWorld[0];
float3 row1 = tangentToWorld[1];
float3 row2 = tangentToWorld[2];
// these are the columns of the inverse matrix but scaled by the determinant
float3 col0 = cross(row1, row2);
float3 col1 = cross(row2, row0);
float3 col2 = cross(row0, row1);
float determinant = dot(row0, col0);
float sgn = determinant<0.0 ? (-1.0) : 1.0;
// inverse transposed but scaled by determinant
// Will remove transpose part by using matrix as the first arg in the mul() below
// this makes it the exact inverse of what TransformTangentToWorld() does.
real3x3 matTBN_I_T = real3x3(col0, col1, col2);
return SafeNormalize( sgn * mul(matTBN_I_T, dirWS) );
}
real3 TransformTangentToObject(real3 dirTS, real3x3 tangentToWorld)
{
// Note matrix is in row major convention with left multiplication as it is build on the fly
real3 normalWS = TransformTangentToWorld(dirTS, tangentToWorld);
return TransformWorldToObjectNormal(normalWS);
}
real3 TransformObjectToTangent(real3 dirOS, real3x3 tangentToWorld)
{
// Note matrix is in row major convention with left multiplication as it is build on the fly
// don't normalize, as normalWS will be normalized after TransformWorldToTangent
float3 normalWS = TransformObjectToWorldNormal(dirOS, false);
// transform from world to tangent
return TransformWorldToTangent(normalWS, tangentToWorld);
}
#if SHADER_API_MOBILE || SHADER_API_GLES || SHADER_API_GLES3
#pragma warning (enable : 3205) // conversion of larger type to smaller
#endif
#endif
ShaderVariablesFunctions合集
- Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.hlsl
- 主要目的是做了一系列的转换,可以用语义名称直接获取需要的数据。
- 比如:
VertexPositionInputs GetVertexPositionInputs(float3 positionOS)
{
VertexPositionInputs input;
input.positionWS = TransformObjectToWorld(positionOS);
input.positionVS = TransformWorldToView(input.positionWS);
input.positionCS = TransformWorldToHClip(input.positionWS);
float4 ndc = input.positionCS * 0.5f;
input.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
input.positionNDC.zw = input.positionCS.zw;
return input;
}
- GetVertexPositionInputs 这个函数内就已经准备好,positionWS positionVS和positionCS 这些数据。
- 其中 WS代表的是W = World,S = Space;V = View;C = Clip也就是裁剪。
代码如下:
#ifndef UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED
#define UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.deprecated.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Debug/DebuggingCommon.hlsl"
VertexPositionInputs GetVertexPositionInputs(float3 positionOS)
{
VertexPositionInputs input;
input.positionWS = TransformObjectToWorld(positionOS);
input.positionVS = TransformWorldToView(input.positionWS);
input.positionCS = TransformWorldToHClip(input.positionWS);
float4 ndc = input.positionCS * 0.5f;
input.positionNDC.xy = float2(ndc.x, ndc.y * _ProjectionParams.x) + ndc.w;
input.positionNDC.zw = input.positionCS.zw;
return input;
}
VertexNormalInputs GetVertexNormalInputs(float3 normalOS)
{
VertexNormalInputs tbn;
tbn.tangentWS = real3(1.0, 0.0, 0.0);
tbn.bitangentWS = real3(0.0, 1.0, 0.0);
tbn.normalWS = TransformObjectToWorldNormal(normalOS);
return tbn;
}
VertexNormalInputs GetVertexNormalInputs(float3 normalOS, float4 tangentOS)
{
VertexNormalInputs tbn;
// mikkts space compliant. only normalize when extracting normal at frag.
real sign = real(tangentOS.w) * GetOddNegativeScale();
tbn.normalWS = TransformObjectToWorldNormal(normalOS);
tbn.tangentWS = real3(TransformObjectToWorldDir(tangentOS.xyz));
tbn.bitangentWS = real3(cross(tbn.normalWS, float3(tbn.tangentWS))) * sign;
return tbn;
}
float4 GetScaledScreenParams()
{
return _ScaledScreenParams;
}
// Returns 'true' if the current view performs a perspective projection.
bool IsPerspectiveProjection()
{
return (unity_OrthoParams.w == 0);
}
float3 GetCameraPositionWS()
{
// Currently we do not support Camera Relative Rendering so
// we simply return the _WorldSpaceCameraPos until then
return _WorldSpaceCameraPos;
// We will replace the code above with this one once
// we start supporting Camera Relative Rendering
//#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
// return float3(0, 0, 0);
//#else
// return _WorldSpaceCameraPos;
//#endif
}
// Could be e.g. the position of a primary camera or a shadow-casting light.
float3 GetCurrentViewPosition()
{
// Currently we do not support Camera Relative Rendering so
// we simply return the _WorldSpaceCameraPos until then
return GetCameraPositionWS();
// We will replace the code above with this one once
// we start supporting Camera Relative Rendering
//#if defined(SHADERPASS) && (SHADERPASS != SHADERPASS_SHADOWS)
// return GetCameraPositionWS();
//#else
// // This is a generic solution.
// // However, for the primary camera, using '_WorldSpaceCameraPos' is better for cache locality,
// // and in case we enable camera-relative rendering, we can statically set the position is 0.
// return UNITY_MATRIX_I_V._14_24_34;
//#endif
}
// Returns the forward (central) direction of the current view in the world space.
float3 GetViewForwardDir()
{
float4x4 viewMat = GetWorldToViewMatrix();
return -viewMat[2].xyz;
}
// Computes the world space view direction (pointing towards the viewer).
float3 GetWorldSpaceViewDir(float3 positionWS)
{
if (IsPerspectiveProjection())
{
// Perspective
return GetCurrentViewPosition() - positionWS;
}
else
{
// Orthographic
return -GetViewForwardDir();
}
}
// Computes the object space view direction (pointing towards the viewer).
half3 GetObjectSpaceNormalizeViewDir(float3 positionOS)
{
if (IsPerspectiveProjection())
{
// Perspective
float3 V = TransformWorldToObject(GetCurrentViewPosition()) - positionOS;
return half3(normalize(V));
}
else
{
// Orthographic
return half3(TransformWorldToObjectNormal(-GetViewForwardDir()));
}
}
half3 GetWorldSpaceNormalizeViewDir(float3 positionWS)
{
if (IsPerspectiveProjection())
{
// Perspective
float3 V = GetCurrentViewPosition() - positionWS;
return half3(normalize(V));
}
else
{
// Orthographic
return half3(-GetViewForwardDir());
}
}
// UNITY_MATRIX_V defines a right-handed view space with the Z axis pointing towards the viewer.
// This function reverses the direction of the Z axis (so that it points forward),
// making the view space coordinate system left-handed.
void GetLeftHandedViewSpaceMatrices(out float4x4 viewMatrix, out float4x4 projMatrix)
{
viewMatrix = UNITY_MATRIX_V;
viewMatrix._31_32_33_34 = -viewMatrix._31_32_33_34;
projMatrix = UNITY_MATRIX_P;
projMatrix._13_23_33_43 = -projMatrix._13_23_33_43;
}
void AlphaDiscard(real alpha, real cutoff, real offset = real(0.0))
{
#ifdef _ALPHATEST_ON
if (IsAlphaDiscardEnabled())
clip(alpha - cutoff + offset);
#endif
}
half OutputAlpha(half outputAlpha, half surfaceType = half(0.0))
{
return surfaceType == 1 ? outputAlpha : half(1.0);
}
// A word on normalization of normals:
// For better quality normals should be normalized before and after
// interpolation.
// 1) In vertex, skinning or blend shapes might vary significantly the lenght of normal.
// 2) In fragment, because even outputting unit-length normals interpolation can make it non-unit.
// 3) In fragment when using normal map, because mikktspace sets up non orthonormal basis.
// However we will try to balance performance vs quality here as also let users configure that as
// shader quality tiers.
// Low Quality Tier: Don't normalize per-vertex.
// Medium Quality Tier: Always normalize per-vertex.
// High Quality Tier: Always normalize per-vertex.
//
// Always normalize per-pixel.
// Too many bug like lighting quality issues otherwise.
half3 NormalizeNormalPerVertex(half3 normalWS)
{
#if defined(SHADER_QUALITY_LOW) && defined(_NORMALMAP)
return normalWS;
#else
return normalize(normalWS);
#endif
}
float3 NormalizeNormalPerVertex(float3 normalWS)
{
#if defined(SHADER_QUALITY_LOW) && defined(_NORMALMAP)
return normalWS;
#else
return normalize(normalWS);
#endif
}
half3 NormalizeNormalPerPixel(half3 normalWS)
{
// With XYZ normal map encoding we sporadically sample normals with near-zero-length causing Inf/NaN
#if defined(UNITY_NO_DXT5nm) && defined(_NORMALMAP)
return SafeNormalize(normalWS);
#else
return normalize(normalWS);
#endif
}
float3 NormalizeNormalPerPixel(float3 normalWS)
{
#if defined(UNITY_NO_DXT5nm) && defined(_NORMALMAP)
return SafeNormalize(normalWS);
#else
return normalize(normalWS);
#endif
}
real ComputeFogFactorZ0ToFar(float z)
{
#if defined(FOG_LINEAR)
// factor = (end-z)/(end-start) = z * (-1/(end-start)) + (end/(end-start))
float fogFactor = saturate(z * unity_FogParams.z + unity_FogParams.w);
return real(fogFactor);
#elif defined(FOG_EXP) || defined(FOG_EXP2)
// factor = exp(-(density*z)^2)
// -density * z computed at vertex
return real(unity_FogParams.x * z);
#else
return real(0.0);
#endif
}
real ComputeFogFactor(float zPositionCS)
{
float clipZ_0Far = UNITY_Z_0_FAR_FROM_CLIPSPACE(zPositionCS);
return ComputeFogFactorZ0ToFar(clipZ_0Far);
}
half ComputeFogIntensity(half fogFactor)
{
half fogIntensity = half(0.0);
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
#if defined(FOG_EXP)
// factor = exp(-density*z)
// fogFactor = density*z compute at vertex
fogIntensity = saturate(exp2(-fogFactor));
#elif defined(FOG_EXP2)
// factor = exp(-(density*z)^2)
// fogFactor = density*z compute at vertex
fogIntensity = saturate(exp2(-fogFactor * fogFactor));
#elif defined(FOG_LINEAR)
fogIntensity = fogFactor;
#endif
#endif
return fogIntensity;
}
// Force enable fog fragment shader evaluation
#define _FOG_FRAGMENT 1
real InitializeInputDataFog(float4 positionWS, real vertFogFactor)
{
real fogFactor = 0.0;
#if defined(_FOG_FRAGMENT)
#if (defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2))
// Compiler eliminates unused math --> matrix.column_z * vec
float viewZ = -(mul(UNITY_MATRIX_V, positionWS).z);
// View Z is 0 at camera pos, remap 0 to near plane.
float nearToFarZ = max(viewZ - _ProjectionParams.y, 0);
fogFactor = ComputeFogFactorZ0ToFar(nearToFarZ);
#endif
#else
fogFactor = vertFogFactor;
#endif
return fogFactor;
}
float ComputeFogIntensity(float fogFactor)
{
float fogIntensity = 0.0;
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
#if defined(FOG_EXP)
// factor = exp(-density*z)
// fogFactor = density*z compute at vertex
fogIntensity = saturate(exp2(-fogFactor));
#elif defined(FOG_EXP2)
// factor = exp(-(density*z)^2)
// fogFactor = density*z compute at vertex
fogIntensity = saturate(exp2(-fogFactor * fogFactor));
#elif defined(FOG_LINEAR)
fogIntensity = fogFactor;
#endif
#endif
return fogIntensity;
}
half3 MixFogColor(half3 fragColor, half3 fogColor, half fogFactor)
{
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
half fogIntensity = ComputeFogIntensity(fogFactor);
fragColor = lerp(fogColor, fragColor, fogIntensity);
#endif
return fragColor;
}
float3 MixFogColor(float3 fragColor, float3 fogColor, float fogFactor)
{
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
if (IsFogEnabled())
{
float fogIntensity = ComputeFogIntensity(fogFactor);
fragColor = lerp(fogColor, fragColor, fogIntensity);
}
#endif
return fragColor;
}
half3 MixFog(half3 fragColor, half fogFactor)
{
return MixFogColor(fragColor, unity_FogColor.rgb, fogFactor);
}
float3 MixFog(float3 fragColor, float fogFactor)
{
return MixFogColor(fragColor, unity_FogColor.rgb, fogFactor);
}
// Linear depth buffer value between [0, 1] or [1, 0] to eye depth value between [near, far]
half LinearDepthToEyeDepth(half rawDepth)
{
#if UNITY_REVERSED_Z
return half(_ProjectionParams.z - (_ProjectionParams.z - _ProjectionParams.y) * rawDepth);
#else
return half(_ProjectionParams.y + (_ProjectionParams.z - _ProjectionParams.y) * rawDepth);
#endif
}
float LinearDepthToEyeDepth(float rawDepth)
{
#if UNITY_REVERSED_Z
return _ProjectionParams.z - (_ProjectionParams.z - _ProjectionParams.y) * rawDepth;
#else
return _ProjectionParams.y + (_ProjectionParams.z - _ProjectionParams.y) * rawDepth;
#endif
}
void TransformScreenUV(inout float2 uv, float screenHeight)
{
#if UNITY_UV_STARTS_AT_TOP
uv.y = screenHeight - (uv.y * _ScaleBiasRt.x + _ScaleBiasRt.y * screenHeight);
#endif
}
void TransformScreenUV(inout float2 uv)
{
#if UNITY_UV_STARTS_AT_TOP
TransformScreenUV(uv, GetScaledScreenParams().y);
#endif
}
void TransformNormalizedScreenUV(inout float2 uv)
{
#if UNITY_UV_STARTS_AT_TOP
TransformScreenUV(uv, 1.0);
#endif
}
float2 GetNormalizedScreenSpaceUV(float2 positionCS)
{
float2 normalizedScreenSpaceUV = positionCS.xy * rcp(GetScaledScreenParams().xy);
TransformNormalizedScreenUV(normalizedScreenSpaceUV);
return normalizedScreenSpaceUV;
}
float2 GetNormalizedScreenSpaceUV(float4 positionCS)
{
return GetNormalizedScreenSpaceUV(positionCS.xy);
}
#if defined(UNITY_SINGLE_PASS_STEREO)
float2 TransformStereoScreenSpaceTex(float2 uv, float w)
{
// TODO: RVS support can be added here, if Universal decides to support it
float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];
return uv.xy * scaleOffset.xy + scaleOffset.zw * w;
}
float2 UnityStereoTransformScreenSpaceTex(float2 uv)
{
return TransformStereoScreenSpaceTex(saturate(uv), 1.0);
}
#else
#define UnityStereoTransformScreenSpaceTex(uv) uv
#endif // defined(UNITY_SINGLE_PASS_STEREO)
#endif // UNITY_SHADER_VARIABLES_FUNCTIONS_INCLUDED
------------------------------------------------------------------------------------------------------------------
BuildIn管线下最简光照shader框架
Shader "NewShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_fwdbase
// #pragma multi_compile DIRECTIONAL SHADOWS_SCREEN
#include "UnityCG.cginc"
#include "AutoLight.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
float4 worldPos : TEXCOORD1;
UNITY_SHADOW_COORDS(2)
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
o.worldPos = mul(unity_ObjectToWorld,v.vertex);
TRANSFER_SHADOW(o)//阴影
return o;
}
fixed4 frag (v2f i) : SV_Target
{
UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos)
fixed4 col = tex2D(_MainTex, i.uv) * atten;
return col;
}
ENDCG
}
// Pass to render object as a shadow caster
Pass
{
//Name "ShadowCaster"
Tags { "LightMode" = "ShadowCaster" }
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders
#include "UnityCG.cginc"
struct appdata
{
float4 vertex:POSITION;
half3 normal:NORMAL;
UNITY_VERTEX_INPUT_INSTANCE_ID
};
struct v2f
{
V2F_SHADOW_CASTER;
UNITY_VERTEX_OUTPUT_STEREO
};
v2f vert( appdata_base v )
{
v2f o;
UNITY_SETUP_INSTANCE_ID(v);
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag( v2f i ) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
}
URP管线下最简光照shader框架
Shader "NewShader"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
...
Pass
{
Tags { "LightMode" = "UniversalForward" }
...
//支持多个平行光,只支持一个平行光的阴影,主光源阴影,屏幕空间阴影,级联阴影
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
//软阴影
#pragma multi_compile_fragment _ _SHADOWS_SOFT
//支持多光源和多光源阴影的宏
//#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
//#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
//反射、环境遮蔽和烘焙相关宏定义
//#pragma multi_compile_fragment _ _REFLECTION_PROBE_BLENDING
//#pragma multi_compile_fragment _ _REFLECTION_PROBE_BOX_PROJECTION
//#pragma multi_compile_fragment _ _SCREEN_SPACE_OCCLUSION
//#pragma multi_compile_fragment _ _DBUFFER_MRT1 _DBUFFER_MRT2 _DBUFFER_MRT3
//#pragma multi_compile_fragment _ _LIGHT_LAYERS
//#pragma multi_compile_fragment _ _LIGHT_COOKIES
//#pragma multi_compile _ _CLUSTERED_RENDERING
...
#pragma vertex LitPassVertex
#pragma fragment LitPassFragment
//HLSL包含文件
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
...
//HLSLPROGRAM
HLSLPROGRAM
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
SHADOW_COORDS(2)//阴影
float4 vertex : SV_POSITION;
};
...
TEXTURE2D(_MainTex ); SAMPLER(sampler_MainTex );
CBUFFER_START(UnityPerMaterial)//用“CBUFFER_START”包围起来,主要是做性能优化。
float4 _MainTex _ST;
CBUFFER_END
...
Varyings LitPassVertex(Attributes input)
{
Varyings output = (Varyings)0;
output.vertex = TransformObjectToHClip(input.positionOS);
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
UNITY_TRANSFER_FOG(input,input.positionOS);
TRANSFER_SHADOW(input)//阴影
return o;
}
half4 LitPassFragment(Varyings input) : SV_Target
{
UNITY_SETUP_INSTANCE_ID(input);
Light mainLight = GetMainLight(input.shadowCoord,input.positionWS,float4(1.0,1.0,1.0,1.0));
float3 lightDir = mainLight.direction;
half shadow = mainLight.shadowAttenuation;
//视线方向
half3 view_dir = normalize(_WorldSpaceCameraPos.xyz - i.pos_world);
//灯光方向
half3 light_dir = normalize(_WorldSpaceLightPos0.xyz);
//主光源颜色信息
half3 mainlight = _LightColor0.xyz;
//多光源
#ifdef _ADDITIONAL_LIGHTS
uint pixelLightCount = GetAdditionalLightsCount();
for(uint lightIndex = 0; lightIndex < pixelLightCount; ++lightIndex)
{
Light light = GetAdditionalLight(lightIndex,input.positionWS,float4(1.0,1.0,1.0,1.0));
half NdotL_add = dot(normalDir, light.direction);
half half_lambert_add = (NdotL_add + 1.0) * 0.5;
float atten_add = lerp(1 , light.shadowAttenuation * light.distanceAttenuation , input.vertexColor.g);
half labmbert_term_add = half_lambert_add * ao * atten_add + diffuse_control;
toon_diffuse += saturate((labmbert_term_add * light.color - _ToonThesHold) * _ToonHardness);
}
#endif
//半角向量
half3 half_dir = normalize(light_dir + view_dir);
//NdotH
half NdotH = dot(normal_dir, half_dir);
// sample the texture
float4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv);
// apply fog
UNITY_APPLY_FOG(input.fogCoord, col);
return col;
}
ENDHLSL
}
}
FallBack "Hidden/Universal Render Pipeline/FallbackError"
}
URP管线下最简GUI 不透明Opaque shader框架
Shader "xukaibo/URP/BaseShader_Opaque"
{
Properties
{
[Enum(UnityEngine.Rendering.CompareFunction)] _CustomZTest ("最上层=>Disable/Always||默认=>LessEqual", Int) = 4
[MainTexture] _MainTex("MainTex", 2D) = "white" {}
[HDR]_BaseColor("Color", Color) = (1, 1, 1, 1)
_Contrast("对比度", Range(0,2)) = 0.5
}
SubShader
{
Tags { "RenderType"="Opaque" }
ZTest [_CustomZTest]
Pass
{
HLSLPROGRAM
#pragma vertex LitPassVertex
#pragma fragment LitPassFragment
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
CBUFFER_START(UnityPerMaterial)
half4 _MainTex_ST,_BaseColor;
half _Contrast;
half _UVBase;
CBUFFER_END
Varyings LitPassVertex(Attributes input)
{
Varyings output = (Varyings)0;
output.vertex = TransformObjectToHClip(input.positionOS.xyz);
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
return output;
}
half4 LitPassFragment(Varyings input) : SV_Target
{
float4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv) * _BaseColor;
col.a = col.a > 0.5 ? col.a : 0;
col.rgb = col.rgb * (1 + _Contrast);
return col;
}
ENDHLSL
}
}
FallBack "Hidden/Universal Render Pipeline/FallbackError"
}
URP管线下最简GUI 透明Transparent shader框架
Shader "xukaibo/URP/BaseShader_Transparent"
{
Properties
{
[Enum(UnityEngine.Rendering.CompareFunction)] _CustomZTest ("最上层=>Disable/Always||默认=>LessEqual", Int) = 4
[HDR]_BaseColor("Color", Color) = (1, 1, 1, 1)
_MainTex ("Texture", 2D) = "white" {}
_Alpha("背景透明度", Range(0,1)) = 0.5
_ColorInt("强度", Range(0,1)) = 0.5
[HideInInspector]_DetailTex ("Detail (RGB)", 2D) = "white" {}
[HideInInspector]_Strength ("Detail Strength", Range(0.0, 1.0)) = 0.2
[HideInInspector]_StencilComp ("Stencil Comparison", Float) = 8
[HideInInspector]_Stencil ("Stencil ID", Float) = 0
[HideInInspector]_StencilOp ("Stencil Operation", Float) = 0
[HideInInspector]_StencilWriteMask ("Stencil Write Mask", Float) = 255
[HideInInspector]_StencilReadMask ("Stencil Read Mask", Float) = 255
[HideInInspector]_ColorMask ("Color Mask", Float) = 15
[HideInInspector]_ZWrite ("ZWrite", Int) = 0.0 // On
// [Toggle(UNITY_UI_ALPHACLIP)] _UseUIAlphaClip ("Use Alpha Clip", Float) = 0
}
SubShader
{
LOD 100
Tags
{
"Queue"="Transparent"
"IgnoreProjector"="True"
"RenderType"="Transparent"
"PreviewType"="Plane"
"CanUseSpriteAtlas"="True"
}
Stencil
{
Ref [_Stencil]
Comp [_StencilComp]
Pass [_StencilOp]
ReadMask [_StencilReadMask]
WriteMask [_StencilWriteMask]
}
Cull Off
Lighting Off
ZWrite Off
ZTest [_CustomZTest]
Blend SrcAlpha OneMinusSrcAlpha
ColorMask [_ColorMask]
Pass
{
HLSLPROGRAM
#pragma vertex LitPassVertex
#pragma fragment LitPassFragment
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Attributes
{
float4 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
CBUFFER_START(UnityPerMaterial)
half4 _MainTex_ST,_BaseColor;
float _Alpha,_ColorInt;
CBUFFER_END
Varyings LitPassVertex(Attributes input)
{
Varyings output = (Varyings)0;
output.vertex = TransformObjectToHClip(input.positionOS.xyz);
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
return output;
}
half4 LitPassFragment(Varyings input) : SV_Target
{
float4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uv) * _BaseColor;
// #ifdef UNITY_UI_ALPHACLIP
// clip (col.a - 0.001);
// #endif
col.rgb *= _ColorInt;
col.a += _Alpha;
return col;
}
ENDHLSL
}
}
FallBack "Hidden/Universal Render Pipeline/FallbackError"
}
HLSL阴影部分的Pass
在UniversalForward Pass之后新增两个ShadowCaster和DepthOnly Pass。
//阴影pass
Pass
{
Name "ShadowCaster"
Tags{"LightMode" = "ShadowCaster"}
ZWrite On
ZTest LEqual
ColorMask 0
Cull[_Cull]
HLSLPROGRAM
#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma multi_compile _ DOTS_INSTANCING_ON
// -------------------------------------
// Universal Pipeline keywords
// This is used during shadow map generation to differentiate between directional and punctual light shadows, as they use different formulas to apply Normal Bias
#pragma multi_compile_vertex _ _CASTING_PUNCTUAL_LIGHT_SHADOW
#pragma vertex ShadowPassVertex
#pragma fragment ShadowPassFragment
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/ShadowCasterPass.hlsl"
ENDHLSL
}
//深度pass,用在屏幕空间阴影和环境遮蔽
Pass
{
Name "DepthOnly"
Tags{"LightMode" = "DepthOnly"}
ZWrite On
ColorMask 0
Cull[_Cull]
HLSLPROGRAM
#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5
#pragma vertex DepthOnlyVertex
#pragma fragment DepthOnlyFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma multi_compile _ DOTS_INSTANCING_ON
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/DepthOnlyPass.hlsl"
ENDHLSL
}
// This pass is used when drawing to a _CameraNormalsTexture texture
Pass
{
Name "DepthNormals"
Tags{"LightMode" = "DepthNormals"}
ZWrite On
Cull[_Cull]
HLSLPROGRAM
#pragma exclude_renderers gles gles3 glcore
#pragma target 4.5
#pragma vertex DepthNormalsVertex
#pragma fragment DepthNormalsFragment
// -------------------------------------
// Material Keywords
#pragma shader_feature_local _NORMALMAP
#pragma shader_feature_local _PARALLAXMAP
#pragma shader_feature_local _ _DETAIL_MULX2 _DETAIL_SCALED
#pragma shader_feature_local_fragment _ALPHATEST_ON
#pragma shader_feature_local_fragment _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
//--------------------------------------
// GPU Instancing
#pragma multi_compile_instancing
#pragma multi_compile _ DOTS_INSTANCING_ON
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitInput.hlsl"
#include "Packages/com.unity.render-pipelines.universal/Shaders/LitDepthNormalsPass.hlsl"
ENDHLSL
}
HDRP管线下最简Unlit shader框架
Shader "Unlit/12"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color("Color", Color) = (1, 1, 1, 1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
HLSLPROGRAM
#pragma vertex LitPassVertex
#pragma fragment LitPassFragment
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/ShaderLibrary/ShaderVariables.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/FragInputs.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl"
TEXTURE2D(_MainTex);
SAMPLER(sampler_MainTex);
CBUFFER_START(UnityPerMaterial)
float4 _MainTex_ST;
CBUFFER_END
struct Attributes
{
float3 positionOS : POSITION;
float2 uv : TEXCOORD0;
};
struct Varyings
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
Varyings LitPassVertex(Attributes input)
{
Varyings output = (Varyings)0;
output.vertex = TransformObjectToHClip(input.positionOS);
output.uv = TRANSFORM_TEX(input.uv, _MainTex);
return output;
}
half4 LitPassFragment(Varyings input) : SV_Target
{
half4 col = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex , input.uv);
return col;
}
ENDHLSL
}
}
}