Skip to content

Instantly share code, notes, and snippets.

@kerrermanisNL
Created September 19, 2024 14:37
Show Gist options
  • Save kerrermanisNL/12796cfdb57640325d4fbd4f3259974e to your computer and use it in GitHub Desktop.
Save kerrermanisNL/12796cfdb57640325d4fbd4f3259974e to your computer and use it in GitHub Desktop.
LearnOpenTK - Simple texture
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;
using OpenTK.Graphics.OpenGL4;
using System.Diagnostics;
namespace OpenTKPractice
{
public class Game : GameWindow
{
int VertexBufferObject;
int VertexArrayObject;
int ElementBufferObject;
float[] vertices = {
0.5f, 0.5f, 0.0f, 1.0f, 1.0f, // top right
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, // bottom right
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, // bottom left
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f // top left
};
uint[] indices = {
0, 1, 3,
1, 2, 3
};
Shader shader;
Texture texture;
public Game(int width, int height, string title)
: base(GameWindowSettings.Default, new NativeWindowSettings() { ClientSize = (width, height), Title = title })
{
}
protected override void OnLoad()
{
base.OnLoad();
GL.ClearColor(0.2f, 0.3f, 0.3f, 1.0f);
this.VertexArrayObject = GL.GenVertexArray();
GL.BindVertexArray(this.VertexArrayObject);
this.VertexBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ArrayBuffer, this.VertexBufferObject);
GL.BufferData(BufferTarget.ArrayBuffer, this.vertices.Length * sizeof(float), this.vertices, BufferUsageHint.StaticDraw);
this.ElementBufferObject = GL.GenBuffer();
GL.BindBuffer(BufferTarget.ElementArrayBuffer, this.ElementBufferObject);
GL.BufferData(BufferTarget.ElementArrayBuffer, indices.Length * sizeof(uint), indices, BufferUsageHint.StaticDraw);
this.shader = new Shader("../../../shader.vert", "../../../shader.frag");
shader.Use();
GL.VertexAttribPointer(0, 3, VertexAttribPointerType.Float, false, 5 * sizeof(float), 0);
GL.EnableVertexAttribArray(0);
GL.EnableVertexAttribArray(1);
GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, 5 * sizeof(float), 3 * sizeof(float));
this.texture = new Texture("../../../Textures/container.jpg");
}
protected override void OnRenderFrame(FrameEventArgs args)
{
base.OnRenderFrame(args);
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.BindVertexArray(this.VertexArrayObject);
this.shader.Use();
GL.DrawElements(PrimitiveType.Triangles, this.indices.Length, DrawElementsType.UnsignedInt, 0);
SwapBuffers();
}
protected override void OnUnload()
{
base.OnUnload();
this.shader.Dispose();
}
protected override void OnUpdateFrame(FrameEventArgs args)
{
base.OnUpdateFrame(args);
if (KeyboardState.IsKeyDown(Keys.Escape))
{
Close();
}
}
protected override void OnFramebufferResize(FramebufferResizeEventArgs e)
{
base.OnFramebufferResize(e);
GL.Viewport(0, 0, e.Width, e.Height);
}
}
}
using OpenTK.Mathematics;
using OpenTK.Windowing.Common;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;
using OpenTK.Graphics.OpenGL4;
namespace OpenTKPractice
{
public static class Program
{
public static void Main()
{
using (Game game = new Game(800, 600, "LearnOpenTK"))
{
game.Run();
}
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using OpenTK.Graphics.OpenGL4;
namespace OpenTKPractice
{
internal class Shader : IDisposable
{
public int Handle;
private bool disposedValue = false;
public Shader(string vertexPath, string fragmentPath)
{
int vertexShader = this.GenerateVertexShader(vertexPath);
int fragmentShader = this.GenerateFragmentShader(fragmentPath);
this.GenerateProgram(vertexShader, fragmentShader);
this.CleanUp(vertexShader, fragmentShader);
}
public void Use()
{
GL.UseProgram(this.Handle);
}
private int GenerateVertexShader(string sourcePath)
{
return this.GenerateShader(sourcePath, ShaderType.VertexShader);
}
private int GenerateFragmentShader(string sourcePath)
{
return this.GenerateShader(sourcePath, ShaderType.FragmentShader);
}
private int GenerateShader(string sourcePath, ShaderType type)
{
string ShaderSource = File.ReadAllText(sourcePath);
int Shader = GL.CreateShader(type);
GL.ShaderSource(Shader, ShaderSource);
GL.CompileShader(Shader);
GL.GetShader(Shader, ShaderParameter.CompileStatus, out int success);
if (success == 0)
{
string infoLog = GL.GetShaderInfoLog(Shader);
Console.WriteLine(infoLog);
}
return Shader;
}
private void GenerateProgram(int vertexShader, int fragmentShader)
{
this.Handle = GL.CreateProgram();
GL.AttachShader(Handle, vertexShader);
GL.AttachShader(Handle, fragmentShader);
GL.LinkProgram(Handle);
GL.GetProgram(Handle, GetProgramParameterName.LinkStatus, out int success);
if (success == 0)
{
string infoLog = GL.GetProgramInfoLog(Handle);
Console.WriteLine(infoLog);
}
}
private void CleanUp(int vertexShader, int fragmentShader)
{
GL.DetachShader(Handle, vertexShader);
GL.DetachShader(Handle, fragmentShader);
GL.DeleteShader(vertexShader);
GL.DeleteShader(fragmentShader);
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
GL.DeleteProgram(Handle);
disposedValue = true;
}
}
~Shader()
{
if (disposedValue == false)
{
Console.WriteLine("GPU Resource leak! Did you forget to call Dispose()?");
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
#version 330 core
out vec4 outputColor;
in vec2 texCoord;
uniform sampler2D texture0;
void main()
{
outputColor = texture(texture0, texCoord);
}
#version 330 core
layout (location = 0) in vec3 aPosition;
layout (location = 1) in vec2 aTexCoord;
out vec2 texCoord;
void main()
{
texCoord = aTexCoord;
gl_Position = vec4(aPosition, 1.0);
}
using System;
using OpenTK.Graphics.OpenGL4;
using StbImageSharp;
namespace OpenTKPractice
{
internal class Texture
{
public int Handle;
public Texture(string path)
{
this.Handle = GL.GenTexture();
GL.ActiveTexture(TextureUnit.Texture0);
GL.BindTexture(TextureTarget.Texture2D, this.Handle);
StbImage.stbi_set_flip_vertically_on_load(1);
using (Stream stream = File.OpenRead(path))
{
ImageResult image = ImageResult.FromStream(stream, ColorComponents.RedGreenBlueAlpha);
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, PixelFormat.Rgba, PixelType.UnsignedByte, image.Data);
}
GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment