From aad1854d7eb4fef6b0070419c1c38dd6462bcb29 Mon Sep 17 00:00:00 2001 From: allem Date: Tue, 11 Dec 2018 02:02:53 -0500 Subject: [PATCH] shader builders --- framework/include/resource.h | 28 ++++++++++++ framework/include/util.h | 84 ++++++++++++++++++++++++++++++++++++ framework/src/framework.cpp | 2 +- glapp/CMakeLists.txt | 23 +++++++++- glapp/shaders/main.frag | 9 ++++ glapp/shaders/main.vert | 13 ++++++ glapp/src/main.cpp | 45 ++++--------------- 7 files changed, 165 insertions(+), 39 deletions(-) create mode 100644 framework/include/resource.h create mode 100644 framework/include/util.h create mode 100644 glapp/shaders/main.frag create mode 100644 glapp/shaders/main.vert diff --git a/framework/include/resource.h b/framework/include/resource.h new file mode 100644 index 0000000..ca93817 --- /dev/null +++ b/framework/include/resource.h @@ -0,0 +1,28 @@ +#ifndef GL_TEMPLATE_RESOURCE_H +#define GL_TEMPLATE_RESOURCE_H + +#include +#include +#include +#include + +std::string readFile(const std::string &path) { + std::ifstream file(path); + if (!file) return std::string(); + + file.ignore(std::numeric_limits::max()); + auto size = file.gcount(); + + if (size > 0x10000) return std::string(); + + file.clear(); + file.seekg(0, std::ios_base::beg); + + std::stringstream sstr; + sstr << file.rdbuf(); + file.close(); + + return sstr.str(); +} + +#endif //GL_TEMPLATE_RESOURCE_H diff --git a/framework/include/util.h b/framework/include/util.h new file mode 100644 index 0000000..86a3078 --- /dev/null +++ b/framework/include/util.h @@ -0,0 +1,84 @@ +#ifndef GL_TEMPLATE_UTIL_H +#define GL_TEMPLATE_UTIL_H + +#include "resource.h" + +#include + +#include +#include + +namespace util { + void shaderFile(GLuint shader, const std::string &path) { + const std::string str = readFile(path); + const char *c_str = str.c_str(); + glShaderSource(shader, 1, &c_str, nullptr); + } + + const std::string shaderInfoLog(GLuint shader) { + GLint log_len; + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len); + char log[log_len]; + glGetShaderInfoLog(shader, log_len, nullptr, log); + return std::string(log); + } + + const std::string programInfoLog(GLuint program) { + GLint log_len; + glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len); + char log[log_len]; + glGetProgramInfoLog(program, log_len, nullptr, log); + return std::string(log); + } + + GLuint buildShader(const std::string &path) { + std::string ext = path.substr(path.rfind(".")); + + GLenum kind; + if (ext == ".vert") { + kind = GL_VERTEX_SHADER; + } else if (ext == ".frag") { + kind = GL_FRAGMENT_SHADER; + } else { + fprintf(stderr, "Cannot parse path %s\n", path.c_str()); + return 0; + } + + GLuint shader = glCreateShader(kind); + util::shaderFile(shader, path); + glCompileShader(shader); + + GLint comp; + glGetShaderiv(shader, GL_COMPILE_STATUS, &comp); + if (!comp) { + const std::string log = shaderInfoLog(shader); + fprintf(stderr, "SHADER ERROR: %s\n%s", path.c_str(), log.c_str()); + glDeleteShader(shader); + return 0; + } + + return shader; + } + + GLuint buildProgram(std::initializer_list shaders) { + GLuint program = glCreateProgram(); + + for (GLuint shader : shaders) + glAttachShader(program, shader); + + glLinkProgram(program); + + GLint link; + glGetProgramiv(program, GL_LINK_STATUS, &link); + if (!link) { + const std::string log = programInfoLog(program); + fprintf(stderr, "PROGRAM ERROR:\n%s", log.c_str()); + glDeleteProgram(program); + return 0; + } + + return program; + } +} + +#endif //GL_TEMPLATE_UTIL_H diff --git a/framework/src/framework.cpp b/framework/src/framework.cpp index e4598b1..6dd7d77 100644 --- a/framework/src/framework.cpp +++ b/framework/src/framework.cpp @@ -93,7 +93,7 @@ void App::center(GLFWmonitor *monitor) { getSize(&w, &h); setPos(x + (mode->width - w) / 2, - y + (mode->height - h) / 2); + y + (mode->height - h) / 2); } void App::close() { diff --git a/glapp/CMakeLists.txt b/glapp/CMakeLists.txt index b2d5945..b0ec6a9 100644 --- a/glapp/CMakeLists.txt +++ b/glapp/CMakeLists.txt @@ -1,10 +1,29 @@ project(sample) -add_executable(sample +add_executable(${PROJECT_NAME} src/main.cpp) -target_link_libraries(sample +target_link_libraries(${PROJECT_NAME} glad glm glfw framework) + + +set(SHADERS + shaders/main.frag + shaders/main.vert) +add_custom_target(shaders DEPENDS ${SHADERS}) + +add_custom_command( + TARGET shaders PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_CURRENT_BINARY_DIR}/shaders/ + COMMENT "clearing shaders" +) +add_custom_command( + TARGET shaders POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_SOURCE_DIR}/shaders/ ${CMAKE_CURRENT_BINARY_DIR}/shaders/ + COMMENT "copying shaders" +) + +add_dependencies(${PROJECT_NAME} shaders) \ No newline at end of file diff --git a/glapp/shaders/main.frag b/glapp/shaders/main.frag new file mode 100644 index 0000000..6271a69 --- /dev/null +++ b/glapp/shaders/main.frag @@ -0,0 +1,9 @@ +#version 330 + +in vec3 color; + +out vec4 fcolor; + +void main() { + fcolor = vec4(color, 1); +} \ No newline at end of file diff --git a/glapp/shaders/main.vert b/glapp/shaders/main.vert new file mode 100644 index 0000000..11c0ab5 --- /dev/null +++ b/glapp/shaders/main.vert @@ -0,0 +1,13 @@ +#version 330 + +uniform mat4 pvm; + +in vec3 vCol; +in vec2 vPos; + +out vec3 color; + +void main() { + gl_Position = pvm * vec4(vPos, 0, 1); + color = vCol; +} \ No newline at end of file diff --git a/glapp/src/main.cpp b/glapp/src/main.cpp index 81e8aa4..62982bc 100644 --- a/glapp/src/main.cpp +++ b/glapp/src/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -16,33 +17,13 @@ struct Vertex { glm::vec3 col; }; -static const char *vertex_shader_text = - "uniform mat4 pvm;\n" - "attribute vec3 vCol;\n" - "attribute vec2 vPos;\n" - "varying vec3 color;\n" - "void main()\n" - "{\n" - " gl_Position = pvm * vec4(vPos, 0.0, 1.0);\n" - " color = vCol;\n" - "}\n"; - - -static const char *fragment_shader_text = - "varying vec3 color;\n" - "void main()\n" - "{\n" - " gl_FragColor = vec4(color, 1.0);\n" - "}\n"; - - class GLApp : public App { private: std::vector vertices = { - {glm::vec2(+0.5f, +0.5f), glm::vec3(1, 0, 0)}, - {glm::vec2(+0.5f, -0.5f), glm::vec3(0, 1, 0)}, - {glm::vec2(-0.5f, -0.5f), glm::vec3(0, 0, 1)}, - {glm::vec2(-0.5f, +0.5f), glm::vec3(1, 1, 1)}, + {glm::vec2(+0.5f, +0.5f), glm::vec3(1, 0, 0)}, + {glm::vec2(+0.5f, -0.5f), glm::vec3(0, 1, 0)}, + {glm::vec2(-0.5f, -0.5f), glm::vec3(0, 0, 1)}, + {glm::vec2(-0.5f, +0.5f), glm::vec3(1, 1, 1)}, }; GLuint vertex_buffer = 0; @@ -62,18 +43,10 @@ protected: glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer); glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices.front(), GL_STATIC_DRAW); - vertex_shader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertex_shader, 1, &vertex_shader_text, nullptr); - glCompileShader(vertex_shader); - - fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(fragment_shader, 1, &fragment_shader_text, nullptr); - glCompileShader(fragment_shader); - - program = glCreateProgram(); - glAttachShader(program, vertex_shader); - glAttachShader(program, fragment_shader); - glLinkProgram(program); + program = util::buildProgram({ + vertex_shader = util::buildShader("shaders/main.vert"), + fragment_shader = util::buildShader("shaders/main.frag"), + }); pvm_location = (GLuint) glGetUniformLocation(program, "pvm"); vpos_location = (GLuint) glGetAttribLocation(program, "vPos");