Skip to content

Instantly share code, notes, and snippets.

@Bigcheese
Created March 13, 2013 01:22
Show Gist options
  • Save Bigcheese/5148643 to your computer and use it in GitHub Desktop.
Save Bigcheese/5148643 to your computer and use it in GitHub Desktop.
#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