顶点着色器中的变换只适用于后期
我目前正在学习OpenGL和GLSL的过程来编写一个简单的软件来加载模型,将它们显示在屏幕上,将它们转换等等。
作为第一阶段,我编写了一个不使用OpenGL的pure-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;
}
为了从模型空间获取剪辑空间,我在C ++中做了以下操作:
vec4 vertexInClipSpace = projectionMat4 * viewMat4 * modelMat4 * vertexInModelSpace;
现在,试图在GLSL Shader(版本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;
}
虽然数学上OK,因为v2 = P * V * M * v1
与transpose(v2) = transpose(v1) * transpose(M) * transpose(V) * transpose(P)
,我甚至没有看到他们在顶点着色器中增加一个顶点的引用。
总结一下,这里有一些具体的问题:
相关问题链接:
链接1
链接2
编辑:
通过改变调用中的“转置”标志来解决问题有点“解决”:
glUniformMatrix4fv(
m_modelTransformID,
1,
GL_TRUE,
&m[0][0]
);
现在着色器中的乘法是一个预乘:
gl_Position = MVP * vec4(vertex,1.0f);
哪一种让我感到困惑,因为数学对于行主矩阵转置的列主矩阵没有意义。
有人能解释一下吗?
引用OpenGL faq:
出于编程目的,OpenGL矩阵是16值阵列,其基本向量在内存中连续布局。 翻译组件占据了16元素矩阵的第13,14,15个元素,其索引编号从1到16,如OpenGL 2.1规范的2.11.2节所述。
列主要与行主要是纯粹的符号约定。 请注意,乘以列主矩阵产生的结果与用行主矩阵预乘相同。 OpenGL规范和OpenGL参考手册都使用列主要标志。 只要明确说明,您可以使用任何符号。
关于一些约定:
行vs列矢量
仅当左矩阵的列数等于右矩阵的行数时,才有可能乘以2矩阵。
MatL[r1,c] x MatR[c,r2]
所以,如果你在一张纸上工作,考虑到一个向量是一维矩阵,如果你想为4x4 矩阵乘以一个4vec,那么向量应该是:
在计算机中,您可以将4个连续值视为列或行(没有维度的概念),因此您可以对同一个矩阵进行后乘或前乘。 隐含地说,你坚持两个约定之一。
行主要vs列主要布局
计算机内存是一个连续的位置空间。 多维度的概念不存在,这是一个纯粹的约定。 所有矩阵元素都被连续存储到一维存储器中。
如果你决定存储一个二维实体,你有两个约定:
顺便提一下,移动存储在主行中的矩阵的元素,相当于按列主要顺序存储其元素。 这意味着,交换矢量和矩阵之间的乘法次序相当于将相同的矢量与转置的矩阵相乘。
打开GL
如上所述,它没有正式规定任何公约。 我建议你看看OpenGL的惯例,就好像翻译存储在最后一列,矩阵布局是专栏一样。
为什么这是有效的? 在glsl中进行繁殖是否合法?
这是合法的。 只要您在代码中保持一致,传统/乘法顺序就可以。
我如何传递我的C ++矩阵,以便它们在着色器内正常工作?
如果您在C ++和着色器中使用2种不同的约定,则可以调换矩阵并保持相同的乘法顺序,也不要转置矩阵并颠倒乘法顺序。
如果您有任何空白,请参阅了解4x4均匀变换矩阵。
如果您在列专业(OpenGL矩阵)和行专业(DX和您的矩阵)矩阵顺序之间切换,那么它与转置相同,所以您是对的。 你错过的是:
对于正交和正交正交均匀变换矩阵,如果您转置矩阵,则与将其倒置相同
这是你的问题的答案,我认为。
transpose(M) = inverse(M)
另一个问题是,如果可以将一个只是约定的问题的顶点进行放大并且它在GLSL中不被禁止。 GLSL的重点在于你几乎可以做任何事情。
链接地址: http://www.djcxy.com/p/91941.html