skein/src/gfx.cpp

161 lines
4.4 KiB
C++

#include "gfx.hpp"
#include <iostream>
#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"
#include "io.hpp"
float aspect_;
// Initialize GLFW, OpenGL and GLEW, open a window and make it the current context.
// Returns 0 for success, and -1 for any failure.
// Failures are printed to STDERR.
int initGraphics(GLFWwindow** window, const std::string& title)
{
// Set up GLFW, OpenGL and GLEW.
if (!glfwInit())
{
std::cerr << "Failed to initialize GLFW" << std::endl;
return -1;
}
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
glfwWindowHint(GLFW_RESIZABLE, GLFW_TRUE);
*window = glfwCreateWindow(640, 480, title.c_str(), NULL, NULL);
if (!window)
{
glfwTerminate();
std::cerr << "Failed to open window with GLFW" << std::endl;
return -1;
}
glfwSetWindowSizeCallback(*window, windowSizeCallback);
glfwMakeContextCurrent(*window);
glewExperimental = GL_TRUE;
if (glewInit() != GLEW_OK)
{
std::cerr << "Failed to initialize GLEW" << std::endl;
return -1;
}
glEnable(GL_DEPTH_TEST);
return 0;
}
void windowSizeCallback(GLFWwindow* window, int width, int height)
{
aspect_ = (float)width / (float)height;
glViewport(0, 0, width, height);
}
GLuint compileShader(const std::string& shaderPath, GLenum shaderType)
{
GLuint shader;
GLint success;
std::string shaderSource = readFile(shaderPath);
const char* source = shaderSource.c_str();
shader = glCreateShader(shaderType);
glShaderSource(shader, 1, &source, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success)
{
GLchar infoLog[512];
glGetShaderInfoLog(shader, 512, NULL, infoLog);
std::cerr << "shader compilation failed" << std::endl
<< infoLog << std::endl;
}
return shader;
}
GLuint compileShaderProgram(const std::string& fragShaderPath)
{
GLuint vertShader = compileShader("./vert.glsl", GL_VERTEX_SHADER);
GLuint fragShader = compileShader(fragShaderPath, GL_FRAGMENT_SHADER);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertShader);
glAttachShader(shaderProgram, fragShader);
glLinkProgram(shaderProgram);
GLint success;
GLchar infoLog[512];
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success)
{
glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
std::cerr << "shader linking failed" << std::endl
<< infoLog << std::endl;
exit(-1);
}
// We no longer need the individual shaders
glDeleteShader(vertShader);
glDeleteShader(fragShader);
return shaderProgram;
}
void updateProjectionMatrix(GLuint shaderProgram)
{
float left = -aspect_, right = aspect_, bottom = -1.0, top = 1.0, near = -2.0, far = 1.0;
glm::mat4 projection = glm::ortho(left, right, bottom, top, near, far);
GLint projectionLocation = getShaderUniformLocation(shaderProgram, "_Projection");
glUniformMatrix4fv(projectionLocation, 1, GL_FALSE, &projection[0][0]);
}
void updateModelMatrix(GLuint shaderProgram)
{
glm::mat4 model = glm::mat4(1.0);
GLint modelLocation = getShaderUniformLocation(shaderProgram, "_Model");
glUniformMatrix4fv(modelLocation, 1, GL_FALSE, &model[0][0]);
}
void updateViewMatrix(GLuint shaderProgram, float time)
{
glm::mat4 view = glm::mat4(1.0);
// Rotation
// TODO: disconnect application and simulation time
constexpr float angle = 0;
//constexpr float angle = glm::radians(10.0);
glm::vec3 axis = glm::vec3(0.0, 1.0, 0.0);
view = glm::rotate(view, angle * time, axis);
GLint viewLocation = getShaderUniformLocation(shaderProgram, "_View");
glUniformMatrix4fv(viewLocation, 1, GL_FALSE, &view[0][0]);
}
void updateModelViewProjectionMatrix(GLuint shaderProgram, float time)
{
// Calculate matrices
updateProjectionMatrix(shaderProgram);
updateModelMatrix(shaderProgram);
updateViewMatrix(shaderProgram, time);
}
GLint getShaderUniformLocation(GLuint shaderProgram, const std::string& uniformName)
{
GLint location = glGetUniformLocation(shaderProgram, uniformName.c_str());
if (location == -1)
{
std::cerr << "Could not find uniform: " << uniformName << std::endl;
return -1;
}
return location;
}