当前位置: 首页 > 知识库问答 >
问题:

顶点着色器中的变换只适用于后乘

巫马嘉祯
2023-03-14

我目前正在学习OpenGL和GLSL编写一个简单的软件,加载模型,在屏幕上显示它们,转换它们等。

作为第一阶段,我编写了一个不使用OpenGL的纯C++程序。它工作得很好,并且它使用行为主的矩阵表示:

例如,mat[i][j]表示第i行和第j列。

class mat4
{
    vec4 _m[4]; // vec4 is a struct with 4 fields
    ...
}
mat4 operator*(const mat4& m) const
{
    mat4 a(0.0);

    for (int i = 0; i < 4; ++i)
    {
        for (int j = 0; j < 4; ++j)
        {
            for (int k = 0; k < 4; ++k)
            {
                a[i][j] += _m[i][k] * m[k][j];
            }
        }
    }

    return a;
}
vec4 vertexInClipSpace =  projectionMat4 * viewMat4 * modelMat4 * vertexInModelSpace;

现在,试图在GLSL着色器(版本1.5)中实现它会产生奇怪的结果。它工作,但只有当我后乘顶点,而不是预乘它,并另外转置每个矩阵。

uniform mat4 m;
uniform mat4 v;
uniform mat4 p;

void main()
{
    // works ok, but using post multiplication and transposed matrices :
    gl_Position =  vec4(vertex, 1.0f) * m * v * p;
}

虽然在数学上可以,因为v2=P*V*M*v1transpose(v2)=transpose(v1)*transpose(M)*transpose(V)*transpose(P)相同,但我显然没有得到什么,因为我甚至没有看到一个引用,它们在顶点着色器中张贴乘法顶点。

总结一下,以下是具体的问题:

  • 这为什么管用?在GLSL中发布multiply是否合法?
  • 如何传递C++矩阵以便它们在着色器中正常工作?

相关问题链接:

链接2

通过将调用中的“转置”标志修改为:

glUniformMatrix4fv(
        m_modelTransformID,
        1,
        GL_TRUE,
        &m[0][0]
        ); 

现在着色器中的乘法是预乘法:

谁能解释一下吗?

共有1个答案

卫志泽
2023-03-14

引用OpenGL常见问题:

出于编程的目的,OpenGL矩阵是16值数组,基向量在内存中连续布局。翻译组件占据16个元素矩阵的第13、14和15个元素,其中索引的编号从1到16,如OpenGL2.1规范第2.11.2节所述。

列大与行大纯粹是一种符号约定。请注意,与以列为主的矩阵相乘后产生的结果与与以行为主的矩阵相乘前产生的结果相同。OpenGL规范和OpenGL参考手册都使用以列为主的表示法。你可以使用任何符号,只要它被清楚地说明。

只有当左矩阵的列数等于右矩阵的行数时,乘2矩阵才是可能的。

MatL[r1,c] x MatR[c,r2]

所以,如果你在写一张纸,考虑到一个向量是一个1维矩阵,如果你想用4vec乘4x4matrix,那么这个向量应该是:

  • 后乘矩阵时的行向量
  • 如果将矩阵预相乘,则为colum向量

在计算机中,你可以把4个连续的值看作一列或一行(没有维数的概念),所以你可以对同一个矩阵的向量进行后乘或前乘。隐含地说,你是在遵守这两个惯例中的一个。

行主布局与列主布局

计算机内存是一个连续的位置空间。多维度的概念是不存在的,它是一个纯粹的约定。所有矩阵元素连续存储到一维存储器中。

    null

顺便说一句,转置以行为主存储的矩阵元素,相当于以列为主的顺序存储其元素。这意味着,在一个向量和一个矩阵之间交换乘法的阶数,相当于用同样的阶数乘同样的向量和转置的矩阵。

打开总帐

如上所述,它没有正式规定任何公约。我建议您查看OpenGL约定,就像翻译存储在最后一列,矩阵布局是列主要的一样。

 类似资料:
  • WebGL的着色器代码分为顶点着色器代码和片元着色器代码两部分,顶点着色器代码会在GPU的顶点着色器单元执行,片元着色器代码会在GPU的片元着色器单元执行,在WebGL渲染管线流程中,或者说GPU的渲染流程中,顶点着色器代码先执行处理顶点,得到一系列片元,然后再执行片元着色器代码处理片元。 main()函数 顶点着色器和片元着色器代码都有一个唯一的主函数main(),attribute、varyi

  • 我正在用OpenGL(PyOpenGL和Python)显示几何图形(文件格式:.stl)。几何数据具有形式,由三角形组合而成。 我保存到 VBO 数据;顶点、法线和颜色。由于法线仅每 3 个顶点(三角形)定义,并且我为每个顶点定义颜色矢量,因此 VBO 中的数据具有以下形式: 大写:;首先我保存所有顶点,然后我“附加”(使用)所有法线(法线数比顶点数和顶点颜色少3倍),然后我附加每个顶点的颜色向量

  • 顶点着色器用来操作ShaderEffect提供的顶点。正常情况下,ShaderEffect有4个顶点(左上top-left,右上top-right,左下bottom-left,右下bottom-right)。每个顶点使用vec4类型记录。为了实现顶点着色器的可视化,我们将编写一个吸收的效果。这个效果通常被用来让一个矩形窗口消失为一个点。 配置场景(Setting up the scene) 首先我

  • 在一个简单的hello world OpenGL程序中,它只是在窗口上绘制一个静态三角形,当我将三角形的3个顶点设置为红色、绿色和蓝色时,三角形将填充渐变。 但是当我使用这样的着色器时: 顶点着色器: 其中属性和来自顶点缓冲区,通过的调用传递。 片段着色器: 三角形仍然充满了梯度,问题来了: 如果顶点着色器是按顶点计算的,则应为的每个实例指定顶点的颜色。顶点颜色应为红色、绿色或蓝色,如顶点缓冲区中

  • 图的变换有什么算法或名称吗?可以把边变换成顶点,顶点变换成边?这样我们就可以得到一个新的图形或者类似的问题?我不确定这是否真的有意义,但我会很高兴,如果你能给我任何关于这样一个问题的提示。