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

查看:166
本文介绍了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问题进行评论:矩阵问题 #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相比,列主顺序矩阵必须从右向右相乘,其中右矩阵是 first应用的矩阵,在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天全站免登陆