Last active
November 13, 2015 23:17
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "GLFWDriver.h" | |
class App { | |
public: | |
App() {}; | |
virtual ~App() {}; | |
int width; | |
int height; | |
char * name; | |
void endApp() { | |
exitGLFWLoop(); | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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() {}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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 *); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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