commit a0e8551c5f81c75329fdba8d461419cf6e4a715b Author: illyum Date: Sat Nov 23 21:54:20 2024 -0700 Working Version diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2cab0c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +hudly-gl.sublime-workspace \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..29679d4 --- /dev/null +++ b/go.mod @@ -0,0 +1,10 @@ +module hudly-gl + +go 1.23.0 + +require ( + github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 + github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a +) + +require github.com/go-gl/mathgl v1.2.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..2f005c7 --- /dev/null +++ b/go.sum @@ -0,0 +1,6 @@ +github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 h1:5BVwOaUSBTlVZowGO6VZGw2H/zl9nrd3eCZfYV+NfQA= +github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71/go.mod h1:9YTyiznxEY1fVinfM7RvRcjRHbw2xLBJ3AAGIT0I4Nw= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a h1:vxnBhFDDT+xzxf1jTJKMKZw3H0swfWk9RpWbBbDK5+0= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/mathgl v1.2.0 h1:v2eOj/y1B2afDxF6URV1qCYmo1KW08lAMtTbOn3KXCY= +github.com/go-gl/mathgl v1.2.0/go.mod h1:pf9+b5J3LFP7iZ4XXaVzZrCle0Q/vNpB/vDe5+3ulRE= diff --git a/hlgl.go b/hlgl.go new file mode 100644 index 0000000..0bff41e --- /dev/null +++ b/hlgl.go @@ -0,0 +1,46 @@ +// HLGL High Level GL Abstraction Layer +package main + +import "github.com/go-gl/gl/v4.1-core/gl" + +type HLRectangle struct { + X int + Y int + Width int + Height int +} + +type HLColorRGBA struct { + R int + G int + B int + A int +} + +func DrawRectangleWH(x, y, width, height int, color HLColorRGBA) { + // Triangle ONE + var triangleOneVerticies = []float32{ + float32(x), float32(y), 0.0, + float32(x), float32(y + height), 0.0, + float32(x + width), float32(y), 0.0, + } + var triangleOneVAO = NewVertexArray() + var trianglOneVBO = NewVertexBuffer(triangleOneVerticies) + triangleOneVAO.AddBuffer(trianglOneVBO, []int32{3}) + triangleOneVAO.Bind() + gl.DrawArrays(gl.TRIANGLES, 0, 3) + + // Triangle TWO + var triangleTwoVerticies = []float32{ + float32(x + width), float32(y + height), 0.0, + float32(x), float32(y + height), 0.0, + float32(x + width), float32(y), 0.0, + } + var triangleTwoVAO = NewVertexArray() + var trianglTwoVBO = NewVertexBuffer(triangleTwoVerticies) + triangleTwoVAO.AddBuffer(trianglTwoVBO, []int32{3}) + triangleTwoVAO.Bind() + gl.DrawArrays(gl.TRIANGLES, 0, 3) +} + +func DrawRectangleRec(rectangle HLRectangle, color HLColorRGBA) {} diff --git a/hudly-gl.sublime-project b/hudly-gl.sublime-project new file mode 100644 index 0000000..21a9059 --- /dev/null +++ b/hudly-gl.sublime-project @@ -0,0 +1,18 @@ +{ + "folders": [ + { + "path": "." + } + ], + "settings": { + "LSP": { + "gopls": { + "enabled": true, + "settings": { + "experimentalWorkspaceModule": true, + } + } + }, + "lsp_format_on_save": true + } +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..04f8465 --- /dev/null +++ b/main.go @@ -0,0 +1,109 @@ +package main + +import ( + "fmt" + "runtime" + + "github.com/go-gl/gl/v4.1-core/gl" + "github.com/go-gl/glfw/v3.3/glfw" + "github.com/go-gl/mathgl/mgl32" +) + +const ( + start_width = 1920 + start_height = 1080 +) + +var vertices = []float32{ + 960, 540, 0.0, + 1460, 540, 0.0, + 960, 1040, 0.0, +} + +const vertexShaderSource = ` +#version 410 core +layout(location = 0) in vec3 position; +uniform mat4 u_Projection; +void main() { + gl_Position = u_Projection * vec4(position, 1.0); +} +` + +const fragmentShaderSource = ` +#version 410 core +out vec4 color; +uniform vec4 u_Color; +void main() { + color = u_Color; +} +` + +func main() { + runtime.LockOSThread() + + if err := glfw.Init(); err != nil { + } + defer glfw.Terminate() + glfw.WindowHint(glfw.Decorated, glfw.True) + glfw.WindowHint(glfw.TransparentFramebuffer, glfw.False) + glfw.WindowHint(glfw.Resizable, glfw.False) + + glfw.WindowHint(glfw.ContextVersionMajor, 4) + glfw.WindowHint(glfw.ContextVersionMinor, 1) + glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile) + // glfw.WindowHint(glfw.TransparentFramebuffer, glfw.True) + + window, err := glfw.CreateWindow(start_width, start_height, "Learning OpenGL", nil, nil) + if err != nil { + } + defer window.Destroy() + + window.MakeContextCurrent() + + if err := gl.Init(); err != nil { + glfw.Terminate() + } + + gl.Viewport(0, 0, int32(start_width), int32(start_height)) + + window.SetMouseButtonCallback(func(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) { + println("Mouse Button Event!") + }) + + window.SetSizeCallback(func(w *glfw.Window, width int, height int) { + fmt.Printf("Window resize event - Width: %d, Height: %d\n", width, height) + }) + + shader, _ := NewShader(vertexShaderSource, fragmentShaderSource) + + projection := CreateOrthographicProjection(start_width, start_height) + + vao := NewVertexArray() + vbo := NewVertexBuffer(vertices) + vao.AddBuffer(vbo, []int32{3}) + + gl.ClearColor(0.2, 0.3, 0.3, 1.0) + + for !window.ShouldClose() { + shader.Use() + + shader.SetUniformM("u_Projection", projection) + color := HLColorRGBA{255, 0, 0, 255} + shader.SetUniform4f("u_Color", float32(color.R)/255.0, float32(color.G)/255.0, float32(color.B)/255.0, float32(color.A)/255.0) + + gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT) + + // Handled by the Draw Rectangle function + // vao.Bind() + // gl.DrawArrays(gl.TRIANGLES, 0, 3) + DrawRectangleWH(0, 0, 100, 200, HLColorRGBA{255, 0, 0, 255}) + + window.SwapBuffers() + glfw.PollEvents() + } + +} + +func CreateOrthographicProjection(width, height int) mgl32.Mat4 { + return mgl32.Ortho(0, float32(width), 0, float32(height), -1, 1) +} diff --git a/shader.go b/shader.go new file mode 100644 index 0000000..8000ac2 --- /dev/null +++ b/shader.go @@ -0,0 +1,83 @@ +package main + +import ( + "fmt" + + "github.com/go-gl/gl/v4.1-core/gl" + "github.com/go-gl/mathgl/mgl32" +) + +type Shader struct { + ProgramID uint32 +} + +func NewShader(vSource, fSource string) (*Shader, error) { + vertexShader := compileShader(gl.VERTEX_SHADER, vSource) + fragmentShader := compileShader(gl.FRAGMENT_SHADER, fSource) + + program := gl.CreateProgram() + gl.AttachShader(program, vertexShader) + gl.AttachShader(program, fragmentShader) + gl.LinkProgram(program) + + var success int32 + gl.GetProgramiv(program, gl.LINK_STATUS, &success) + if success == gl.FALSE { + var logLength int32 + gl.GetProgramiv(program, gl.INFO_LOG_LENGTH, &logLength) + + log := make([]byte, logLength+1) + gl.GetProgramInfoLog(program, logLength, nil, &log[0]) + fmt.Printf("Failed to link program: %s\n", log) + return nil, fmt.Errorf("failed to link shader program") + } + + gl.DeleteShader(vertexShader) + gl.DeleteShader(fragmentShader) + + return &Shader{ProgramID: program}, nil +} + +func (s *Shader) Use() { + gl.UseProgram(s.ProgramID) +} + +func (s *Shader) SetUniform(name string, value float32) { + location := s.getUniformLocation(name) + gl.Uniform1f(location, value) +} + +func (s *Shader) SetUniformM(name string, matrix mgl32.Mat4) { + location := s.getUniformLocation(name) + gl.UniformMatrix4fv(location, 1, false, &matrix[0]) +} + +func (s *Shader) SetUniform4f(name string, v0, v1, v2, v3 float32) { + location := gl.GetUniformLocation(s.ProgramID, gl.Str(name+"\x00")) + gl.Uniform4f(location, v0, v1, v2, v3) +} + +func (s *Shader) getUniformLocation(name string) int32 { + cName := gl.Str(name + "\x00") + return gl.GetUniformLocation(s.ProgramID, cName) +} + +func compileShader(shaderType uint32, source string) uint32 { + shader := gl.CreateShader(shaderType) + cSource, free := gl.Strs(source + "\x00") + gl.ShaderSource(shader, 1, cSource, nil) + free() + gl.CompileShader(shader) + + var success int32 + gl.GetShaderiv(shader, gl.COMPILE_STATUS, &success) + if success == gl.FALSE { + var logLength int32 + gl.GetShaderiv(shader, gl.INFO_LOG_LENGTH, &logLength) + + log := make([]byte, logLength+1) + gl.GetShaderInfoLog(shader, logLength, nil, &log[0]) + fmt.Printf("Failed to compile shader: %s\n", log) + } + return shader +} diff --git a/vertex_buffer.go b/vertex_buffer.go new file mode 100644 index 0000000..be23872 --- /dev/null +++ b/vertex_buffer.go @@ -0,0 +1,59 @@ +package main + +import "github.com/go-gl/gl/v4.1-core/gl" + +type VertexBuffer struct { + bufferId uint32 +} + +func NewVertexBuffer(data []float32) *VertexBuffer { + var bufferID uint32 + gl.GenBuffers(1, &bufferID) + gl.BindBuffer(gl.ARRAY_BUFFER, bufferID) + gl.BufferData(gl.ARRAY_BUFFER, len(data)*4, gl.Ptr(data), gl.STATIC_DRAW) + + return &VertexBuffer{bufferId: bufferID} +} + +func (vb *VertexBuffer) Bind() { + gl.BindBuffer(gl.ARRAY_BUFFER, vb.bufferId) +} + +func (vb *VertexBuffer) Unbind() { + gl.BindBuffer(gl.ARRAY_BUFFER, 0) +} + +type VertexArray struct { + ID uint32 +} + +func NewVertexArray() *VertexArray { + var id uint32 + gl.GenVertexArrays(1, &id) + return &VertexArray{ID: id} +} + +func (va *VertexArray) AddBuffer(vb *VertexBuffer, layout []int32) { + va.Bind() + vb.Bind() + stride := int32(0) + for _, size := range layout { + stride += size + } + stride *= 4 // Each float is 4 bytes + + offset := uintptr(0) + for i, size := range layout { + gl.EnableVertexAttribArray(uint32(i)) + gl.VertexAttribPointer(uint32(i), size, gl.FLOAT, false, stride, gl.PtrOffset(int(offset))) + offset += uintptr(size * 4) + } +} + +func (va *VertexArray) Bind() { + gl.BindVertexArray(va.ID) +} + +func (va *VertexArray) Unbind() { + gl.BindVertexArray(0) +}