diff --git a/src/EngineSharp.Core/EngineSharp.Core/ECS/Entity.cs b/src/EngineSharp.Core/EngineSharp.Core/ECS/Entity.cs index 24fb507..8850f70 100644 --- a/src/EngineSharp.Core/EngineSharp.Core/ECS/Entity.cs +++ b/src/EngineSharp.Core/EngineSharp.Core/ECS/Entity.cs @@ -11,11 +11,11 @@ public struct Entity public readonly long Id; private Scene _scene; - public string Name { get; set; } + public required string Name { get; set; } internal Entity(long id, Scene scene) { - this.Id = id; + Id = id; _scene = scene; } diff --git a/src/EngineSharp.Core/EngineSharp.Core/ECS/Scene.cs b/src/EngineSharp.Core/EngineSharp.Core/ECS/Scene.cs index 8fcd6b4..c3e4c2f 100644 --- a/src/EngineSharp.Core/EngineSharp.Core/ECS/Scene.cs +++ b/src/EngineSharp.Core/EngineSharp.Core/ECS/Scene.cs @@ -14,7 +14,10 @@ public class Scene public Entity CreateEntity(string name) { - return new Entity(_nextSceneId++, this); + return new Entity(_nextSceneId++, this) + { + Name = name, + }; } internal void StartComponents() diff --git a/src/EngineSharp.Core/EngineSharp.Core/OpenGLEngine.cs b/src/EngineSharp.Core/EngineSharp.Core/OpenGLEngine.cs index 683fd99..17eb80c 100644 --- a/src/EngineSharp.Core/EngineSharp.Core/OpenGLEngine.cs +++ b/src/EngineSharp.Core/EngineSharp.Core/OpenGLEngine.cs @@ -82,10 +82,7 @@ internal class OpenGLEngine : IEngine // TODO: Here render all meshes etc. // MeshRenderer contains a mesh; Mesh contains a material; Material contains a shader and the values for all uniforms of the shader (apart from the matrices; I am not sure how to best handle the model matrix with this approach) - if (_currentScene is not null) - { - _currentScene.RenderComponents(_gl); - } + _currentScene?.RenderComponents(_gl); } private void OnResize(Vector2D newDimensions) diff --git a/src/EngineSharp.Core/EngineSharp.Core/Rendering/Material.cs b/src/EngineSharp.Core/EngineSharp.Core/Rendering/Material.cs new file mode 100644 index 0000000..9dcf173 --- /dev/null +++ b/src/EngineSharp.Core/EngineSharp.Core/Rendering/Material.cs @@ -0,0 +1,52 @@ +using Silk.NET.Maths; + +namespace EngineSharp.Core.Rendering; + +public class Material +{ + public required Shader Shader { get; init; } + + internal void UseShader() => Shader.Use(); + + #region Set uniforms + // All of this just relays to the shader. While it is a lot of "unnecessary" code it ensures that everything unsafe of OpenGL/Vulkan specific is abstracted away + + public void SetInt(string name, int value) + { + UseShader(); + Shader.SetInt(name, value); + } + + public void SetFloat(string name, float value) + { + UseShader(); + Shader.SetFloat(name, value); + } + + public void SetVector(string name, Vector3D value) + { + UseShader(); + Shader.SetVector(name, value); + } + + public void SetVector(string name, Vector3D value) + { + UseShader(); + Shader.SetVector(name, value); + } + + public void SetMatrix(string name, Matrix4X4 matrix) + { + UseShader(); + Shader.SetMatrix(name, matrix); + } + + public void SetMatrix(string name, Matrix4X4 matrix) + { + UseShader(); + Shader.SetMatrix(name, matrix); + } + + #endregion + +} \ No newline at end of file diff --git a/src/EngineSharp.Core/EngineSharp.Core/Rendering/Mesh.cs b/src/EngineSharp.Core/EngineSharp.Core/Rendering/Mesh.cs index 3a6935f..5c49671 100644 --- a/src/EngineSharp.Core/EngineSharp.Core/Rendering/Mesh.cs +++ b/src/EngineSharp.Core/EngineSharp.Core/Rendering/Mesh.cs @@ -4,6 +4,7 @@ namespace EngineSharp.Core.Rendering; public class Mesh { + public required Material Material { get; set; } public Vector3D[] Vertices { get; set; } = []; public Vector3D[] Normals { get; set; } = []; public uint[] Indices { get; set; } = []; @@ -30,8 +31,7 @@ public class Mesh var v2 = Vertices[i2]; var normal = Vector3D.Cross(v1-v0, v2-v0); - // Commenting this out, will result in the normals being weighted based on the triangle area - normal = Vector3D.Normalize(normal); + normal = Vector3D.Normalize(normal); // Commenting this out, will result in the normals being weighted based on the triangle area Normals[i0] += normal; Normals[i1] += normal; Normals[i2] += normal; @@ -42,4 +42,7 @@ public class Mesh Normals[i] = Vector3D.Normalize(Normals[i]); // smoothing for shared vertices } } + + // This is probably the location where the model, view, projection matrices will be set! + internal void PrepareForRendering() => Material.UseShader(); } \ No newline at end of file diff --git a/src/EngineSharp.Core/EngineSharp.Core/Rendering/MeshRenderer.cs b/src/EngineSharp.Core/EngineSharp.Core/Rendering/MeshRenderer.cs index ab1f974..558a680 100644 --- a/src/EngineSharp.Core/EngineSharp.Core/Rendering/MeshRenderer.cs +++ b/src/EngineSharp.Core/EngineSharp.Core/Rendering/MeshRenderer.cs @@ -5,7 +5,7 @@ namespace EngineSharp.Core.Rendering; public class MeshRenderer : RenderComponent { - public required Mesh Mesh { get; set; } + public required Mesh Mesh { get; set; } // in the future this might be an array, or alternatively, a mesh can have submeshes. we will see private uint vao, vbo, ebo; @@ -24,6 +24,7 @@ public class MeshRenderer : RenderComponent if(vbo == 0) { vbo = gl.GenBuffer(); } if(ebo == 0) { ebo = gl.GenBuffer(); } + Mesh.PrepareForRendering(); var meshData = new float[Mesh.Vertices.Length * 3 + Mesh.Indices.Length * 3]; for (int i = 0, insert = 0; i < Mesh.Vertices.Length; i++, insert += 6) { diff --git a/src/EngineSharp.Core/EngineSharp.Core/Rendering/Shader.cs b/src/EngineSharp.Core/EngineSharp.Core/Rendering/Shader.cs index ded7465..45ec3b7 100644 --- a/src/EngineSharp.Core/EngineSharp.Core/Rendering/Shader.cs +++ b/src/EngineSharp.Core/EngineSharp.Core/Rendering/Shader.cs @@ -4,9 +4,12 @@ using Silk.NET.OpenGL; namespace EngineSharp.Core.Rendering; +// Do the following to not JIT compile the shader: +// use the file paths as an index to a dictionary; the dictionary stores the programID to the already compiled shader +// I don't know if Vulkan also uses an ID as a uint but I think so. If so, this change would decouple the shader from OpenGL (but the question is, do I want to decouple the shader? Maybe not, as this could then couple the material to OpenGL) public class Shader { - private readonly GL _gl; + private readonly GL _gl; // not as a variable. Add it as a parameter to the methods probably (in the future it should be possible to compile the shaders beforehand. if context is passed as parameter, all shaders are JIT compiled which isn't great private readonly uint _shaderProgramId; public Shader(GL openGLContext, string pathToVertexShader, string pathToFragmentShader) @@ -21,36 +24,36 @@ public class Shader _shaderProgramId = CreateProgram(vertexShader, fragmentShader); } - public void Use() => _gl.UseProgram(_shaderProgramId); + internal void Use() => _gl.UseProgram(_shaderProgramId); #region Set uniforms - public void SetInt(string name, int value) + internal void SetInt(string name, int value) { _gl.Uniform1(_gl.GetUniformLocation(_shaderProgramId, name), value); } - public void SetFloat(string name, float value) + internal void SetFloat(string name, float value) { _gl.Uniform1(_gl.GetUniformLocation(_shaderProgramId, name), value); } - public void SetVector(string name, Vector3D value) + internal void SetVector(string name, Vector3D value) { _gl.Uniform3(_gl.GetUniformLocation(_shaderProgramId, name), value.X, value.Y, value.Z); } - public void SetVector(string name, Vector3D value) + internal void SetVector(string name, Vector3D value) { _gl.Uniform3(_gl.GetUniformLocation(_shaderProgramId, name), value.X, value.Y, value.Z); } - public void SetMatrix(string name, Matrix4X4 matrix) + internal void SetMatrix(string name, Matrix4X4 matrix) { unsafe { _gl.UniformMatrix4(_gl.GetUniformLocation(_shaderProgramId, name), 1, false, (double*) &matrix); } } - public void SetMatrix(string name, Matrix4X4 matrix) + internal void SetMatrix(string name, Matrix4X4 matrix) { unsafe { @@ -61,9 +64,9 @@ public class Shader /// - /// Compiles the given shadercode. + /// Compiles the given shader code. /// - /// The shadercode + /// The shader code /// The type of shader to compile /// Returns the id of the compiled shader. /// diff --git a/src/EngineSharp/IcoSphere.cs b/src/EngineSharp/IcoSphere.cs index b720e7f..6bb230c 100644 --- a/src/EngineSharp/IcoSphere.cs +++ b/src/EngineSharp/IcoSphere.cs @@ -6,6 +6,8 @@ namespace Engine_silk.NET; public class IcoSphere { + public required Material Material { get; set; } + private readonly IcoSphereGenerator _generator = new(); public required int Resolution @@ -25,7 +27,10 @@ public class IcoSphere public Mesh CreateSphere() { - var mesh = new Mesh(); + var mesh = new Mesh + { + Material = Material, + }; _generator.Generate(Resolution); mesh.Vertices = _generator.Vertices; diff --git a/src/EngineSharp/Program.cs b/src/EngineSharp/Program.cs index a7001b5..1c6a563 100644 --- a/src/EngineSharp/Program.cs +++ b/src/EngineSharp/Program.cs @@ -20,9 +20,16 @@ static class Program var engine = EngineFactory.Create(GraphicsAPI.OpenGL, options); var mainScene = engine.CreateScene(); var cube = mainScene.CreateEntity("cube"); + + var shader = new Shader(null, "", ""); // make a factory in IEngine so I don't have to pass graphics library specific values + var material = new Material + { + Shader = shader, + }; var sphereGenerator = new IcoSphere { - Resolution = 10 + Resolution = 10, + Material = material, }; var cubeMeshRenderer = new MeshRenderer {