我正在开发一个CG着色器,它将在低端硬件上进行有限数量的顶点动画(或“变形”)。我将动画帧打包成额外的texcoords(有限的分辨率可以接受我需要做的事)并在运行时根据主机程序提供的控制值在它们之间进行插值 - 实际上是一个从姿势1到N的滑块(N可能是6,看起来像我必须玩的texcoords数量。)
我知道如何在传统的编程环境中实现catmull插值,但我不确定采用着色器的正确方法。这是一些具体的问题:
1)我已经看到以代数和矩阵形式表示的catmull插值(例子here。在OGL-ES2硬件上,一种形式可能比另一种更有效吗?
2)我已经得到了一系列浮点数的代数形式;它工作正常。但是我似乎无法声明一个float4s数组来保存数据。如果我在此示例中更改统一浮点键[8] 行:
sampler2D _MainTex;
float _KeyTime;
uniform float Key[8];
struct v2f {
float4 pos : SV_POSITION;
float4 color : COLOR0;
};
float4 catmull (float p0, float p1, float p2, float p3, fixed t)
{
fixed t2 = pow(t, 2);
fixed t3 = pow(t, 3);
return .5 * ((2.0 * p1) + (-1 * p0 + p2) * t +
(2 * p0 - 5 * p1 + 4 * p2 - p3) * t2 +
(-1 * p0 + 3 * p1 - 3 * p2 + p3) * t3)
;
}
v2f vert (appdata_base v)
{
v2f o;
o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
Key[0] = float(1);
Key[1] = float(1);
Key[2] = float(.8);
Key[3] = float(.6);
Key[4] = float(.4);
Key[5] = float(.2);
Key[6] = float(.1);
Key[7] = float(.1);
int prior = trunc(_KeyTime);
o.color = catmull(Key[prior],
Key[prior + 1],
Key[prior + 2],
Key[prior + 3],
frac(_KeyTime));
return o;
到 uniform float4 [8] Key; 着色器仍在编译,但是我从团结中得到一个错误,说“没有子载体可以在这个硬件上运行”,我认为这是一个误导性的反映别的东西(我有很多其他着色器有多通道等等,工作正常)。如果我在vert程序中声明数组而不是统一,我得到一个错误,即非静态索引器的数组需要是统一的。那么,有没有办法摆脱这种混乱?
PS我匆忙改变了catmull函数来处理浮点数只是为了检验这个假设是关于声明导致问题的float4s数组的事情。
答案 0 :(得分:0)
我注意到,当输入为float时,你声明你的catrom输出float4。为什么呢?
尝试实际执行您所说的计划:将键值声明为输入顶点数据的一部分。在此上下文中将其声明为“统一”似乎很尴尬,可能会混淆编译器,只需将其作为输入结构的一部分,并且不要尝试覆盖着色器中的值。以这种方式在texcoords上声明额外值对于动画蒙皮是非常常见的。
答案 1 :(得分:0)
对于未来的读者:
分辨率显然不希望编译包含动态索引的着色器 - 这不适用于所有平台,因此编译器显然过于热心决定在目标的情况下不允许它针对(IOS 6+ / DX9)。所以这是'设计'而不是一个错误,虽然这不会让它变得不那么烦人。
我能够提出的最好的解决方法是使用 Float4x4s ,就好像它们是16个单元阵列一样。除了要选择的正确行和列之外,您可以使用全部为零的float4向量来获取正确的值。将列向量乘以矩阵(就像将其转换一样),然后将其与行向量相加。这给出了[row,column]的项目。这是一个痛苦的对接解决方法,但它确实有效。显然,同样的技巧可以使用sans dot product步骤来仅将行提取为float4s。