Skip to content

Instantly share code, notes, and snippets.

@allj
Last active April 23, 2017 19:53
Show Gist options
  • Save allj/19c69291f5f4fbec0397 to your computer and use it in GitHub Desktop.
Save allj/19c69291f5f4fbec0397 to your computer and use it in GitHub Desktop.
A colorful triangle in nim OpenGL.
import os
import opengl
import glfw/wrapper as glfw
template `&`[T](v: var T): ptr[T] = addr(v)
template `*`[T](v: ptr[T]): T = v[]
template `*`[T](v: ref[T]): T = v[]
var
win: GLFWwindow
vaoID: GLuint
vboID: GLuint
cboID: GLuint
vertexShaderID: GLuint
vertexShaderSrc: cstringArray
fragmentShaderSrc: cstringArray
fragmentShaderID: GLuint
programID: GLuint
vertices: array[12, GLdouble] =
[ -0.8, -0.8, 0.0, 1.0, # Vertex 1
0.0, 0.8, 0.0, 1.0, # Vertex 2
0.8, -0.8, 0.0, 1.0 ] # Vertex 3
colors: array[12, GLdouble] =
[ 1.0, 0.0, 0.0, 1.0, # Red
0.0, 1.0, 0.0, 1.0, # Green
0.0, 0.0, 1.0, 1.0 ] # Blue
proc createContext =
if glfw.init() != 1:
stderr.writeln("Failed to initialize GLFW")
stderr.flushFile
glfw.windowHint(glfw.CONTEXT_VERSION_MAJOR, 4)
glfw.windowHint(glfw.CONTEXT_VERSION_MINOR, 0)
glfw.windowHint(glfw.OPENGL_PROFILE, glfw.OPENGL_CORE_PROFILE)
glfw.windowHint(glfw.OPENGL_FORWARD_COMPAT, GL_TRUE)
glfw.windowHint(glfw.OPENGL_DEBUG_CONTEXT, GL_TRUE)
glfw.windowHint(glfw.RESIZABLE, GL_FALSE)
glfw.windowHint(glfw.REFRESH_RATE, 1000)
win = glfw.createWindow(width = 800, height = 600, title = "GLFW Nim", nil, nil)
glfw.makeContextCurrent(win)
proc createVertexShader =
vertexShaderID = glCreateShader(GL_VERTEX_SHADER)
vertexShaderSrc = allocCStringArray([
"""
#version 400
layout(location=0) in vec4 inPosition;
layout(location=1) in vec4 inColor;
out vec4 exColor;
void main() {
exColor = inColor;
gl_Position = inPosition;
}
"""])
glShaderSource(vertexShaderID, 1, vertexShaderSrc, nil)
glCompileShader(vertexShaderID)
var status: GLint
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &status)
if status == GL_FALSE:
var logLength: GLint
glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &logLength)
var errorLog: cstring = cast[cstring](alloc(logLength))
glGetShaderInfoLog(vertexShaderID, logLength, &logLength, errorLog)
stderr.writeln(errorLog)
stderr.writeln(vertexShaderSrc[0])
proc createFragmentShader =
fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER)
fragmentShaderSrc = allocCStringArray([
"""
#version 400
in vec4 exColor;
out vec4 outColor;
void main() {
outColor = exColor;
}
"""])
glShaderSource(fragmentShaderID, 1, fragmentShaderSrc, nil)
glCompileShader(fragmentShaderID)
var status: GLint
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &status)
if status == GL_FALSE:
var logLength: GLint
glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &logLength)
var errorLog: cstring = cast[cstring](alloc(logLength))
glGetShaderInfoLog(fragmentShaderID, logLength, &logLength, errorLog)
stderr.writeln(errorLog)
stderr.writeln(fragmentShaderSrc[0])
proc linkShaders =
# Link the vertex and fragment shader into a shader program
programID = glCreateProgram()
glAttachShader(programID, vertexShaderID)
glAttachShader(programID, fragmentShaderID)
glBindFragDataLocation(programID, 0, "outColor")
glLinkProgram(programID)
var status: GLint
glGetProgramiv(programID, GL_LINK_STATUS, &status)
if status == GL_FALSE:
var logLength: GLint
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &logLength)
var errorLog: cstring = cast[cstring](alloc(logLength))
glGetProgramInfoLog(programID, logLength, &logLength, errorLog)
stderr.writeln(errorLog)
glUseProgram(programID)
proc createShaders =
createVertexShader()
createFragmentShader()
linkShaders()
proc createBuffers =
glGenVertexArrays(1, &vaoID)
glBindVertexArray(vaoID)
glGenBuffers(1, &vboID)
glBindBuffer(GL_ARRAY_BUFFER, vboID)
glBufferData(GL_ARRAY_BUFFER, cast[GLsizeiptrArb](sizeof(vertices)), cast[pointer](&vertices), GL_STATIC_DRAW)
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 4, cGL_DOUBLE, false, 0, nil)
glGenBuffers(1, &cboID)
glBindBuffer(GL_ARRAY_BUFFER, cboID)
glBufferData(GL_ARRAY_BUFFER, cast[GLsizeiptrArb](sizeof(colors)), cast[pointer](&colors), GL_STATIC_DRAW)
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 4, cGL_DOUBLE, false, 0, nil)
proc initGL =
glEnable(GL_DEPTH_TEST)
glClearColor(0.0, 0.0, 0.0, 1.0)
proc init =
createContext()
loadExtensions()
createShaders()
createBuffers()
initGL()
stderr.writeln("INFO: OpenGL version ", cast[cstring](glGetString(GL_VERSION)))
proc render =
while glfw.windowShouldClose(win) == GL_FALSE:
# Clear the screen to black
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT)
# Draw a triangle from the 3 vertices
glDrawArrays(GL_TRIANGLES, 0, 3)
# Swap buffers and poll window events
glfw.swapBuffers(win)
glfw.pollEvents()
if glfw.getKey(win, glfw.KEY_Q) == glfw.PRESS:
glfw.setWindowShouldClose(win, GL_TRUE)
sleep(30)
proc destroyShaders =
glUseProgram(0)
glDetachShader(programID, vertexShaderID)
glDetachShader(programID, fragmentShaderiD)
glDeleteProgram(programID)
glDeleteShader(fragmentShaderID)
glDeleteShader(vertexShaderID)
proc destroyBuffers =
glDisableVertexAttribArray(0)
glDisableVertexAttribArray(1)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glDeleteBuffers(1, &vboID)
glDeleteBuffers(1, &cboID)
glBindVertexArray(0)
glDeleteVertexArrays(1, &vaoID)
proc cleanup =
destroyShaders()
destroyBuffers()
deallocCStringArray(vertexShaderSrc)
deallocCStringArray(fragmentShaderSrc)
proc exit =
glfw.destroyWindow(win)
glfw.terminate()
init()
render()
cleanup()
exit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment