This commit is contained in:
Colin McMillen 2023-06-29 22:10:24 -04:00
parent 225a1a623c
commit 712472bdfb

View File

@ -1,366 +1,366 @@
using OpenTK.Graphics.OpenGL4; using OpenTK.Graphics.OpenGL4;
using OpenTK.Mathematics; using OpenTK.Mathematics;
using OpenTK.Windowing.Common; using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop; using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework; using OpenTK.Windowing.GraphicsLibraryFramework;
// https://docs.sixlabors.com/api/ImageSharp/SixLabors.ImageSharp.Image.html // https://docs.sixlabors.com/api/ImageSharp/SixLabors.ImageSharp.Image.html
using SixLabors.ImageSharp; using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Metadata.Profiles.Exif; using SixLabors.ImageSharp.Metadata.Profiles.Exif;
using System.IO; using System.IO;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static System.Runtime.InteropServices.JavaScript.JSType; using static System.Runtime.InteropServices.JavaScript.JSType;
using System.Xml.Linq; using System.Xml.Linq;
using Image = SixLabors.ImageSharp.Image; using Image = SixLabors.ImageSharp.Image;
namespace SemiColinGames; namespace SemiColinGames;
public class Shader : IDisposable { public class Shader : IDisposable {
int Handle; int Handle;
public Shader() { public Shader() {
int VertexShader; int VertexShader;
int FragmentShader; int FragmentShader;
string VertexShaderSource = @" string VertexShaderSource = @"
#version 330 #version 330
layout(location = 0) in vec3 aPosition; layout(location = 0) in vec3 aPosition;
layout(location = 1) in vec2 aTexCoord; layout(location = 1) in vec2 aTexCoord;
out vec2 texCoord; out vec2 texCoord;
uniform mat4 projection; uniform mat4 projection;
void main(void) { void main(void) {
texCoord = aTexCoord; texCoord = aTexCoord;
gl_Position = vec4(aPosition, 1.0) * projection; gl_Position = vec4(aPosition, 1.0) * projection;
}"; }";
string FragmentShaderSource = @" string FragmentShaderSource = @"
#version 330 #version 330
out vec4 outputColor; out vec4 outputColor;
in vec2 texCoord; in vec2 texCoord;
uniform sampler2D texture0; uniform sampler2D texture0;
void main() { void main() {
outputColor = texture(texture0, texCoord); outputColor = texture(texture0, texCoord);
}"; }";
VertexShader = GL.CreateShader(ShaderType.VertexShader); VertexShader = GL.CreateShader(ShaderType.VertexShader);
GL.ShaderSource(VertexShader, VertexShaderSource); GL.ShaderSource(VertexShader, VertexShaderSource);
FragmentShader = GL.CreateShader(ShaderType.FragmentShader); FragmentShader = GL.CreateShader(ShaderType.FragmentShader);
GL.ShaderSource(FragmentShader, FragmentShaderSource); GL.ShaderSource(FragmentShader, FragmentShaderSource);
GL.CompileShader(VertexShader); GL.CompileShader(VertexShader);
int success; int success;
GL.GetShader(VertexShader, ShaderParameter.CompileStatus, out success); GL.GetShader(VertexShader, ShaderParameter.CompileStatus, out success);
if (success == 0) { if (success == 0) {
string infoLog = GL.GetShaderInfoLog(VertexShader); string infoLog = GL.GetShaderInfoLog(VertexShader);
Console.WriteLine(infoLog); Console.WriteLine(infoLog);
} }
GL.CompileShader(FragmentShader); GL.CompileShader(FragmentShader);
GL.GetShader(FragmentShader, ShaderParameter.CompileStatus, out success); GL.GetShader(FragmentShader, ShaderParameter.CompileStatus, out success);
if (success == 0) { if (success == 0) {
string infoLog = GL.GetShaderInfoLog(FragmentShader); string infoLog = GL.GetShaderInfoLog(FragmentShader);
Console.WriteLine(infoLog); Console.WriteLine(infoLog);
} }
Handle = GL.CreateProgram(); Handle = GL.CreateProgram();
GL.AttachShader(Handle, VertexShader); GL.AttachShader(Handle, VertexShader);
GL.AttachShader(Handle, FragmentShader); GL.AttachShader(Handle, FragmentShader);
GL.LinkProgram(Handle); GL.LinkProgram(Handle);
GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out success); GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out success);
if (success == 0) { if (success == 0) {
string infoLog = GL.GetProgramInfoLog(Handle); string infoLog = GL.GetProgramInfoLog(Handle);
Console.WriteLine(infoLog); Console.WriteLine(infoLog);
} }
GL.DetachShader(Handle, VertexShader); GL.DetachShader(Handle, VertexShader);
GL.DetachShader(Handle, FragmentShader); GL.DetachShader(Handle, FragmentShader);
GL.DeleteShader(FragmentShader); GL.DeleteShader(FragmentShader);
GL.DeleteShader(VertexShader); GL.DeleteShader(VertexShader);
} }
public void Use() { public void Use() {
GL.UseProgram(Handle); GL.UseProgram(Handle);
} }
private bool disposedValue = false; private bool disposedValue = false;
protected virtual void Dispose(bool disposing) { protected virtual void Dispose(bool disposing) {
if (!disposedValue) { if (!disposedValue) {
GL.DeleteProgram(Handle); GL.DeleteProgram(Handle);
disposedValue = true; disposedValue = true;
} }
} }
~Shader() { ~Shader() {
if (disposedValue == false) { if (disposedValue == false) {
Console.WriteLine("~Shader(): resource leak? Dispose() should be called manually."); Console.WriteLine("~Shader(): resource leak? Dispose() should be called manually.");
} }
} }
public void Dispose() { public void Dispose() {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
public int GetAttribLocation(string name) { public int GetAttribLocation(string name) {
return GL.GetAttribLocation(Handle, name); return GL.GetAttribLocation(Handle, name);
} }
public int GetUniformLocation(string name) { public int GetUniformLocation(string name) {
return GL.GetUniformLocation(Handle, name); return GL.GetUniformLocation(Handle, name);
} }
} }
public class Texture : IDisposable { public class Texture : IDisposable {
public int Handle; public int Handle;
public Texture(string path) { public Texture(string path) {
Image<Rgba32> image = Image.Load<Rgba32>(path); Image<Rgba32> image = Image.Load<Rgba32>(path);
Console.WriteLine($"image loaded: {image.Width}x{image.Height}"); Console.WriteLine($"image loaded: {image.Width}x{image.Height}");
//foreach (IExifValue exif in image.Metadata.ExifProfile.Values) { //foreach (IExifValue exif in image.Metadata.ExifProfile.Values) {
// Console.WriteLine($"{exif.Tag} : {exif.GetValue()}"); // Console.WriteLine($"{exif.Tag} : {exif.GetValue()}");
//} //}
byte[] pixelBytes = new byte[image.Width * image.Height * Unsafe.SizeOf<Rgba32>()]; byte[] pixelBytes = new byte[image.Width * image.Height * Unsafe.SizeOf<Rgba32>()];
image.CopyPixelDataTo(pixelBytes); image.CopyPixelDataTo(pixelBytes);
image.Dispose(); image.Dispose();
Handle = GL.GenTexture(); Handle = GL.GenTexture();
GL.ActiveTexture(TextureUnit.Texture0); GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, Handle); GL.BindTexture(TextureTarget.Texture2D, Handle);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixelBytes); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, pixelBytes);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.LinearMipmapLinear); // FIXME: is this right? GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int) TextureMinFilter.LinearMipmapLinear); // FIXME: is this right?
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) TextureMagFilter.Nearest); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int) TextureMagFilter.Nearest);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToBorder); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToBorder);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToBorder); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToBorder);
float[] borderColor = { 0.0f, 0.0f, 0.0f, 1.0f }; float[] borderColor = { 0.0f, 0.0f, 0.0f, 1.0f };
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, borderColor); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, borderColor);
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
} }
private bool disposedValue = false; private bool disposedValue = false;
protected virtual void Dispose(bool disposing) { protected virtual void Dispose(bool disposing) {
if (!disposedValue) { if (!disposedValue) {
GL.DeleteTexture(Handle); GL.DeleteTexture(Handle);
disposedValue = true; disposedValue = true;
} }
} }
~Texture() { ~Texture() {
if (!disposedValue) { if (!disposedValue) {
Console.WriteLine("~Texture(): resource leak? Dispose() should be called manually."); Console.WriteLine("~Texture(): resource leak? Dispose() should be called manually.");
} }
} }
public void Dispose() { public void Dispose() {
Dispose(true); Dispose(true);
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
} }
public class Game : GameWindow { public class Game : GameWindow {
public Game(GameWindowSettings gwSettings, NativeWindowSettings nwSettings) : base(gwSettings, nwSettings) { } public Game(GameWindowSettings gwSettings, NativeWindowSettings nwSettings) : base(gwSettings, nwSettings) { }
int frameCount; int frameCount;
int windowWidth; int windowWidth;
int windowHeight; int windowHeight;
float[] vertices = { float[] vertices = {
// Position Texture coordinates // Position Texture coordinates
0f, 0f, 0.0f, 0.0f, 0.0f, // top left 0f, 0f, 0.0f, 0.0f, 0.0f, // top left
2560f, 0f, 0.0f, 1.0f, 0.0f, // top right 2560f, 0f, 0.0f, 1.0f, 0.0f, // top right
2560f, 1440f, 0.0f, 1.0f, 1.0f, // bottom right 2560f, 1440f, 0.0f, 1.0f, 1.0f, // bottom right
0f, 1440f, 0.0f, 0.0f, 1.0f, // bottom left 0f, 1440f, 0.0f, 0.0f, 1.0f, // bottom left
}; };
uint[] indices = { uint[] indices = {
0, 1, 3, // first triangle 0, 1, 3, // first triangle
1, 2, 3 // second triangle 1, 2, 3 // second triangle
}; };
int VertexBufferObject; int VertexBufferObject;
int ElementBufferObject; int ElementBufferObject;
int VertexArrayObject; int VertexArrayObject;
List<Texture> textures; List<Texture> textures;
int textureIndex = 0; int textureIndex = 0;
Shader shader; Shader shader;
Matrix4 projection; Matrix4 projection;
protected override void OnUpdateFrame(FrameEventArgs e) { protected override void OnUpdateFrame(FrameEventArgs e) {
base.OnUpdateFrame(e); base.OnUpdateFrame(e);
KeyboardState input = KeyboardState; KeyboardState input = KeyboardState;
if (input.IsKeyDown(Keys.Escape)) { if (input.IsKeyDown(Keys.Escape)) {
Close(); Close();
} }
if (input.IsKeyPressed(Keys.Down)) { if (input.IsKeyPressed(Keys.Down)) {
if (textureIndex < textures.Count - 1) { if (textureIndex < textures.Count - 1) {
textureIndex++; textureIndex++;
} }
} }
if (input.IsKeyPressed(Keys.Up)) { if (input.IsKeyPressed(Keys.Up)) {
if (textureIndex > 0) { if (textureIndex > 0) {
textureIndex--; textureIndex--;
} }
} }
} }
protected override void OnLoad() { protected override void OnLoad() {
base.OnLoad(); base.OnLoad();
GL.ClearColor(0.0f, 0.0f, 0.05f, 1.0f); GL.ClearColor(0.0f, 0.0f, 0.05f, 1.0f);
VertexArrayObject = GL.GenVertexArray(); VertexArrayObject = GL.GenVertexArray();
GL.BindVertexArray(VertexArrayObject); GL.BindVertexArray(VertexArrayObject);
VertexBufferObject = GL.GenBuffer(); VertexBufferObject = GL.GenBuffer();
ElementBufferObject = GL.GenBuffer(); ElementBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject); GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.DynamicDraw); GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.DynamicDraw);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, ElementBufferObject); GL.BindBuffer(BufferTarget.ElementArrayBuffer, ElementBufferObject);
GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length * sizeof(uint), indices, BufferUsageHint.DynamicDraw); GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length * sizeof(uint), indices, BufferUsageHint.DynamicDraw);
shader = new Shader(); shader = new Shader();
shader.Use(); shader.Use();
// Because there's now 5 floats between the start of the first vertex and the start of the second, // Because there's now 5 floats between the start of the first vertex and the start of the second,
// we modify the stride from 3 * sizeof(float) to 5 * sizeof(float). // we modify the stride from 3 * sizeof(float) to 5 * sizeof(float).
// This will now pass the new vertex array to the buffer. // This will now pass the new vertex array to the buffer.
var vertexLocation = shader.GetAttribLocation("aPosition"); var vertexLocation = shader.GetAttribLocation("aPosition");
GL.EnableVertexAttribArray(vertexLocation); GL.EnableVertexAttribArray(vertexLocation);
GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0); GL.VertexAttribPointer(vertexLocation, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0);
// Next, we also setup texture coordinates. It works in much the same way. // Next, we also setup texture coordinates. It works in much the same way.
// We add an offset of 3, since the texture coordinates comes after the position data. // We add an offset of 3, since the texture coordinates comes after the position data.
// We also change the amount of data to 2 because there's only 2 floats for texture coordinates. // We also change the amount of data to 2 because there's only 2 floats for texture coordinates.
var texCoordLocation = shader.GetAttribLocation("aTexCoord"); var texCoordLocation = shader.GetAttribLocation("aTexCoord");
GL.EnableVertexAttribArray(texCoordLocation); GL.EnableVertexAttribArray(texCoordLocation);
GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float));
// Load textures from JPEGs. // Load textures from JPEGs.
string[] files = Directory.GetFiles(@"c:\users\colin\pictures\photos\2023\06\27\"); string[] files = Directory.GetFiles(@"c:\users\colin\pictures\photos\2023\06\27\");
textures = new List<Texture>(); textures = new List<Texture>();
foreach (string file in files) { foreach (string file in files) {
if (file.ToLower().EndsWith(".jpg")) { if (file.ToLower().EndsWith(".jpg")) {
textures.Add(new Texture(file)); textures.Add(new Texture(file));
} }
} }
} }
protected override void OnUnload() { protected override void OnUnload() {
base.OnUnload(); base.OnUnload();
} }
protected override void OnRenderFrame(FrameEventArgs e) { protected override void OnRenderFrame(FrameEventArgs e) {
base.OnRenderFrame(e); base.OnRenderFrame(e);
frameCount++; frameCount++;
GL.Clear(ClearBufferMask.ColorBufferBit); GL.Clear(ClearBufferMask.ColorBufferBit);
SetVertices(0, 0, windowWidth - 152, windowHeight); SetVertices(0, 0, windowWidth - 152, windowHeight);
GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject); GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.DynamicDraw); GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.DynamicDraw);
GL.ActiveTexture(TextureUnit.Texture0); GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, textures[textureIndex].Handle); GL.BindTexture(TextureTarget.Texture2D, textures[textureIndex].Handle);
shader.Use(); shader.Use();
GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0); GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0);
for (int i = 0; i < textures.Count; i++) { for (int i = 0; i < textures.Count; i++) {
SetVertices(windowWidth - 150, i * 100, windowWidth, i * 100 + 98); SetVertices(windowWidth - 150, i * 100, windowWidth, i * 100 + 98);
GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject); GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBufferObject);
GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.DynamicDraw); GL.BufferData(BufferTarget.ArrayBuffer, vertices.Length * sizeof(float), vertices, BufferUsageHint.DynamicDraw);
GL.ActiveTexture(TextureUnit.Texture0); GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, textures[i].Handle); GL.BindTexture(TextureTarget.Texture2D, textures[i].Handle);
shader.Use(); shader.Use();
GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0); GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0);
} }
SwapBuffers(); SwapBuffers();
} }
protected override void OnResize(ResizeEventArgs e) { protected override void OnResize(ResizeEventArgs e) {
base.OnResize(e); base.OnResize(e);
Console.WriteLine($"OnResize: {e.Width}x{e.Height}"); Console.WriteLine($"OnResize: {e.Width}x{e.Height}");
windowWidth = e.Width; windowWidth = e.Width;
windowHeight = e.Height; windowHeight = e.Height;
projection = Matrix4.CreateOrthographicOffCenter(0f, windowWidth, windowHeight, 0f, -1f, 1f); projection = Matrix4.CreateOrthographicOffCenter(0f, windowWidth, windowHeight, 0f, -1f, 1f);
GL.UniformMatrix4(shader.GetUniformLocation("projection"), true, ref projection); GL.UniformMatrix4(shader.GetUniformLocation("projection"), true, ref projection);
GL.Viewport(0, 0, windowWidth, windowHeight); GL.Viewport(0, 0, windowWidth, windowHeight);
} }
private void SetVertices(float left, float top, float right, float bottom) { private void SetVertices(float left, float top, float right, float bottom) {
// top left // top left
vertices[0] = left; vertices[0] = left;
vertices[1] = top; vertices[1] = top;
vertices[2] = 0f; vertices[2] = 0f;
vertices[3] = 0f; vertices[3] = 0f;
vertices[4] = 0f; vertices[4] = 0f;
// top right // top right
vertices[5] = right; vertices[5] = right;
vertices[6] = top; vertices[6] = top;
vertices[7] = 0f; vertices[7] = 0f;
vertices[8] = 1f; vertices[8] = 1f;
vertices[9] = 0f; vertices[9] = 0f;
// bottom right // bottom right
vertices[10] = right; vertices[10] = right;
vertices[11] = bottom; vertices[11] = bottom;
vertices[12] = 0f; vertices[12] = 0f;
vertices[13] = 1f; vertices[13] = 1f;
vertices[14] = 1f; vertices[14] = 1f;
// bottom left // bottom left
vertices[15] = left; vertices[15] = left;
vertices[16] = bottom; vertices[16] = bottom;
vertices[17] = 0f; vertices[17] = 0f;
vertices[18] = 0f; vertices[18] = 0f;
vertices[19] = 1f; vertices[19] = 1f;
} }
} }
static class Program { static class Program {
static void Main(string[] args) { static void Main(string[] args) {
List<MonitorInfo> monitors = Monitors.GetMonitors(); List<MonitorInfo> monitors = Monitors.GetMonitors();
MonitorInfo bestMonitor = monitors[0]; MonitorInfo bestMonitor = monitors[0];
int bestResolution = bestMonitor.HorizontalResolution * bestMonitor.VerticalResolution; int bestResolution = bestMonitor.HorizontalResolution * bestMonitor.VerticalResolution;
for (int i = 1; i < monitors.Count; i++) { for (int i = 1; i < monitors.Count; i++) {
MonitorInfo monitor = monitors[i]; MonitorInfo monitor = monitors[i];
int resolution = monitor.HorizontalResolution * monitor.VerticalResolution; int resolution = monitor.HorizontalResolution * monitor.VerticalResolution;
if (resolution > bestResolution) { if (resolution > bestResolution) {
bestResolution = resolution; bestResolution = resolution;
bestMonitor = monitor; bestMonitor = monitor;
} }
} }
Console.WriteLine($"best monitor: {bestMonitor.HorizontalResolution}x{bestMonitor.VerticalResolution}"); Console.WriteLine($"best monitor: {bestMonitor.HorizontalResolution}x{bestMonitor.VerticalResolution}");
GameWindowSettings gwSettings = new GameWindowSettings(); GameWindowSettings gwSettings = new GameWindowSettings();
gwSettings.RenderFrequency = 60.0; gwSettings.RenderFrequency = 60.0;
NativeWindowSettings nwSettings = new NativeWindowSettings(); NativeWindowSettings nwSettings = new NativeWindowSettings();
nwSettings.WindowState = WindowState.Normal; nwSettings.WindowState = WindowState.Normal;
nwSettings.CurrentMonitor = bestMonitor.Handle; nwSettings.CurrentMonitor = bestMonitor.Handle;
nwSettings.Location = new Vector2i(bestMonitor.WorkArea.Min.X + 1, bestMonitor.WorkArea.Min.Y + 31); nwSettings.Location = new Vector2i(bestMonitor.WorkArea.Min.X + 1, bestMonitor.WorkArea.Min.Y + 31);
nwSettings.Size = new Vector2i(bestMonitor.WorkArea.Size.X - 2, bestMonitor.WorkArea.Size.Y - 32); nwSettings.Size = new Vector2i(bestMonitor.WorkArea.Size.X - 2, bestMonitor.WorkArea.Size.Y - 32);
nwSettings.Title = "Totte"; nwSettings.Title = "Totte";
// FIXME: nwSettings.Icon = ... // FIXME: nwSettings.Icon = ...
using (Game game = new Game(gwSettings, nwSettings)) { using (Game game = new Game(gwSettings, nwSettings)) {
game.Run(); game.Run();
} }
} }
} }