Не рисуется куб OpenGL
Задача следующая: нужно создать куб цветовой модели RGB и реализовать вращение камеры вокруг него клавишами W, A, S, D. Написал следующий код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL4;
using OpenTK.Input;
using System.IO;
using System.Diagnostics;
using System.Drawing.Text;
using AGU_lr2;
namespace AGU_lr2
{
public partial class MainWindow : GameWindow
{
private Color4 backColor = new Color4(0.1f, 0.1f, 0.3f, 1.0f);
private const float fovY = (float)Math.PI / 4;
private const float nearDistance = 0.1f;
private const float farDistance = 100.0f;
private float cameraPositionAngleXAxis = 0.0f;
private float cameraPositionAngleYAxis = 0.0f;
private float cameraPositionAngleDelta = (float)Math.PI / 36;
private float cameraPositionDistanceFromOrigin = 5.0f;
private Vector4 startEye = new Vector4(0.0f, 0.0f, 0.0f, 1.0f);
private Vector4 viewTarget = new Vector4(0.0f, 0.0f, 0.0f, 1.0f);
private Vector4 viewYUp = new Vector4(0.0f, 1.0f, 0.0f, 1.0f);
private int program;
private int cubeVertexArray;
private int cubeVertexBuffer;
private int cubeColorBuffer;
private double time;
private Matrix4 modelMatrix;
private Matrix4 viewMatrix;
private Matrix4 projectionMatrix;
private Matrix4 mvpMatrix;
private int mvpMatrixLocation;
public MainWindow() : base(
800, 600, GraphicsMode.Default, "", GameWindowFlags.Default,
DisplayDevice.Default, 4, 4, GraphicsContextFlags.Debug
)
{
Title += "OpenGL version: " + GL.GetString(StringName.Version);
Load += MainWindow_Load;
Resize += MainWindow_Resize;
KeyDown += MainWindow_KeyDown;
RenderFrame += MainWindow_RenderFrame;
}
private int CompileShader(ShaderType type, string path)
{
var shader = GL.CreateShader(type);
var src = File.ReadAllText(path);
GL.ShaderSource(shader, src);
GL.CompileShader(shader);
var info = GL.GetShaderInfoLog(shader);
if(!string.IsNullOrWhiteSpace(info))
{
Debug.WriteLine($"GL.CompileShader [{type}] had info log: {info}");
}
return shader;
}
private int CreateProgram()
{
var program = GL.CreateProgram();
var shaders = new List<int>();
shaders.Add(CompileShader(ShaderType.VertexShader, "vertexShader.glsl"));
shaders.Add(CompileShader(ShaderType.FragmentShader, "fragmentShader.glsl"));
foreach(var shader in shaders)
{
GL.AttachShader(program, shader);
}
GL.LinkProgram(program);
var info = GL.GetProgramInfoLog(program);
if(!string.IsNullOrWhiteSpace(info))
{
Debug.WriteLine($"GL.LinkProgram had info log: {info}");
}
foreach(var shader in shaders)
{
GL.DetachShader(program, shader);
GL.DeleteShader(shader);
}
return program;
}
private void MainWindow_Load(object sender, EventArgs e)
{
Vector4[] cubeVertices =
{
new Vector4(-0.5f, -0.5f, -0.5f, 1.0f), // #0 bottom left back black
new Vector4(0.5f, -0.5f, -0.5f, 1.0f), // #1 bottom right back red
new Vector4(0.5f, 0.5f, -0.5f, 1.0f), // #2 top right back yellow
new Vector4(-0.5f, 0.5f, -0.5f, 1.0f), // #3 top left back green
new Vector4(-0.5f, 0.5f, 0.5f, 1.0f), // #4 top left front cyan
new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), // #5 bottom left front blue
new Vector4(0.5f, -0.5f, 0.5f, 1.0f), // #6 bottom right front magenta
new Vector4(0.5f, 0.5f, 0.5f, 1.0f) // #7 top right front white
};
Color4[] cubeColors =
{
new Color4(0.0f, 0.0f, 0.0f, 0.4f), // #0 bottom left back black
new Color4(1.0f, 0.0f, 0.0f, 0.4f), // #1 bottom right back red
new Color4(1.0f, 1.0f, 0.0f, 0.4f), // #2 top right back yellow
new Color4(0.0f, 1.0f, 0.0f, 0.4f), // #3 top left bac green
new Color4(0.0f, 1.0f, 1.0f, 0.4f), // #4 top left fron cyan
new Color4(0.0f, 0.0f, 1.0f, 0.4f), // #5 bottom left fron blue
new Color4(1.0f, 0.0f, 1.0f, 0.4f), // #6 bottom right front magenta
new Color4(1.0f, 1.0f, 1.0f, 0.4f) // #7 top right fron white
};
CursorVisible = true;
program = CreateProgram();
mvpMatrixLocation = GL.GetUniformLocation(program, "mvpMatrix");
cubeVertexArray = GL.GenVertexArray();
GL.BindVertexArray(cubeVertexArray);
cubeVertexBuffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, cubeVertexBuffer);
Vector4[] vertices =
{
cubeVertices[0], cubeVertices[3], cubeVertices[2],
cubeVertices[2], cubeVertices[1], cubeVertices[0], // back
cubeVertices[0], cubeVertices[5], cubeVertices[4],
cubeVertices[4], cubeVertices[3], cubeVertices[0], // left
cubeVertices[0], cubeVertices[1], cubeVertices[6],
cubeVertices[6], cubeVertices[5], cubeVertices[0], // bottom
cubeVertices[7], cubeVertices[4], cubeVertices[5],
cubeVertices[5], cubeVertices[6], cubeVertices[7], // front
cubeVertices[7], cubeVertices[6], cubeVertices[1],
cubeVertices[1], cubeVertices[2], cubeVertices[7], // right
cubeVertices[7], cubeVertices[2], cubeVertices[3],
cubeVertices[3], cubeVertices[4], cubeVertices[7] // top
};
GL.BufferData(BufferTarget.ArrayBuffer, Vector4.SizeInBytes * vertices.Length, vertices, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(0);
GL.VertexAttribPointer(0, 4, VertexAttribPointerType.Float, false, 0, 0);
cubeColorBuffer = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, cubeColorBuffer);
Color4[] colors =
{
cubeColors[0], cubeColors[3], cubeColors[2], cubeColors[2], cubeColors[1], cubeColors[0], // back
cubeColors[0], cubeColors[5], cubeColors[4], cubeColors[4], cubeColors[3], cubeColors[0], // left
cubeColors[0], cubeColors[1], cubeColors[6], cubeColors[6], cubeColors[5], cubeColors[0], // bottom
cubeColors[7], cubeColors[4], cubeColors[5], cubeColors[5], cubeColors[6], cubeColors[7], // front
cubeColors[7], cubeColors[6], cubeColors[1], cubeColors[1], cubeColors[2], cubeColors[7], // right
cubeColors[7], cubeColors[2], cubeColors[3], cubeColors[3], cubeColors[4], cubeColors[7] // top
};
GL.BufferData(BufferTarget.ArrayBuffer, 16 * colors.Length, colors, BufferUsageHint.StaticDraw);
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(1, 4, VertexAttribPointerType.Float, false, 0, 0);
GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
GL.Enable(EnableCap.DepthTest);
GL.DepthFunc(DepthFunction.Less);
}
private void UpdateMatrices()
{
modelMatrix = Matrix4.Identity;
if (cameraPositionAngleXAxis > (float) Math.PI)
{
cameraPositionAngleXAxis -= (float)Math.PI * 2.0f;
}
else if (cameraPositionAngleXAxis<(float)-Math.PI)
{
cameraPositionAngleXAxis += (float) Math.PI * 2.0f;
}
if (cameraPositionAngleYAxis > (float) Math.PI)
{
cameraPositionAngleYAxis -= (float)Math.PI * 2.0f;
}
else if (cameraPositionAngleYAxis<(float)-Math.PI)
{
cameraPositionAngleYAxis += (float) Math.PI * 2.0f;
}
Vector4 eye = startEye;
eye.Z = cameraPositionDistanceFromOrigin;
viewMatrix = Matrix4.CreateRotationY(cameraPositionAngleYAxis) *
Matrix4.CreateRotationX(cameraPositionAngleXAxis) *
Matrix4.LookAt(
eye.X, eye.Y, eye.Z,
viewTarget.X, viewTarget.Y, viewTarget.Z,
viewYUp.X, viewYUp.Y, viewYUp.Z
);
mvpMatrix = modelMatrix * viewMatrix * projectionMatrix;
}
private void MainWindow_RenderFrame(object sender, FrameEventArgs e)
{
Title = $" (VSync: {VSync}) FPS: {1f / e.Time:0}";
time += e.Time;
UpdateMatrices();
GL.ClearColor(backColor);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.UseProgram(program);
GL.UniformMatrix4(mvpMatrixLocation, false, ref mvpMatrix);
GL.DrawArrays(PrimitiveType.Triangles, 0, 36);
SwapBuffers();
}
private void MainWindow_KeyDown(object sender, KeyboardKeyEventArgs e)
{
switch (e.Key)
{
case Key.A:
{
cameraPositionAngleYAxis += cameraPositionAngleDelta;
break;
}
case Key.D:
{
cameraPositionAngleYAxis -= cameraPositionAngleDelta;
break;
}
case Key.S:
{
cameraPositionAngleXAxis -= cameraPositionAngleDelta;
break;
}
case Key.W:
{
cameraPositionAngleXAxis += cameraPositionAngleDelta;
break;
}
case Key.Escape:
{
Exit();
break;
}
}
}
private void MainWindow_Resize(object sender, EventArgs e)
{
GL.Viewport(0, 0, Width, Height);
float aspectRatio = Width / (float)Height;
projectionMatrix = Matrix4.CreatePerspectiveFieldOfView(fovY, aspectRatio, nearDistance, farDistance);
}
protected override void Dispose(bool manual)
{
GL.DisableVertexAttribArray(1);
GL.DisableVertexAttribArray(0);
GL.DeleteBuffer(cubeColorBuffer);
GL.DeleteBuffer(cubeVertexBuffer);
GL.DeleteVertexArray(cubeVertexArray);
GL.DeleteProgram(program);
}
}
}
Но куб не отрисовывается, вместо этого на его месте появляется белый прямоугольник.(см. изображение)
И вроде бы перепроверил всё уже раз 10, не понимаю в чём дело. Приложение WindowsForms .NET Framework 4.7.2 openTK последняя третья версия.
Источник: Stack Overflow на русском