Вопрос OpenTK (OpenGL) Неверный рендер куба

Участник
Статус
Оффлайн
Регистрация
6 Сен 2020
Сообщения
749
Реакции[?]
364
Поинты[?]
8K
Использую библиотеку OpenTK, пытаюсь отрендерить обычный куб из блендера, но выводится он криво, вопрос где я обосрался?:
1720806803174.png1720806824026.png
C#:
using Game.Engine.Graphics;
using OpenTK.Mathematics;
using OpenTK.Graphics.OpenGL4;
using System.Globalization;

namespace Game.Engine
{
    public class Mesh
    {
        public bool active;
        public Material material;
        public Vector3 position;
        public Vector3 rotation;
        public float scale;

        private readonly List<Vector3> vertices = new List<Vector3>();
        private readonly List<Vector2> texCoords = new List<Vector2>();
        private readonly List<Vector3> normals = new List<Vector3>();
        List<Tuple<uint, uint, uint>> faces = new List<Tuple<uint, uint, uint>>();
        private List<uint> indices = new List<uint>();

        private VertexArrayObject vao;
        private ElementBufferObject vbo;
        private ElementBufferObject ibo;

        public Mesh(string meshFileName, Material material, Vector3 position, Vector3 rotation, float scale = 1)
        {
            active = true;
            this.material = material;
            this.position = position;
            this.rotation = rotation;
            this.scale = scale;

            ImportFromFile(meshFileName);

            vao = new VertexArrayObject();
            vbo = new ElementBufferObject(GenerateVertexBuffer());
            ibo = new ElementBufferObject(indices);

            vao.LinkVertexBuffer(0, 3, vbo, 8 * sizeof(float), 0);
            vao.LinkVertexBuffer(1, 3, vbo, 8 * sizeof(float), 3 * sizeof(float));
            vao.LinkVertexBuffer(2, 2, vbo, 8 * sizeof(float), 5 * sizeof(float));
        }

        public void Render(Camera camera, List<Light> lights)
        {
            if (!active)
                return;

            Matrix4 model = Matrix4.CreateScale(scale) * Matrix4.CreateRotationX(rotation.X) * Matrix4.CreateRotationY(rotation.Y) * Matrix4.CreateRotationZ(rotation.Z) * Matrix4.CreateTranslation(position);
            Matrix4 view = camera.GetViewMatrix();
            Matrix4 projection = camera.GetProjectionMatrix();

            material.shader.SetUniform("model", ref model);
            material.shader.SetUniform("view",  ref view);
            material.shader.SetUniform("projection", ref projection);

            material.shader.SetUniform("camPosition", camera.position);

            material.shader.SetUniform("material.ambient", material.ambient);
            material.shader.SetUniform("material.diffuse", material.diffuse);
            material.shader.SetUniform("material.specular", material.specular);
            material.shader.SetUniform("material.shininess", material.shininess);

            /*material.shader.SetUniform("pointLight.position", pointLight.position);
            material.shader.SetUniform("pointLight.ambient", pointLight.ambient);
            material.shader.SetUniform("pointLight.diffuse", pointLight.diffuse);
            material.shader.SetUniform("pointLight.specular", pointLight.specular);*/

            material.shader.Bind();
            vao.Bind();
            ibo.Bind();

            GL.DrawElements(PrimitiveType.Triangles, indices.Count, DrawElementsType.UnsignedInt, 0);

            ibo.Unbind();
            vao.Unbind();
            material.shader.Unbind();
        }

        private List<float> GenerateVertexBuffer()
        {
            List<float> vertexBuffer = new List<float>();

            foreach (var face in faces)
            {
                Vector3 vertex = vertices[(int)face.Item1];
                Vector2 texCoord = texCoords[(int)face.Item2];
                Vector3 normal = normals[(int)face.Item3];

                vertexBuffer.Add(vertex.X);
                vertexBuffer.Add(vertex.Y);
                vertexBuffer.Add(vertex.Z);
                vertexBuffer.Add(texCoord.X);
                vertexBuffer.Add(texCoord.Y);
                vertexBuffer.Add(normal.X);
                vertexBuffer.Add(normal.Y);
                vertexBuffer.Add(normal.Z);
            }

            return vertexBuffer;
        }

        private void ImportFromFile(string fileName)
        {
            string meshBuffer = "";

            try
            {
                using (StreamReader reader = new StreamReader("../../../Assets/Meshes/" + fileName))
                {
                    meshBuffer = reader.ReadToEnd();
                    reader.Close();
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Failed to read mesh file: {0}", ex.Message);
            }

            string[] lines = meshBuffer.Split("\n", StringSplitOptions.RemoveEmptyEntries);

            foreach (string line in lines)
            {
                string[] parameters = line.Split(" ", StringSplitOptions.RemoveEmptyEntries);

                if (parameters.Length < 1)
                    continue;

                switch(parameters[0])
                {
                    case "v":
                        float x = float.Parse(parameters[1], CultureInfo.InvariantCulture.NumberFormat);
                        float y = float.Parse(parameters[2], CultureInfo.InvariantCulture.NumberFormat);
                        float z = float.Parse(parameters[3], CultureInfo.InvariantCulture.NumberFormat);
                        vertices.Add(new Vector3(x, y, z));
                        break;
                    case "vn":
                        float nx = float.Parse(parameters[1], CultureInfo.InvariantCulture.NumberFormat);
                        float ny = float.Parse(parameters[2], CultureInfo.InvariantCulture.NumberFormat);
                        float nz = float.Parse(parameters[3], CultureInfo.InvariantCulture.NumberFormat);
                        normals.Add(new Vector3(nx, ny, nz));
                        break;
                    case "vt":
                        float u = float.Parse(parameters[1], CultureInfo.InvariantCulture.NumberFormat);
                        float v = float.Parse(parameters[2], CultureInfo.InvariantCulture.NumberFormat);
                        texCoords.Add(new Vector2(u, v));
                        break;
                    case "f":
                        foreach (string parameter in parameters)
                        {
                            if (parameter == parameters[0])
                                continue;

                            string[] parts = parameter.Split("/");

                            uint vertexIndex = uint.Parse(parts[0]) - 1;
                            uint vertexTexCoordIndex = uint.Parse(parts[1]) - 1;
                            uint vertexNormalIndex = uint.Parse(parts[2]) - 1;

                            faces.Add(new Tuple<uint, uint, uint>(vertexIndex, vertexTexCoordIndex, vertexNormalIndex));
                        }

                        break;
                }
            }

            foreach (var face in faces)
                indices.Add(face.Item1);
        }
    }
}
Код:
#version 330 core
layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec2 aTexCoords;
layout(location = 2) in vec3 aNormal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

void main()
{
    gl_Position = vec4(aPosition, 1.0) * model * view * projection;
}

Блендер экспортирует лица как квадраты, а OpenGL рендерит треугольниками соответственно ожидает что на одно лицо будет по 3 индекса, а в блендере их 4, нужно конвертировать квадратные лица в треугольные перед тем как их сохранять
 
Последнее редактирование:
Участник
Статус
Оффлайн
Регистрация
19 Апр 2020
Сообщения
1,180
Реакции[?]
314
Поинты[?]
152K
private List<float> GenerateVertexBuffer() { List<float> vertexBuffer = new List<float>(); foreach (var face in faces) { Vector3 vertex = vertices[(int)face.Item1]; Vector2 texCoord = texCoords[(int)face.Item2]; Vector3 normal = normals[(int)face.Item3]; vertexBuffer.Add(vertex.X); vertexBuffer.Add(vertex.Y); vertexBuffer.Add(vertex.Z); vertexBuffer.Add(texCoord.X); vertexBuffer.Add(texCoord.Y); vertexBuffer.Add(normal.X); vertexBuffer.Add(normal.Y); vertexBuffer.Add(normal.Z); } return vertexBuffer; }
Код:
vertexBuffer.Add(vertex.X);
        vertexBuffer.Add(vertex.Y);
        vertexBuffer.Add(vertex.Z);
        vertexBuffer.Add(normal.X);
        vertexBuffer.Add(normal.Y);
        vertexBuffer.Add(normal.Z);
        vertexBuffer.Add(texCoord.X);
        vertexBuffer.Add(texCoord.Y);
vao.LinkVertexBuffer(2, 2, vbo, 8 * sizeof(float), 5 * sizeof(float));
здесь вместо 5 попробуй 6
 
Участник
Статус
Оффлайн
Регистрация
6 Сен 2020
Сообщения
749
Реакции[?]
364
Поинты[?]
8K
Код:
vertexBuffer.Add(vertex.X);
        vertexBuffer.Add(vertex.Y);
        vertexBuffer.Add(vertex.Z);
        vertexBuffer.Add(normal.X);
        vertexBuffer.Add(normal.Y);
        vertexBuffer.Add(normal.Z);
        vertexBuffer.Add(texCoord.X);
        vertexBuffer.Add(texCoord.Y);
здесь вместо 5 попробуй 6
Там ведь отступ на нулевой позиции 3 потому что 3 координата точки, затем 2 координата UV, и потом 3+2=5, то есть отступ нормалей 5, в общем получилось 8 и вот размер одного "шага"?
Но у меня не в правильном порядке передавались размеры, сейчас должны правильно но куб всё равно не куб
C#:
vao.LinkVertexBuffer(0, 3, vbo, 8 * sizeof(float), 0);
vao.LinkVertexBuffer(1, 2, vbo, 8 * sizeof(float), 3 * sizeof(float));
vao.LinkVertexBuffer(2, 3, vbo, 8 * sizeof(float), 5 * sizeof(float));
 
Участник
Статус
Оффлайн
Регистрация
6 Сен 2020
Сообщения
749
Реакции[?]
364
Поинты[?]
8K
Блендер экспортирует лица как квадраты, а OpenGL рендерит треугольниками соответственно ожидает что на одно лицо будет по 3 индекса, а в блендере их 4, нужно конвертировать квадратные лица в треугольные перед тем как их сохранять
Нашёл решение, может кому надо будет
 
Сверху Снизу