You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
199 lines
4.7 KiB
199 lines
4.7 KiB
3 years ago
|
package main
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"image"
|
||
|
"log"
|
||
|
"runtime"
|
||
|
"strings"
|
||
|
|
||
|
"github.com/go-gl/gl/v4.1-core/gl" // OR: github.com/go-gl/gl/v2.1/gl
|
||
|
"github.com/go-gl/glfw/v3.2/glfw"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
vertexShaderSource = `
|
||
|
#version 410
|
||
|
in vec3 vp;
|
||
|
in vec2 vertTexCoord;
|
||
|
out vec2 fragTexCoord;
|
||
|
void main() {
|
||
|
fragTexCoord = vertTexCoord;
|
||
|
gl_Position = vec4(vp, 1.0);
|
||
|
}
|
||
|
` + "\x00"
|
||
|
|
||
|
fragmentShaderSource = `
|
||
|
#version 330
|
||
|
uniform sampler2D tex;
|
||
|
in vec2 fragTexCoord;
|
||
|
out vec4 outputColor;
|
||
|
void main() {
|
||
|
outputColor = texture(tex, fragTexCoord);
|
||
|
}
|
||
|
` + "\x00"
|
||
|
)
|
||
|
|
||
|
var fullscreenQuad = []float32{
|
||
|
// X, Y, Z, U, V
|
||
|
-1, 1, 0, 0, 1,
|
||
|
-1, -1, 0, 0, 0,
|
||
|
1, -1, 0, 1, 0,
|
||
|
-1, 1, 0, 0, 1,
|
||
|
1, 1, 0, 1, 1,
|
||
|
1, -1, 0, 1, 0,
|
||
|
}
|
||
|
|
||
|
// basic OpenGL based display application copy and pasted from
|
||
|
// https://kylewbanks.com/blog/tutorial-opengl-with-golang-part-1-hello-opengl
|
||
|
func run_opengl_app(getImage func() *image.RGBA) {
|
||
|
runtime.LockOSThread()
|
||
|
|
||
|
window := initGlfw()
|
||
|
defer glfw.Terminate()
|
||
|
|
||
|
program := initOpenGL()
|
||
|
|
||
|
for !window.ShouldClose() {
|
||
|
texture, err := newTexture(getImage())
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
draw(makeVertexArrayObject(fullscreenQuad, program), texture, window, program)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func draw(vertexArrayObject uint32, texture uint32, window *glfw.Window, program uint32) {
|
||
|
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
|
||
|
gl.UseProgram(program)
|
||
|
|
||
|
gl.BindVertexArray(vertexArrayObject)
|
||
|
|
||
|
gl.ActiveTexture(gl.TEXTURE0)
|
||
|
gl.BindTexture(gl.TEXTURE_2D, texture)
|
||
|
|
||
|
gl.DrawArrays(gl.TRIANGLES, 0, int32(len(fullscreenQuad)/3))
|
||
|
|
||
|
glfw.PollEvents()
|
||
|
window.SwapBuffers()
|
||
|
}
|
||
|
|
||
|
func initOpenGL() uint32 {
|
||
|
if err := gl.Init(); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
version := gl.GoStr(gl.GetString(gl.VERSION))
|
||
|
log.Println("OpenGL version", version)
|
||
|
|
||
|
vertexShader, err := compileShader(vertexShaderSource, gl.VERTEX_SHADER)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
fragmentShader, err := compileShader(fragmentShaderSource, gl.FRAGMENT_SHADER)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
prog := gl.CreateProgram()
|
||
|
gl.AttachShader(prog, vertexShader)
|
||
|
gl.AttachShader(prog, fragmentShader)
|
||
|
gl.LinkProgram(prog)
|
||
|
return prog
|
||
|
}
|
||
|
|
||
|
// initGlfw initializes glfw and returns a Window to use.
|
||
|
func initGlfw() *glfw.Window {
|
||
|
if err := glfw.Init(); err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
|
||
|
glfw.WindowHint(glfw.Resizable, glfw.False)
|
||
|
glfw.WindowHint(glfw.ContextVersionMajor, 4) // OR 2
|
||
|
glfw.WindowHint(glfw.ContextVersionMinor, 1)
|
||
|
glfw.WindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
|
||
|
glfw.WindowHint(glfw.OpenGLForwardCompatible, glfw.True)
|
||
|
|
||
|
window, err := glfw.CreateWindow(dim, dim, "hilbert test", nil, nil)
|
||
|
if err != nil {
|
||
|
panic(err)
|
||
|
}
|
||
|
window.MakeContextCurrent()
|
||
|
|
||
|
return window
|
||
|
}
|
||
|
|
||
|
// texure coordinate stuff sourced from https://github.com/go-gl/example/blob/master/gl41core-cube/cube.go
|
||
|
func makeVertexArrayObject(points []float32, program uint32) uint32 {
|
||
|
|
||
|
var vao uint32
|
||
|
gl.GenVertexArrays(1, &vao)
|
||
|
gl.BindVertexArray(vao)
|
||
|
|
||
|
var vbo uint32
|
||
|
gl.GenBuffers(1, &vbo)
|
||
|
gl.BindBuffer(gl.ARRAY_BUFFER, vbo)
|
||
|
gl.BufferData(gl.ARRAY_BUFFER, len(points)*4, gl.Ptr(points), gl.STATIC_DRAW)
|
||
|
|
||
|
vertAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vp\x00")))
|
||
|
gl.EnableVertexAttribArray(vertAttrib)
|
||
|
gl.VertexAttribPointerWithOffset(vertAttrib, 3, gl.FLOAT, false, 5*4, 0)
|
||
|
|
||
|
texCoordAttrib := uint32(gl.GetAttribLocation(program, gl.Str("vertTexCoord\x00")))
|
||
|
gl.EnableVertexAttribArray(texCoordAttrib)
|
||
|
gl.VertexAttribPointerWithOffset(texCoordAttrib, 2, gl.FLOAT, false, 5*4, 3*4)
|
||
|
|
||
|
return vao
|
||
|
}
|
||
|
|
||
|
func compileShader(source string, shaderType uint32) (uint32, error) {
|
||
|
shader := gl.CreateShader(shaderType)
|
||
|
|
||
|
csources, free := gl.Strs(source)
|
||
|
gl.ShaderSource(shader, 1, csources, nil)
|
||
|
free()
|
||
|
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)
|
||
|
|
||
|
log := strings.Repeat("\x00", int(logLength+1))
|
||
|
gl.GetShaderInfoLog(shader, logLength, nil, gl.Str(log))
|
||
|
|
||
|
return 0, fmt.Errorf("failed to compile %v: %v", source, log)
|
||
|
}
|
||
|
|
||
|
return shader, nil
|
||
|
}
|
||
|
|
||
|
func newTexture(rgba *image.RGBA) (uint32, error) {
|
||
|
|
||
|
if rgba.Stride != rgba.Rect.Size().X*4 {
|
||
|
return 0, fmt.Errorf("unsupported stride")
|
||
|
}
|
||
|
|
||
|
var texture uint32
|
||
|
gl.GenTextures(1, &texture)
|
||
|
gl.ActiveTexture(gl.TEXTURE0)
|
||
|
gl.BindTexture(gl.TEXTURE_2D, texture)
|
||
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR)
|
||
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR)
|
||
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE)
|
||
|
gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE)
|
||
|
gl.TexImage2D(
|
||
|
gl.TEXTURE_2D,
|
||
|
0,
|
||
|
gl.RGBA,
|
||
|
int32(rgba.Rect.Size().X),
|
||
|
int32(rgba.Rect.Size().Y),
|
||
|
0,
|
||
|
gl.RGBA,
|
||
|
gl.UNSIGNED_BYTE,
|
||
|
gl.Ptr(rgba.Pix))
|
||
|
|
||
|
return texture, nil
|
||
|
}
|