Initial commit
This commit is contained in:
commit
686dcaf351
68 changed files with 6230 additions and 0 deletions
265
glHelper.h
Normal file
265
glHelper.h
Normal file
|
@ -0,0 +1,265 @@
|
|||
#ifndef GLHELPERS_H
|
||||
#define GLHELPERS_H
|
||||
|
||||
#include "path_glsl_files.h"
|
||||
|
||||
class GlHelper {
|
||||
public:
|
||||
GLFWwindow* window;
|
||||
|
||||
std::vector<std::string> all_paths;
|
||||
std::vector<std::string> vertex_shader_paths;
|
||||
std::vector<std::string> tess_control_shader_paths;
|
||||
std::vector<std::string> tess_evaluation_shader_paths;
|
||||
std::vector<std::string> fragment_shader_paths;
|
||||
|
||||
double time_of_last_shader_compilation = 0;
|
||||
bool isFirstCompilation = true;
|
||||
|
||||
GlHelper(int task) {
|
||||
last_time = get_seconds();
|
||||
|
||||
setShaderPaths(task, all_paths, vertex_shader_paths, tess_control_shader_paths, tess_evaluation_shader_paths, fragment_shader_paths);
|
||||
}
|
||||
|
||||
// Use GLFW and GLAD to create a window
|
||||
GLFWwindow* createWindow() {
|
||||
// Initialize GLFW
|
||||
if (!glfwInit()) {
|
||||
std::cerr << "Failed to initialize GLFW" << std::endl;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Set GLFW to create an OpenGL context (version 440 core)
|
||||
glfwWindowHint(GLFW_SAMPLES, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
|
||||
GLFWwindow* window = glfwCreateWindow(width, height, "shader-pipeline", NULL, NULL);
|
||||
if (!window) {
|
||||
std::cerr << "Failed to create GLFW window" << std::endl;
|
||||
glfwTerminate();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Make the OpenGL context current
|
||||
glfwMakeContextCurrent(window);
|
||||
|
||||
// Initialize GLAD
|
||||
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
|
||||
std::cerr << "Failed to initialized GLAD" << std::endl;
|
||||
glfwTerminate();
|
||||
return NULL;
|
||||
}
|
||||
this->window = window;
|
||||
return window;
|
||||
}
|
||||
|
||||
// Handle window rescaling and update the projection matrix accordingly
|
||||
void setPerspectiveMatrixBasedOnWindowScale() {
|
||||
const auto& reshape = [](
|
||||
GLFWwindow* window,
|
||||
int _width,
|
||||
int _height)
|
||||
{
|
||||
::width = _width, ::height = _height;
|
||||
|
||||
// windows can't handle variables named near and far.
|
||||
float nearVal = 0.01f;
|
||||
float farVal = 100.0f;
|
||||
float top = static_cast<float>(tan(35. / 360. * M_PI)) * nearVal;
|
||||
float right = top * (float)::width / (float)::height;
|
||||
float left = -right;
|
||||
float bottom = -top;
|
||||
proj.setConstant(4, 4, 0.);
|
||||
proj(0, 0) = (2.0f * nearVal) / (right - left);
|
||||
proj(1, 1) = (2.0f * nearVal) / (top - bottom);
|
||||
proj(0, 2) = (right + left) / (right - left);
|
||||
proj(1, 2) = (top + bottom) / (top - bottom);
|
||||
proj(2, 2) = -(farVal + nearVal) / (farVal - nearVal);
|
||||
proj(3, 2) = -1.0f;
|
||||
proj(2, 3) = -(2.0f * farVal * nearVal) / (farVal - nearVal);
|
||||
};
|
||||
// Set up window resizing
|
||||
glfwSetWindowSizeCallback(window, reshape);
|
||||
{
|
||||
int width_window, height_window;
|
||||
glfwGetWindowSize(window, &width_window, &height_window);
|
||||
reshape(window, width_window, height_window);
|
||||
}
|
||||
}
|
||||
|
||||
// Setup a VAO from a mesh
|
||||
void createVAO() {
|
||||
icosahedron(V, F);
|
||||
mesh_to_vao(V, F, VAO);
|
||||
igl::opengl::report_gl_error("mesh_to_vao");
|
||||
}
|
||||
|
||||
// Make GLFW listen for keyboard and mouse inputs
|
||||
// and change the user input state accordingly
|
||||
void setKeyboardAndMouseCallbacks() {
|
||||
std::cout << R"(
|
||||
Usage:
|
||||
[] the window can be rescaled
|
||||
[Click and drag] to orbit view
|
||||
[Scroll] to translate view in and out
|
||||
A,a toggle animation
|
||||
L,l toggle wireframe rending
|
||||
Z,z reset view to look along z-axis
|
||||
|
||||
)";
|
||||
|
||||
// Close the window if user presses ESC or CTRL+C
|
||||
glfwSetKeyCallback(
|
||||
window,
|
||||
[](GLFWwindow* window, int key, int scancode, int action, int mods)
|
||||
{
|
||||
if (key == 256 || (key == 67 && (mods & GLFW_MOD_CONTROL)))
|
||||
{
|
||||
glfwSetWindowShouldClose(window, true);
|
||||
}
|
||||
});
|
||||
// Listen to keypresses on A, L and Z
|
||||
glfwSetCharModsCallback(
|
||||
window,
|
||||
[](GLFWwindow* window, unsigned int codepoint, int modifier)
|
||||
{
|
||||
switch (codepoint)
|
||||
{
|
||||
case 'A':
|
||||
case 'a':
|
||||
is_animating ^= 1;
|
||||
if (is_animating)
|
||||
{
|
||||
last_time = get_seconds();
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
case 'l':
|
||||
wire_frame ^= 1;
|
||||
if (wire_frame) {
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
else {
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
break;
|
||||
case 'Z':
|
||||
case 'z':
|
||||
view.matrix().block(0, 0, 3, 3).setIdentity();
|
||||
break;
|
||||
default:
|
||||
std::cout << "Unrecognized key: " << (unsigned char)codepoint << std::endl;
|
||||
break;
|
||||
}
|
||||
});
|
||||
glfwSetMouseButtonCallback(
|
||||
window,
|
||||
[](GLFWwindow* window, int button, int action, int mods)
|
||||
{
|
||||
mouse_down = action == GLFW_PRESS;
|
||||
});
|
||||
glfwSetCursorPosCallback(
|
||||
window,
|
||||
[](GLFWwindow* window, double x, double y)
|
||||
{
|
||||
static double mouse_last_x = x;
|
||||
static double mouse_last_y = y;
|
||||
float dx = static_cast<float>(x - mouse_last_x);
|
||||
float dy = static_cast<float>(y - mouse_last_y);
|
||||
if (mouse_down)
|
||||
{
|
||||
// Two axis valuator with fixed up
|
||||
float factor = std::abs(view.matrix()(2, 3));
|
||||
view.rotate(
|
||||
Eigen::AngleAxisf(
|
||||
dx * factor / float(width),
|
||||
Eigen::Vector3f(0, 1, 0)));
|
||||
view.rotate(
|
||||
Eigen::AngleAxisf(
|
||||
dy * factor / float(height),
|
||||
view.matrix().topLeftCorner(3, 3).inverse() * Eigen::Vector3f(1, 0, 0)));
|
||||
}
|
||||
mouse_last_x = x;
|
||||
mouse_last_y = y;
|
||||
});
|
||||
glfwSetScrollCallback(window,
|
||||
[](GLFWwindow* window, double xoffset, double yoffset)
|
||||
{
|
||||
view.matrix()(2, 3) =
|
||||
std::min(std::max(view.matrix()(2, 3) + (float)yoffset, -100.0f), -2.0f);
|
||||
});
|
||||
}
|
||||
|
||||
bool glslFileChanged() {
|
||||
for (std::string& path : all_paths)
|
||||
{
|
||||
if (last_modification_time(path) > time_of_last_shader_compilation)
|
||||
{
|
||||
if (isFirstCompilation) {
|
||||
isFirstCompilation = false;
|
||||
}
|
||||
else {
|
||||
std::cout << path << " has changed since last compilation attempt." << std::endl;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool compileShaderIfChanged() {
|
||||
if (glslFileChanged()) {
|
||||
time_of_last_shader_compilation = get_seconds();
|
||||
|
||||
// (re)compile shader
|
||||
if (!create_shader_program_from_files(
|
||||
vertex_shader_paths,
|
||||
tess_control_shader_paths,
|
||||
tess_evaluation_shader_paths,
|
||||
fragment_shader_paths,
|
||||
prog_id)) {
|
||||
// failed to compile shader
|
||||
glDeleteProgram(prog_id);
|
||||
prog_id = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Update the uniforms used in the GLSL shaders
|
||||
void updateShaderUniforms() {
|
||||
// select program
|
||||
glUseProgram(prog_id);
|
||||
// Attach uniforms
|
||||
{
|
||||
if (is_animating)
|
||||
{
|
||||
double now = get_seconds();
|
||||
animation_seconds += now - last_time;
|
||||
last_time = now;
|
||||
}
|
||||
glUniform1f(glGetUniformLocation(prog_id, "animation_seconds"), static_cast<GLfloat>(animation_seconds));
|
||||
}
|
||||
glUniformMatrix4fv(
|
||||
glGetUniformLocation(prog_id, "proj"), 1, false, proj.data());
|
||||
glUniformMatrix4fv(
|
||||
glGetUniformLocation(prog_id, "view"), 1, false, view.matrix().data());
|
||||
// Draw mesh as wireframe
|
||||
if (wire_frame)
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
Reference in a new issue