Skip to content

Instantly share code, notes, and snippets.

@krysseltillada
Created June 19, 2016 18:36
Show Gist options
  • Save krysseltillada/1c04b4d38903d46a365694d856607bdb to your computer and use it in GitHub Desktop.
Save krysseltillada/1c04b4d38903d46a365694d856607bdb to your computer and use it in GitHub Desktop.
exercise 18 (translation, scaling, rotation) matrix stack
#version 330
smooth in vec4 vertexColorOutput;
out vec4 fragmentColor;
void main ()
{
fragmentColor = vertexColorOutput;
}
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <cstdlib>
#include <string>
#include <stdexcept>
#include <iostream>
#include <stack>
#include <glm.hpp>
#include <gtc/type_ptr.hpp>
#include "Shader.hpp"
namespace WindowProperties {
float width = 800.0f;
float height = 600.0f;
const float xPOSITION = 200;
const float yPOSITION = 200;
std::string windowTitle = "exercise 18 (translation, scaling, rotation) matrix stack";
const GLuint displayMode = GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH;
const GLuint openGLMINVERSION = 3;
const GLuint openGLMAXVERSION = 3;
const GLuint openglProfile = GLUT_CORE_PROFILE;
}
namespace Window {
class MatrixStack {
public:
MatrixStack() :
currMat(1.0f) { }
MatrixStack(const int &i) :
currMat(i) { }
MatrixStack &Translate(const glm::vec3 &position) {
glm::mat4 translationMatrix(1.0f);
translationMatrix[3].x = position.x;
translationMatrix[3].y = position.y;
translationMatrix[3].z = position.z;
currMat *= translationMatrix;
return *this;
}
MatrixStack &Scale(const glm::vec3 &scale) {
glm::mat4 scaleMatrix(1.0f);
scaleMatrix[0].x = scale.x;
scaleMatrix[1].y = scale.y;
scaleMatrix[2].z = scale.z;
currMat *= scaleMatrix;
return *this;
}
MatrixStack &Rotate(const glm::vec3 &rotationAxis) {
glm::mat4 rotationMatrixX(1.0f);
glm::mat4 rotationMatrixY(1.0f);
glm::mat4 rotationMatrixZ(1.0f);
rotationMatrixX[1].y = glm::cos(rotationAxis.x);
rotationMatrixX[1].z = glm::sin(rotationAxis.x);
rotationMatrixX[2].y = -glm::sin(rotationAxis.x);
rotationMatrixX[2].z = glm::cos(rotationAxis.x);
rotationMatrixY[0].x = glm::cos(rotationAxis.y);
rotationMatrixY[0].z = -glm::sin(rotationAxis.y);
rotationMatrixY[2].x = glm::sin(rotationAxis.y);
rotationMatrixY[2].z = glm::cos(rotationAxis.y);
rotationMatrixZ[0].x = glm::cos(rotationAxis.z);
rotationMatrixZ[0].y = glm::sin(rotationAxis.z);
rotationMatrixZ[1].x = -glm::sin(rotationAxis.z);
rotationMatrixZ[1].y = glm::cos(rotationAxis.z);
currMat *= rotationMatrixY * rotationMatrixX * rotationMatrixZ;
return *this;
}
MatrixStack &push() {
matStack.push(currMat);
return *this;
}
MatrixStack &pop() {
currMat = matStack.top();
matStack.pop();
return *this;
}
glm::mat4 peek() {
return currMat;
}
private:
glm::mat4 currMat;
std::stack <glm::mat4> matStack;
};
class Camera {
public:
glm::vec3 position;
float fov, zNear, zFar;
};
class Object {
public:
glm::vec3 position;
glm::vec3 scale;
glm::vec3 rotate;
};
const float vertexData[] = {
0.25f, 0.25f, -1.25f, 1.0f,
0.25f, -0.25f, -1.25f, 1.0f,
-0.25f, 0.25f, -1.25f, 1.0f,
0.25f, -0.25f, -1.25f, 1.0f,
-0.25f, -0.25f, -1.25f, 1.0f,
-0.25f, 0.25f, -1.25f, 1.0f,
0.25f, 0.25f, -2.75f, 1.0f,
-0.25f, 0.25f, -2.75f, 1.0f,
0.25f, -0.25f, -2.75f, 1.0f,
0.25f, -0.25f, -2.75f, 1.0f,
-0.25f, 0.25f, -2.75f, 1.0f,
-0.25f, -0.25f, -2.75f, 1.0f,
-0.25f, 0.25f, -1.25f, 1.0f,
-0.25f, -0.25f, -1.25f, 1.0f,
-0.25f, -0.25f, -2.75f, 1.0f,
-0.25f, 0.25f, -1.25f, 1.0f,
-0.25f, -0.25f, -2.75f, 1.0f,
-0.25f, 0.25f, -2.75f, 1.0f,
0.25f, 0.25f, -1.25f, 1.0f,
0.25f, -0.25f, -2.75f, 1.0f,
0.25f, -0.25f, -1.25f, 1.0f,
0.25f, 0.25f, -1.25f, 1.0f,
0.25f, 0.25f, -2.75f, 1.0f,
0.25f, -0.25f, -2.75f, 1.0f,
0.25f, 0.25f, -2.75f, 1.0f,
0.25f, 0.25f, -1.25f, 1.0f,
-0.25f, 0.25f, -1.25f, 1.0f,
0.25f, 0.25f, -2.75f, 1.0f,
-0.25f, 0.25f, -1.25f, 1.0f,
-0.25f, 0.25f, -2.75f, 1.0f,
0.25f, -0.25f, -2.75f, 1.0f,
-0.25f, -0.25f, -1.25f, 1.0f,
0.25f, -0.25f, -1.25f, 1.0f,
0.25f, -0.25f, -2.75f, 1.0f,
-0.25f, -0.25f, -2.75f, 1.0f,
-0.25f, -0.25f, -1.25f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.0f, 0.0f, 1.0f, 1.0f,
0.8f, 0.8f, 0.8f, 1.0f,
0.8f, 0.8f, 0.8f, 1.0f,
0.8f, 0.8f, 0.8f, 1.0f,
0.8f, 0.8f, 0.8f, 1.0f,
0.8f, 0.8f, 0.8f, 1.0f,
0.8f, 0.8f, 0.8f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.0f, 1.0f, 0.0f, 1.0f,
0.5f, 0.5f, 0.0f, 1.0f,
0.5f, 0.5f, 0.0f, 1.0f,
0.5f, 0.5f, 0.0f, 1.0f,
0.5f, 0.5f, 0.0f, 1.0f,
0.5f, 0.5f, 0.0f, 1.0f,
0.5f, 0.5f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
0.0f, 1.0f, 1.0f, 1.0f,
};
GLfloat triangle[] = {
0.5f, -0.5f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 1.0f,
0.0f, 0.5f, 0.0f, 1.0f
};
glm::mat4 cameraToClipMatrix;
GLboolean ifInit = GL_FALSE;
GLboolean ifToggleAspect = GL_FALSE;
GLboolean ifToggleDClamping = GL_FALSE;
GLboolean ifToggleFCulling = GL_FALSE;
GLboolean ifToggleDTest = GL_FALSE;
GLchar DIkey = '+';
GLuint vertexBufferObject;
GLuint vertexArrayObject;
GLuint modelToCameraMatrixUniformLocation;
GLuint cameraToClipMatrixUniformLocation;
GLuint shaderProgram;
Camera camera;
Object object1;
MatrixStack transformationStack;
float calcFrustumScale(const float &angle) {
return (1.0f / glm::tan(glm::radians(angle) / 2.0f));
}
void Update() {
if (ifToggleAspect) {
cameraToClipMatrix[0].x = calcFrustumScale(camera.fov) / (WindowProperties::width / WindowProperties::height);
cameraToClipMatrix[1].y = calcFrustumScale(camera.fov);
}
else {
cameraToClipMatrix[0].x = calcFrustumScale(camera.fov);
cameraToClipMatrix[1].y = calcFrustumScale(camera.fov);
}
if (ifToggleFCulling) {
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
}
else
glDisable(GL_CULL_FACE);
if (ifToggleDTest) {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
glDepthMask(GL_TRUE);
}
else
glDisable(GL_DEPTH_TEST);
if (ifToggleDClamping)
glEnable(GL_DEPTH_CLAMP);
else
glDisable(GL_DEPTH_CLAMP);
transformationStack.push();
transformationStack.Translate(glm::vec3(-camera.position.x, -camera.position.y, camera.position.z));
transformationStack.Translate(glm::vec3(object1.position.x, object1.position.y, object1.position.z));
transformationStack.Rotate(glm::vec3(object1.rotate.x, object1.rotate.y, object1.rotate.z));
transformationStack.Scale(glm::vec3(object1.scale.x, object1.scale.y, object1.scale.z));
glUseProgram(shaderProgram);
glUniformMatrix4fv(modelToCameraMatrixUniformLocation, 1, GL_FALSE, glm::value_ptr(transformationStack.peek()));
glUniformMatrix4fv(cameraToClipMatrixUniformLocation, 1, GL_FALSE, glm::value_ptr(cameraToClipMatrix));
glUseProgram(0);
transformationStack.pop();
}
void Render() {
glUseProgram(shaderProgram);
glBindVertexArray(vertexArrayObject);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
glUseProgram(0);
glutSwapBuffers();
glutPostRedisplay();
}
void initObjects() {
std::cout << "setting the required objects" << std::endl;
camera.fov = 45.0f;
camera.position.x = 0.0f;
camera.position.y = 0.0f;
camera.position.z = 0.0f;
camera.zNear = 1.0f;
camera.zFar = 100.0f;
object1.position.x = 0.5f;
object1.position.y = 0.4;
object1.position.z = -1.0f;
object1.scale.x = 1.0f;
object1.scale.y = 3.0f;
object1.scale.z = 1.0f;
object1.rotate.y = 0.0f;
object1.rotate.x = 0.0f;
object1.rotate.z = 0.0f;
std::cout << "loading the shader files" << std::endl;
std::string vertexCode = Shader::ShaderUtility::loadShaderFile("transformation.vert");
std::string fragmentCode = Shader::ShaderUtility::loadShaderFile("fragmentColor.frag");
std::cout << "compiling and building the shader program" << std::endl;
shaderProgram = Shader::ShaderUtility::buildProgram({ Shader::ShaderUtility::compileShader(vertexCode.c_str(), GL_VERTEX_SHADER),
Shader::ShaderUtility::compileShader(fragmentCode.c_str(), GL_FRAGMENT_SHADER) });
glGenBuffers(1, &vertexBufferObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData), vertexData, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glGenVertexArrays(1, &vertexArrayObject);
glBindVertexArray(vertexArrayObject);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferObject);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, (void *)0);
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, (void *)576);
glBindVertexArray(0);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, 0);
if (ifToggleAspect) {
cameraToClipMatrix[0].x = calcFrustumScale(camera.fov) / (WindowProperties::width / WindowProperties::height);
cameraToClipMatrix[1].y = calcFrustumScale(camera.fov);
}
else {
cameraToClipMatrix[0].x = calcFrustumScale(camera.fov);
cameraToClipMatrix[1].y = calcFrustumScale(camera.fov);
}
cameraToClipMatrix[2].z = (camera.zNear + camera.zFar) / (camera.zNear - camera.zFar);
cameraToClipMatrix[3].z = (2 * camera.zNear + camera.zFar) / (camera.zNear - camera.zFar);
cameraToClipMatrix[2].w = -1.0f;
cameraToClipMatrixUniformLocation = glGetUniformLocation(shaderProgram, "cameraToClipMatrix");
modelToCameraMatrixUniformLocation = glGetUniformLocation(shaderProgram, "modelToCameraMatrix");
transformationStack.push();
transformationStack.Translate(glm::vec3(object1.position.x, object1.position.y, object1.position.z));
transformationStack.Translate(glm::vec3(-camera.position.x, -camera.position.y, camera.position.z));
transformationStack.Rotate(glm::vec3(object1.rotate.x, object1.rotate.y, object1.rotate.z));
transformationStack.Scale(glm::vec3(object1.scale.x, object1.scale.y, object1.scale.z));
glUseProgram(shaderProgram);
glUniformMatrix4fv(cameraToClipMatrixUniformLocation, 1, GL_FALSE, glm::value_ptr(cameraToClipMatrix));
glUniformMatrix4fv(modelToCameraMatrixUniformLocation, 1, GL_FALSE, glm::value_ptr(transformationStack.peek()));
glUseProgram(0);
transformationStack.pop();
if (ifToggleFCulling) {
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glFrontFace(GL_CW);
}
if (ifToggleDTest) {
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glDepthRange(0.0f, 1.0f);
glDepthMask(GL_TRUE);
}
if (ifToggleDClamping)
glEnable(GL_DEPTH_CLAMP);
}
void Clear() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearDepth(1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void Run() {
if (!ifInit) {
initObjects();
ifInit = GL_TRUE;
std::cout << "press 1 to toggle aspect ratio" << std::endl
<< "press 2 to toggle Depth clamping" << std::endl
<< "press 3 to toggle Face culling" << std::endl
<< "press 4 to toggle Depth testing" << std::endl;
}
Clear();
Render();
Update();
}
void KeyEvent(unsigned char key, int x, int y) {
switch (key) {
case '+':
std::cout << "increase" << std::endl;
DIkey = '+';
break;
case '-':
std::cout << "decrease" << std::endl;
DIkey = '-';
break;
case 'r':
camera.position.y += 0.1f;
break;
case 'f':
camera.position.y -= 0.1f;
break;
case 'w':
camera.position.z += 0.1f;
break;
case 's':
camera.position.z -= 0.1f;
break;
case 'a':
camera.position.x -= 0.1f;
break;
case 'd':
camera.position.x += 0.1f;
break;
case 'x':
if (DIkey == '+')
object1.scale.x += 1.0f;
else if (DIkey == '-')
object1.scale.x -= 1.0f;
break;
case 'z':
if (DIkey == '+')
object1.scale.z += 1.0f;
else if (DIkey == '-')
object1.scale.z -= 1.0f;
break;
case 'c':
if (DIkey == '+')
object1.scale.y += 1.0f;
else if (DIkey == '-')
object1.scale.y -= 1.0f;
break;
case 'i':
object1.position.y += 0.1f;
break;
case 'k':
object1.position.y -= 0.1f;
break;
case 'j':
object1.position.x -= 0.1f;
break;
case 'l':
object1.position.x += 0.1f;
break;
case 'b':
if (DIkey == '+')
object1.rotate.x += 0.1f;
else if (DIkey == '-')
object1.rotate.x -= 0.1f;
break;
case 'n':
if (DIkey == '+')
object1.rotate.y += 0.1f;
else if (DIkey == '-')
object1.rotate.y -= 0.1f;
break;
case 'm':
if (DIkey == '+')
object1.rotate.z += 0.1f;
else if (DIkey == '-')
object1.rotate.z -= 0.1f;
break;
case '1':
if (!ifToggleAspect) {
ifToggleAspect = GL_TRUE;
std::cout << "toggle on aspect ratio" << std::endl;
}
else {
ifToggleAspect = GL_FALSE;
std::cout << "toggle off aspect ratio" << std::endl;
}
break;
case '2':
if (!ifToggleDClamping) {
ifToggleDClamping = GL_TRUE;
std::cout << "toggle on Depth Clamping" << std::endl;
}
else {
ifToggleDClamping = GL_FALSE;
std::cout << "toggle off Depth Clamping" << std::endl;
}
break;
case '3':
if (!ifToggleFCulling) {
ifToggleFCulling = GL_TRUE;
std::cout << "toggle on Face Culling" << std::endl;
}
else {
ifToggleFCulling = GL_FALSE;
std::cout << "toggle off Face Culling" << std::endl;
}
break;
case '4':
if (!ifToggleDTest) {
ifToggleDTest = GL_TRUE;
std::cout << "toggle on Depth Testing" << std::endl;
}
else {
ifToggleDTest = GL_FALSE;
std::cout << "toggle off Depth Testing" << std::endl;
}
break;
default:
break;
}
}
void Resize(int w, int h) {
WindowProperties::width = w;
WindowProperties::height = h;
glViewport(0, 0, WindowProperties::width, WindowProperties::height);
if (ifToggleAspect) {
cameraToClipMatrix[0].x = calcFrustumScale(camera.fov) / (WindowProperties::width / WindowProperties::height);
cameraToClipMatrix[1].y = calcFrustumScale(camera.fov);
}
else {
cameraToClipMatrix[0].x = calcFrustumScale(camera.fov);
cameraToClipMatrix[1].y = calcFrustumScale(camera.fov);
}
glUseProgram(shaderProgram);
glUniformMatrix4fv(cameraToClipMatrixUniformLocation, 1, GL_FALSE, glm::value_ptr(cameraToClipMatrix));
glUseProgram(0);
}
void initWindow(int *const cp_argn, char **const cp_argc) {
glutInit(cp_argn, cp_argc);
glutInitContextProfile(GLUT_CORE_PROFILE);
glutInitContextVersion(WindowProperties::openGLMAXVERSION, WindowProperties::openGLMINVERSION);
glutInitDisplayMode(WindowProperties::displayMode);
glutInitWindowSize(WindowProperties::width, WindowProperties::height);
glutInitWindowPosition(200, 200);
glutCreateWindow(WindowProperties::windowTitle.c_str());
std::cout << "exercise 18 (translation, scale, rotation / orientation, matrix stack)" << std::endl;
std::cout << "opening window..." << std::endl;
glewExperimental = GLEW_OK;
std::cout << "initializing the open gl context" << std::endl;
if (glewInit()) {
std::cerr << "cannot initialized the contesxt" << std::endl;
throw std::runtime_error("error check your drivers");
}
std::cout << glGetString(GL_VERSION) << std::endl;
std::cout << "successfully initialized" << std::endl;
std::cout << "registering callback events " << std::endl;
glutReshapeFunc(&Resize);
glutDisplayFunc(&Run);
glutKeyboardFunc(&KeyEvent);
glutMainLoop();
}
}
int main(int argn, char **argc)
{
Window::initWindow(&argn, argc);
return EXIT_SUCCESS;
}
#include "Shader.hpp"
namespace Shader {
std::string ShaderUtility::loadShaderFile(const std::string &fileName) {
std::fstream readFile(fileName, std::fstream::in, std::fstream::trunc);
std::string sourceCode, line;
if (!readFile) {
std::cerr << "cannot load File " << fileName << std::endl;
throw std::runtime_error("error cannot load file");
}
for (; std::getline(readFile, line);) {
sourceCode += line + '\n';
}
if (sourceCode[sourceCode.length() - 1] != '\0')
sourceCode.push_back('\0');
return sourceCode;
}
GLuint ShaderUtility::compileShader(const char *sourceCode, const GLenum &shaderType) {
GLuint shaderObject = glCreateShader (shaderType);
GLint compileStatus;
glShaderSource(shaderObject, 1, &sourceCode, nullptr);
glCompileShader(shaderObject);
glGetShaderiv(shaderObject, GL_COMPILE_STATUS, &compileStatus);
if (!compileStatus) {
std::string typeOfShader;
GLint errorLogLength;
glGetShaderiv(shaderObject, GL_INFO_LOG_LENGTH, &errorLogLength);
GLchar *errorLog = new GLchar[errorLogLength + 1];
glGetShaderInfoLog(shaderObject, errorLogLength + 1, nullptr, errorLog);
switch (shaderType) {
case GL_VERTEX_SHADER:
typeOfShader = "VERTEX";
break;
case GL_FRAGMENT_SHADER:
typeOfShader = "FRAGMENT";
break;
default:
typeOfShader = "NONE";
break;
}
std::cerr << "error " << typeOfShader << std::endl
<< errorLog << std::endl;
delete[] errorLog;
}
return shaderObject;
}
GLuint ShaderUtility::buildProgram(std::initializer_list <GLuint> shaderObjectList) {
GLuint programObject = glCreateProgram();
GLint linkingStatus;
for (std::initializer_list <GLuint>::iterator it = shaderObjectList.begin(); it != shaderObjectList.end(); ++it)
glAttachShader(programObject, *it);
glLinkProgram(programObject);
glGetProgramiv(programObject, GL_LINK_STATUS, &linkingStatus);
if (!linkingStatus) {
GLint errorLogLength;
glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &errorLogLength);
std::unique_ptr <GLchar> errorLog(new GLchar[errorLogLength + 1]);
glGetProgramInfoLog(programObject, errorLogLength + 1, nullptr, errorLog.get());
std::cerr << "LINKING ERROR::" << std::endl
<< errorLog.get() << std::endl;
}
for (std::initializer_list <GLuint>::iterator it2 = shaderObjectList.begin(); it2 != shaderObjectList.end(); ++it2) {
glDetachShader(programObject, *it2);
glDeleteShader(*it2);
}
return programObject;
}
}
#ifndef SHADER_HEADER
#define SHADER_HEADER
#define GLEW_STATIC
#include <GL/glew.h>
#include <GL/freeglut.h>
#include <fstream>
#include <memory>
#include <initializer_list>
#include <iostream>
#include <string>
#include <stdexcept>
namespace Shader {
class ShaderUtility {
public:
static std::string loadShaderFile(const std::string &);
static GLuint compileShader(const char *, const GLenum &);
static GLuint buildProgram(std::initializer_list <GLuint>);
};
}
#endif
#version 330
layout (location = 0) in vec4 vertexPositionInput;
layout (location = 1) in vec4 vertexColorInput;
uniform mat4 cameraToClipMatrix;
uniform mat4 modelToCameraMatrix;
smooth out vec4 vertexColorOutput;
void main ()
{
vec4 cameraSpace = modelToCameraMatrix * vertexPositionInput;
gl_Position = cameraToClipMatrix * cameraSpace;
vertexColorOutput = vertexColorInput;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment