Skip to content

Instantly share code, notes, and snippets.

@danielcrenna
Last active March 30, 2024 20:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danielcrenna/c15446b7439bad90ca2831cb719cb84a to your computer and use it in GitHub Desktop.
Save danielcrenna/c15446b7439bad90ca2831cb719cb84a to your computer and use it in GitHub Desktop.
Red Triangle using SILK.NET and SharpGLTF
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
];
}
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
];
}
<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