Skip to content

Instantly share code, notes, and snippets.

@tinne26
Created August 3, 2022 09:49
Show Gist options
  • Save tinne26/73ee853978c07140bdcaf3d6b358359f to your computer and use it in GitHub Desktop.
Save tinne26/73ee853978c07140bdcaf3d6b358359f to your computer and use it in GitHub Desktop.
package main
import "time"
import "fmt"
import "log"
import "strings"
import "runtime"
import "math"
import "github.com/go-gl/glfw/v3.3/glfw"
import "github.com/go-gl/gl/v4.1-core/gl"
func init() { runtime.LockOSThread() }
var shaderStr = `
#version 300 es // ****** YOU MAY NEED TO CHANGE THE OPEN GL VERSION ******
precision mediump float;
out vec4 outputColor;
uniform float blue;
uniform float scrWidth;
uniform float scrHeight;
void main() {
if (gl_FragCoord.x < 2.0 || gl_FragCoord.x > scrWidth - 2.0) {
outputColor = vec4(1.0, 1.0, 0.0, 1.0);
} else if (gl_FragCoord.y < 2.0 || gl_FragCoord.y > scrHeight - 2.0) {
outputColor = vec4(0.0, 1.0, 1.0, 1.0);
} else {
outputColor = vec4(1.0, 0.0, blue, 1.0);
}
}
` + "\x00"
func main() {
var err error
// glfw / window init
fmt.Printf("glfw and window init\n")
err = glfw.Init()
if err != nil { log.Fatal(err) }
defer glfw.Terminate()
monitor := glfw.GetPrimaryMonitor()
xScale, yScale := monitor.GetContentScale()
fmt.Printf("content scale: %f, %f\n", xScale, yScale)
w, h, refreshRate := getResolutionAndRate(monitor)
var window *glfw.Window
fullscreen := true // switch for debugging and comparing to windowed version and seeing fps
if fullscreen {
window, err = glfw.CreateWindow(w, h, "glfw fullscreen test", nil, nil)
if err != nil { log.Fatal(err) }
window.SetMonitor(monitor, 0, 0, w, h, refreshRate)
} else {
w, h = 640, 480
window, err = glfw.CreateWindow(w, h, "glfw fullscreen test", nil, nil)
if err != nil { log.Fatal(err) }
}
window.MakeContextCurrent()
glfw.SwapInterval(1)
// gl init
fmt.Printf("initializing go-gl\n")
err = gl.Init()
if err != nil { log.Fatal(err) }
// create shader
shader, err := compileShader(shaderStr, gl.FRAGMENT_SHADER)
if err != nil { log.Fatal(err) }
program := gl.CreateProgram()
gl.AttachShader(program, shader)
gl.LinkProgram(program)
gl.DeleteShader(shader)
gl.UseProgram(program)
blueUniform := gl.GetUniformLocation(program, gl.Str("blue\x00"))
scrWidthUniform := gl.GetUniformLocation(program, gl.Str("scrWidth\x00"))
scrHeightUniform := gl.GetUniformLocation(program, gl.Str("scrHeight\x00"))
gl.Uniform1f(scrWidthUniform , float32(w))
gl.Uniform1f(scrHeightUniform, float32(h))
// create vertex buffer and vertex array objects
var vertexBufferObject, vertexArrayObject uint32
gl.GenBuffers(1, &vertexBufferObject)
gl.BindBuffer(gl.ARRAY_BUFFER, vertexBufferObject)
vertices := []float32{-1, -1, -1, 1, 1, 1, -1, -1, 1, 1, 1, -1}
gl.BufferData(gl.ARRAY_BUFFER, 12*4, gl.Ptr(vertices), gl.STATIC_DRAW)
gl.GenVertexArrays(1, &vertexArrayObject)
gl.BindVertexArray(vertexArrayObject)
// leave vertex attrib enabled
gl.EnableVertexAttribArray(0)
gl.VertexAttribPointer(0, 2, gl.FLOAT, false, 0, nil)
// leave the program running
fpsTime := time.Now()
ticks := 0
for !window.ShouldClose() {
// update title fps every second
now := time.Now()
elapsed := now.Sub(fpsTime)
if elapsed >= time.Second {
window.SetTitle(fmt.Sprintf("glfw fullscreen test %.2ffps", float64(ticks)/elapsed.Seconds()))
fpsTime = now
ticks = 0
}
// poll events so the app is not detected as unresponsive
glfw.PollEvents()
// draw stuff
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
gl.UseProgram(program)
gl.Uniform1f(blueUniform, float32(math.Sin(float64(now.UnixNano())/666666666))/1.6) // sorcery
gl.DrawArrays(gl.TRIANGLES, 0, 6)
gl.UseProgram(0)
window.SwapBuffers()
ticks += 1
}
}
func compileShader(source string, shaderType uint32) (uint32, error) {
shader := gl.CreateShader(shaderType)
csources, freeCallback := gl.Strs(source)
gl.ShaderSource(shader, 1, csources, nil)
freeCallback()
gl.CompileShader(shader)
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)
logStr := strings.Repeat("\x00", int(logLength+1))
gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(logStr))
return 0, fmt.Errorf("failed to compile %v: %v", source, logStr)
}
return shader, nil
}
// returns the maximum width, height and refresh rates found among video modes.
// not technically correct, but should almost always work ok in practice
func getResolutionAndRate(monitor *glfw.Monitor) (int, int, int) {
var width, height, rate int
for _, vidMode := range monitor.GetVideoModes() {
if vidMode.Width > width { width = vidMode.Width }
if vidMode.Height > height { height = vidMode.Height }
if vidMode.RefreshRate > rate {
rate = vidMode.RefreshRate
}
}
return width, height, rate
}
@tinne26
Copy link
Author

tinne26 commented Aug 3, 2022

Note: this is missing window.SetAttrib and not setting window titles while in fullscreen, which may cause a top bar to appear even in fullscreen (or even a black bar).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment