Created
March 13, 2013 01:22
-
-
Save Bigcheese/5148643 to your computer and use it in GitHub Desktop.
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
#define GLEW_STATIC | |
#include "GL/glew.h" | |
#include "GL/glfw3.h" | |
#include "glm/ext.hpp" | |
#include "glm/glm.hpp" | |
#include <cstdlib> | |
#include <functional> | |
#include <iostream> | |
#include <memory> | |
#include <vector> | |
void handleGLFWError(int error, const char *msg) { | |
std::cerr << "gltest: error: " << msg << ". (" << error << ")\n"; | |
} | |
struct Terminator { | |
~Terminator() { | |
glfwTerminate(); | |
} | |
}; | |
struct WindowDeleter { | |
void operator ()(GLFWwindow *window) { | |
glfwDestroyWindow(window); | |
} | |
}; | |
void handleWindowResize(GLFWwindow *window, int width, int height) { | |
glViewport(0, 0, width, height); | |
} | |
// An array of 3 vectors which represents 3 vertices | |
static const GLfloat g_vertex_buffer_data[] = { | |
-1.0f, -1.0f, 0.0f, | |
1.0f, -1.0f, 0.0f, | |
0.0f, 1.0f, 0.0f, | |
}; | |
bool printGLError() { | |
GLenum error = glGetError(); | |
if (error != GL_NO_ERROR) { | |
std::cerr << "gltest: error: " << glewGetErrorString(error) | |
<< ". (" << error << ")\n"; | |
return true; | |
} | |
return false; | |
} | |
struct scope_exit { | |
scope_exit(std::function<void (void)> f) : f_(f) {} | |
~scope_exit(void) { f_(); } | |
private: | |
std::function<void (void)> f_; | |
}; | |
GLuint loadShaders(const char *vertexProgram, const char *fragmentProgram){ | |
// Create the shaders | |
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER); | |
if (!vertexShaderID) { | |
printGLError(); | |
return 0; | |
} | |
scope_exit exit0([&]{glDeleteShader(vertexShaderID);}); | |
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER); | |
if (!fragmentShaderID) { | |
printGLError(); | |
return 0; | |
} | |
scope_exit exit1([&]{glDeleteShader(fragmentShaderID);}); | |
GLint result = GL_FALSE; | |
int infoLogLength; | |
// Compile Vertex Shader | |
char const *vertexSourcePointer = vertexProgram; | |
glShaderSource(vertexShaderID, 1, &vertexSourcePointer, nullptr); | |
glCompileShader(vertexShaderID); | |
// Check Vertex Shader | |
glGetShaderiv(vertexShaderID, GL_COMPILE_STATUS, &result); | |
glGetShaderiv(vertexShaderID, GL_INFO_LOG_LENGTH, &infoLogLength); | |
if (infoLogLength > 0) { | |
std::vector<char> vertexShaderErrorMessage(infoLogLength); | |
glGetShaderInfoLog(vertexShaderID, infoLogLength, nullptr, | |
vertexShaderErrorMessage.data()); | |
std::cerr << vertexShaderErrorMessage.data() << "\n"; | |
} | |
// Compile Fragment Shader | |
char const *fragmentSourcePointer = fragmentProgram; | |
glShaderSource(fragmentShaderID, 1, &fragmentSourcePointer , nullptr); | |
glCompileShader(fragmentShaderID); | |
// Check Fragment Shader | |
glGetShaderiv(fragmentShaderID, GL_COMPILE_STATUS, &result); | |
glGetShaderiv(fragmentShaderID, GL_INFO_LOG_LENGTH, &infoLogLength); | |
if (infoLogLength > 0) { | |
std::vector<char> fragmentShaderErrorMessage(infoLogLength); | |
glGetShaderInfoLog(fragmentShaderID, infoLogLength, nullptr, | |
fragmentShaderErrorMessage.data()); | |
std::cerr << fragmentShaderErrorMessage.data() << "\n"; | |
} | |
// Link the program | |
GLuint programID = glCreateProgram(); | |
if (!programID) { | |
printGLError(); | |
return 0; | |
} | |
glAttachShader(programID, vertexShaderID); | |
glAttachShader(programID, fragmentShaderID); | |
glLinkProgram(programID); | |
// Check the program | |
glGetProgramiv(programID, GL_LINK_STATUS, &result); | |
glGetProgramiv(programID, GL_INFO_LOG_LENGTH, &infoLogLength); | |
std::vector<char> programErrorMessage(std::max(infoLogLength, 1)); | |
glGetProgramInfoLog(programID, infoLogLength, nullptr, | |
programErrorMessage.data()); | |
std::cerr << programErrorMessage.data() << "\n"; | |
std::cerr.flush(); | |
return programID; | |
} | |
const char vertexProgram[] = | |
"#version 330 core\n" | |
"layout(location = 0) in vec3 vertexPosition_modelspace;\n" | |
"uniform mat4 MVP;\n" | |
"void main() {\n" | |
" vec4 v = vec4(vertexPosition_modelspace, 1);\n" | |
" gl_Position = MVP * v;\n" | |
"}\n" | |
; | |
const char fragmentProgram[] = | |
"#version 330 core\n" | |
"out vec3 color;\n" | |
"void main() {\n" | |
" color = vec3(1, 0, 0);\n" | |
"}\n" | |
; | |
int main() { | |
glfwSetErrorCallback(handleGLFWError); | |
if (!glfwInit()) | |
return EXIT_FAILURE; | |
Terminator t; | |
glfwWindowHint(GLFW_SAMPLES, 16); | |
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); | |
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); | |
std::unique_ptr<GLFWwindow, WindowDeleter> window( | |
glfwCreateWindow(640, 480, "Hi", nullptr, nullptr)); | |
if (!window) | |
return EXIT_FAILURE; | |
glfwSetWindowSizeCallback(window.get(), handleWindowResize); | |
glfwMakeContextCurrent(window.get()); | |
glewExperimental = true; | |
if (GLenum error = glewInit() != GLEW_OK) { | |
std::cerr << "gltest: error: " << glewGetErrorString(error) << ".\n"; | |
return EXIT_FAILURE; | |
} | |
GLuint program = loadShaders(vertexProgram, fragmentProgram); | |
if (!program) { | |
printGLError(); | |
return EXIT_FAILURE; | |
} | |
scope_exit exit0([&]{glDeleteProgram(program);}); | |
GLuint matrixID = glGetUniformLocation(program, "MVP"); | |
if (!matrixID) { | |
printGLError(); | |
return EXIT_FAILURE; | |
} | |
glm::mat4 proj = glm::perspective(45.f, 4.f / 3.f, 0.1f, 100.f); | |
glm::mat4 view = glm::lookAt( | |
glm::vec3(4, 3, 3), glm::vec3(0, 0, 0), glm::vec3(0, 1, 0)); | |
glm::mat4 model = glm::mat4(1); | |
glm::mat4 MVP = proj * view * model; | |
glUniformMatrix4fv(matrixID, 1, GL_FALSE, &MVP[0][0]); | |
GLuint vertexArrayID; | |
glGenVertexArrays(1, &vertexArrayID); | |
glBindVertexArray(vertexArrayID); | |
GLuint vertexBuffer; | |
glGenBuffers(1, &vertexBuffer); | |
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); | |
glBufferData(GL_ARRAY_BUFFER, sizeof(g_vertex_buffer_data), | |
g_vertex_buffer_data, GL_STATIC_DRAW); | |
while (!glfwWindowShouldClose(window.get())) { | |
glfwWaitEvents(); | |
if (glfwGetKey(window.get(), GLFW_KEY_ESC)) | |
glfwSetWindowShouldClose(window.get(), true); | |
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); | |
glUseProgram(program); | |
glEnableVertexAttribArray(0); | |
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); | |
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr); | |
glDrawArrays(GL_TRIANGLES, 0, 3); | |
glDisableVertexAttribArray(0); | |
glfwSwapBuffers(window.get()); | |
} | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment