[ShaderGraph]Time字段重定义问题
[ShaderGraph]Time字段重定义问题
00 前置知识
在写ShaderGraph的Custom Function的时候, 经常会遇到redefinition of '_Time' at line 40的问题.
经过排查.
ShaderGraph在Preview的时候会调用PreviewTarget这个Target.
路径是Library/PackageCache/com.unity.shadergraph@12.1.10/Editor/Generation/Targets/PreviewTarget.cs
能在代码中查到include是这些:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
includes = new IncludeCollection
{
// Pre-graph
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/TextureStack.hlsl", IncludeLocation.Pregraph }, // TODO: put this on a conditional
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/NormalSurfaceGradient.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/Texture.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/UnityInstancing.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.shadergraph/ShaderGraphLibrary/ShaderVariables.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.shadergraph/ShaderGraphLibrary/ShaderVariablesFunctions.hlsl", IncludeLocation.Pregraph },
{ "Packages/com.unity.shadergraph/ShaderGraphLibrary/Functions.hlsl", IncludeLocation.Pregraph },
// Post-graph
{ "Packages/com.unity.shadergraph/ShaderGraphLibrary/PreviewVaryings.hlsl", IncludeLocation.Postgraph },
{ "Packages/com.unity.shadergraph/ShaderGraphLibrary/PreviewPass.hlsl", IncludeLocation.Postgraph },
}
其中这个文件Packages/com.unity.shadergraph/ShaderGraphLibrary/ShaderVariables.hlsl里面有如下代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
CBUFFER_START(UnityPerCamera)
// Time (t = time since current level load) values from Unity
float4 _Time; // (t/20, t, t*2, t*3)
float4 _LastTime; // Last frame time (t/20, t, t*2, t*3)
float4 _SinTime; // sin(t/8), sin(t/4), sin(t/2), sin(t)
float4 _CosTime; // cos(t/8), cos(t/4), cos(t/2), cos(t)
float4 unity_DeltaTime; // dt, 1/dt, smoothdt, 1/smoothdt
float4 _TimeParameters;
#if !defined(USING_STEREO_MATRICES)
float3 _WorldSpaceCameraPos;
#endif
// x = 1 or -1 (-1 if projection is flipped)
// y = near plane
// z = far plane
// w = 1/far plane
float4 _ProjectionParams;
// x = width
// y = height
// z = 1 + 1.0/width
// w = 1 + 1.0/height
float4 _ScreenParams;
// Values used to linearize the Z buffer (http://www.humus.name/temp/Linearize%20depth.txt)
// x = 1-far/near
// y = far/near
// z = x/far
// w = y/far
// or in case of a reversed depth buffer (UNITY_REVERSED_Z is 1)
// x = -1+far/near
// y = 1
// z = x/far
// w = 1/far
float4 _ZBufferParams;
// x = orthographic camera's width
// y = orthographic camera's height
// z = unused
// w = 1.0 if camera is ortho, 0.0 if perspective
float4 unity_OrthoParams;
CBUFFER_END
可以看到, 定义了_Time这个变量.
而非ShaderGraph的hlsl编写, 在Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl文件中, 有引用Packages/com.unity.render-pipelines.universal/ShaderLibrary/UnityInput.hlsl, 在该被引用的文件UnityInput.hlsl中, 有如下代码
1
2
3
4
5
6
// Time (t = time since current level load) values from Unity
float4 _Time; // (t/20, t, t*2, t*3)
float4 _SinTime; // sin(t/8), sin(t/4), sin(t/2), sin(t)
float4 _CosTime; // cos(t/8), cos(t/4), cos(t/2), cos(t)
float4 unity_DeltaTime; // dt, 1/dt, smoothdt, 1/smoothdt
float4 _TimeParameters; // t, sin(t), cos(t)
可以看到也声明了这个_Time.
这就是造成报错的原因.
01 解决方案
找出include了Input.hlsl的引用
比如:
当你使用了了
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/GlobalIllumination.hlsl"进入
GlobalIllumination.hlsl, 会发现1 2 3
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/EntityLighting.hlsl" #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/RealtimeLights.hlsl"
再进入
RealtimeLights.hlsl, 会发现1 2 3 4 5
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/AmbientOcclusion.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/LightCookie/LightCookie.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Clustering.hlsl"
这个
Input.hlsl就是造成冲突的原因了.
确定你要使用的代码在具体的hlsl中, 引用具体的hlsl
比如我要使用的代码其实不在GlobalIllumination.hlsl中, 而是在Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl中.
则, 注释掉GlobalIllumination.hlsl的引用, 先引用除了_Time之外的其他文件
1
2
// #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/GlobalIllumination.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl"
将Input.hlsl做为#ifndef SHADERGRAPH_PREVIEW条件引用
1
2
3
#ifndef SHADERGRAPH_PREVIEW
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
#endif
最后代码修改结果:
1
2
3
4
5
// #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/GlobalIllumination.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/ImageBasedLighting.hlsl"
#ifndef SHADERGRAPH_PREVIEW
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Input.hlsl"
#endif
就可以避免重定义字段的问题了.