如何在 ShaderLab 中缓存公共(对于所有像素)变量?
How to cache common (for all pixels) variables in ShaderLab?
假设我有以下着色器:
Shader "Sprites/X"
{
Properties
{
[HideInInspector] _MainTex("Sprite Texture", 2D) = "black" {}
}
SubShader
{
Pass
{
CGPROGRAM
// bla bla
fixed4 frag(v2f i) : SV_Target
{
float a = calculateA();
float b = calculateB();
.
.
.
float z = calculateZ();
// Here the values above mix with x-y position of the pixel
// and then return a color
}
ENDCG
}
}
}
在上面的代码中,我需要从相关函数 calculateA()
- calculateZ()
中计算变量 a
- z
的值(这只是一个泛化示例).假设这些函数很复杂,并且它们依赖于着色器在每个帧中发生变化的其他属性,而不是像素本身。我们知道每次为每个像素计算复杂的函数。
有没有办法"cache"这些值可以避免每次对每个像素都进行计算?在每一帧中,所有像素的值都相同。
目前我正在通过在 C# 脚本中设置值来解决问题:
gameObject.GetComponent<Renderer>().material.SetFloat("a", calculateA());
.
.
.
gameObject.GetComponent<Renderer>().material.SetFloat("z", calculateZ());
但我更喜欢将着色器和 C# 脚本代码分开。
好吧,这正是你要做的:)
这取决于您为什么要避免使用 C#
- 如果所述方法仅由常量计算,则编译器
会优化它。
- 如果该方法几乎没有可预测的结果
您可以将它们 pre-compute 放入在着色器本身中声明的数组中,或者从代码而不是每一帧设置一次。
- 如果有很多可预测的结果,您可以考虑烘焙它们
进入纹理,或者如果你可以使用现代 GPU,进入结构化
缓冲区。
假设我有以下着色器:
Shader "Sprites/X"
{
Properties
{
[HideInInspector] _MainTex("Sprite Texture", 2D) = "black" {}
}
SubShader
{
Pass
{
CGPROGRAM
// bla bla
fixed4 frag(v2f i) : SV_Target
{
float a = calculateA();
float b = calculateB();
.
.
.
float z = calculateZ();
// Here the values above mix with x-y position of the pixel
// and then return a color
}
ENDCG
}
}
}
在上面的代码中,我需要从相关函数 calculateA()
- calculateZ()
中计算变量 a
- z
的值(这只是一个泛化示例).假设这些函数很复杂,并且它们依赖于着色器在每个帧中发生变化的其他属性,而不是像素本身。我们知道每次为每个像素计算复杂的函数。
有没有办法"cache"这些值可以避免每次对每个像素都进行计算?在每一帧中,所有像素的值都相同。
目前我正在通过在 C# 脚本中设置值来解决问题:
gameObject.GetComponent<Renderer>().material.SetFloat("a", calculateA());
.
.
.
gameObject.GetComponent<Renderer>().material.SetFloat("z", calculateZ());
但我更喜欢将着色器和 C# 脚本代码分开。
好吧,这正是你要做的:)
这取决于您为什么要避免使用 C#
- 如果所述方法仅由常量计算,则编译器 会优化它。
- 如果该方法几乎没有可预测的结果 您可以将它们 pre-compute 放入在着色器本身中声明的数组中,或者从代码而不是每一帧设置一次。
- 如果有很多可预测的结果,您可以考虑烘焙它们 进入纹理,或者如果你可以使用现代 GPU,进入结构化 缓冲区。