如何在单位CG中实现catmull插值

时间:2013-09-11 07:28:49

标签: opengl unity3d opengl-es-2.0 cg

我正在开发一个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数组的事情。

2 个答案:

答案 0 :(得分:0)

我注意到,当输入为float时,你声明你的catrom输出float4。为什么呢?

尝试实际执行您所说的计划:将键值声明为输入顶点数据的一部分。在此上下文中将其声明为“统一”似乎很尴尬,可能会混淆编译器,只需将其作为输入结构的一部分,并且不要尝试覆盖着色器中的值。以这种方式在texcoords上声明额外值对于动画蒙皮是非常常见的。

答案 1 :(得分:0)

对于未来的读者:

分辨率显然不希望编译包含动态索引的着色器 - 这不适用于所有平台,因此编译器显然过于热心决定在目标的情况下不允许它针对(IOS 6+ / DX9)。所以这是'设计'而不是一个错误,虽然这不会让它变得不那么烦人。

我能够提出的最好的解决方法是使用 Float4x4s ,就好像它们是16个单元阵列一样。除了要选择的正确行和列之外,您可以使用全部为零的float4向量来获取正确的值。将列向量乘以矩阵(就像将其转换一样),然后将其与行向量相加。这给出了[row,column]的项目。这是一个痛苦的对接解决方法,但它确实有效。显然,同样的技巧可以使用sans dot product步骤来仅将行提取为float4s。