我的Go矩阵函数(Perspective / Frustum& Lookat矩阵)对于OpenGL有什么问题?

时间:2012-10-11 19:29:24

标签: opengl matrix go glsl vertex-shader

首先,这是非常简单的“新手标准”顶点着色器:

in vec3 aPos;
uniform mat4 uMatModel; uniform mat4 uMatView; uniform mat4 uMatProj;

void main () {
    gl_Position = uMatProj * uMatView * uMatModel * vec4(aPos, 1.0);
}

现在我正在渲染的是一个简单的6面立方体。 36个顶点坐标中没有应用或固有的旋转。标准教程风格-0.5 .. + 0.5的东西。我会在这里省略顶点数组,但请放心,就像那样简单。

  • uMatModel 现在只是身份矩阵,没有缩放/翻译/旋转
  • uMatView 是一个 LookAt矩阵(下面的Go代码),调用pos = {0.1,0.1,-3.0},target = {0.1,0.1,0.1}, up = {0,1,0}(记住立方体顶点坐标在所有维度中都在-0.5和0.5之间,所以0.1s应该“几乎是中心”)。
  • uMatProj 是一个透视矩阵(下面的Go代码),调用fov = 45 aspect = winwidth / winheight near = 0.1 far = 100

理论上,“相机”应该是面向它的立方体“后面”约2-3个单位。相反,我得到......

enter image description here

我想知道轮换的来源......我甚至没有实现轮换。

总而言之,我试图在Go中自己实现所需的矩阵函数,从而解决数学问题。但在某个地方,我一定是在窃听。 我可以在下面的代码中发现任何矩阵理论问题吗?

type Mat4x4 [4][4]float64

func (me *Mat4x4) Identity () {
    me[0][0], me[0][1], me[0][2], me[0][3] = 1, 0, 0, 0
    me[1][0], me[1][1], me[1][2], me[1][3] = 0, 1, 0, 0
    me[2][0], me[2][1], me[2][2], me[2][3] = 0, 0, 1, 0
    me[3][0], me[3][1], me[3][2], me[3][3] = 0, 0, 0, 1
}

func (me *Mat4x4) Frustum (left, right, bottom, top, near, far float64) {
    me[0][0], me[0][1], me[0][2], me[0][3] = (near * 2) / (right - left), 0, 0, 0
    me[1][0], me[1][1], me[1][2], me[1][3] = 0, (near * 2) / (top - bottom), 0, 0
    me[2][0], me[2][1], me[2][2], me[2][3] = (right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1
    me[3][0], me[3][1], me[3][2], me[3][3] = 0, 0, -(far * near * 2) / (far - near), 0
}

func (me *Mat4x4) Perspective (fovY, aspect, near, far float64) {
    var top = near * math.Tan(fovY * math.Pi / 360)
    var right = top * aspect
    me.Frustum(aspect * -top, right, -top, top, near, far)
}

func (me *Mat4x4) LookAt (eyePos, lookTarget, worldUp *Vec3) {
    var vz = eyePos.Sub(lookTarget)
    vz.Normalize()
    var vx = worldUp.Cross(&vz)
    vx.Normalize()
    var vy = vz.Cross(&vx)
    vy.Normalize()
    me[0][0], me[0][1], me[0][2], me[0][3] = vx.X, vy.X, vz.X, 0
    me[1][0], me[1][1], me[1][2], me[1][3] = vx.Y, vy.Y, vz.Y, 0
    me[2][0], me[2][1], me[2][2], me[2][3] = vx.Z, vy.Z, vz.Z, 0
    me[3][0], me[3][1], me[3][2], me[3][3] = -((vx.X * eyePos.X) + (vx.Y * eyePos.Y) + (vx.Z * eyePos.Z)), -((vy.X * eyePos.X) + (vy.Y * eyePos.Y) + (vy.Z * eyePos.Z)), -((vz.X * eyePos.X) + (vz.Y * eyePos.Y) + (vz.Z * eyePos.Z)), 1
}

注意, Vec3 这是同一个包中的自定义类型,我没有在此处包含它。现在我假设Vec3函数是正确的(也更容易验证)并且怀疑我在某种程度上弄乱了矩阵结构中的 LookAt 和/或 Perspective 算法。

1 个答案:

答案 0 :(得分:1)

这个(推测)deg对rad转换好吗?

func (me *Mat4x4) Perspective (fovY, aspect, near, far float64) {
        var top = near * math.Tan(fovY * math.Pi / 360)
        var right = top * aspect
        me.Frustum(aspect * -top, right, -top, top, near, far)
}

也许应该有:

        top := near * math.Tan(fovY * 2 * math.Pi / 360)