原因很简单,因为 SRP 后的 shader 编译语法基于 HLSL 来分析,而 HLSL 中 scalar 标量类型是没有 fixed 的:MSDN Graphics DX12 Grahpics HLSL - Scalar Type
大致内容如下:
HLSL supports several scalar data types:
- bool - true or false.
- int - 32-bit signed integer.
- uint - 32-bit unsigned integer.
- dword - 32-bit unsigned integer.
- half - 16-bit floating point value. This data type is provided only for language compatibility. Direct3D 10 shader targets map all half data types to float data types. A half data type cannot be used on a uniform global variable (use the /Gec flag if this functionality is desired).
float - 32-bit floating point value. - double - 64-bit floating point value. You cannot use double precision values as inputs and outputs for a stream. To pass double precision values between shaders, declare each double as a pair of uint data types. Then, use the asuint function to pack each double into the pair of uints and the asdouble function to unpack the pair of uints back into the double.
Starting with Windows 8 HLSL also supports minimum precision scalar data types. Graphics drivers can implement minimum precision scalar data types by using any precision greater than or equal to their specified bit precision. We recommend not to rely on clamping or wrapping behavior that depends on specific underlying precision. For example, the graphics driver might execute arithmetic on a min16float value at full 32-bit precision.
- min16float - minimum 16-bit floating point value.
- min10float - minimum 10-bit floating point value.
- min16int - minimum 16-bit signed integer.
- min12int - minimum 12-bit signed integer.
- min16uint - minimum 16-bit unsigned integer.
For more information about scalar literals, see Grammar.
Differences between Direct3D 9 and Direct3D 10:
In Direct3D 10, the following types are modifiers to the float type.
- snorm float - IEEE 32-bit signed-normalized float in range -1 to 1 inclusive.
- unorm float - IEEE 32-bit unsigned-normalized float in range 0 to 1 inclusive.
For example, here is a 4-component signed-normalized float-variable declaration.
snorm float4 fourComponentIEEEFloat;
看到上文我以为 cg 的 fixed4 可以使用 min10float4 或是 min16float4 都替代,结果发现在 unity shaderlab 里没有反应,我也是使用:HLSLPROGRAM … ENDHLSL 标记为 HLSL 语法块,一样不行
代码块如下:
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
//#define col_t min10float4
#define col_t min16float4
//#define col_t half4
CBUFFER_START(UnityPerMaterial)
col_t _Color;
col_t _Color1;
float4 _MainTex_ST;
CBUFFER_END
sampler2D _MainTex;
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
col_t frag (v2f i) : SV_Target
{
col_t col = tex2D(_MainTex, i.uv);
return col * _Color * _Color1;
}
ENDHLSL
留意其中的:#define col_t min16float4
,然后在 FrameDebugger 查看,压根就没用是哪个 _Color, _Color1
:
然后,我们将 col_t 定义为 half4 就正常了:
//#define col_t min10float4
//#define col_t min16float4
#define col_t half4
完整测试 shader
// jave.lin 2021/10/14
Shader "Test/UnlitSTD"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_Color ("Color", Color) = (1, 1, 1, 1)
_Color1 ("Color1", Color) = (1, 1, 1, 1)
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float4 vertex : SV_POSITION;
float2 uv : TEXCOORD0;
};
//#define col_t min10float4
#define col_t min16float4
//#define col_t half4
CBUFFER_START(UnityPerMaterial)
col_t _Color;
col_t _Color1;
float4 _MainTex_ST;
CBUFFER_END
sampler2D _MainTex;
v2f vert (appdata v)
{
v2f o;
o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
col_t frag (v2f i) : SV_Target
{
col_t col = tex2D(_MainTex, i.uv);
return col * _Color * _Color1;
}
ENDHLSL
}
Pass
{
Tags{ "LightMode" = "ShadowCaster" }
HLSLPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
float4 vert(float4 vertex : POSITION) : SV_POSITION
{
return mul(UNITY_MATRIX_MVP, vertex);
}
real4 frag() : SV_Target
{
return 0;
}
ENDHLSL
}
//UsePass "Universal Render Pipeline/Lit/ShadowCaster"
}
}