为GLSL准备模型、视图和投影矩阵

5
我正在使用vecmath库来帮助矩阵数学,在将OpenGL程序转换为更好地利用glsl时使用。

写完问题后,我有三个小问题:

  • 模型矩阵从哪里获取它的值?
  • 我需要在display()中重置所有模型、视图和投影矩阵吗?即每一帧
  • 在绘制每个对象后,我需要重置模式、视图和投影矩阵吗?

这是我在GLEventListenerreshape函数中计算我的projectionview矩阵的方法..

Matrix4f mProjectionMatrix = createPerspectiveProjection(
    60.0f, width / height, 0.1f, 100.0f);
Matrix4f mViewMatrix = new Matrix4f();
mViewMatrix.setIdentity();

辅助函数...

private Matrix4f createPerspectiveProjection(float fov, float aspect, float zNear, float zFar){

    Matrix4f mat = new Matrix4f();

    float yScale = (float) (1 / (Math.tan(Math.toRadians(fov / 2))));
    float xScale = yScale / aspect;
    float frustrumLength = zFar - zNear;

    mat.m00 = xScale;
    mat.m11 = yScale;
    mat.m22 = -((zFar + zNear) / frustrumLength);
    mat.m23 = -1;
    mat.m32  = -((2 * zFar * zNear) / frustrumLength);
    mat.m33 = 0;

    return mat;
}

GLEventListenerdisplay()方法中,我对下一步操作不确定。

从概念上讲,我脑海中有以下步骤,请问这些是我需要执行的正确步骤吗?..

public void display(GLAutoDrawable gLDrawable){

    // reset view matrix, needed?

    // Calculate the model view projection matrix .. where does model matrix get it's values from?

    // translate to Square1's position?
    // rotate to Square1's angle?
    // draw Square1 .. passing MVP matrix

    // translate to Square2's position?
    // rotate to Square2's angle?
    // draw Square2 .. passing MVP matrix
}

这是我的顶点着色器...

uniform mat4 uMVPMatrix;
attribute vec4 vPosition;
void main() {
    gl_Position = uMVPMatrix * vPosition;
}

[SO]推荐每个线程只提出一个问题。虽然您的子问题可能更或少相关,但考虑将它们分成单独的问题线程仍然是一个好主意。这将提高您获得每个问题的良好答案的机会,并且也符合[SO]的建议。 - Eugene Podskal
1个回答

9

在我的OpenGL应用程序中,我保留了三个矩阵。它们是模型视图投影矩阵。所有这些矩阵都使用uniforms发送到着色器,并且着色器会处理它们。

gl_Position = mProj * mView * mModel * vec4(position, 1.0);

也就是说,位置默认在本地对象空间中。将其与模型矩阵相乘应用于该模型的平移、旋转和缩放,转换后的顶点现在位于世界空间中。
现在,顶点被视图矩阵乘以,它应用了相机的变换,如相机位置和方向。现在,顶点将位于眼睛空间中。
最后,顶点将与投影矩阵相乘,应用透视或正交的效果,这取决于我选择使用什么。最终,在变换之后,顶点将处于规范化设备坐标中(从-1+1),并由OpenGL渲染。

模型矩阵的值从哪里获取?

模型矩阵默认为单位矩阵。每当您只想转换实体而不是整个世界时,您将把变换矩阵与模型矩阵相乘,并将结果设置为新的模型矩阵。这使您可以为场景中每个模型实例保留单独的属性。

我需要在display()中重置所有模型、视图和投影矩阵吗?即每一帧?

不需要。您可以创建矩阵,但是每当客户端即程序中的矩阵值更改时,您必须更新着色器程序中的uniform。

绘制每个对象后,我是否需要重置模式、视图和投影矩阵?

通常不需要。通常您会保留一个投影矩阵和一个视图矩阵,但对于场景中的每个对象,会有多个模型矩阵。投影矩阵通常在应用程序的整个过程中都不会更改,因此无需重新更新它。视图矩阵与相机一起使用,因此通常也是整个场景中的一个。但是,每个对象的模型矩阵将不同,因此您必须在每个帧中更新它。

您从哪里获取模型矩阵值?即它们是由什么生成的?

有某些公式可以创建这些矩阵,例如您上面的辅助方法,它基于相机镜头的视野和纵横比生成透视投影矩阵。很难在此处解释所有这些公式,因此您可以查看我的Transforms类的源代码,其中包含此类函数。

在我的GitHub代码库中查看Transforms类的源代码。它并没有完全记录,但我认为你可以使用它们。

希望这可以帮到你。


感谢您的输入@Sri,您的“Model”矩阵值是从哪里获取的?即它们是由什么生成的? - bobbyrne01
@bobbyrne01 已更新答案。现在请查看。 - Sri Harsha Chilakapati
@SriHarshaChilakapati:(引用你的回答):“顶点将在剪裁坐标系中(范围从-1到+1)”。 剪辑空间不在[-1,1]范围内。 在_规范化设备坐标_中,查看体积表示为[-1,1]立方体。 剪辑空间在透视分割之前,在那里查看体积为[-w,w] - 但是,每个顶点的w可能会有所不同,因此这实际上很难想象为3D立方体。 - derhass

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接