Skip to content

Instantly share code, notes, and snippets.

@leonkasovan
Created November 8, 2024 10:28
Show Gist options
  • Save leonkasovan/d8e620ce6639b687dcaa2193f138b4e2 to your computer and use it in GitHub Desktop.
Save leonkasovan/d8e620ce6639b687dcaa2193f138b4e2 to your computer and use it in GitHub Desktop.
Compile OpenGL shader using GLFW
package main
import (
"fmt"
"io/ioutil"
"log"
"runtime"
"os"
"path/filepath"
"strings"
"github.com/leonkasovan/gl/v2.1/gl"
"github.com/go-gl/glfw/v3.3/glfw"
)
// Initialize GLFW and set up an OpenGL context for version 2.1
func initGLFW() *glfw.Window {
if err := glfw.Init(); err != nil {
log.Fatalln("failed to initialize glfw:", err)
}
// Set OpenGL version to 2.1
glfw.WindowHint(glfw.ContextVersionMajor, 2)
glfw.WindowHint(glfw.ContextVersionMinor, 1)
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLAnyProfile) // OpenGL 2.1 does not require core profile
// Create a windowed mode window and OpenGL context
window, err := glfw.CreateWindow(800, 600, "OpenGL 2.1 in Go", nil, nil)
if err != nil {
glfw.Terminate()
log.Fatalln("failed to create glfw window:", err)
}
window.MakeContextCurrent()
return window
}
// Initialize OpenGL, must be called after creating the OpenGL context
func initOpenGL() {
if err := gl.Init(); err != nil {
log.Fatalln("failed to initialize OpenGL:", err)
}
version := gl.GoStr(gl.GetString(gl.VERSION))
fmt.Println("OpenGL version", version)
}
// Reads shader source code from a file
func readShaderSource(filename string) (string, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
return "", err
}
return string(data) + "\x00", nil // Add null terminator for OpenGL
}
// Compiles a shader from a file
func compileShaderFromFile(filename string, shaderType uint32) (uint32, error) {
// Read the shader source from file
source, err := readShaderSource(filename)
if err != nil {
return 0, fmt.Errorf("failed to read shader file %s: %v", filename, err)
}
// Create and compile shader
shader := gl.CreateShader(shaderType)
csources, free := gl.Strs(source)
defer free()
gl.ShaderSource(shader, 1, csources, nil)
gl.CompileShader(shader)
// Check for compile errors
var status int32
gl.GetShaderiv(shader, gl.COMPILE_STATUS, &status)
if status == 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])
return 0, fmt.Errorf("failed to compile shader from %s: %s", filename, log)
}
return shader, nil
}
// Link shaders into a program
func createProgram(vertexShader, fragmentShader uint32) (uint32, error) {
program := gl.CreateProgram()
gl.AttachShader(program, vertexShader)
gl.AttachShader(program, fragmentShader)
gl.LinkProgram(program)
var status int32
gl.GetProgramiv(program, gl.LINK_STATUS, &status)
if status == 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])
return 0, fmt.Errorf("failed to link program: %s", log)
}
gl.DeleteShader(vertexShader)
gl.DeleteShader(fragmentShader)
return program, nil
}
func main() {
// Lock the OS thread, as OpenGL requires
runtime.LockOSThread()
defer glfw.Terminate()
// Initialize GLFW and create an OpenGL context
// var vertexShader, fragmentShader uint32
initGLFW()
initOpenGL() // Initialize OpenGL after creating a context
// Get the current directory
dir, err := os.Getwd()
if err != nil {
fmt.Println("Error getting current directory:", err)
return
}
// Walk through the directory
err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// Check if the item is a file and if "frag" is in the file name
if !info.IsDir() && strings.Contains(info.Name(), "frag") {
fmt.Printf("\n------------------------------------------------\n%v\n", info.Name()) // Print the file name
_, err = compileShaderFromFile(info.Name(), gl.FRAGMENT_SHADER)
if err != nil {
log.Fatalln("Error compiling fragment shader:", err)
}
}
if !info.IsDir() && strings.Contains(info.Name(), "vert") {
fmt.Printf("\n------------------------------------------------\n%v\n", info.Name()) // Print the file name
_, err = compileShaderFromFile(info.Name(), gl.VERTEX_SHADER)
if err != nil {
log.Fatalln("Error compiling fragment shader:", err)
}
}
return nil
})
if err != nil {
fmt.Println("Error walking through directory:", err)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment