initial commit to new instance

This commit is contained in:
2023-09-28 13:40:20 +02:00
commit 8ce55e986d
20 changed files with 1398 additions and 0 deletions

113
src/Camera/Camera.cs Normal file
View File

@ -0,0 +1,113 @@
using Silk.NET.Maths;
namespace Engine_silk.NET;
public enum MovementDirection
{
Forward,
Backward,
Left,
Right,
Up,
Down,
}
public class Camera
{
private readonly Vector3D<float> _worldUp;
private Vector3D<float> _position;
private Vector3D<float> _front;
private Vector3D<float> _right;
private Vector3D<float> _up;
private float _yaw;
private float _pitch;
private float _movementSpeed;
/// <summary>
/// The view matrix according to the current camera position and rotation
/// </summary>
public Matrix4X4<float> ViewMatrix { get => Matrix4X4.CreateLookAt(_position, _position + _front, _worldUp); }
public float MouseSensitivity { get; set; } = 0.1f;
/// <summary>
/// Controlls how fast the camera moves if a key is pressed
/// </summary>
public float MovementSpeed { get; set; } = 2.5f;
public float Fov { get; set; }
public Camera(Vector3D<float> position, float yaw = -90.0f, float pitch = 0, float movementSpeed = 2.5f, float fov = 45.0f)
{
_position = position;
_yaw = yaw;
_pitch = pitch;
_movementSpeed = movementSpeed;
Fov = fov;
_worldUp = Vector3D<float>.UnitY;
UpdateCameraVectors();
}
public void ProcessKeyboard(float deltaTime, MovementDirection direction)
{
float velocity = MovementSpeed * deltaTime;
switch (direction)
{
case MovementDirection.Forward:
_position += _front * velocity;
break;
case MovementDirection.Backward:
_position -= _front * velocity;
break;
case MovementDirection.Left:
_position -= _right * velocity;
break;
case MovementDirection.Right:
_position += _right * velocity;
break;
case MovementDirection.Up:
_position += _up * velocity;
break;
case MovementDirection.Down:
_position -= _up * velocity;
break;
}
}
public void ProcessMouseMovement(float xOffset, float yOffset)
{
xOffset *= MouseSensitivity; yOffset *= MouseSensitivity;
_yaw += xOffset;
_pitch += yOffset;
if (_pitch > 89.0f)
_pitch = 89.0f;
else if (_pitch < -89.0f)
_pitch = -89.0f;
UpdateCameraVectors(); // Recalculate front, right and up vectors since the view angle has changed
}
public void ProcessMouseScroll(float yOffset)
{
Fov -= yOffset;
if (Fov < 1.0f)
Fov = 1.0f;
if (Fov > 90.0f)
Fov = 90.0f;
}
private void UpdateCameraVectors()
{
Vector3D<float> front = new(
MathF.Cos(Maths.Convert.ToRadians(_yaw)) * MathF.Cos(Maths.Convert.ToRadians(_pitch)),
MathF.Sin(Maths.Convert.ToRadians(_pitch)),
MathF.Sin(Maths.Convert.ToRadians(_yaw)) * MathF.Cos(Maths.Convert.ToRadians(_pitch))
);
_front = Vector3D.Normalize(front);
_right = Vector3D.Normalize(Vector3D.Cross(_front, _worldUp));
_up = Vector3D.Normalize(Vector3D.Cross(_right, _front));
}
}

View File

@ -0,0 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Silk.NET.Input" Version="2.17.1" />
<PackageReference Include="Silk.NET.OpenGL" Version="2.17.1" />
<PackageReference Include="Silk.NET.Windowing" Version="2.17.1" />
<PackageReference Include="StbImageSharp" Version="2.27.13" />
</ItemGroup>
<ItemGroup>
<None Update="images\container.jpg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="images\container.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="shader.frag">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="shader.vert">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="images\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Nebulix\Nebulix.csproj" />
</ItemGroup>
</Project>

40
src/Engine_silk.NET.sln Normal file
View File

@ -0,0 +1,40 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.7.34031.279
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Engine_silk.NET", "Engine_silk.NET.csproj", "{FDB52744-20D9-4ED3-AE8E-73466169E83D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nebulix", "..\Nebulix\Nebulix.csproj", "{0DEED1E3-932E-47C3-AF2D-FCA74000908E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Nebulix.Test", "..\Nebulix.Test\Nebulix.Test.csproj", "{60B8C905-7AC4-45EE-BAB1-26D3F826124B}"
ProjectSection(ProjectDependencies) = postProject
{0DEED1E3-932E-47C3-AF2D-FCA74000908E} = {0DEED1E3-932E-47C3-AF2D-FCA74000908E}
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FDB52744-20D9-4ED3-AE8E-73466169E83D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FDB52744-20D9-4ED3-AE8E-73466169E83D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FDB52744-20D9-4ED3-AE8E-73466169E83D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FDB52744-20D9-4ED3-AE8E-73466169E83D}.Release|Any CPU.Build.0 = Release|Any CPU
{0DEED1E3-932E-47C3-AF2D-FCA74000908E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0DEED1E3-932E-47C3-AF2D-FCA74000908E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0DEED1E3-932E-47C3-AF2D-FCA74000908E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0DEED1E3-932E-47C3-AF2D-FCA74000908E}.Release|Any CPU.Build.0 = Release|Any CPU
{60B8C905-7AC4-45EE-BAB1-26D3F826124B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{60B8C905-7AC4-45EE-BAB1-26D3F826124B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{60B8C905-7AC4-45EE-BAB1-26D3F826124B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{60B8C905-7AC4-45EE-BAB1-26D3F826124B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {43EA4F27-E976-465D-BBBB-C37937F0515E}
EndGlobalSection
EndGlobal

20
src/Maths/Convert.cs Normal file
View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Engine_silk.NET.Maths
{
public static class Convert
{
public static double ToRadians(double degrees)
{
return degrees * Math.PI / 180;
}
public static float ToRadians(float degrees)
{
return degrees * MathF.PI / 180f;
}
}
}

233
src/Program.cs Normal file
View File

@ -0,0 +1,233 @@
namespace Engine_silk.NET;
using Engine_silk.NET.Textures;
using Nebulix.InputSystem;
using Silk.NET.Input;
using Silk.NET.Maths;
using Silk.NET.OpenGL;
using Silk.NET.Windowing;
using System;
using System.Drawing;
using System.Numerics;
// Section: https://github.com/dotnet/Silk.NET/tree/main/examples/CSharp/OpenGL%20Tutorials
// Chapter: Continue with 1.3
// Next to do will be cleaning this up by creating a shader class and maybe even an engine class
// IEngine -> IEngine.Create(WindowOptions) -> return OpenGLEngine/VulkanEngine maybe?
public class Program
{
private const int Width = 800;
private const int Height = 600;
private static IWindow _window;
private static GL _gl;
private static Shaders.Shader _shader;
private static Texture2D _texture;
private static Camera _cam;
private static Vector2 _lastMousePosition;
private static uint _vao, _vbo, _ebo;
public static void Main(string[] args)
{
WindowOptions options = WindowOptions.Default with
{
Size = new Vector2D<int>(Width, Height),
Title = "My first Silk.NET application!"
};
_window = Window.Create(options);
_window.Load += OnLoad;
_window.Update += OnUpdate;
_window.Render += OnRender;
_window.Run();
}
private static unsafe void OnLoad()
{
_gl = _window.CreateOpenGL();
_gl.ClearColor(Color.CornflowerBlue);
_gl.Enable(EnableCap.DepthTest);
//_gl.PolygonMode(GLEnum.FrontAndBack, GLEnum.Fill);
_cam = new Camera(new(0.0f, 0.0f, 3.0f));
IInputContext input = _window.CreateInput();
Input.Init(input);
for (int i = 0; i < input.Keyboards.Count; i++)
{
input.Keyboards[i].KeyDown += OnKeyDown;
}
for (int i = 0; i < input.Mice.Count; i++)
{
input.Mice[i].MouseMove += OnMouseMove;
input.Mice[i].Cursor.CursorMode = CursorMode.Disabled;
}
_vao = _gl.GenVertexArray();
_gl.BindVertexArray(_vao);
float[] vertices =
{
// positions // normals // texture coords
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 1.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, 0.0f, 1.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f,
0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
};
ReadOnlySpan<float> verticesData = new(vertices);
//uint[] indices =
//{
// 0u, 1u, 3u,
// 1u, 2u, 3u,
// 4u, 5u, 7u,
// 5u, 6u, 7u,
// 3u, 2u, 7u,
// 7u, 2u, 6u,
// 0u, 4u, 5u,
// 0u, 5u, 1u,
// 0u, 3u, 7u,
// 0u, 7u, 4u,
// 1u, 6u, 5u,
// 1u, 2u, 6u
//};
_vbo = _gl.GenBuffer();
_gl.BindBuffer(BufferTargetARB.ArrayBuffer, _vbo);
_gl.BufferData(BufferTargetARB.ArrayBuffer, (nuint)(vertices.Length * sizeof(float)), verticesData, BufferUsageARB.StaticDraw);
//_ebo = _gl.GenBuffer();
//_gl.BindBuffer(BufferTargetARB.ElementArrayBuffer, _ebo);
//fixed (uint* buffer = indices)
// _gl.BufferData(BufferTargetARB.ElementArrayBuffer, (nuint)(indices.Length * sizeof(uint)), buffer, BufferUsageARB.StaticDraw);
_shader = new Shaders.Shader(_gl, "shader.vert", "shader.frag");
_gl.EnableVertexAttribArray(0);
_gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), (void*)0);
_gl.EnableVertexAttribArray(1);
_gl.VertexAttribPointer(1, 3, VertexAttribPointerType.Float, false, 8 * sizeof(float), (void*)(3 * sizeof(float)));
_gl.EnableVertexAttribArray(2);
_gl.VertexAttribPointer(2, 2, VertexAttribPointerType.Float, false, 8 * sizeof(float), (void*)(6 * sizeof(float)));
_texture = new Texture2D(_gl, "images/container.png", ImageFormat.RGBA);
}
private static void OnUpdate(double deltaTime)
{
if(Input.AnyKeyPressed())
{
const float movementSpeedMultiplier = 2;
if(Input.IsKeyPressed(Key.ShiftLeft))
_cam.MovementSpeed *= movementSpeedMultiplier;
if (Input.IsKeyPressed(Key.W))
_cam.ProcessKeyboard((float)deltaTime, MovementDirection.Forward);
if(Input.IsKeyPressed(Key.S))
_cam.ProcessKeyboard((float)deltaTime, MovementDirection.Backward);
if (Input.IsKeyPressed(Key.A))
_cam.ProcessKeyboard((float)deltaTime, MovementDirection.Left);
if(Input.IsKeyPressed(Key.D))
_cam.ProcessKeyboard((float)deltaTime, MovementDirection.Right);
if (Input.IsKeyPressed(Key.Space))
_cam.ProcessKeyboard((float)deltaTime, MovementDirection.Up);
if(Input.IsKeyPressed(Key.ControlLeft))
_cam.ProcessKeyboard((float)deltaTime, MovementDirection.Down);
if (Input.IsKeyPressed(Key.ShiftLeft))
_cam.MovementSpeed /= movementSpeedMultiplier;
}
}
private static void OnRender(double deltaTime)
{
_gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
var difference = (float)(_window.Time * 10);
var modelMatrix = Matrix4x4.CreateRotationY(Maths.Convert.ToRadians(difference)) * Matrix4x4.CreateRotationX(Maths.Convert.ToRadians(difference));
var viewMatrix = _cam.ViewMatrix;
var projectionMatrix = Matrix4X4.CreatePerspectiveFieldOfView(Maths.Convert.ToRadians(_cam.Fov), Width / Height, 0.1f, 100.0f);
_gl.BindVertexArray(_vao);
_shader.Use();
_shader.SetMatrix("modelMatrix", modelMatrix);
_shader.SetMatrix("projectionMatrix", projectionMatrix);
_shader.SetMatrix("viewMatrix", viewMatrix);
_shader.SetInt("tex", 0);
_texture.Bind();
_gl.DrawArrays(PrimitiveType.Triangles, 0, 36);
}
private static void OnKeyDown(IKeyboard keyboard, Key key, int keyCode)
{
if (key == Key.Escape)
{
_window.Close();
}
}
private static void OnMouseMove(IMouse mouse, Vector2 position)
{
if(_lastMousePosition == default)
{
_lastMousePosition = position;
return;
}
float xOffset = position.X - _lastMousePosition.X;
float yOffset = _lastMousePosition.Y - position.Y;
_lastMousePosition = position;
_cam.ProcessMouseMovement(xOffset, yOffset);
}
}

94
src/Shaders/Shader.cs Normal file
View File

@ -0,0 +1,94 @@
using Silk.NET.Maths;
using Silk.NET.OpenGL;
using System.Numerics;
namespace Engine_silk.NET.Shaders;
public class Shader
{
private readonly GL _glContext;
private readonly uint _shaderProgramId;
public Shader(GL openGLContext, string pathToVertexShader, string pathToFragmentShader)
{
_glContext = openGLContext;
var vertexCode = File.ReadAllText(pathToVertexShader);
var fragmentCode = File.ReadAllText(pathToFragmentShader);
var vertexShader = CompileShader(vertexCode, ShaderType.VertexShader);
var fragmentShader = CompileShader(fragmentCode, ShaderType.FragmentShader);
_shaderProgramId = CreateProgram(vertexShader, fragmentShader);
}
public void Use() { _glContext.UseProgram(_shaderProgramId); }
#region Set uniforms
public void SetInt(string name, int value)
{
_glContext.Uniform1(_glContext.GetUniformLocation(_shaderProgramId, name), value);
}
public void SetFloat(string name, float value)
{
_glContext.Uniform1(_glContext.GetUniformLocation(_shaderProgramId, name), value);
}
public unsafe void SetMatrix(string name, Matrix4x4 matrix)
{
_glContext.UniformMatrix4(_glContext.GetUniformLocation(_shaderProgramId, name), 1, false, (float*) &matrix);
}
public unsafe void SetMatrix(string name, Matrix4X4<float> matrix)
{
_glContext.UniformMatrix4(_glContext.GetUniformLocation(_shaderProgramId, name), 1, false, (float*) &matrix);
}
#endregion
/// <summary>
/// Compiles the given shadercode.
/// </summary>
/// <param name="shaderCode">The shadercode</param>
/// <param name="shaderType">The type of shader to compile</param>
/// <returns>Returns the id of the compiled shader.</returns>
/// <exception cref="ShaderCompileException"></exception>
protected uint CompileShader(string shaderCode, ShaderType shaderType)
{
uint shader = _glContext.CreateShader(shaderType);
_glContext.ShaderSource(shader, shaderCode);
_glContext.CompileShader(shader);
_glContext.GetShader(shader, ShaderParameterName.CompileStatus, out int status);
if (status != (int)GLEnum.True)
throw new ShaderCompileException(shaderType, $"Failed to compile shader with message: \n {_glContext.GetShaderInfoLog(shader)}");
return shader;
}
/// <summary>
/// Creates a shader program and links the vertex and fragment shader together.
/// </summary>
/// <returns>Returns the id of the created shader program</returns>
/// <exception cref="ShaderLinkException"></exception>
protected uint CreateProgram(uint vertexShader, uint fragmentShader)
{
uint program = _glContext.CreateProgram();
_glContext.AttachShader(program, vertexShader);
_glContext.AttachShader(program, fragmentShader);
_glContext.LinkProgram(program);
_glContext.GetProgram(program, ProgramPropertyARB.LinkStatus, out int lStatus);
if (lStatus != (int)GLEnum.True)
throw new ShaderLinkException("Error occured while trying to link a shader with message: \n" + _glContext.GetProgramInfoLog(program));
// should be done right after compiling and linking
_glContext.DetachShader(program, vertexShader);
_glContext.DetachShader(program, fragmentShader);
_glContext.DeleteShader(vertexShader);
_glContext.DeleteShader(fragmentShader);
return program;
}
}

View File

@ -0,0 +1,27 @@
using Silk.NET.OpenGL;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Engine_silk.NET.Shaders;
[Serializable]
public class ShaderCompileException : Exception
{
protected ShaderType _shaderType;
public ShaderCompileException(ShaderType shaderType) : base("Unable to compile shader.") { _shaderType = shaderType; }
public ShaderCompileException(ShaderType shaderType, string message) : base(message) { _shaderType = shaderType; }
public ShaderCompileException(ShaderType shaderType, string message, Exception inner) : base(message, inner) { _shaderType = shaderType; }
protected ShaderCompileException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
public override string ToString()
{
return $"Type of Shader: '{_shaderType}'" + "\n" + Message;
}
}

View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Engine_silk.NET.Shaders;
[Serializable]
public class ShaderLinkException : Exception
{
public ShaderLinkException() : base("Error occured while trying to link a shader.") { }
public ShaderLinkException(string message) : base(message) { }
public ShaderLinkException(string message, Exception inner) : base(message, inner) { }
protected ShaderLinkException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context) : base(info, context) { }
}

28
src/Textures/Enums.cs Normal file
View File

@ -0,0 +1,28 @@
using Silk.NET.OpenGL;
using StbImageSharp;
namespace Engine_silk.NET.Textures;
public enum ImageFormat
{
Grey = ColorComponents.Grey,
GreyAlpha = ColorComponents.GreyAlpha,
RGB = ColorComponents.RedGreenBlue,
RGBA = ColorComponents.RedGreenBlueAlpha,
}
internal static class ConverterExtensions
{
internal static PixelFormat ImageFormatToPixelFormat(this ImageFormat imageFormat)
{
switch (imageFormat)
{
case ImageFormat.RGB:
return PixelFormat.Rgb;
case ImageFormat.RGBA:
return PixelFormat.Rgba;
default:
throw new NotImplementedException($"Cannot map the given {nameof(ImageFormat)} '{imageFormat}' to a {nameof(PixelFormat)}");
}
}
}

85
src/Textures/Texture2D.cs Normal file
View File

@ -0,0 +1,85 @@

using Silk.NET.OpenGL;
using StbImageSharp;
namespace Engine_silk.NET.Textures;
public class Texture2D : IDisposable
{
/// <summary>
/// Defines how the texture should be wrapped if the uv-coordinates are out of bounds
/// Default: Repeat
/// </summary>
public TextureWrapMode WrapMode { get; set; }
/// <summary>
/// Defines how a texel should be interpolated when zooming out of the texture.
/// Default: BiLinear
/// </summary>
public TextureMinFilter MinifyingInterpolation { get; set; }
/// <summary>
/// Defines how a texel should be interpolated when zooming in to the texture.
/// Default: Bilinear
/// </summary>
public TextureMagFilter MagnifyingInterpolation { get; set; }
protected GL _glContext;
protected uint _textureId;
private bool disposedValue;
public Texture2D(GL glContext, string pathToTexture, ImageFormat format = ImageFormat.RGB, TextureWrapMode wrapMode = TextureWrapMode.Repeat,
TextureMinFilter minifyingInterpolation = TextureMinFilter.Linear, TextureMagFilter magnifyingInterpolation = TextureMagFilter.Linear)
{
_glContext = glContext;
WrapMode = wrapMode;
MinifyingInterpolation = minifyingInterpolation;
MagnifyingInterpolation = magnifyingInterpolation;
byte[] buffer = File.ReadAllBytes(pathToTexture);
ImageResult image = ImageResult.FromMemory(buffer, (ColorComponents)format);
ReadOnlySpan<byte> imageData = new(image.Data);
_glContext.GenTextures(1, out _textureId);
_glContext.BindTexture(TextureTarget.Texture2D, _textureId);
_glContext.TexImage2D(TextureTarget.Texture2D, 0, InternalFormat.Rgb, (uint)image.Width, (uint)image.Height, 0, format.ImageFormatToPixelFormat(), PixelType.UnsignedByte, imageData);
_glContext.GenerateMipmap(TextureTarget.Texture2D);
}
public void Bind(TextureUnit textureUnit = TextureUnit.Texture0)
{
_glContext.TexParameter(TextureTarget.Texture2D, GLEnum.TextureWrapT, (int)WrapMode);
_glContext.TexParameter(TextureTarget.Texture2D, GLEnum.TextureMinFilter, (int)MinifyingInterpolation);
_glContext.TexParameter(TextureTarget.Texture2D, GLEnum.TextureMagFilter, (int)MagnifyingInterpolation);
_glContext.ActiveTexture(textureUnit);
_glContext.BindTexture(TextureTarget.Texture2D, _textureId);
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
_glContext.DeleteTexture(_textureId);
}
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
// TODO: set large fields to null
disposedValue = true;
}
}
// // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
// ~Texture2D()
// {
// // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
// Dispose(disposing: false);
// }
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}

BIN
src/images/container.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 457 KiB

17
src/shader.frag Normal file
View File

@ -0,0 +1,17 @@
#version 330 core
out vec4 colour;
in vec2 TexCoords;
in vec3 FragPos;
in vec3 Normal;
uniform sampler2D tex;
void main()
{
//vec3 col = vec3(1.0, 0.5, 0.2) * FragPos;
//colour = vec4(texture(tex, TexCoords).rgb, 1.0);
colour = texture(tex, TexCoords);
}

24
src/shader.vert Normal file
View File

@ -0,0 +1,24 @@
#version 330 core
layout (location=0) in vec3 aPosition;
layout (location = 1) in vec3 normalVector;
layout (location = 2) in vec2 texCoords;
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
out vec2 TexCoords;
out vec3 FragPos;
out vec3 Normal;
void main()
{
vec4 pos = vec4(aPosition, 1.0);
// TODO: calculate the inverse of the model matrix since "inverse()" is very costly to calculate for every vertex
Normal = mat3(transpose(inverse(modelMatrix))) * normalVector;
FragPos = vec3(modelMatrix * pos);
TexCoords = texCoords;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * pos;
}