Skip to content

Instantly share code, notes, and snippets.

@metaleap
Created October 25, 2012 05:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save metaleap/3950516 to your computer and use it in GitHub Desktop.
Save metaleap/3950516 to your computer and use it in GitHub Desktop.
Simple OpenGL 2D drawing
package main
import (
"fmt"
"strings"
gl "github.com/chsc/gogl/gl42"
glfw "github.com/go-gl/glfw"
glutil "github.com/go3d/go-util/gl"
)
type tGeometry struct {
glVerts []gl.Float
glNumVerts gl.Sizei
glMode gl.Enum
glVertBuf gl.Uint
}
var (
faceTri, faceQuad = &tGeometry {}, &tGeometry {}
useStrictCoreProfile = false // set this to true to see the problem...
isFirstLoop = true // only output glLastError in the loop's first iteration
lastErr error
shaderProg *glutil.TShaderProgram
srcVertShader = "in vec3 aPos; void main () { gl_Position = vec4(aPos, 1.0); }"
srcFragShader = "out vec4 oColor; void main () { oColor = vec4(0.0, 0.6, 0.9, 1.0); }"
)
func compileShaders () (err error) {
var glStatus gl.Int
var glFrag = gl.CreateShader(gl.FRAGMENT_SHADER)
var glVert = gl.CreateShader(gl.VERTEX_SHADER)
glutil.ShaderSource("test", glFrag, srcFragShader, nil, false, "150")
gl.CompileShader(glFrag)
if gl.GetShaderiv(glFrag, gl.COMPILE_STATUS, &glStatus); glStatus == 0 {
err = fmt.Errorf("SHADER %s: %s\n", "Frag", glutil.ShaderInfoLog(glFrag, true)); return
}
glutil.ShaderSource("test", glVert, srcVertShader, nil, false, "150")
gl.CompileShader(glVert)
if gl.GetShaderiv(glVert, gl.COMPILE_STATUS, &glStatus); glStatus == 0 {
err = fmt.Errorf("SHADER %s: %s\n", "Vert", glutil.ShaderInfoLog(glVert, true)); return
}
if shaderProg, err = glutil.NewShaderProgram("test", 0, glFrag, 0, 0, 0, glVert); err == nil {
err = shaderProg.SetAttrLocations("aPos")
}
return
}
func deleteGeometry () {
gl.DeleteBuffers(1, &faceTri.glVertBuf)
gl.DeleteBuffers(1, &faceQuad.glVertBuf)
}
func renderGeometry (mesh *tGeometry) {
gl.BindBuffer(gl.ARRAY_BUFFER, mesh.glVertBuf)
if isFirstLoop { logLastGlError("render.BindBuffer(buf)") }
gl.VertexAttribPointer(shaderProg.AttrLocs["aPos"], 3, gl.FLOAT, gl.FALSE, 0, gl.Pointer(nil))
if isFirstLoop { logLastGlError("render.VertexAttribPointer()") }
gl.DrawArrays(mesh.glMode, 0, mesh.glNumVerts)
if isFirstLoop { logLastGlError("render.DrawArrays()") }
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
if isFirstLoop { logLastGlError("render.BindBuffer(0)") }
}
func setupGeometry () {
var z gl.Float = -1
faceTri.glMode, faceTri.glNumVerts, faceTri.glVerts = gl.TRIANGLES, 3, []gl.Float {
0, 1, z,
-1, -1, z,
1, -1, z,
}
uploadGeometry(faceTri)
faceQuad.glMode, faceQuad.glNumVerts, faceQuad.glVerts = gl.TRIANGLE_STRIP, 4, []gl.Float {
0.5, 0.5, z,
-0.5, 0.5, z,
0.5, -0.5, z,
-0.5, -0.5, z,
}
uploadGeometry(faceQuad)
}
func uploadGeometry (mesh *tGeometry) {
gl.GenBuffers(1, &mesh.glVertBuf)
gl.BindBuffer(gl.ARRAY_BUFFER, mesh.glVertBuf)
gl.BufferData(gl.ARRAY_BUFFER, gl.Sizeiptr(4 * len(mesh.glVerts)), gl.Pointer(&mesh.glVerts[0]), gl.STATIC_DRAW)
gl.BindBuffer(gl.ARRAY_BUFFER, 0)
}
func logLastGlError (step string) {
if lastErr = glutil.LastError(step); lastErr != nil { fmt.Printf("LASTERR: %v\n", lastErr) }
}
func main () {
var err error
var looping = true
defer fmt.Println("EXIT")
if err = glfw.Init(); err != nil { panic(err) }
defer glfw.Terminate()
glfw.OpenWindowHint(glfw.FsaaSamples, 0)
if useStrictCoreProfile {
glfw.OpenWindowHint(glfw.OpenGLVersionMajor, 3)
glfw.OpenWindowHint(glfw.OpenGLVersionMinor, 2)
glfw.OpenWindowHint(glfw.OpenGLProfile, glfw.OpenGLCoreProfile)
// if runtime.GOOS == "darwin" { glfw.OpenWindowHint(glfw.OpenGLForwardCompat, 1) }
}
if err = glfw.OpenWindow(1280, 720, 8, 8, 8, 0, 24, 8, glfw.Windowed); err != nil { panic(err) }
defer glfw.CloseWindow()
glfw.Enable(glfw.StickyKeys)
if err = gl.Init(); (err != nil) && (strings.Index(err.Error(), "VERSION_") < 0) { panic(err) }
defer logLastGlError("(post loop)")
glutil.SetVersion()
fmt.Printf("GLCONN: %v\n", glutil.GlConnInfo())
gl.ClearColor(0.3, 0.1, 0.0, 1.0)
gl.Enable(gl.DEPTH_TEST)
gl.FrontFace(gl.CCW)
gl.CullFace(gl.BACK)
gl.Disable(gl.CULL_FACE)
if err = compileShaders(); err != nil { panic(err) }
setupGeometry()
logLastGlError("(pre loop)")
for looping {
gl.UseProgram(shaderProg.Program)
if isFirstLoop { logLastGlError("gl.UseProgram") }
gl.Viewport(0, 0, 1280, 720)
if isFirstLoop { logLastGlError("gl.ViewPort") }
gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT)
if isFirstLoop { logLastGlError("gl.Clear") }
renderGeometry(faceTri)
renderGeometry(faceQuad)
if (glfw.WindowParam(glfw.Opened) != 1) || (glfw.Key(glfw.KeyEsc) == glfw.KeyPress) {
looping = false
} else {
glfw.SwapBuffers()
}
isFirstLoop = false
}
}
@metaleap
Copy link
Author

With useStrictCoreProfile set to false, the program outputs no error messages to the console and draws a quad and a triangle: http://dl.dropbox.com/u/136375/gl-quad-tri.png

With useStrictCoreProfile set to true, it clears the background color but does not draw the tri & quad, console output is this:

GLCONN: OpenGL 3.2.0 @ NVIDIA Corporation GeForce GT 640M LE/PCIe/SSE2 (GLSL: 1.50 NVIDIA via Cg compiler)
LASTERR: OpenGL error at step 'render.VertexAttribPointer()':   GL_INVALID_OPERATION
LASTERR: OpenGL error at step 'render.DrawArrays()':    GL_INVALID_OPERATION
LASTERR: OpenGL error at step 'render.VertexAttribPointer()':   GL_INVALID_OPERATION
LASTERR: OpenGL error at step 'render.DrawArrays()':    GL_INVALID_OPERATION
LASTERR: OpenGL error at step '(post loop)':    GL_INVALID_OPERATION
EXIT

... if a 4.2 strict core profile is requested instead of 3.2, same issue. Applies to 3 different nvidia GPUs so I assume I'm not conforming to the strict core profile properly.

@metaleap
Copy link
Author

Note, you won't find a glEnableVertexAttribArray call in the above Gist, as it's inside the glutil package I'm importing -- but this does get called as the last step in this Gist's compileShaders() func.

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