本文介绍了为什么在GLSL中与矩阵相乘后z坐标会翻转-OpenGL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm making a small game engine in which i want to draw stuff using OpenGL. I abstracted all the OpenGL objects into classes (Buffers, VertexArrays, Shaders, Programs...). Everything worked fine until i got to 3D rendering. I implemented my own matrices and vectors(i didn't use like glm), and when i multiply my vertex position in the shader with any matrix, the z coordinate flips (z = -z). I even tried with the identity matrix. Here is the vertex shader:

#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制服.在这里,我设置了制服:

I used the u_Pos uniform just for debugging reasons. And here i set the uniforms:

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);
    }

尽管我不确定矩阵结构没有任何内容,但这是:

Although im sure there's nothing with the matrix struct, here it is:

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]);

我制作了矩阵结构,这样我就不必在glUniformMatrix4fv中的transpose参数中使用GL_TRUE了.我很确定不是我的矩阵实现会反转z坐标.就像照相机在-Z方向上看,但是当我在+ X方向上移动对象时,它也在屏幕上也移动+ X(也适用于Y方向),如果照相机朝向,则不应该这样做-Z这是否应该发生,如果可以的话我可以更改吗?

I made the matrix struct such that i don't have to use GL_TRUE for transpose parameter in glUniformMatrix4fv. I am pretty sure it isnt my matrix implementation that is inverting the z coordinate.It is like the camera is looking in the -Z direction, but when i move a object in the +X direction it moves also +X on the screen(also applies for Y direction), which it shouldn't if the camera is facing -Z.Is this supposed to happen, if so can i change it?

推荐答案

如果不变换顶点坐标(或通过身份矩阵),然后直接在规范化的设备空间中设置坐标. NDC是一个唯一的多维数据集,其左侧,底部,(-1,-1,-1)附近,右侧,顶部,(1,1,1)远.这意味着X轴在右侧,Y轴在上方,Z轴指向视图.

If you do not transform the vertex coordinates (or transform it by the Identity matrix), then you directly set the coordinates in normalized device space. The NDC is a unique cube, with the left, bottom, near of (-1, -1, -1) and the right, top, far of (1, 1, 1). That means the X-axis is to the right, the Y-axis is upwards and the Z-axis points into the view.

常见的OpenGL坐标系是右手系统.在视图空间中,X轴指向右侧,Y轴指向上方.
由于Z轴是X轴和Y轴的叉积,它指向视口之外,并且似乎是倒置的.

In common the OpenGL coordinate system is a Right-handed system. In view space the X-axis points to the right and the Y-axis points up.
Since the Z-axis is the Cross product of the X-axis and the Y-axis, it points out of the viewport and appears to be inverted.

与标准设备空间相比,为了补偿视图空间中Z轴方向的差异,必须反转Z轴.
典型的OpenGL投影矩阵(例如 glm::ortho glm::perspective glm::frustum )将右手系统转换为左手系统并对其进行镜像Z轴.

To compensate the difference in the direction of the Z-axis in view space in compare to normalized device space the Z-axis has to be inverted.
A typical OpenGL projection matrix (e.g. glm::ortho, glm::perspective or glm::frustum) turns the right handed system to a left handed system and mirrors the Z-axis.

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

That means, if you use a (typical) projection matrix (and no other transformations), then the vertex coordinates are equal to the view space coordinates. The X-axis is to the right, the Y-axis is upwards and the Z-axis points out of the view.

简而言之,在规范化的设备空间中,相机指向+ Z.在视图空间中(在通过典型投影矩阵进行转换之前),相机指向-Z.

In simplified words, in normalized device space the camera points in +Z. In view space (before the transformation by a typical projection matrix) the camera points in -Z.

请注意,如果您设置了查看视锥" ,则依次选择0 < nearnear < far.这两个条件都必须满足.几何必须在近平面和远平面之间,否则将被裁剪.通常,视图矩阵用于从特定角度查看场景.以这种方式选择了视锥的近平面和远平面,使几何形状介于两者之间.
由于深度不是线性的(请参阅),应将近平面尽可能地靠近几何.

Note if you setup a Viewing frustum, then 0 < near and near < far. Both conditions have to be fulfilled. The geometry has to be between the near and the far plane, else it is clipped. In common a view matrix is used to look at the scene from a certain point of view. The near and far plane of the viewing frustum are chosen in that way, that the geometry is in between.
Since the depth is not linear (see How to render depth linearly in modern OpenGL with gl_FragCoord.z in fragment shader?), the near plane should be placed as close as possible to the geometry.

这篇关于为什么在GLSL中与矩阵相乘后z坐标会翻转-OpenGL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 20:29