Commit 79dc2263 authored by minus's avatar minus
Browse files

completed migration to OpenGL 3

now with a static quad instead of a spinning cube
parent 4c0c11b7
#!/usr/bin/env nimscript
## OpenGL example using SDL2
import os
import sdl2
import opengl
import glu
import glm
import math
#import glu
import strutils
import times
......@@ -23,7 +26,7 @@ discard sdl2.glSetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8);
var screenWidth: cint = 640
var screenHeight: cint = 480
var window = createWindow("SDL/OpenGL Skeleton", 100, 100, screenWidth, screenHeight, SDL_WINDOW_OPENGL or SDL_WINDOW_RESIZABLE)
var window = createWindow(":float:SDL/OpenGL Skeleton", 100, 100, screenWidth, screenHeight, SDL_WINDOW_OPENGL or SDL_WINDOW_RESIZABLE)
var context = window.glCreateContext()
# Initialize OpenGL
......@@ -41,6 +44,12 @@ glDebugMessageCallback(printGlDebug, nil)
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS)
glEnable(GL_DEBUG_OUTPUT)
discard sdl2.glSetSwapInterval(1);
var vao: GLuint
glGenVertexArrays(1, addr vao)
glBindVertexArray(vao)
glClearColor(0.0, 0.0, 0.0, 1.0) # Set background color to black and opaque
glClearDepth(1.0) # Set background depth to farthest
#glEnable(GL_DEPTH_TEST) # Enable depth testing for z-culling
......@@ -50,129 +59,132 @@ glClearDepth(1.0) # Set background depth to fart
type ShaderCompilerError = object of type Exception
proc load_shader(source_file: string, typ: GLenum): GLuint =
var shader = glCreateShader GL_VERTEX_SHADER
var shader = glCreateShader(typ)
var source = source_file.readFile
var sourcePtr = addr source[0]
shader.glShaderSource(1, cast[cstringArray](addr sourcePtr), nil)
shader.glCompileShader
shader.glCompileShader()
var status: GLint
shader.glGetShaderiv(GL_COMPILE_STATUS, addr status)
if status == GL_FALSE:
var buf: array[4096, char]
shader.glGetShaderInfoLog(cast[GLsizei](buf.len), nil, buf)
shader.glGetShaderInfoLog(GLsizei(buf.len), nil, buf)
raise newException(ShaderCompilerError, $buf)
shader
type ShaderLinkerError = object of type Exception
proc build_shader_program(shaders: varargs[GLuint]): GLuint =
var program = glCreateProgram()
for shader in shaders:
program.glAttachShader(shader)
# Shouldn't be needed, as the location for color is 0 by default
# https://gamedev.stackexchange.com/questions/72756/how-does-opengl-determine-different-outputs-with-shaders
#program.glBindFragDataLocation(0, "color")
program.glLinkProgram()
var status: GLint
program.glGetProgramiv(GL_LINK_STATUS, addr status)
if status == GL_FALSE:
var buf: array[4096, char]
program.glGetProgramInfoLog(GLsizei(buf.len), nil, buf)
raise newException(ShaderLinkerError, $buf)
for shader in shaders:
echo shader
0
program.glDetachShader(shader)
shader.glDeleteShader()
program.glUseProgram()
program
var vertex_shader = load_shader("shaders/vertex.glsl", GL_VERTEX_SHADER)
var fragment_shader = load_shader("shaders/fragment.glsl", GL_FRAGMENT_SHADER)
var shader_program = build_shader_program(vertex_shader, fragment_shader)
var
attribs_in_position = cast[GLuint](shader_program.glGetAttribLocation("in_position"))
attribs_in_color = cast[GLuint](shader_program.glGetAttribLocation("in_color"))
attribs_in_normal = cast[GLuint](shader_program.glGetAttribLocation("in_normal"))
uniforms_model = shader_program.glGetUniformLocation("model")
uniforms_view = shader_program.glGetUniformLocation("view")
uniforms_proj = shader_program.glGetUniformLocation("proj")
var view = lookAt(
vec3[GLfloat](0.0, 0.0, 1.0), # pos
vec3[GLfloat](0.0), # target
vec3[GLfloat](0.0, 1.0, 0.0) # up
)
uniforms_view.glUniformMatrix4fv(GLsizei(1), false, view.caddr)
proc radians[T](deg: T): T = deg/180*PI
proc reshape(newWidth: cint, newHeight: cint) =
echo "Resizing window to $1x$2".format(newWidth, newHeight)
glViewport(0, 0, newWidth, newHeight) # Set the viewport to cover the new window
#glMatrixMode(GL_PROJECTION) # To operate on the projection matrix
#glLoadIdentity() # Reset
#gluPerspective(45.0, newWidth / newHeight, 0.1, 100.0) # Enable perspective projection with fovy, aspect, zNear and zFar
var proj = perspective[GLfloat](radians 45.0, newWidth / newHeight, 0.01, 100.0)
uniforms_proj.glUniformMatrix4fv(GLsizei(1), false, proj.caddr)
var quad_vao: GLuint
proc init_quad =
glGenVertexArrays(1, addr quad_vao)
quad_vao.glBindVertexArray()
var vertices =
[
GLfloat(-0.5), 0.5, 0.0, 1.0, 0.0, 0.0, # Top-left
0.5, 0.5, 0.0, 0.0, 1.0, 0.0, # Top-right
0.5, -0.5, 0.0, 0.0, 0.0, 1.0, # Bottom-right
-0.5, -0.5, 0.0, 1.0, 1.0, 1.0 # Bottom-left
]
var vbo: GLuint
glGenBuffers(1, addr vbo)
GL_ARRAY_BUFFER.glBindBuffer(vbo)
GL_ARRAY_BUFFER.glBufferData(vertices.sizeof, addr vertices, GL_STATIC_DRAW)
var elements = [GLuint(3), 2, 0, 1]
var ebo: GLuint
glGenBuffers(1, addr ebo)
GL_ELEMENT_ARRAY_BUFFER.glBindBuffer(ebo)
GL_ELEMENT_ARRAY_BUFFER.glBufferData(elements.sizeof, addr elements, GL_STATIC_DRAW)
attribs_in_position.glEnableVertexAttribArray()
# attrib, num components, type, normalize, stride (bytes between values), offset
attribs_in_position.glVertexAttribPointer(3, cGL_FLOAT, false, 6*GLfloat.sizeof, cast[pointer](0))
attribs_in_color.glEnableVertexAttribArray()
# attrib, num components, type, normalize, stride (bytes between values), offset
attribs_in_color.glVertexAttribPointer(3, cGL_FLOAT, false, 6*GLfloat.sizeof, cast[pointer](3*GLfloat.sizeof))
glBindVertexArray(0)
init_quad()
proc render(t: float) =
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT) # Clear color and depth buffers
glMatrixMode(GL_MODELVIEW) # To operate on model-view matrix
glLoadIdentity() # Reset the model-view matrix
glTranslatef(1.5, 0.0, -7.0) # Move right and into the screen
glRotatef(t * 360, 0, 1, 0)
# Render a cube consisting of 6 quads
# Each quad consists of 2 triangles
# Each triangle consists of 3 vertices
glBegin(GL_TRIANGLES) # Begin drawing of triangles
# Top face (y = 1.0f)
glColor3f(0.0, 1.0, 0.0) # Green
glVertex3f( 1.0, 1.0, -1.0)
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f( 1.0, 1.0, -1.0)
glVertex3f(-1.0, 1.0, 1.0)
# Bottom face (y = -1.0f)
glColor3f(1.0, 0.5, 0.0) # Orange
glVertex3f( 1.0, -1.0, 1.0)
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f( 1.0, -1.0, -1.0)
glVertex3f( 1.0, -1.0, 1.0)
glVertex3f(-1.0, -1.0, -1.0)
# Front face (z = 1.0f)
glColor3f(1.0, 0.0, 0.0) # Red
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f( 1.0, -1.0, 1.0)
glVertex3f( 1.0, 1.0, 1.0)
glVertex3f(-1.0, -1.0, 1.0)
# Back face (z = -1.0f)
glColor3f(1.0, 1.0, 0.0) # Yellow
glVertex3f( 1.0, -1.0, -1.0)
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f( 1.0, 1.0, -1.0)
glVertex3f( 1.0, -1.0, -1.0)
glVertex3f(-1.0, 1.0, -1.0)
# Left face (x = -1.0f)
glColor3f(0.0, 0.0, 1.0) # Blue
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, 1.0, -1.0)
glVertex3f(-1.0, -1.0, -1.0)
glVertex3f(-1.0, -1.0, 1.0)
glVertex3f(-1.0, 1.0, 1.0)
glVertex3f(-1.0, -1.0, -1.0)
# Right face (x = 1.0f)
glColor3f(1.0, 0.0, 1.0) # Magenta
glVertex3f(1.0, 1.0, -1.0)
glVertex3f(1.0, 1.0, 1.0)
glVertex3f(1.0, -1.0, 1.0)
glVertex3f(1.0, -1.0, -1.0)
glVertex3f(1.0, 1.0, -1.0)
glVertex3f(1.0, -1.0, 1.0)
glEnd() # End of drawing
#glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT) # Clear color and depth buffers
window.glSwapWindow() # Swap the front and back frame buffers (double buffering)
# Frame rate limiter
quad_vao.glBindVertexArray()
var model = mat4x4[GLfloat](1.0)
uniforms_model.glUniformMatrix4fv(GLsizei(1), false, model.caddr)
GL_TRIANGLE_STRIP.glDrawElements(GLsizei(4), GL_UNSIGNED_INT, cast[pointer](0))
let targetFramePeriod: uint32 = 20 # 20 milliseconds corresponds to 50 fps
var frameTime: uint32 = 0
window.glSwapWindow() # Swap the front and back frame buffers (double buffering)
proc limitFrameRate() =
let now = getTicks()
if frameTime > now:
delay(frameTime - now) # Delay to maintain steady frame rate
frameTime += targetFramePeriod
# Main loop
var
evt = sdl2.defaultEvent
runGame = true
t0 = epochTime()
reshape(screenWidth, screenHeight) # Set up initial viewport and projection
var t0 = epochTime()
while runGame:
while pollEvent(evt):
if evt.kind == QuitEvent:
if evt.kind == QuitEvent or (evt.kind == KeyDown and (
evt.key.keysym.scancode == SDL_SCANCODE_Q or
evt.key.keysym.scancode == SDL_SCANCODE_ESCAPE)):
runGame = false
break
if evt.kind == WindowEvent:
......@@ -182,8 +194,6 @@ while runGame:
let newHeight = windowEvent.data2
reshape(newWidth, newHeight)
#render(epochTime() - t0)
limitFrameRate()
render(epochTime() - t0)
destroy window
......@@ -10,3 +10,4 @@ license = "MIT"
requires "nim >= 0.14.0"
requires "sdl2 >= 1.1.0"
requires "opengl >= 1.0.1"
requires "glm >= 0.1.1"
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment