Last active
March 30, 2024 20:01
-
-
Save danielcrenna/c15446b7439bad90ca2831cb719cb84a to your computer and use it in GitHub Desktop.
Red Triangle using SILK.NET and SharpGLTF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Numerics; | |
using System.Runtime.InteropServices; | |
using SharpGLTF.Geometry; | |
using SharpGLTF.Materials; | |
using Silk.NET.Input; | |
using Silk.NET.OpenGL; | |
using Silk.NET.Windowing; | |
using VERTEX = SharpGLTF.Geometry.VertexTypes.VertexPosition; | |
var material1 = new MaterialBuilder() | |
.WithDoubleSide(true) | |
.WithMetallicRoughnessShader() | |
.WithChannelParam(KnownChannel.BaseColor, KnownProperty.RGBA, new Vector4(1, 0, 0, 1)); | |
var mesh = new MeshBuilder<VERTEX>("mesh"); | |
var prim = mesh.UsePrimitive(material1); | |
prim.AddTriangle(new VERTEX(-0.5f, -0.5f, 0), new VERTEX(0.5f, -0.5f, 0), new VERTEX(0, 0.5f, 0)); | |
var scene = new SharpGLTF.Scenes.SceneBuilder(); | |
scene.AddRigidMesh(mesh, Matrix4x4.Identity); | |
var model = scene.ToGltf2(); | |
var window = Window.Create(WindowOptions.Default with | |
{ | |
Title = "Red Triangle (OpenGL)" | |
}); | |
GL? gl = null; | |
uint vertexBuffer; | |
uint vertexArray = 0; | |
uint shaderProgram = 0; | |
var modelMatrix = Matrix4x4.Identity; | |
var viewMatrix = Matrix4x4.CreateLookAt(new Vector3(0, 0, 10), Vector3.Zero, Vector3.UnitY); | |
var projectionMatrix = Matrix4x4.CreatePerspectiveFieldOfView( | |
(float)Math.PI / 4, | |
window.Size.X / (float)window.Size.Y, | |
0.1f, | |
100f | |
); | |
int modelLoc = 0, viewLoc = 0, projLoc = 0; | |
window.Load += () => | |
{ | |
unsafe | |
{ | |
gl = GL.GetApi(window); | |
gl.Viewport(0, 0, (uint)window.Size.X, (uint) window.Size.Y); | |
var vertexShader = gl.CreateShader(ShaderType.VertexShader); | |
gl.ShaderSource(vertexShader, """ | |
#version 330 core | |
layout(location = 0) in vec3 vertexPosition; | |
out vec3 fragmentColor; | |
uniform mat4 projectionMatrix; | |
uniform mat4 viewMatrix; | |
uniform mat4 modelMatrix; | |
void main() | |
{ | |
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(vertexPosition, 1.0); | |
fragmentColor = vec3(1.0, 0.0, 0.0); // red | |
} | |
"""); | |
gl.CompileShader(vertexShader); | |
gl.GetShader(vertexShader, ShaderParameterName.CompileStatus, out var vertexCompileStatus); | |
if (vertexCompileStatus == 0) | |
{ | |
var infoLog = gl.GetProgramInfoLog(vertexShader); | |
Console.WriteLine($"Error linking shader program: {infoLog}"); | |
} | |
var fragmentShader = gl.CreateShader(ShaderType.FragmentShader); | |
gl.ShaderSource(fragmentShader, """ | |
#version 330 core | |
in vec3 fragmentColor; | |
out vec4 color; | |
void main() | |
{ | |
color = vec4(fragmentColor, 1.0); | |
} | |
"""); | |
gl.CompileShader(fragmentShader); | |
gl.GetShader(fragmentShader, ShaderParameterName.CompileStatus, out var fragmentCompileStatus); | |
if (fragmentCompileStatus == 0) | |
{ | |
var infoLog = gl.GetProgramInfoLog(fragmentShader); | |
Console.WriteLine($"Error linking shader program: {infoLog}"); | |
} | |
shaderProgram = gl.CreateProgram(); | |
gl.AttachShader(shaderProgram, vertexShader); | |
gl.AttachShader(shaderProgram, fragmentShader); | |
gl.LinkProgram(shaderProgram); | |
gl.GetProgram(shaderProgram, GLEnum.LinkStatus, out var linkStatus); | |
if (linkStatus == 0) | |
{ | |
var infoLog = gl.GetProgramInfoLog(shaderProgram); | |
Console.WriteLine($"Error linking shader program: {infoLog}"); | |
} | |
modelLoc = gl.GetUniformLocation(shaderProgram, "modelMatrix"); | |
if (modelLoc == -1) | |
Console.WriteLine("Model location is wrong"); | |
viewLoc = gl.GetUniformLocation(shaderProgram, "viewMatrix"); | |
if (viewLoc == -1) | |
Console.WriteLine("View location is wrong"); | |
projLoc = gl.GetUniformLocation(shaderProgram, "projectionMatrix"); | |
if (viewLoc == -1) | |
Console.WriteLine("Projection location is wrong"); | |
vertexBuffer = gl.GenBuffer(); | |
vertexArray = gl.GenVertexArray(); | |
gl.BindVertexArray(vertexArray); | |
gl.BindBuffer(BufferTargetARB.ArrayBuffer, vertexBuffer); | |
if (model.LogicalMeshes.Count > 0 && model.LogicalMeshes[0].Primitives.Count > 0) | |
{ | |
var primitive = model.LogicalMeshes[0].Primitives[0]; | |
var accessor = primitive.VertexAccessors["POSITION"]; | |
if (accessor != null) | |
{ | |
var positions = accessor.AsVector3Array(); | |
Vector3[] vertices = [.. positions]; | |
gl.BufferData<Vector3>(BufferTargetARB.ArrayBuffer, (nuint)(vertices.Length * Marshal.SizeOf<Vector3>()), vertices, BufferUsageARB.StaticDraw); | |
} | |
} | |
gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), null); | |
gl.EnableVertexAttribArray(0); | |
} | |
}; | |
window.Render += _ => | |
{ | |
gl!.Enable(EnableCap.DepthTest); | |
gl.ClearColor(0.5f, 0.5f, 0.5f, 1.0f); | |
gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); | |
gl.UseProgram(shaderProgram); | |
var modelArray = ToArray(modelMatrix); | |
var viewArray = ToArray(viewMatrix); | |
var projectionArray = ToArray(projectionMatrix); | |
gl.UniformMatrix4(modelLoc, 1, false, modelArray); | |
gl.UniformMatrix4(viewLoc, 1, false, viewArray); | |
gl.UniformMatrix4(projLoc, 1, false, projectionArray); | |
gl.BindVertexArray(vertexArray); | |
gl.DrawArrays(PrimitiveType.Triangles, 0, 3); | |
}; | |
window.Initialize(); | |
var input = window.CreateInput(); | |
foreach (var keyboard in input.Keyboards) | |
{ | |
keyboard.KeyDown += (_, key, _) => | |
{ | |
Console.WriteLine(key); | |
}; | |
} | |
window.Run(); | |
return; | |
static float[] ToArray(Matrix4x4 matrix) | |
{ | |
return | |
[ | |
matrix.M11, matrix.M12, matrix.M13, matrix.M14, | |
matrix.M21, matrix.M22, matrix.M23, matrix.M24, | |
matrix.M31, matrix.M32, matrix.M33, matrix.M34, | |
matrix.M41, matrix.M42, matrix.M43, matrix.M44 | |
]; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Numerics; | |
using Silk.NET.Input; | |
using Silk.NET.OpenGL; | |
using Silk.NET.Windowing; | |
var window = Window.Create(WindowOptions.Default with | |
{ | |
Title = "Red Triangle (OpenGL)" | |
}); | |
GL? gl = null; | |
uint vertexBuffer; | |
uint vertexArray = 0; | |
uint shaderProgram = 0; | |
var modelMatrix = Matrix4x4.Identity; | |
var viewMatrix = Matrix4x4.CreateLookAt(new Vector3(0, 0, 10), Vector3.Zero, Vector3.UnitY); | |
var projectionMatrix = Matrix4x4.CreatePerspectiveFieldOfView( | |
(float)Math.PI / 4, | |
window.Size.X / (float)window.Size.Y, | |
0.1f, | |
100f | |
); | |
int modelLoc = 0, viewLoc = 0, projLoc = 0; | |
float[] vertices = | |
[ | |
-0.5f, -0.5f, 0.0f, | |
0.5f, -0.5f, 0.0f, | |
0.0f, 0.5f, 0.0f | |
]; | |
window.Load += () => | |
{ | |
unsafe | |
{ | |
gl = GL.GetApi(window); | |
gl.Viewport(0, 0, (uint)window.Size.X, (uint) window.Size.Y); | |
var vertexShader = gl.CreateShader(ShaderType.VertexShader); | |
gl.ShaderSource(vertexShader, """ | |
#version 330 core | |
layout(location = 0) in vec3 vertexPosition; | |
out vec3 fragmentColor; | |
uniform mat4 projectionMatrix; | |
uniform mat4 viewMatrix; | |
uniform mat4 modelMatrix; | |
void main() | |
{ | |
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vec4(vertexPosition, 1.0); | |
fragmentColor = vec3(1.0, 0.0, 0.0); // red | |
} | |
"""); | |
gl.CompileShader(vertexShader); | |
gl.GetShader(vertexShader, ShaderParameterName.CompileStatus, out var vertexCompileStatus); | |
if (vertexCompileStatus == 0) | |
{ | |
var infoLog = gl.GetProgramInfoLog(vertexShader); | |
Console.WriteLine($"Error linking shader program: {infoLog}"); | |
} | |
var fragmentShader = gl.CreateShader(ShaderType.FragmentShader); | |
gl.ShaderSource(fragmentShader, """ | |
#version 330 core | |
in vec3 fragmentColor; | |
out vec4 color; | |
void main() | |
{ | |
color = vec4(fragmentColor, 1.0); | |
} | |
"""); | |
gl.CompileShader(fragmentShader); | |
gl.GetShader(fragmentShader, ShaderParameterName.CompileStatus, out var fragmentCompileStatus); | |
if (fragmentCompileStatus == 0) | |
{ | |
var infoLog = gl.GetProgramInfoLog(fragmentShader); | |
Console.WriteLine($"Error linking shader program: {infoLog}"); | |
} | |
shaderProgram = gl.CreateProgram(); | |
gl.AttachShader(shaderProgram, vertexShader); | |
gl.AttachShader(shaderProgram, fragmentShader); | |
gl.LinkProgram(shaderProgram); | |
gl.GetProgram(shaderProgram, GLEnum.LinkStatus, out var linkStatus); | |
if (linkStatus == 0) | |
{ | |
var infoLog = gl.GetProgramInfoLog(shaderProgram); | |
Console.WriteLine($"Error linking shader program: {infoLog}"); | |
} | |
modelLoc = gl.GetUniformLocation(shaderProgram, "modelMatrix"); | |
if (modelLoc == -1) | |
Console.WriteLine("Model location is wrong"); | |
viewLoc = gl.GetUniformLocation(shaderProgram, "viewMatrix"); | |
if (viewLoc == -1) | |
Console.WriteLine("View location is wrong"); | |
projLoc = gl.GetUniformLocation(shaderProgram, "projectionMatrix"); | |
if (viewLoc == -1) | |
Console.WriteLine("Projection location is wrong"); | |
vertexBuffer = gl.GenBuffer(); | |
vertexArray = gl.GenVertexArray(); | |
gl.BindVertexArray(vertexArray); | |
gl.BindBuffer(BufferTargetARB.ArrayBuffer, vertexBuffer); | |
gl.BufferData<float>(BufferTargetARB.ArrayBuffer, (nuint)(vertices.Length * sizeof(float)), vertices, BufferUsageARB.StaticDraw); | |
gl.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 3 * sizeof(float), null); | |
gl.EnableVertexAttribArray(0); | |
} | |
}; | |
window.Render += _ => | |
{ | |
gl!.Enable(EnableCap.DepthTest); | |
gl.ClearColor(0.5f, 0.5f, 0.5f, 1.0f); | |
gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); | |
gl.UseProgram(shaderProgram); | |
var modelArray = ToArray(modelMatrix); | |
var viewArray = ToArray(viewMatrix); | |
var projectionArray = ToArray(projectionMatrix); | |
gl.UniformMatrix4(modelLoc, 1, false, modelArray); | |
gl.UniformMatrix4(viewLoc, 1, false, viewArray); | |
gl.UniformMatrix4(projLoc, 1, false, projectionArray); | |
gl.BindVertexArray(vertexArray); | |
gl.DrawArrays(PrimitiveType.Triangles, 0, 3); | |
}; | |
window.Initialize(); | |
var input = window.CreateInput(); | |
foreach (var keyboard in input.Keyboards) | |
{ | |
keyboard.KeyDown += (_, key, _) => | |
{ | |
Console.WriteLine(key); | |
}; | |
} | |
window.Run(); | |
return; | |
static float[] ToArray(Matrix4x4 matrix) | |
{ | |
return | |
[ | |
matrix.M11, matrix.M12, matrix.M13, matrix.M14, | |
matrix.M21, matrix.M22, matrix.M23, matrix.M24, | |
matrix.M31, matrix.M32, matrix.M33, matrix.M34, | |
matrix.M41, matrix.M42, matrix.M43, matrix.M44 | |
]; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>net8.0</TargetFramework> | |
<ImplicitUsings>enable</ImplicitUsings> | |
<Nullable>enable</Nullable> | |
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="SharpGLTF.Toolkit" Version="1.0.0-alpha0031" /> | |
<PackageReference Include="Silk.NET" Version="2.20.0" /> | |
</ItemGroup> | |
</Project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment