-
Автор темы
- #1
Использую библиотеку OpenTK, пытаюсь отрендерить обычный куб из блендера, но выводится он криво, вопрос где я обосрался?:
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, нужно конвертировать квадратные лица в треугольные перед тем как их сохранять
Последнее редактирование: