【问题标题】:GLSL - Problem of casting and weird bugGLSL - 铸造问题和奇怪的错误
【发布时间】:2010-08-02 15:04:43
【问题描述】:

我来这里是为了获得有关我的 GLSL 代码的奇怪行为的帮助,当我将浮点数转换为 int 时,自从我启动 GLSL 以来我从未见过这样的错误

实际上我正在尝试使用 GLSL 在 CPU 上实现网格蒙皮

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

所以在 CPU 端,我收集骨骼索引和权重,然后将它们扔到带有顶点属性的着色器中 然后我将骨骼矩阵与权重相乘,并使用结果来计算 normal 和 gl_Position

到那里很平常

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

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

此外,每个顶点的骨骼索引仍然相同: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 计算中删除 mat,FPS 速率会上升到 2000

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

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

在循环之后,计算 Normal gl_Position 而不用 mat 乘法

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));

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

有人在 Nvidia 遇到过这种行为吗?我在 Google 上一无所获

希望你能帮到我

谢谢:)

【问题讨论】:

    标签: opengl casting glsl


    【解决方案1】:

    您的错误是您查看每秒帧数而不是每帧时间(timedelta)。 2000 fps 和 1500 fps 之间的差异非常小。 2000 fps 意味着每帧 0.5 毫秒。 1500 fps 意味着每帧 0.6 毫秒。 fps 和每帧时间之间的相关性不是线性的。有效 fps 为 1/timedelta。您拥有的 fps 越多,fps 就越敏感,因为时间窗口非常小。假设你有 10,000 fps,它在 10,000 fps 和 5,000 fps 之间波动。这将为您提供 0.1 毫秒到 0.2 毫秒之间的时间窗口。此时,任何操作都可能影响时间增量。

    【讨论】:

    • 很有趣,我知道 FPS 不是很准确,但实际上这不是主题你如何解释两行代码做同样事情的区别(如果你阅读了上面的代码?)演员阵容及其有效性如何?
    • 哦,那些不是演员表。他们是构造函数。
    • 好的解决了,我刚刚声明骨骼索引在 CPU 端是浮动的,现在没有减速,但是 ivec4 和 uvec4 仍然不起作用:(
    【解决方案2】:

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

    #extension GL_EXT_gpu_shader4 : enable
    

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

    该扩展是 Core OpenGL 3.0 的一部分。

    【讨论】:

    猜你喜欢
    • 2020-09-17
    • 1970-01-01
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-02
    • 2019-07-07
    • 2021-01-16
    相关资源
    最近更新 更多