Last active
August 29, 2015 14:01
-
-
Save milesrout/04617d0e1f7decffb547 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 GL_GLEXT_PROTOTYPES | |
#include <GLFW/glfw3.h> | |
#include <cstdlib> | |
#include <cstdio> | |
#include <cstring> | |
#include <cmath> | |
#include <algorithm> | |
#include <fstream> | |
#include <iostream> | |
#include <streambuf> | |
#include <string> | |
#include <vector> | |
#ifdef M_PI | |
#define PI M_PI | |
#else | |
#define PI 3.14159265359 | |
#endif | |
template <typename T> | |
using vec4 = std::array<T, 4>; | |
template <typename T> | |
using vec3 = std::array<T, 3>; | |
template <typename T> | |
using vec2 = std::array<T, 2>; | |
struct Vertex { | |
vec3<GLfloat> position; | |
vec4<GLfloat> colour; | |
}; | |
class Mesh { | |
GLuint vao; | |
union { | |
struct { | |
GLuint vbo_vertices; | |
GLuint vbo_indices; | |
}; | |
GLuint vbo[2]; | |
}; | |
int numVertices; | |
std::vector<GLfloat> vertexData; | |
std::vector<GLshort> indices; | |
GLfloat offsetX, offsetY, offsetZ; | |
public: | |
Mesh(std::vector<Vertex>, std::vector<GLshort>); | |
void draw() const; | |
void offset(GLfloat x, GLfloat y, GLfloat z); | |
}; | |
GLuint theProgram; | |
GLuint perspectiveMatrixUniform; | |
GLuint offsetUniform; | |
void Mesh::offset(GLfloat x, GLfloat y, GLfloat z) | |
{ | |
this->offsetX = x; | |
this->offsetY = y; | |
this->offsetZ = z; | |
} | |
Mesh::Mesh(const std::vector<Vertex> vertices, const std::vector<GLshort> indices) | |
{ | |
this->numVertices = vertices.size(); | |
this->vertexData.reserve(7*this->numVertices); | |
for (const Vertex &vertex : vertices) | |
{ | |
vertexData.push_back(vertex.position[0]); | |
vertexData.push_back(vertex.position[1]); | |
vertexData.push_back(vertex.position[2]); | |
vertexData.push_back(vertex.colour[0]); | |
vertexData.push_back(vertex.colour[1]); | |
vertexData.push_back(vertex.colour[2]); | |
vertexData.push_back(vertex.colour[3]); | |
} | |
for (const GLshort index : indices) | |
this->indices.push_back(index); | |
// Generate and bind vertex array. | |
glGenVertexArrays(1, &this->vao); | |
glBindVertexArray(this->vao); | |
// Generate vertex buffers. | |
glGenBuffers(2, this->vbo); | |
// Bind vertex buffer. | |
glBindBuffer(GL_ARRAY_BUFFER, this->vbo_vertices); | |
// Copy data into vertex buffer. | |
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*this->vertexData.size(), this->vertexData.data(), GL_STATIC_DRAW); | |
// Define the format of the position data. | |
glEnableVertexAttribArray(0); | |
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), 0); | |
// Define the format of the colour data. | |
glEnableVertexAttribArray(1); | |
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 7*sizeof(GLfloat), (GLvoid*)(3*sizeof(GLfloat))); | |
// Clean up | |
glBindBuffer(GL_ARRAY_BUFFER, 0); | |
// Bind index buffer. | |
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->vbo_indices); | |
// Copy data into vertex buffer. | |
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLshort)*this->indices.size(), this->indices.data(), GL_STATIC_DRAW); | |
// Clean up | |
glBindVertexArray(0); | |
} | |
void Mesh::draw() const | |
{ | |
// Bind object 1's vertex array | |
glBindVertexArray(this->vao); | |
// Offset the object. | |
glUniform3f(offsetUniform, this->offsetX, this->offsetY, this->offsetZ); | |
// Draw the triangle | |
glDrawElements(GL_TRIANGLES, this->indices.size(), GL_UNSIGNED_SHORT, 0); | |
// Clean up | |
glBindVertexArray(0); | |
} | |
std::vector<Mesh> meshes; | |
GLfloat frustumScale = 1.0f, zNear = 0.1f, zFar = 3.0f; | |
GLfloat perspectiveMatrix[16] = {0}; | |
int degreesX = 0; | |
int degreesY = 0; | |
int degreesZ = 0; | |
void Display(GLFWwindow *window) | |
{ | |
// Clear the screen | |
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); | |
glClear(GL_COLOR_BUFFER_BIT); | |
glClearDepth(1.0); | |
glClear(GL_DEPTH_BUFFER_BIT); | |
glUseProgram(theProgram); | |
glUniformMatrix4fv(perspectiveMatrixUniform, 1, GL_FALSE, perspectiveMatrix); | |
for (Mesh &mesh : meshes) | |
mesh.draw(); | |
glUseProgram(0); | |
glfwSwapBuffers(window); | |
glfwPollEvents(); | |
} | |
/*std::vector<Vertex> vertices1 = { | |
{{0.33f, 0.33f, -1.15f}, {1.0f, 0.2f, 0.2f, 1.0f}}, | |
{{0.66f, 0.33f, -1.15f}, {0.2f, 1.0f, 0.2f, 1.0f}}, | |
{{0.33f, 0.66f, -1.15f}, {0.2f, 0.2f, 1.0f, 1.0f}}, | |
{{0.66f, 0.66f, -1.15f}, {1.0f, 1.0f, 0.2f, 1.0f}}, | |
{{0.33f, 0.33f, -1.85f}, {0.2f, 1.0f, 1.0f, 1.0f}}, | |
{{0.66f, 0.33f, -1.85f}, {1.0f, 0.2f, 1.0f, 1.0f}}, | |
{{0.33f, 0.66f, -1.85f}, {1.0f, 1.0f, 1.0f, 1.0f}}, | |
{{0.66f, 0.66f, -1.85f}, {0.2f, 0.2f, 0.2f, 1.0f}}, | |
};*/ | |
std::vector<Vertex> vertices1 = { | |
{{-0.33f, -0.33f, 0.33f}, {1.0f, 0.2f, 0.2f, 1.0f}}, | |
{{0.33f, -0.33f, 0.33f}, {0.2f, 1.0f, 0.2f, 1.0f}}, | |
{{-0.33f, 0.33f, 0.33f}, {0.2f, 0.2f, 1.0f, 1.0f}}, | |
{{0.33f, 0.33f, 0.33f}, {1.0f, 1.0f, 0.2f, 1.0f}}, | |
{{-0.33f, -0.33f, -0.33f}, {0.2f, 1.0f, 1.0f, 1.0f}}, | |
{{0.33f, -0.33f, -0.33f}, {1.0f, 0.2f, 1.0f, 1.0f}}, | |
{{-0.33f, 0.33f, -0.33f}, {1.0f, 1.0f, 1.0f, 1.0f}}, | |
{{0.33f, 0.33f, -0.33f}, {0.2f, 0.2f, 0.2f, 1.0f}}, | |
}; | |
std::vector<GLshort> indices1 = { | |
0, 2, 3, | |
0, 3, 1, | |
1, 3, 7, | |
1, 7, 5, | |
5, 7, 6, | |
5, 6, 4, | |
4, 6, 2, | |
4, 2, 0, | |
2, 6, 7, | |
2, 7, 3, | |
4, 0, 5, | |
0, 1, 5, | |
}; | |
/* | |
std::vector<Vertex> vertices2 = { | |
{{0.33f, 0.33f, -2.15f}, {1.0f, 0.2f, 0.2f, 1.0f}}, | |
{{0.66f, 0.33f, -2.15f}, {0.2f, 1.0f, 0.2f, 1.0f}}, | |
{{0.33f, 0.66f, -2.15f}, {0.2f, 0.2f, 1.0f, 1.0f}}, | |
{{0.66f, 0.66f, -2.15f}, {1.0f, 1.0f, 0.2f, 1.0f}}, | |
{{0.33f, 0.33f, -2.85f}, {0.2f, 1.0f, 1.0f, 1.0f}}, | |
{{0.66f, 0.33f, -2.85f}, {1.0f, 0.2f, 1.0f, 1.0f}}, | |
{{0.33f, 0.66f, -2.85f}, {1.0f, 1.0f, 1.0f, 1.0f}}, | |
{{0.66f, 0.66f, -2.85f}, {0.2f, 0.2f, 0.2f, 1.0f}}, | |
}; | |
std::vector<GLshort> indices2 = { | |
0, 2, 3, | |
0, 3, 1, | |
1, 3, 7, | |
1, 7, 5, | |
5, 7, 6, | |
5, 6, 4, | |
4, 6, 2, | |
4, 2, 0, | |
2, 6, 7, | |
2, 7, 3, | |
4, 0, 5, | |
0, 1, 5, | |
}; | |
*/ | |
void InitializeVertexBuffer() | |
{ | |
// meshes.emplace_back(vertices1, indices1); | |
// meshes.emplace_back(vertices2, indices2); | |
for (int i = 0; i < 2 * 2 * 2; i++) | |
{ | |
meshes.emplace_back(vertices1, indices1); | |
meshes[i].offset(((i / 4) * 2 - 1) * 0.66f, (((i / 2) % 2) * 2 - 1) * 0.66f, -(1.66f + (i % 2))); | |
} | |
} | |
GLuint CreateProgram(std::vector<GLuint> shaders) | |
{ | |
GLuint program = glCreateProgram(); | |
for (GLuint shader : shaders) | |
glAttachShader(program, shader); | |
glLinkProgram(program); | |
GLint linkStatus; | |
glGetProgramiv(program, GL_LINK_STATUS, &linkStatus); | |
if (linkStatus == GL_FALSE) { | |
GLint infoLogLength; | |
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLogLength); | |
GLchar *infoLog = new GLchar[infoLogLength + 1]; | |
glGetProgramInfoLog(program, infoLogLength, NULL, infoLog); | |
fprintf(stderr, "Linker failure: %s\n", infoLog); | |
delete[] infoLog; | |
} | |
return program; | |
} | |
GLuint CreateShader(GLenum type, const std::string &filename) | |
{ | |
GLuint shader = glCreateShader(type); | |
std::ifstream shaderFile(filename); | |
std::string shaderText((std::istreambuf_iterator<char>(shaderFile)), | |
std::istreambuf_iterator<char>()); | |
const char *fileData = shaderText.c_str(); | |
glShaderSource(shader, 1, &fileData, NULL); | |
glCompileShader(shader); | |
GLint compileStatus; | |
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus); | |
if (compileStatus = GL_FALSE) { | |
GLint infoLogLength; | |
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength); | |
GLchar *infoLog = new GLchar[infoLogLength + 1]; | |
glGetShaderInfoLog(shader, infoLogLength, NULL, infoLog); | |
const char *shaderType = NULL; | |
switch(type) { | |
case GL_VERTEX_SHADER: shaderType = "vertex"; break; | |
case GL_FRAGMENT_SHADER: shaderType = "fragment"; break; | |
case GL_GEOMETRY_SHADER: shaderType = "geometry"; break; | |
} | |
fprintf(stderr, "Compile failure in %s shader:\n%s\n", shaderType, infoLog); | |
delete[] infoLog; | |
} | |
return shader; | |
} | |
void InitializeProgram() | |
{ | |
std::vector<GLuint> shaderList; | |
shaderList.push_back(CreateShader(GL_VERTEX_SHADER, "shader.vert")); | |
shaderList.push_back(CreateShader(GL_FRAGMENT_SHADER, "shader.frag")); | |
theProgram = CreateProgram(shaderList); | |
perspectiveMatrixUniform = glGetUniformLocation(theProgram, "perspectiveMatrix"); | |
offsetUniform = glGetUniformLocation(theProgram, "offset"); | |
for (GLuint shader : shaderList) | |
glDeleteShader(shader); | |
} | |
void WindowSizeCallback(GLFWwindow *window, int w, int h) | |
{ | |
perspectiveMatrix[0] = frustumScale / (w / (float) h); | |
perspectiveMatrix[5] = frustumScale; | |
glViewport(0, 0, w, h); | |
} | |
void KeyCallback(GLFWwindow *window, int key, int scancode, int action, int mods) | |
{ | |
if (action == GLFW_PRESS) | |
if (key == GLFW_KEY_SPACE) | |
if (degreesX == 0) | |
{ | |
degreesX += 2; | |
degreesY += 2; | |
degreesZ += 2; | |
} | |
else | |
degreesX = degreesY = degreesZ = 0.0f; | |
} | |
void Initialize(GLFWwindow* window) | |
{ | |
glfwMakeContextCurrent(window); | |
glfwSetKeyCallback(window, KeyCallback); | |
glfwSetWindowSizeCallback(window, WindowSizeCallback); | |
InitializeProgram(); | |
InitializeVertexBuffer(); | |
int w, h; | |
glfwGetFramebufferSize(window, &w, &h); | |
memset(perspectiveMatrix, 0, sizeof(GLfloat) * 16); | |
perspectiveMatrix[10] = (zFar + zNear) / (zNear - zFar); | |
perspectiveMatrix[14] = (2 * zFar * zNear) / (zNear - zFar); | |
perspectiveMatrix[11] = -1.0f; | |
perspectiveMatrix[0] = frustumScale / (w / (GLfloat) h); | |
perspectiveMatrix[5] = frustumScale; | |
glViewport(0, 0, w, h); | |
glEnable(GL_CULL_FACE); | |
glCullFace(GL_BACK); | |
glFrontFace(GL_CW); | |
glEnable(GL_DEPTH_TEST); | |
glEnable(GL_DEPTH_CLAMP); | |
glDepthMask(GL_TRUE); | |
glDepthFunc(GL_LEQUAL); | |
glDepthRange(0.0f, 1.0f); | |
} | |
int main() | |
{ | |
glfwInit(); | |
glfwWindowHint(GLFW_SAMPLES, 16); | |
GLFWwindow *window = glfwCreateWindow(800, 800, "My Title", NULL, NULL); | |
Initialize(window); | |
while (!glfwWindowShouldClose(window)) { | |
Display(window); | |
} | |
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
#version 440 core | |
layout(location = 0) in vec3 position; | |
layout(location = 1) in vec4 colour_in; | |
uniform mat4 perspectiveMatrix; | |
uniform mat4 rotationMatrix; | |
uniform vec3 offset; | |
smooth out vec4 colour; | |
void main() { | |
gl_Position = perspectiveMatrix * vec4(position + offset, 1.0f); | |
colour = colour_in; | |
} |
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
#version 440 core | |
smooth in vec4 colour; | |
smooth out vec4 colour_out; | |
void main() { | |
colour_out = colour; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment