GLSL - 铸造问题和奇怪的错误

时间:2010-08-02 15:04:43

标签: opengl casting glsl

我在这里得到关于我的GLSL代码的奇怪行为的帮助,当我将一个浮点数转换为int并且我从未见过这样的错误,因为我开始使用GLSL

实际上我正在尝试使用GLSL在CPU上实现网状皮肤

我使用的是ATI Radeon HD 4850(Gainward),我在Windows XP上使用OpenGL 2.1

所以在CPU方面我收集了骨骼索引和权重,然后我将它们抛向带有顶点属性的着色器 然后我用权重乘以骨骼矩阵并使用结果来计算法线和gl_Position

非常平常,直到那里

当我必须从Bones索引中检索Bones时出现问题

我使用一个带有4块骨头的简单圆柱网;我通过统一变量从Cpu发送骨骼,似乎问题不是来自这些骨骼矩阵,我在着色器中硬编码它们并且bug仍然存在 顺便说一句,当我与maya渲染相比时,形状是正确的

此外,每个顶点的骨骼索引仍然相同:0,1,2,3;它们通过VBO发送GL_UNSIGNED_INT类型;但在着色器中,uvec4似乎不起作用(既不是ivec4),所以我必须使用float vec4并使用int()

进行强制转换

所以这是我的顶点着色器代码:

uniform mat4 ModelViewMatrix;
uniform mat4 ProjectionMatrix;
uniform mat3 NormalMatrix;

uniform mat4 bones[4];

varying vec3 normal;

attribute vec3 v_pos;
attribute vec3 v_normal;

//the 4 first bones indices of the vertex;
attribute vec4 v_boneIndices0;
//the 4 first bones weights of the vertex
attribute vec4 v_boneWeights0;

void main()
{   

/* To compare with bones sent via uniform, i hardcoded the bones matrices in this array; doesn't seem to make a difference

        mat4 mattab[4];

        mattab[0] = mat4(1.0f, 0.0f, 0.0f, 0.0f,
                         0.0f, 1.0f, 0.0f, 0.0f,
                         0.0f, 0.0f, 1.0f, 0.0f,
                         0.0f, 0.0f, 0.0f, 1.0f);

        mattab[1] = mat4(1.0f, 0.0f, 0.0f, 0.0f,
                         0.0f, 0.816489f, 0.57736f, 0.0f,
                         0.0f, -0.57736f, 0.816489f, 0.0f,
                         0.0f, -0.341108f, 1.07319f, 1.0f);

        mattab[2] = mat4(0.999949f, -0.00863831f, 0.00528692f, 0.0f,
                         -0.00400147f, 0.142574f, 0.989776f, 0.0f, 
                         -0.00930377f, -0.989746f, 0.142532f, 0.0f, 
                         0.00201152f, -0.00111439f, 0.865123f, 1.0f); 

        mattab[3] = mat4(0.799844f, -0.0233416f, -0.599754f, 0.0f,
                         0.448905f, 0.686556f, 0.571949f, 0.0f,
                         0.398414f, -0.726702f, 0.559616f, 0.0f, 
                         -1.23581f, -1.4976f, 2.0412f, 1.0f );

*/

        //the average matrix of weighted bones
        mat4 mat = mat4(0.0f);

        for ( int i = 0; i < 4; i++){

               //normally, the both lines below are equivalent 
               //because v_boneIndices0 is always 0,1,3,4

               mat += v_boneWeights0[i] * bones[int(v_boneIndices0[i])];
               //mat += v_boneWeights0[i] * bones[i];  

                }

        //Here, I multiply the average matrix with v_normal and v_pos

        normal = NormalMatrix * (mat3(mat[0].xyz,mat[1].xyz,mat[2].xyz) * v_normal);

        gl_Position = ProjectionMatrix*ModelViewMatrix*(mat*vec4(v_pos, 1.0f));

}

当我查看FPS费率时会出现错误;没有蒙皮,我得到2000 FPS

当我使用

行时

mat += v_boneWeights0[i] * bones[i];

我得到了正确的形状与一些人工制品,FPS保持在2000

但是当我使用

行时
mat += v_boneWeights0[i] * bones[int(v_boneIndices0[i])];

(与其他系列相似)形状完美但FPS坍塌至1500 FPS ......

我认为这条线本身会减慢循环;但是如果我离开这条线并从正常和gl_Position计算中移除垫子,则FPS率上升到2000

另一种奇怪的行为,如果我计算

vec4 test = ProjectionMatrix*ModelViewMatrix*(mat*vec4(v_pos, 1.0f));

在循环之后,并计算不带mat乘法的Normal gl_Position

normal = NormalMatrix * v_normal;
gl_Position = ProjectionMatrix*ModelViewMatrix* vec4(v_pos, 1.0f);

FPS率也上升到2000

只有当我结合

时才会出现错误
mat += v_boneWeights0[i] * bones[int(v_boneIndices0[i])];

and

normal = NormalMatrix * (mat3(mat[0].xyz,mat[1].xyz,mat[2].xyz) * v_normal);
gl_Position = ProjectionMatrix*ModelViewMatrix*(mat*vec4(v_pos, 1.0f));

我认为这是一个硬件错误,或者我做错了,我不知道 但我确定问题与cast int()有关 顺便说一句,为什么uvec4和ivec4不起作用?

有没有人遇到过Nvidia的这种行为?我在谷歌上找不到任何东西

我希望你能帮助我

谢谢:)

2 个答案:

答案 0 :(得分:3)

您的错误是您查看每秒帧数的性能,而不是每帧的时间(timedelta)。 2000 fps和1500 fps之间的差异是令人遗憾的。 2000 fps表示每帧0.5 ms。 1500 fps表示每帧0.6 ms。 fps与每帧时间之间的相关性是线性的。有效fps是1 / timedelta。你拥有的fps越多,fps就越灵敏,因为时间窗口太小了。假如你有10,000 fps,它在10,000 fps和5,000 fps之间波动。这将为您提供0.1 ms和0.2 ms之间的时间窗口。此时,任何操作都可能影响timedelta。

答案 1 :(得分:0)

ivec4和uvec4不是OpenGL 2.1中的GLSL的一部分,它是一个扩展(GL_EXT_gpu_shader4),因此您需要使用以下命令启用该扩展:

#extension GL_EXT_gpu_shader4 : enable

在着色器的开头,然后您将能够在着色器中使用实数整数。请注意,此扩展仅在DX 10和更新的卡(您的卡可以使用)中受支持。

扩展程序是Core OpenGL 3.0的一部分。