|
|
@ -103,7 +103,7 @@ void main() { |
|
|
|
|
|
|
|
~Shader() { |
|
|
|
if (disposedValue == false) { |
|
|
|
Console.WriteLine("GPU Resource leak! Did you forget to call Dispose()?"); |
|
|
|
Console.WriteLine("~Shader(): resource leak? Dispose() should be called manually."); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -122,6 +122,53 @@ void main() { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
public class Texture : IDisposable { |
|
|
|
public int Handle; |
|
|
|
|
|
|
|
public Texture(string path) { |
|
|
|
Image<Rgba32> image = Image.Load<Rgba32>(path); |
|
|
|
Console.WriteLine($"{image.Width}x{image.Height}"); |
|
|
|
//foreach (IExifValue exif in image.Metadata.ExifProfile.Values) {
|
|
|
|
// Console.WriteLine($"{exif.Tag} : {exif.GetValue()}");
|
|
|
|
//}
|
|
|
|
byte[] pixelBytes = new byte[image.Width * image.Height * Unsafe.SizeOf<Rgba32>()]; |
|
|
|
image.CopyPixelDataTo(pixelBytes); |
|
|
|
image.Dispose(); |
|
|
|
|
|
|
|
Handle = GL.GenTexture(); |
|
|
|
GL.ActiveTexture(TextureUnit.Texture0); |
|
|
|
GL.BindTexture(TextureTarget.Texture2D, Handle); |
|
|
|
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.TextureMagFilter, (int) TextureMagFilter.Nearest); |
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToBorder); |
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToBorder); |
|
|
|
float[] borderColor = { 0.0f, 0.0f, 0.0f, 1.0f }; |
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, borderColor); |
|
|
|
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); |
|
|
|
} |
|
|
|
|
|
|
|
private bool disposedValue = false; |
|
|
|
|
|
|
|
protected virtual void Dispose(bool disposing) { |
|
|
|
if (!disposedValue) { |
|
|
|
GL.DeleteTexture(Handle); |
|
|
|
disposedValue = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
~Texture() { |
|
|
|
if (!disposedValue) { |
|
|
|
Console.WriteLine("~Texture(): resource leak? Dispose() should be called manually."); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public void Dispose() { |
|
|
|
Dispose(true); |
|
|
|
GC.SuppressFinalize(this); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public class Game : GameWindow { |
|
|
|
public Game(GameWindowSettings gwSettings, NativeWindowSettings nwSettings) : base(gwSettings, nwSettings) { } |
|
|
|
|
|
|
@ -144,7 +191,7 @@ public class Game : GameWindow { |
|
|
|
int VertexBufferObject; |
|
|
|
int ElementBufferObject; |
|
|
|
int VertexArrayObject; |
|
|
|
int texture; |
|
|
|
Texture texture; |
|
|
|
Shader shader; |
|
|
|
Matrix4 projection; |
|
|
|
|
|
|
@ -191,29 +238,8 @@ public class Game : GameWindow { |
|
|
|
GL.EnableVertexAttribArray(texCoordLocation); |
|
|
|
GL.VertexAttribPointer(texCoordLocation, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float)); |
|
|
|
|
|
|
|
// Decode a JPEG image.
|
|
|
|
//Image<Rgba32> image = Image.Load<Rgba32>(@"c:\users\colin\pictures\texture.jpg");
|
|
|
|
Image<Rgba32> image = Image.Load<Rgba32>(@"c:\users\colin\pictures\photos\2023\06\27\DSC_0035.jpg"); |
|
|
|
Console.WriteLine($"{image.Width}x{image.Height}"); |
|
|
|
//foreach (IExifValue exif in image.Metadata.ExifProfile.Values) {
|
|
|
|
// Console.WriteLine($"{exif.Tag} : {exif.GetValue()}");
|
|
|
|
//}
|
|
|
|
byte[] pixelBytes = new byte[image.Width * image.Height * Unsafe.SizeOf<Rgba32>()]; |
|
|
|
image.CopyPixelDataTo(pixelBytes); |
|
|
|
image.Dispose(); |
|
|
|
|
|
|
|
// TODO: put the texture into an actual class.
|
|
|
|
texture = GL.GenTexture(); |
|
|
|
GL.ActiveTexture(TextureUnit.Texture0); |
|
|
|
GL.BindTexture(TextureTarget.Texture2D, texture); |
|
|
|
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.TextureMagFilter, (int) TextureMagFilter.Nearest); |
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int) TextureWrapMode.ClampToBorder); |
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int) TextureWrapMode.ClampToBorder); |
|
|
|
float[] borderColor = { 0.0f, 0.0f, 0.0f, 1.0f }; |
|
|
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, borderColor); |
|
|
|
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D); |
|
|
|
// Load textures from JPEGs.
|
|
|
|
texture = new Texture(@"c:\users\colin\pictures\photos\2023\06\27\DSC_0035.jpg"); |
|
|
|
} |
|
|
|
|
|
|
|
protected override void OnUnload() { |
|
|
@ -226,7 +252,7 @@ public class Game : GameWindow { |
|
|
|
GL.Clear(ClearBufferMask.ColorBufferBit); |
|
|
|
GL.BindVertexArray(VertexArrayObject); |
|
|
|
GL.ActiveTexture(TextureUnit.Texture0); |
|
|
|
GL.BindTexture(TextureTarget.Texture2D, texture); |
|
|
|
GL.BindTexture(TextureTarget.Texture2D, texture.Handle); |
|
|
|
shader.Use(); |
|
|
|
GL.DrawElements(PrimitiveType.Triangles, indices.Length, DrawElementsType.UnsignedInt, 0); |
|
|
|
SwapBuffers(); |
|
|
|