为什么在与GLSL-OpenGL中的矩阵相乘后翻转z坐标

问题描述 投票:1回答:1

我正在制作一个小型游戏引擎,我想在其中使用OpenGL绘制内容。我将所有OpenGL对象抽象为类(缓冲区,VertexArrays,着色器,程序...)。一切正常,直到我开始进行3D渲染。我实现了自己的矩阵和向量(我没有像glm那样使用),当我将着色器中的顶点位置与任何矩阵相乘时,z坐标就会翻转(z = -z)。我什至尝试使用身份矩阵。这是顶点着色器:

#version 330 core

layout(location = 0) in vec4 i_pos;
layout(location = 1) in vec4 i_color;

out vec4 p_color;

uniform mat4 u_MVP;
uniform vec4 u_pos;

void main()
{    
    gl_Position = u_MVP * (i_pos + u_pos);
    p_color = i_color;
}

我仅出于调试原因而使用u_Pos制服。我在这里设置制服:

void Frame() override
    {       
        deltaTime = timer.Reset();

        if (Input::GetKey(Key::W).value == KeyDown) pos.z += deltaTime;     
        if (Input::GetKey(Key::S).value == KeyDown) pos.z -= deltaTime;             

        //mat4f(1.0f) creates a identity matrix
        shaderSelection.SetUniform("u_MVP", mat4f(1.0f));       
        shaderSelection.SetUniform("u_pos", vec4f(pos));

        ren.DrawTriangles(vertexArray, indexBuffer, shaderSelection);
    }

尽管我不确定矩阵结构没有任何东西,但它是:

template<typename T = float, int sizeX = 4, int sizeY = 4>
struct BLAZE_API mat
{
private:
    T v[sizeY][sizeX];
public:
    mat()
    {
        for (unsigned i = 0; i < sizeX * sizeY; i++)
            ((T*)v)[i] = 0;
    }
    mat(T* ptr, bool transpose = false)
    {
        if (transpose)
            for (unsigned i = 0; i < sizeX * sizeY; i++)
                ((T*)v)[i] = ptr[i];
        else
            for (unsigned i = 0; i < sizeX * sizeY; i++)
                ((T*)v)[i] = ptr[i % sizeY * sizeX + i / sizeY];        
    }
    mat(T n)
    {
        for (int x = 0; x < sizeX; x++)
            for (int y = 0; y < sizeY; y++)
                if (x == y)
                    operator[](x)[y] = n;
                else
                    operator[](x)[y] = 0;
    }   
    mat(const mat<T, sizeX, sizeY>& mat)
    {
        for (int x = 0; x < sizeX; x++)
            for (int y = 0; y < sizeY; y++)
                v[x][y] = mat[x][y];
    }

    inline T* operator[] (unsigned i) const { return (T*)(v[i]); }  
    inline void operator= (const mat<T, sizeX, sizeY>& mat)
    {
        for (int x = 0; x < sizeX; x++)
            for (int y = 0; y < sizeY; y++)
                v[x][y] = mat[x][y];
    }
};

[SetUniform执行此操作:

glUniformMatrix4fv( ... , 1, GL_FALSE, m[0]);

我制作了矩阵结构,因此我不必在GL_TRUE中的transpose参数中使用glUniformMatrix4fv。我很确定不是我的矩阵实现会反转z坐标。就像照相机在-Z方向上看,但是当我在+ X方向上移动对象时,它也在屏幕上也移动+ X(也适用于Y方向),如果照相机朝向,则不应该这样做-Z这是否应该发生,如果可以的话我可以更改吗?外观如下所示,相机朝-z方向看,立方体位于(0,0,-2),蓝色是-z平面,红色是+ z平面,这是一个完整的立方体:enter image description here

我不知道右平面的颜色发生了什么。

c++ opengl matrix glsl shader
1个回答
1
投票

如果不变换顶点坐标(或不通过Identity matrix进行变换),则可以直接在规范化的设备空间中设置坐标。 NDC是一个唯一的多维数据集,其左侧,底部,(-1,-1,-1)附近,右侧,顶部,(1、1、1)远。这意味着X轴在右侧,Y轴在上方,Z轴指向视图。

[通常,OpenGL坐标系是Right-handed系统。在视图空间中,X轴指向右侧,Y轴指向上方。由于Z轴是X轴和Y轴的Cross product,因此它指向视口之外并看起来是倒置的。

为了补偿与规范化设备空间相比,视图空间中Z轴方向的差异,Z轴必须反转。典型的OpenGL投影矩阵(例如glm::orthoglm::orthoglm::perspective)将右手系统转换为左手系统并镜像Z轴。

这意味着,如果您使用(典型)投影矩阵(而不进行其他任何变换),则顶点坐标等于视图空间坐标。 X轴在右侧,Y轴在上方,Z轴指向视图之外。

换句话说,在标准化设备空间中,相机指向+ Z。在视图空间中(在通过典型投影矩阵进行转换之前),摄像机指向-Z。

© www.soinside.com 2019 - 2024. All rights reserved.