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.
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).
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?
Here is the complete program:
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();
}
}
}
See Question&Answers more detail:
os