152 lines
3.8 KiB
C++
152 lines
3.8 KiB
C++
#define _USE_MATH_DEFINES
|
|
#include <cmath>
|
|
#include <iostream>
|
|
|
|
#define GLEW_STATIC
|
|
#include <GL/glew.h>
|
|
#include <GLFW/glfw3.h>
|
|
|
|
#define GLM_FORCE_RADIANS
|
|
#include <glm/glm.hpp>
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
|
|
#include "GLSL.h"
|
|
#include "MatrixStack.h"
|
|
#include "Program.h"
|
|
#include "Shape.h"
|
|
|
|
using namespace std;
|
|
|
|
GLFWwindow *window; // Main application window
|
|
string RES_DIR = ""; // Where data files live
|
|
shared_ptr<Program> prog;
|
|
shared_ptr<Shape> shape;
|
|
|
|
static void error_callback(int error, const char *description)
|
|
{
|
|
cerr << description << endl;
|
|
}
|
|
|
|
static void key_callback(GLFWwindow *window, int key, int scancode, int action, int mods)
|
|
{
|
|
if(key == GLFW_KEY_ESCAPE && action == GLFW_PRESS) {
|
|
glfwSetWindowShouldClose(window, GL_TRUE);
|
|
}
|
|
}
|
|
|
|
static void init()
|
|
{
|
|
GLSL::checkVersion();
|
|
|
|
// Set background color.
|
|
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
|
// Enable z-buffer test.
|
|
glEnable(GL_DEPTH_TEST);
|
|
|
|
// Initialize mesh.
|
|
shape = make_shared<Shape>();
|
|
shape->loadMesh(RES_DIR + "teapot.obj");
|
|
shape->init();
|
|
|
|
// Initialize the GLSL program.
|
|
prog = make_shared<Program>();
|
|
prog->setVerbose(false); // Set this to true when debugging.
|
|
prog->setShaderNames(RES_DIR + "simple_vert.glsl", RES_DIR + "simple_frag.glsl");
|
|
prog->init();
|
|
prog->addUniform("P");
|
|
prog->addUniform("MV");
|
|
prog->addAttribute("vertPos");
|
|
prog->addAttribute("vertNor");
|
|
|
|
// If there were any OpenGL errors, this will print something.
|
|
// You can intersperse this line in your code to find the exact location
|
|
// of your OpenGL error.
|
|
GLSL::checkError(GET_FILE_LINE);
|
|
}
|
|
|
|
static void render()
|
|
{
|
|
// Get current frame buffer size.
|
|
int width, height;
|
|
glfwGetFramebufferSize(window, &width, &height);
|
|
float aspect = width/(float)height;
|
|
glViewport(0, 0, width, height);
|
|
|
|
// Clear framebuffer.
|
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
|
|
|
// Create matrix stacks.
|
|
auto P = make_shared<MatrixStack>();
|
|
auto MV = make_shared<MatrixStack>();
|
|
// Apply projection.
|
|
P->pushMatrix();
|
|
P->multMatrix(glm::perspective((float)(45.0*M_PI/180.0), aspect, 0.01f, 100.0f));
|
|
// Apply camera transform.
|
|
MV->pushMatrix();
|
|
MV->translate(glm::vec3(0, -0.5, -3));
|
|
|
|
// Draw mesh using GLSL.
|
|
prog->bind();
|
|
glUniformMatrix4fv(prog->getUniform("P"), 1, GL_FALSE, &P->topMatrix()[0][0]);
|
|
glUniformMatrix4fv(prog->getUniform("MV"), 1, GL_FALSE, &MV->topMatrix()[0][0]);
|
|
shape->draw(prog);
|
|
prog->unbind();
|
|
|
|
// Pop matrix stacks.
|
|
MV->popMatrix();
|
|
P->popMatrix();
|
|
|
|
GLSL::checkError(GET_FILE_LINE);
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
if(argc < 2) {
|
|
cout << "Please specify the resource directory." << endl;
|
|
return 0;
|
|
}
|
|
RES_DIR = argv[1] + string("/");
|
|
|
|
// Set error callback.
|
|
glfwSetErrorCallback(error_callback);
|
|
// Initialize the library.
|
|
if(!glfwInit()) {
|
|
return -1;
|
|
}
|
|
// Create a windowed mode window and its OpenGL context.
|
|
window = glfwCreateWindow(640, 480, "YOUR NAME", NULL, NULL);
|
|
if(!window) {
|
|
glfwTerminate();
|
|
return -1;
|
|
}
|
|
// Make the window's context current.
|
|
glfwMakeContextCurrent(window);
|
|
// Initialize GLEW.
|
|
glewExperimental = true;
|
|
if(glewInit() != GLEW_OK) {
|
|
cerr << "Failed to initialize GLEW" << endl;
|
|
return -1;
|
|
}
|
|
glGetError(); // A bug in glewInit() causes an error that we can safely ignore.
|
|
cout << "OpenGL version: " << glGetString(GL_VERSION) << endl;
|
|
cout << "GLSL version: " << glGetString(GL_SHADING_LANGUAGE_VERSION) << endl;
|
|
// Set vsync.
|
|
glfwSwapInterval(1);
|
|
// Set keyboard callback.
|
|
glfwSetKeyCallback(window, key_callback);
|
|
// Initialize scene.
|
|
init();
|
|
// Loop until the user closes the window.
|
|
while(!glfwWindowShouldClose(window)) {
|
|
// Render scene.
|
|
render();
|
|
// Swap front and back buffers.
|
|
glfwSwapBuffers(window);
|
|
// Poll for and process events.
|
|
glfwPollEvents();
|
|
}
|
|
// Quit program.
|
|
glfwDestroyWindow(window);
|
|
glfwTerminate();
|
|
return 0;
|
|
}
|