Lab06 completed.

This commit is contained in:
Alex 2017-02-28 10:55:40 -06:00
parent d064750ed1
commit d97e700c59
10 changed files with 716 additions and 2 deletions

View file

@ -1,7 +1,8 @@
#version 120 #version 120
uniform int height;
varying vec3 vMyColor; varying vec3 vMyColor;
void main() void main()
{ {
gl_FragColor = vec4(vMyColor.r, vMyColor.g, vMyColor.b, 1.0); gl_FragColor = vec4(vMyColor.r, vMyColor.g, vMyColor.b, 1.0);
} }

Binary file not shown.

View file

@ -157,7 +157,7 @@ static void init()
// Get uniform IDs // Get uniform IDs
PUnifID = glGetUniformLocation(progID, "P"); PUnifID = glGetUniformLocation(progID, "P");
// //
// Vertex buffer setup // Vertex buffer setup
// //

1
L06/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
build/

127
L06/CMakeLists.txt Normal file
View file

@ -0,0 +1,127 @@
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# Name of the project
PROJECT(L06)
# FOR LAB MACHINES ONLY!
# DO NOT EDIT
SET(DEF_DIR_GLM "C:\\c++\\glm")
SET(DEF_DIR_GLFW "C:\\c++\\glfw-3.2.1")
SET(DEF_DIR_GLEW "C:\\c++\\glew-2.0.0")
# Is this the solution?
# Override with `cmake -DSOL=ON ..`
OPTION(SOL "Solution" OFF)
# Use glob to get the list of all source files.
# We don't really need to include header and resource files to build, but it's
# nice to have them also show up in IDEs.
IF(${SOL})
FILE(GLOB_RECURSE SOURCES "src0/*.cpp")
FILE(GLOB_RECURSE HEADERS "src0/*.h")
FILE(GLOB_RECURSE GLSL "resources0/*.glsl")
ELSE()
FILE(GLOB_RECURSE SOURCES "src/*.cpp")
FILE(GLOB_RECURSE HEADERS "src/*.h")
FILE(GLOB_RECURSE GLSL "resources/*.glsl")
ENDIF()
# Set the executable.
ADD_EXECUTABLE(${CMAKE_PROJECT_NAME} ${SOURCES} ${HEADERS} ${GLSL})
# Get the GLM environment variable. Since GLM is a header-only library, we
# just need to add it to the include directory.
SET(GLM_INCLUDE_DIR "$ENV{GLM_INCLUDE_DIR}")
IF(NOT GLM_INCLUDE_DIR)
# The environment variable was not set
SET(ERR_MSG "Please point the environment variable GLM_INCLUDE_DIR to the root directory of your GLM installation.")
IF(WIN32)
# On Windows, try the default location
MESSAGE(STATUS "Looking for GLM in ${DEF_DIR_GLM}")
IF(IS_DIRECTORY ${DEF_DIR_GLM})
MESSAGE(STATUS "Found!")
SET(GLM_INCLUDE_DIR ${DEF_DIR_GLM})
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ENDIF()
INCLUDE_DIRECTORIES(${GLM_INCLUDE_DIR})
# Get the GLFW environment variable. There should be a CMakeLists.txt in the
# specified directory.
SET(GLFW_DIR "$ENV{GLFW_DIR}")
IF(NOT GLFW_DIR)
# The environment variable was not set
SET(ERR_MSG "Please point the environment variable GLFW_DIR to the root directory of your GLFW installation.")
IF(WIN32)
# On Windows, try the default location
MESSAGE(STATUS "Looking for GLFW in ${DEF_DIR_GLFW}")
IF(IS_DIRECTORY ${DEF_DIR_GLFW})
MESSAGE(STATUS "Found!")
SET(GLFW_DIR ${DEF_DIR_GLFW})
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ENDIF()
OPTION(GLFW_BUILD_EXAMPLES "GLFW_BUILD_EXAMPLES" OFF)
OPTION(GLFW_BUILD_TESTS "GLFW_BUILD_TESTS" OFF)
OPTION(GLFW_BUILD_DOCS "GLFW_BUILD_DOCS" OFF)
IF(CMAKE_BUILD_TYPE MATCHES Release)
ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/release)
ELSE()
ADD_SUBDIRECTORY(${GLFW_DIR} ${GLFW_DIR}/debug)
ENDIF()
INCLUDE_DIRECTORIES(${GLFW_DIR}/include)
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} glfw ${GLFW_LIBRARIES})
# Get the GLEW environment variable.
SET(GLEW_DIR "$ENV{GLEW_DIR}")
IF(NOT GLEW_DIR)
# The environment variable was not set
SET(ERR_MSG "Please point the environment variable GLEW_DIR to the root directory of your GLEW installation.")
IF(WIN32)
# On Windows, try the default location
MESSAGE(STATUS "Looking for GLEW in ${DEF_DIR_GLEW}")
IF(IS_DIRECTORY ${DEF_DIR_GLEW})
MESSAGE(STATUS "Found!")
SET(GLEW_DIR ${DEF_DIR_GLEW})
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ELSE()
MESSAGE(FATAL_ERROR ${ERR_MSG})
ENDIF()
ENDIF()
INCLUDE_DIRECTORIES(${GLEW_DIR}/include)
IF(WIN32)
# With prebuilt binaries
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/Release/Win32/glew32s.lib)
ELSE()
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} ${GLEW_DIR}/lib/libGLEW.a)
ENDIF()
# OS specific options and libraries
IF(WIN32)
# c++11 is enabled by default.
# -Wall produces way too many warnings.
# -pedantic is not supported.
# Disable warning 4996.
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4996")
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} opengl32.lib)
ELSE()
# Enable all pedantic warnings.
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -pedantic")
IF(APPLE)
# Add required frameworks for GLFW.
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "-framework OpenGL -framework Cocoa -framework IOKit -framework CoreVideo")
ELSE()
#Link the Linux OpenGL library
TARGET_LINK_LIBRARIES(${CMAKE_PROJECT_NAME} "GL")
ENDIF()
ENDIF()

View file

@ -0,0 +1,17 @@
#version 120
uniform vec2 middle;
varying vec3 vMyColor;
void main()
{
if(distance(vec2(middle, vec2(gl_FragCoord.x, gl_FragCoord.y)) < 20)
{
discard;
}
else
{
float light = ((distance(middle, vec2(gl_FragCoord.x, gl_FragCoord.y))- 20.0)/200.0);
gl_FragColor = vec4(light+vMyColor.r, light+vMyColor.g, light+vMyColor.b, 1.0);
}
}

View file

@ -0,0 +1,12 @@
#version 120
uniform mat4 P;
attribute vec3 vertPos;
attribute vec3 vertCol;
varying vec3 vMyColor;
void main()
{
gl_Position = P * vec4(vertPos, 1.0);
vMyColor = 1.0 * vertCol;
}

152
L06/src/GLSL.cpp Normal file
View file

@ -0,0 +1,152 @@
//
// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book
// Created by zwood on 2/21/10.
// Modified by sueda 10/15/15.
//
#include "GLSL.h"
#include <stdio.h>
#include <stdlib.h>
#include <cassert>
#include <cstring>
using namespace std;
namespace GLSL {
const char * errorString(GLenum err)
{
switch(err) {
case GL_NO_ERROR:
return "No error";
case GL_INVALID_ENUM:
return "Invalid enum";
case GL_INVALID_VALUE:
return "Invalid value";
case GL_INVALID_OPERATION:
return "Invalid operation";
case GL_STACK_OVERFLOW:
return "Stack overflow";
case GL_STACK_UNDERFLOW:
return "Stack underflow";
case GL_OUT_OF_MEMORY:
return "Out of memory";
default:
return "No error";
}
}
void checkVersion()
{
int major, minor;
major = minor = 0;
const char *verstr = (const char *)glGetString(GL_VERSION);
if((verstr == NULL) || (sscanf(verstr, "%d.%d", &major, &minor) != 2)) {
printf("Invalid GL_VERSION format %d.%d\n", major, minor);
}
if(major < 2) {
printf("This shader example will not work due to the installed Opengl version, which is %d.%d.\n", major, minor);
exit(0);
}
}
void checkError(const char *str)
{
GLenum glErr = glGetError();
if(glErr != GL_NO_ERROR) {
if(str) {
printf("%s: ", str);
}
printf("GL_ERROR = %s.\n", errorString(glErr));
assert(false);
}
}
void printShaderInfoLog(GLuint shader)
{
GLint infologLength = 0;
GLint charsWritten = 0;
GLchar *infoLog = 0;
checkError(GET_FILE_LINE);
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infologLength);
checkError(GET_FILE_LINE);
if(infologLength > 0) {
infoLog = (GLchar *)malloc(infologLength);
if(infoLog == NULL) {
puts("ERROR: Could not allocate InfoLog buffer");
exit(1);
}
glGetShaderInfoLog(shader, infologLength, &charsWritten, infoLog);
checkError(GET_FILE_LINE);
printf("Shader InfoLog:\n%s\n\n", infoLog);
free(infoLog);
}
}
void printProgramInfoLog(GLuint program)
{
GLint infologLength = 0;
GLint charsWritten = 0;
GLchar *infoLog = 0;
checkError(GET_FILE_LINE);
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infologLength);
checkError(GET_FILE_LINE);
if(infologLength > 0) {
infoLog = (GLchar *)malloc(infologLength);
if(infoLog == NULL) {
puts("ERROR: Could not allocate InfoLog buffer");
exit(1);
}
glGetProgramInfoLog(program, infologLength, &charsWritten, infoLog);
checkError(GET_FILE_LINE);
printf("Program InfoLog:\n%s\n\n", infoLog);
free(infoLog);
}
}
char *textFileRead(const char *fn)
{
FILE *fp;
char *content = NULL;
int count = 0;
if(fn != NULL) {
fp = fopen(fn,"rt");
if(fp != NULL) {
fseek(fp, 0, SEEK_END);
count = (int)ftell(fp);
rewind(fp);
if(count > 0) {
content = (char *)malloc(sizeof(char) * (count+1));
count = (int)fread(content,sizeof(char),count,fp);
content[count] = '\0';
}
fclose(fp);
} else {
printf("error loading %s\n", fn);
}
}
return content;
}
int textFileWrite(const char *fn, const char *s)
{
FILE *fp;
int status = 0;
if(fn != NULL) {
fp = fopen(fn,"w");
if(fp != NULL) {
if(fwrite(s,sizeof(char),strlen(s),fp) == strlen(s)) {
status = 1;
}
fclose(fp);
}
}
return(status);
}
}

40
L06/src/GLSL.h Normal file
View file

@ -0,0 +1,40 @@
//
// Many useful helper functions for GLSL shaders - gleaned from various sources including orange book
// Created by zwood on 2/21/10.
// Modified by sueda 10/15/15.
//
#pragma once
#ifndef __GLSL__
#define __GLSL__
#define GLEW_STATIC
#include <GL/glew.h>
///////////////////////////////////////////////////////////////////////////////
// For printing out the current file and line number //
///////////////////////////////////////////////////////////////////////////////
#include <sstream>
template <typename T>
std::string NumberToString(T x)
{
std::ostringstream ss;
ss << x;
return ss.str();
}
#define GET_FILE_LINE (std::string(__FILE__) + ":" + NumberToString(__LINE__)).c_str()
///////////////////////////////////////////////////////////////////////////////
namespace GLSL {
void checkVersion();
void checkError(const char *str = 0);
void printProgramInfoLog(GLuint program);
void printShaderInfoLog(GLuint shader);
int textFileWrite(const char *filename, const char *s);
char *textFileRead(const char *filename);
}
#endif

364
L06/src/main.cpp Normal file
View file

@ -0,0 +1,364 @@
#include <cassert>
#include <iostream>
#include <vector>
#define GLEW_STATIC
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#define GLM_FORCE_RADIANS
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include "GLSL.h"
using namespace std;
using namespace glm;
GLFWwindow *window; // Main application window
string RESOURCE_DIR = "./"; // Where the resources are loaded from
GLuint progID;
GLint PUnifID;
GLint vertPosAttrID;
GLint vertColAttrID;
GLuint posBufID;
GLuint colBufID;
GLint middleID;
float worldSize = 1.2f;
// This function is called when a GLFW error occurs
static void error_callback(int error, const char *description)
{
cerr << description << endl;
}
// This function is called when a key is pressed
static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
{
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
glfwSetWindowShouldClose(window, GL_TRUE);
}
}
// This function is called when the mouse is clicked
static void mouse_callback(GLFWwindow *window, int button, int action, int mods)
{
double posX, posY;
float newPt[2];
if(action == GLFW_PRESS) {
// Get window size
int width, height;
glfwGetWindowSize(window, &width, &height);
// Get cursor position
glfwGetCursorPos(window, &posX, &posY);
posY = height - posY; // flip the Y-axis
cout << "Pos X " << posX << " Pos Y " << posY << endl;
// Compute where the cursor is in world coords
float aspect = width/(float)height;
float xMinWorld, xMaxWorld, yMinWorld, yMaxWorld;
if(width > height) {
xMinWorld = -worldSize*aspect;
xMaxWorld = worldSize*aspect;
yMinWorld = -worldSize;
yMaxWorld = worldSize;
} else {
xMinWorld = -worldSize;
xMaxWorld = worldSize;
yMinWorld = -worldSize/aspect;
yMaxWorld = worldSize/aspect;
}
// At this point:
// - The lower left corner of the world is (xMinWorld, xMaxWorld)
// - The top right corner of the world is (yMinWorld, yMaxWorld)
// - The lower left corner of the window is (0, 0)
// - The top right corner of the window is (width, height)
//
// THIS IS BROKEN - YOU GET TO FIX IT - yay!
newPt[0] = ((xMaxWorld - xMinWorld)/width)*posX + xMinWorld;
newPt[1] = ((yMaxWorld - yMinWorld)/height)*posY + yMinWorld;
cout << "converted: " << newPt[0] << " " << newPt[1] << endl;
// Update the vertex array with newPt
glBindBuffer(GL_ARRAY_BUFFER, posBufID);
glBufferSubData(GL_ARRAY_BUFFER, 6*sizeof(float), 2*sizeof(float), newPt);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
// If the window is resized, capture the new size and reset the viewport
static void resize_callback(GLFWwindow *window, int width, int height)
{
glViewport(0, 0, width, height);
}
// This function is called once to initialize the scene and OpenGL
static void init()
{
//
// General setup
//
// Set background color.
glClearColor(0.1f, 0.2f, 0.4f, 1.0f);
// Enable z-buffer test.
glEnable(GL_DEPTH_TEST);
//
// GLSL program setup
//
// Create shader handles
GLuint vShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fShaderID = glCreateShader(GL_FRAGMENT_SHADER);
// Read shader sources
string vShaderName = RESOURCE_DIR + "simple_vert.glsl";
string fShaderName = RESOURCE_DIR + "simple_frag.glsl";
const char *vShaderText = GLSL::textFileRead(vShaderName.c_str());
const char *fShaderText = GLSL::textFileRead(fShaderName.c_str());
glShaderSource(vShaderID, 1, &vShaderText, NULL);
glShaderSource(fShaderID, 1, &fShaderText, NULL);
// Compile vertex shader
int rc;
glCompileShader(vShaderID);
glGetShaderiv(vShaderID, GL_COMPILE_STATUS, &rc);
if(!rc) {
GLSL::printShaderInfoLog(vShaderID);
cout << "Error compiling vertex shader " << vShaderName << endl;
return;
}
// Compile fragment shader
glCompileShader(fShaderID);
glGetShaderiv(fShaderID, GL_COMPILE_STATUS, &rc);
if(!rc) {
GLSL::printShaderInfoLog(fShaderID);
cout << "Error compiling fragment shader " << fShaderName << endl;
return;
}
// Create the program and link
progID = glCreateProgram();
glAttachShader(progID, vShaderID);
glAttachShader(progID, fShaderID);
glLinkProgram(progID);
glGetProgramiv(progID, GL_LINK_STATUS, &rc);
if(!rc) {
GLSL::printProgramInfoLog(progID);
cout << "Error linking shaders " << vShaderName << " and " << fShaderName << endl;
return;
}
// Get vertex attribute IDs
vertPosAttrID = glGetAttribLocation(progID, "vertPos");
// Get vertex attribute IDs
vertColAttrID = glGetAttribLocation(progID, "vertCol");
// Get uniform IDs
PUnifID = glGetUniformLocation(progID, "P");
middleID = glGetUniformLocation(progID, "middle");
//
// Vertex buffer setup
//
// Vertex position data
vector<float> posBuf;
posBuf.push_back(-1.0f); // x
posBuf.push_back(-1.0f); // y
posBuf.push_back( 0.0f); // z
posBuf.push_back( 1.0f); // x
posBuf.push_back(-1.0f); // y
posBuf.push_back( 0.0f); // z
posBuf.push_back( 0.0f); // x
posBuf.push_back( 1.0f); // y
posBuf.push_back( 0.0f); // z
// Vertex position data
posBuf.push_back(-1.1f); // x
posBuf.push_back(-1.0f); // y
posBuf.push_back( 0.0f); // z
posBuf.push_back(-0.1f); // x
posBuf.push_back( 1.0f); // y
posBuf.push_back( 0.0f); // z
posBuf.push_back(-1.1f); // x
posBuf.push_back( 1.0f); // y
posBuf.push_back( 0.0f); // z
// Vertex position data
posBuf.push_back( 1.1f); // x
posBuf.push_back(-1.0f); // y
posBuf.push_back( 0.0f); // z
posBuf.push_back( 0.1f); // x
posBuf.push_back( 1.0f); // y
posBuf.push_back( 0.0f); // z
posBuf.push_back( 1.1f); // x
posBuf.push_back( 1.0f); // y
posBuf.push_back( 0.0f); // z
// Color data
vector<float> colBuf;
colBuf.push_back( 0.0f); // r
colBuf.push_back( 1.0f); // g
colBuf.push_back( 0.0f); // b
colBuf.push_back( 1.0f); // r
colBuf.push_back( 1.0f); // g
colBuf.push_back( 0.0f); // b
colBuf.push_back( 0.0f); // r
colBuf.push_back( 0.0f); // g
colBuf.push_back( 1.0f); // b
// Color data
colBuf.push_back( 1.0f); // r
colBuf.push_back( 0.0f); // g
colBuf.push_back( 0.0f); // b
colBuf.push_back( 0.0f); // r
colBuf.push_back( 0.0f); // g
colBuf.push_back( 1.0f); // b
colBuf.push_back( 0.0f); // r
colBuf.push_back( 0.0f); // g
colBuf.push_back( 1.0f); // b
// Color data
colBuf.push_back( 1.0f); // r
colBuf.push_back( 0.0f); // g
colBuf.push_back( 0.0f); // b
colBuf.push_back( 0.0f); // r
colBuf.push_back( 0.0f); // g
colBuf.push_back( 1.0f); // b
colBuf.push_back( 0.0f); // r
colBuf.push_back( 0.0f); // g
colBuf.push_back( 1.0f); // b
// Generate a buffer object
glGenBuffers(1, &posBufID);
// Bind the buffer object to make it the currently active buffer
glBindBuffer(GL_ARRAY_BUFFER, posBufID);
// Send the buffer data
glBufferData(GL_ARRAY_BUFFER, posBuf.size()*sizeof(float), &posBuf[0], GL_DYNAMIC_DRAW);
// Unbind the buffer object
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Generate a buffer object
glGenBuffers(1, &colBufID);
// Bind the buffer object to make it the currently active buffer
glBindBuffer(GL_ARRAY_BUFFER, colBufID);
// Send the buffer data
glBufferData(GL_ARRAY_BUFFER, colBuf.size()*sizeof(float), &colBuf[0], GL_DYNAMIC_DRAW);
// Unbind the buffer object
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
// This function is called every frame to draw the scene.
static void render()
{
// Clear framebuffer.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Get current frame buffer size.
int width, height;
glfwGetFramebufferSize(window, &width, &height);
float aspect = width/(float)height;
// Set up projection matrix (camera intrinsics)
mat4 P;
if(width > height) {
P = ortho(-worldSize*aspect, worldSize*aspect, -worldSize, worldSize, -1.0f, 1.0f);
} else {
P = ortho(-worldSize, worldSize, -worldSize/aspect, worldSize/aspect, -1.0f, 1.0f);
}
float middle[2];
middle[0] = 100*cos(glfwGetTime()) + (width/2.0);
middle[1] = 100*sin(glfwGetTime()) + (height/2.0);
std::cout << middle[0] << middle[1] << std::endl;
// Tell OpenGL which GLSL program to use
glUseProgram(progID);
// Pass in the current projection matrix
glUniform2fv(middleID, 1, middle);
// Pass in the current projection matrix
glUniformMatrix4fv(PUnifID, 1, GL_FALSE, &P[0][0]);
// Enable the attribute
glEnableVertexAttribArray(vertPosAttrID);
// Bind the position buffer object to make it the currently active buffer
glBindBuffer(GL_ARRAY_BUFFER, posBufID);
// Set the pointer -- the data is already on the GPU
glVertexAttribPointer(vertPosAttrID, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
// Enable the attribute
glEnableVertexAttribArray(vertColAttrID);
// Bind the position buffer object to make it the currently active buffer
glBindBuffer(GL_ARRAY_BUFFER, colBufID);
// Set the pointer -- the data is already on the GPU
glVertexAttribPointer(vertColAttrID, 3, GL_FLOAT, GL_FALSE, 0, (void *)0);
// Actually draw here
glDrawArrays(GL_TRIANGLES, 0, 9);
// Unbind the buffer object
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Disable the attribute
glDisableVertexAttribArray(vertPosAttrID);
// Disable the attribute
glDisableVertexAttribArray(vertColAttrID);
// Unbind our GLSL program
glUseProgram(0);
}
int main(int argc, char **argv)
{
if(argc < 2) {
cout << "Please specify the resource directory." << endl;
return 0;
}
RESOURCE_DIR = argv[1] + string("/");
// Set error callback.
glfwSetErrorCallback(error_callback);
// Initialize the library.
if(!glfwInit()) {
return -1;
}
// Create a windowed mode window and its OpenGL context.
window = glfwCreateWindow(640, 480, "Alex Huddleston", NULL, NULL);
if(!window) {
glfwTerminate();
return -1;
}
// Make the window's context current.
glfwMakeContextCurrent(window);
// Initialize GLEW.
glewExperimental = true;
if(glewInit() != GLEW_OK) {
cerr << "Failed to initialize GLEW" << endl;
return -1;
}
glGetError(); // A bug in glewInit() causes an error that we can safely ignore.
cout << "OpenGL version: " << glGetString(GL_VERSION) << endl;
cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl;
GLSL::checkVersion();
// Set vsync.
glfwSwapInterval(1);
// Set keyboard callback.
glfwSetKeyCallback(window, key_callback);
// Set the mouse call back.
glfwSetMouseButtonCallback(window, mouse_callback);
// Set the window resize call back.
glfwSetFramebufferSizeCallback(window, resize_callback);
// Initialize scene.
init();
// Loop until the user closes the window.
while(!glfwWindowShouldClose(window)) {
// Render scene.
render();
// Swap front and back buffers.
glfwSwapBuffers(window);
// Poll for and process events.
glfwPollEvents();
}
// Quit program.
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}