Skip to content

Instantly share code, notes, and snippets.

@mhintz
Last active November 13, 2015 23:17
Show Gist options
  • Save mhintz/7bd6420521dceacef641 to your computer and use it in GitHub Desktop.
Save mhintz/7bd6420521dceacef641 to your computer and use it in GitHub Desktop.
Posting the OGL tutorials demo framework I'm using (hey Bojan!) - some of this code is my own, some is from the excellent tutorials at ogldev.atspace.co.uk.
#pragma once
#include "GLFWDriver.h"
class App {
public:
App() {};
virtual ~App() {};
int width;
int height;
char * name;
void endApp() {
exitGLFWLoop();
}
};
#pragma once
#include "util.h"
class Callbacks {
public:
virtual void onKeyDown(int glfwKey) { UNUSED(glfwKey); };
virtual void onKeyUp(int glfwKey) { UNUSED(glfwKey); };
virtual void onMouseMove(double mousex, double mousey) { UNUSED(mousex); UNUSED(mousey); };
virtual void onClick(double mousex, double mousey) { UNUSED(mousex); UNUSED(mousey); };
virtual void setup() {};
virtual void update() {};
virtual void draw() {};
};
#include "GLFWDriver.h"
#include <cstdlib>
#include "util.h"
static GLFWwindow * windowPtr = NULL;
static Callbacks * eventHandler = NULL;
void terminateGLFWAndExit() {
glfwDestroyWindow(windowPtr);
glfwTerminate();
std::exit(1);
}
void exitGLFWLoop() {
glfwSetWindowShouldClose(windowPtr, 1);
}
static void onGLFWError(int error, const char * description) {
fprintf(stderr, "GLFW Error! code: %d - description: %s\n", error, description);
exitGLFWLoop();
}
void initGLFWDriver(int argc, char ** argv) {
UNUSED(argc); UNUSED(argv);
if (!glfwInit()) {
fprintf(stderr, "Error initializing GLFW\n");
std::exit(1);
}
glfwSetErrorCallback(onGLFWError);
int majorVersion, minorVersion, revisionVersion;
glfwGetVersion(& majorVersion, & minorVersion, & revisionVersion);
printf("GLFW %d.%d.%d initialized\n", majorVersion, minorVersion, revisionVersion);
}
bool initGLFWWindow(int width, int height, const char * name) {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
windowPtr = glfwCreateWindow(width, height, name, NULL, NULL);
if (windowPtr != NULL) {
printf("Successfully initialized GLFW window! Using OpenGL %s - GLSL %s\n", glGetString(GL_VERSION), glGetString(GL_SHADING_LANGUAGE_VERSION));
}
glfwMakeContextCurrent(windowPtr);
glfwSwapInterval(1);
return (windowPtr != NULL);
}
static void onGLFWKeyboard(GLFWwindow * window, int key, int scancode, int action, int mods) {
UNUSED(window); UNUSED(scancode); UNUSED(mods);
// TODO: translate key input from different backend systems to standard representation here
if (action == GLFW_PRESS || action == GLFW_REPEAT) {
eventHandler->onKeyDown(key);
}
if (action == GLFW_RELEASE) {
if (key == GLFW_KEY_ESCAPE) {
exitGLFWLoop();
} else {
eventHandler->onKeyUp(key);
}
}
}
static void onGLFWMouseMove(GLFWwindow * window, double mouseX, double mouseY) {
UNUSED(mouseX); UNUSED(mouseY);
double mx, my;
glfwGetCursorPos(window, & mx, & my);
eventHandler->onMouseMove(mx, my);
}
static void onGLFWMouseButton(GLFWwindow * window, int button, int action, int mods) {
UNUSED(button); UNUSED(mods);
if (action == GLFW_RELEASE) {
double mx, my;
glfwGetCursorPos(window, & mx, & my);
eventHandler->onClick(mx, my);
}
}
static void bindGLFWCallbacks() {
glfwSetKeyCallback(windowPtr, onGLFWKeyboard);
glfwSetCursorPosCallback(windowPtr, onGLFWMouseMove);
glfwSetMouseButtonCallback(windowPtr, onGLFWMouseButton);
}
void runGLFWMainLoop(Callbacks * _eventHandler) {
if (!_eventHandler) {
fprintf(stderr, "No callback handler specified!");
std::exit(1);
}
eventHandler = _eventHandler;
bindGLFWCallbacks();
while (!glfwWindowShouldClose(windowPtr)) {
eventHandler->update();
eventHandler->draw();
glfwSwapBuffers(windowPtr);
glfwPollEvents();
}
glfwDestroyWindow(windowPtr);
glfwTerminate();
}
#pragma once
#define GLFW_INCLUDE_GLCOREARB
#include <GLFW/glfw3.h>
#include "Callbacks.h"
void terminateGLFWAndExit();
void exitGLFWLoop();
void initGLFWDriver(int, char * *);
bool initGLFWWindow(int, int, const char *);
void runGLFWMainLoop(Callbacks *);
// Note: I'm not sure this is functional!
// I removed a lot of the setup and render code that is tutorial-specific
#include <iostream>
#include <memory>
#include <vector>
#include <cstdio>
#define GLFW_INCLUDE_GLCOREARB
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/constants.hpp>
#include "App.h"
#include "Camera.h"
#include "GLFWDriver.h"
#include "Lights.h"
#include "MathHelpers.h"
#include "MatrixGroup.h"
#include "Shader.h"
#include "Texture.h"
#include "util.h"
class DemoApp : public App, public Callbacks {
public:
const int width = 1024;
const int height = 800;
const char * name = "Demo App";
GLuint VAO;
GLuint VBO;
GLuint IBO;
std::shared_ptr<Shader> shaderProgram;
bool shaderDirty = true;
DemoApp() {}
~DemoApp() {}
// Simple setup/update/draw framework
void setup() {
GenerateVAO();
unsigned int Indices[] = { 0, 3, 1,
1, 3, 2,
2, 3, 0,
1, 2, 0 };
GenerateVBO(Indices, ARRAY_SIZE_IN_ELEMENTS(Indices));
GenerateIBO(Indices, sizeof(Indices));
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
}
void update() {
if (shaderDirty) {
std::shared_ptr<Shader> tmpShader = std::shared_ptr<Shader>(new Shader());
bool shaderSuccess = tmpShader->load("shader.vs", "shader.fs");
if (shaderSuccess) {
shaderProgram = tmpShader;
std::cout << "Successfully reloaded shader" << std::endl;
} else {
shaderProgram = std::shared_ptr<Shader>(new Shader());
std::cout << "Shader couldn't load!" << std::endl;
exitGLFWLoop();
}
shaderDirty = false;
}
}
void draw() {
// VAO
glBindVertexArray(VAO);
shaderProgram->validate();
shaderProgram->bind();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
/* ... More render code ... */
// VBO
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0);
// Texture coordinates
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) sizeof(glm::vec3));
// Normals
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *) (sizeof(glm::vec3) + sizeof(glm::vec2)));
// IBO
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
// Draw
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);
// reset state
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
shaderProgram->unbind();
glBindVertexArray(0);
// check for errors that occurred
checkGLError();
}
void CalculateNormals(const unsigned int * indices, unsigned int numIndices, Vertex * vertices, unsigned int numVertices) {
for (unsigned int i = 0; i < numIndices; i += 3) {
unsigned int index1 = indices[i];
unsigned int index2 = indices[i + 1];
unsigned int index3 = indices[i + 2];
glm::vec3 side1 = vertices[index2].pos - vertices[index1].pos;
glm::vec3 side2 = vertices[index3].pos - vertices[index1].pos;
// glm::vec3 normal = glm::normalize(glm::cross(side1, side2));
glm::vec3 normal = glm::normalize(glm::cross(side2, side1));
vertices[index1].normal += normal;
vertices[index2].normal += normal;
vertices[index3].normal += normal;
}
for (unsigned int i = 0; i < numVertices; ++i) {
vertices[i].normal = glm::normalize(vertices[i].normal);
}
}
void GenerateVAO() {
glGenVertexArrays(1, & VAO);
}
void GenerateVBO(const unsigned int * indices, unsigned int numIndices) {
Vertex Vertices[4] = { Vertex(Vector3f(-1.0f, -1.0f, 0.5773f), Vector2f(0.0f, 0.0f)),
Vertex(Vector3f(0.0f, -1.0f, -1.15475f), Vector2f(0.5f, 0.0f)),
Vertex(Vector3f(1.0f, -1.0f, 0.5773f), Vector2f(1.0f, 0.0f)),
Vertex(Vector3f(0.0f, 1.0f, 0.0f), Vector2f(0.5f, 1.0f)) };
unsigned int numVertices = ARRAY_SIZE_IN_ELEMENTS(Vertices);
CalculateNormals(indices, numIndices, Vertices, numVertices);
glGenBuffers(1, & VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void GenerateIBO(const unsigned int * indices, unsigned int indicesBytes) {
glGenBuffers(1, & IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indicesBytes, indices, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void onKeyDown(int key) {
}
void onKeyUp(int key) {
if (key == GLFW_KEY_SPACE) {
shaderDirty = true;
}
}
void onMouseMove(double mouseX, double mouseY) {
}
void onClick(double glfwMouseButton, double glfwMouseState) {
}
};
int main(int argc, char ** argv) {
Magick::InitializeMagick(*argv);
initGLFWDriver(argc, argv);
DemoApp * app = new DemoApp();
if (!initGLFWWindow(app->width, app->height, app->name)) {
return 1;
}
app->setup();
runGLFWMainLoop(app);
delete app;
return 0;
}
#include <cstdio>
#define GLFW_INCLUDE_GLCOREARB
#include <GLFW/glfw3.h>
#include "util.h"
void checkGLError() {
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
switch (error) {
case GL_INVALID_ENUM:
printf("GLERROR: Invalid Enum\n"); break;
case GL_INVALID_VALUE:
printf("GLERROR: Invalid Value\n"); break;
case GL_INVALID_OPERATION:
printf("GLERROR: Invalid Operation\n"); break;
case GL_INVALID_FRAMEBUFFER_OPERATION:
printf("GLERROR: Invalid Framebuffer Operation"); break;
default:
printf("GLERROR: Other - %d", error); break;
}
}
}
#pragma once
#include <string>
#define UNUSED(x) (void)(x)
#define ARRAY_SIZE_IN_ELEMENTS(a) (sizeof(a)/sizeof(a[0]))
void checkGLError();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment