OpenGL 4.2 LookAt 矩阵仅适用于眼睛位置的 -z 值 [英] OpenGL 4.2 LookAt matrix only works with -z value for eye position

查看:27
本文介绍了OpenGL 4.2 LookAt 矩阵仅适用于眼睛位置的 -z 值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试理解和应用现代 OpenGL 矩阵变换.我已经阅读了很多不同的来源,但我不确定我到底做错了什么.

I am trying to understand and apply modern OpenGL matrix transformations. I already read a lot of different sources but I am not sure what I am actually doing wrong.

代码中也评论了我遇到的问题:如果我将 Matrix4.LookAt 的眼睛坐标设置为大于或等于 0 或小于 -2 的 z 值,则三角形不再可见.

The issue I have is also commented in the code: If I set the eye coordinates of the Matrix4.LookAt to a z value that is greater or equal 0 or lower -2 the triangle is not visible anymore.

谁能解释一下为什么?就我理解的方法而言,三角形应该只是从另一侧可见(明确禁用面部剔除不会改变任何东西).

Can someone explain why? As far as I understood the method the triangle should just be visible just from the other side (explicitly disabling face culling does not change anything).

另一件事很奇怪:如果我旋转三角形,如果我使用 eye-z = -2; 它似乎被剪裁了;如果我使用 -1 它看起来更平滑".有什么想法吗?

Another thing is strange: if i rotate the triangle it seems to get clipped if I use eye-z = -2; if I use -1 it looks "smoother". Any ideas?

这是完整的程序:

using System;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;

namespace OGL420_Matrices
{
    // OpenTK version 3.1.0
    internal class Program
    {
        public static void Main(string[] args)
        {
            var program = new Program();
            program.Run();
        }

        private GameWindow _gameWindow;
        private Matrix4 _projectionMatrix;
        private Matrix4 _viewMatrix;
        private Matrix4 _viewProjectionMatrix;
        private Matrix4 _modelMatrix;
        private int _vbaId, _programId, _viewProjectionUniformId, _modelMatrixUniformId;

        private void Run()
        {
            // 4, 2 is OpenGL 4.2
            using (_gameWindow = new GameWindow(800, 600, GraphicsMode.Default, "", GameWindowFlags.Default,
                DisplayDevice.Default, 4, 2, GraphicsContextFlags.Default))
            {
                _gameWindow.Load += OnLoad;
                _gameWindow.Resize += OnResize;
                _gameWindow.RenderFrame += OnRenderFrame;

                _gameWindow.Run();
            }
        }

        private void OnResize(object sender, EventArgs e)
        {
            var clientArea = _gameWindow.ClientRectangle;
            GL.Viewport(0, 0, clientArea.Width, clientArea.Height);
        }

        private void OnLoad(object sender, EventArgs e)
        {
            _projectionMatrix = Matrix4.CreateOrthographic(3, 3, 0.001f, 50);

            // change -1 to -2.1f you dont see anything
            // change -1 to -2f you still see the same
            // change -1 to >= 0 you dont see anything; of course 0 doesn't make sense but 1 would
            _viewMatrix = Matrix4.LookAt(
                new Vector3(0, 0, -1f), // eye
                new Vector3(0, 0, 0), // target
                new Vector3(0, 1, 0)); // up
            _modelMatrix = Matrix4.Identity;

            var data = new float[]
            {
                0, 0, 0,
                1, 0, 0,
                0, 1, 0
            };

            var vboId = GL.GenBuffer();

            GL.BindBuffer(BufferTarget.ArrayBuffer, vboId);
            GL.BufferData(BufferTarget.ArrayBuffer, data.Length * sizeof(float), data, BufferUsageHint.StaticDraw);

            _vbaId = GL.GenVertexArray();

            GL.BindVertexArray(_vbaId);
            GL.BindBuffer(BufferTarget.ArrayBuffer, vboId);

            GL.EnableVertexAttribArray(0);
            GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 0, 0);

            var vertexShaderId = GL.CreateShader(ShaderType.VertexShader);
            GL.ShaderSource(vertexShaderId, @"#version 420

layout(location = 0) in vec3 position;

uniform mat4 viewProjection;
uniform mat4 model;

out vec3 outColor;

void main()
{
    gl_Position = viewProjection * model * vec4(position, 1);
    outColor = vec3(1,1,1);
}");

            GL.CompileShader(vertexShaderId);
            GL.GetShader(vertexShaderId, ShaderParameter.CompileStatus, out var result);

            if (result != 1)
                throw new Exception("compilation error: " + GL.GetShaderInfoLog(vertexShaderId));

            var fragShaderId = GL.CreateShader(ShaderType.FragmentShader);
            GL.ShaderSource(fragShaderId, @"#version 420

in vec3 outColor;
out vec4 fragmentColor;

void main()
{
    fragmentColor = vec4(outColor, 1);
}");

            GL.CompileShader(fragShaderId);
            GL.GetShader(fragShaderId, ShaderParameter.CompileStatus, out result);

            if (result != 1)
                throw new Exception("compilation error: " + GL.GetShaderInfoLog(fragShaderId));

            _programId = GL.CreateProgram();
            GL.AttachShader(_programId, vertexShaderId);
            GL.AttachShader(_programId, fragShaderId);

            GL.LinkProgram(_programId);
            GL.GetProgram(_programId, GetProgramParameterName.LinkStatus, out var linkStatus);

            if (linkStatus != 1) // 1 for true
                throw new Exception("Shader program compilation error: " + GL.GetProgramInfoLog(_programId));

            GL.DeleteShader(vertexShaderId);
            GL.DeleteShader(fragShaderId);

            _viewProjectionUniformId = GL.GetUniformLocation(_programId, "viewProjection");
            _modelMatrixUniformId = GL.GetUniformLocation(_programId, "model");
        }

        private void OnRenderFrame(object sender, FrameEventArgs e)
        {
            GL.Clear(ClearBufferMask.ColorBufferBit);

            _viewProjectionMatrix = _projectionMatrix * _viewMatrix;

            GL.UniformMatrix4(_viewProjectionUniformId, false, ref _viewProjectionMatrix);
            GL.UniformMatrix4(_modelMatrixUniformId, false, ref _modelMatrix);

            GL.UseProgram(_programId);
            GL.BindVertexArray(_vbaId);
            GL.DrawArrays(PrimitiveType.Triangles, 0, 3);

            _gameWindow.SwapBuffers();
        }
    }
}

推荐答案

首先引用 OpenTK issue 的评论:矩阵问题#687:

First I'll quote a comment to the OpenTK issue: Problem with matrices #687:

由于矩阵在 C# 和 OpenTK 中的处理方式,乘法顺序与您在 C/C++ 和 GLSL 中可能期望的顺序相反.这是图书馆里的旧物,很遗憾,现在改变已经太晚了.

Because of how matrices are treated in C# and OpenTK, multiplication order is inverted from what you might expect in C/C++ and GLSL. This is an old artefact in the library, and it's too late to change now, unfortunately.

<小时>

与 glsl 相比,列主阶矩阵必须从右到左相乘,其中右矩阵是首先"应用的矩阵,在 OpenTK 中,矩阵必须从左到左相乘正确的.


In compare to glsl, where column major order matrices have to be multiplied form the right to the left, where the right matrix is the matrix which is applied "first", in OpenTK the matrices have to be multiplied from the left to the right.

这意味着,如果你想在 glsl 中计算 viewProjectionMatrix,它进行视图转换,然后是投影,那么在 glsl 中它是(对于列主阶矩阵):

This means, if you want to calculate the viewProjectionMatrix in glsl, which does the view transformation followed by the projection, then in glsl it is (for column major order matrices):

mat4 viewProjectionMatrix = projectionMatrix * viewMatrix;

如果你想在 OpenTK 中做同样的事情,使用 Matrix4,那么你必须这样做:

If you want to do the same in in OpenTK, by the use of Matrix4, then you've to do:

_viewProjectionMatrix = _viewMatrix * _projectionMatrix;

这篇关于OpenGL 4.2 LookAt 矩阵仅适用于眼睛位置的 -z 值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆