Created
November 8, 2024 10:28
-
-
Save leonkasovan/d8e620ce6639b687dcaa2193f138b4e2 to your computer and use it in GitHub Desktop.
Compile OpenGL shader using GLFW
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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