From b50cb62ac3ebe11b1c2f82cb282688f14ea776ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mario=20H=C3=BCttel?= Date: Wed, 18 Mar 2020 22:42:04 +0100 Subject: [PATCH] Add small example --- CMakeLists.txt | 12 ++- include/opengl-playground/openglgraphics.hpp | 19 ++++ include/opengl-playground/openglshader.hpp | 3 + .../opengl-playground/textured-rectangle.hpp | 27 ++++++ shaders/2d-passthrough-vertex.glsl | 8 ++ shaders/2d-zoom-translate-vertex.glsl | 11 +++ shaders/fixed-red-fragment.glsl | 8 ++ shaders/textured-rectangle-fragment.glsl | 8 ++ shaders/textured-rectangle-vertex.glsl | 11 +++ shaders/triangle-gen-geometry.glsl | 15 +++ shaders/triangle-gen-zoomed-geometry.glsl | 17 ++++ src/main.cpp | 93 ++++++++++++++++++- src/openglgraphics.cpp | 13 +++ src/openglshader.cpp | 73 +++++++++++---- src/sdlmainwindow.cpp | 5 + src/textured-rectangle.cpp | 86 +++++++++++++++++ 16 files changed, 386 insertions(+), 23 deletions(-) create mode 100644 include/opengl-playground/openglgraphics.hpp create mode 100644 include/opengl-playground/textured-rectangle.hpp create mode 100644 shaders/2d-passthrough-vertex.glsl create mode 100644 shaders/2d-zoom-translate-vertex.glsl create mode 100644 shaders/fixed-red-fragment.glsl create mode 100644 shaders/textured-rectangle-fragment.glsl create mode 100644 shaders/textured-rectangle-vertex.glsl create mode 100644 shaders/triangle-gen-geometry.glsl create mode 100644 shaders/triangle-gen-zoomed-geometry.glsl create mode 100644 src/openglgraphics.cpp create mode 100644 src/textured-rectangle.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4ab37e4..51d29e7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,10 +11,20 @@ pkg_check_modules(SDL2 REQUIRED sdl2) include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include" ${EPOXY_INCLUDE_DIRS} ${SDL2_INCLUDE_DIRS}) + +configure_file("shaders/2d-passthrough-vertex.glsl" "shaders/2d-passthrough-vertex.glsl" COPYONLY) +configure_file("shaders/fixed-red-fragment.glsl" "shaders/fixed-red-fragment.glsl" COPYONLY) +configure_file("shaders/triangle-gen-geometry.glsl" "shaders/triangle-gen-geometry.glsl" COPYONLY) +configure_file("shaders/triangle-gen-zoomed-geometry.glsl" "shaders/triangle-gen-zoomed-geometry.glsl" COPYONLY) +configure_file("shaders/textured-rectangle-vertex.glsl" "shaders/textured-rectangle-vertex.glsl" COPYONLY) +configure_file("shaders/textured-rectangle-fragment.glsl" "shaders/textured-rectangle-fragment.glsl" COPYONLY) + + +configure_file("shaders/2d-zoom-translate-vertex.glsl" "shaders/2d-zoom-translate-vertex.glsl" COPYONLY) + aux_source_directory("src" SOURCES) add_compile_options(-Wall) add_executable(${PROJECT_NAME} ${SOURCES}) target_link_libraries(${PROJECT_NAME} m pthread ${EPOXY_LIBRARIES} ${SDL2_LIBRARIES}) install (TARGETS ${PROJECT_NAME} DESTINATION bin) - diff --git a/include/opengl-playground/openglgraphics.hpp b/include/opengl-playground/openglgraphics.hpp new file mode 100644 index 0000000..84bc2a7 --- /dev/null +++ b/include/opengl-playground/openglgraphics.hpp @@ -0,0 +1,19 @@ +#ifndef OPENGLGRAPHICS_H +#define OPENGLGRAPHICS_H + +#include +#include +#include + +class OpenGlGraphics +{ + public: + OpenGlGraphics(OpenGlShaderProgram &prog); + ~OpenGlGraphics(); + virtual void realize() = 0; + virtual void render() = 0; + protected: + OpenGlShaderProgram shaderprog; +}; + +#endif // OPENGLGRAPHICS_H diff --git a/include/opengl-playground/openglshader.hpp b/include/opengl-playground/openglshader.hpp index 8dafe4c..1b0f3e6 100644 --- a/include/opengl-playground/openglshader.hpp +++ b/include/opengl-playground/openglshader.hpp @@ -12,6 +12,9 @@ class OpenGlShaderProgram int compile(); void unload(); int use(); + int getUniformLoc(const std::string &uniform); + void setUniformFloat(const std::string &uniform, float value); + void setUniformVec2(const std::string &uniform, float *vector); private: bool compiled; GLuint shader_program; diff --git a/include/opengl-playground/textured-rectangle.hpp b/include/opengl-playground/textured-rectangle.hpp new file mode 100644 index 0000000..44c99ca --- /dev/null +++ b/include/opengl-playground/textured-rectangle.hpp @@ -0,0 +1,27 @@ +#ifndef TEXTURED_RECTANGLE_H +#define TEXTURED_RECTANGLE_H + +#include +#include + +class TexturedRectangle : OpenGlGraphics +{ + public: + TexturedRectangle(float x0, float y0, float x1, float y1, OpenGlShaderProgram &shaderprog); + void realize(); + void render(); + void setZoom(float zoom); + float getZoom(); + void setOffset(float x_off, float y_off); + float getOffsetX(); + float getOffsetY(); + private: + float pos1[2]; + float pos2[2]; + float x_offset; + float y_offset; + float zoom; + GLuint vao; +}; + +#endif // TEXTURED_RECTANGLE_H diff --git a/shaders/2d-passthrough-vertex.glsl b/shaders/2d-passthrough-vertex.glsl new file mode 100644 index 0000000..68947b6 --- /dev/null +++ b/shaders/2d-passthrough-vertex.glsl @@ -0,0 +1,8 @@ +#version 330 core + +layout (location = 0) in vec2 inputVertex; + +void main() +{ + gl_Position = vec4(inputVertex.x, inputVertex.y, 0.0, 1.0); +} diff --git a/shaders/2d-zoom-translate-vertex.glsl b/shaders/2d-zoom-translate-vertex.glsl new file mode 100644 index 0000000..38b0a58 --- /dev/null +++ b/shaders/2d-zoom-translate-vertex.glsl @@ -0,0 +1,11 @@ +#version 330 core + +layout (location = 0) in vec2 inputVertex; +uniform float zoom; +uniform vec2 center_pos; + +void main() +{ + vec4 translated = (vec4(inputVertex.x, inputVertex.y, 0.0, 1.0) - vec4(center_pos.x, center_pos.y, 0.0, 0.0)); + gl_Position = vec4(translated.x, translated.y, translated.z, translated.w) * vec4(zoom, zoom, 1, 1); +} diff --git a/shaders/fixed-red-fragment.glsl b/shaders/fixed-red-fragment.glsl new file mode 100644 index 0000000..10de971 --- /dev/null +++ b/shaders/fixed-red-fragment.glsl @@ -0,0 +1,8 @@ +#version 330 core + +out vec4 fragmentColor; + +void main() +{ + fragmentColor = vec4(1.0, 0.0, 0.0, 0.0); +} diff --git a/shaders/textured-rectangle-fragment.glsl b/shaders/textured-rectangle-fragment.glsl new file mode 100644 index 0000000..10de971 --- /dev/null +++ b/shaders/textured-rectangle-fragment.glsl @@ -0,0 +1,8 @@ +#version 330 core + +out vec4 fragmentColor; + +void main() +{ + fragmentColor = vec4(1.0, 0.0, 0.0, 0.0); +} diff --git a/shaders/textured-rectangle-vertex.glsl b/shaders/textured-rectangle-vertex.glsl new file mode 100644 index 0000000..25d445b --- /dev/null +++ b/shaders/textured-rectangle-vertex.glsl @@ -0,0 +1,11 @@ +#version 330 core + +layout (location = 0) in vec2 inputVertex; +uniform float zoom; +uniform vec2 pos_offset; + +void main() +{ + vec2 pos2d = (inputVertex - pos_offset) * zoom; + gl_Position = vec4(pos2d.x , pos2d.y, 0.0, 1.0); +} diff --git a/shaders/triangle-gen-geometry.glsl b/shaders/triangle-gen-geometry.glsl new file mode 100644 index 0000000..302f299 --- /dev/null +++ b/shaders/triangle-gen-geometry.glsl @@ -0,0 +1,15 @@ +#version 330 core + +layout (points) in; +layout (triangle_strip, max_vertices=3) out; + +void main() +{ + gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0); + EmitVertex(); + gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0); + EmitVertex(); + gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0); + EmitVertex(); + EndPrimitive(); +} diff --git a/shaders/triangle-gen-zoomed-geometry.glsl b/shaders/triangle-gen-zoomed-geometry.glsl new file mode 100644 index 0000000..edd7208 --- /dev/null +++ b/shaders/triangle-gen-zoomed-geometry.glsl @@ -0,0 +1,17 @@ +#version 330 core + +layout (points) in; +layout (triangle_strip, max_vertices=3) out; + +uniform float zoom; + +void main() +{ + gl_Position = gl_in[0].gl_Position + vec4(-0.1, 0.0, 0.0, 0.0) * zoom; + EmitVertex(); + gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.1, 0.0, 0.0) * zoom; + EmitVertex(); + gl_Position = gl_in[0].gl_Position + vec4(0.1, 0.0, 0.0, 0.0) * zoom; + EmitVertex(); + EndPrimitive(); +} diff --git a/src/main.cpp b/src/main.cpp index 2a0eb3b..33b540c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ -#include +#include #include -#include +#include +#include #define WINDOW_WIDTH 800 #define WINDOW_HEIGHT 640 @@ -10,8 +11,26 @@ int main(int argc, char **argv) (void)argc; (void)argv; MainWindow *window; + GLuint triangle_vao; + GLuint triangle_vbo; + SDL_Event event; + bool run = true; + bool got_event = false; - window = new SdlMainWindow(WINDOW_WIDTH, WINDOW_HEIGHT); + float nav_point[2] = {0.0f, 0.0f}; + float zoom = 1.0; + + float triangle_vertices[] = { -0.5f, 0.0f, + 0.0f, 0.5f, + 0.0f, 0.0f, + 0.8f, 0.0f, + 0.8f, 0.5f, + 0.5f, 0.2f, + }; + + + + window = new SdlMainWindow(WINDOW_HEIGHT, WINDOW_WIDTH); window->show(); window->activateGlContext(); @@ -21,9 +40,73 @@ int main(int argc, char **argv) glClearColor(0.1f, 0.1f, 0.1f, 0.f); glClear(GL_COLOR_BUFFER_BIT); - window->swapBuffer(); + glGenVertexArrays(1, &triangle_vao); + glBindVertexArray(triangle_vao); + glGenBuffers(1, &triangle_vbo); + glBindBuffer(GL_ARRAY_BUFFER, triangle_vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(triangle_vertices), triangle_vertices, GL_STATIC_DRAW); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0); + glEnableVertexAttribArray(0); - SDL_Delay(5000); + OpenGlShaderProgram prog = OpenGlShaderProgram("shaders/2d-zoom-translate-vertex.glsl", "shaders/triangle-gen-zoomed-geometry.glsl", "shaders/fixed-red-fragment.glsl"); + prog.compile(); + OpenGlShaderProgram textured_rect_prog = OpenGlShaderProgram("shaders/textured-rectangle-vertex.glsl", "", "shaders/textured-rectangle-fragment.glsl"); + textured_rect_prog.compile(); + + TexturedRectangle rect = TexturedRectangle(-0.1, -0.1, 0.1, 0.1, textured_rect_prog); + rect.realize(); + + while (run) { + glClear(GL_COLOR_BUFFER_BIT); + // Draw the triangles + prog.use(); + + prog.setUniformFloat("zoom", zoom); + prog.setUniformVec2("center_pos", nav_point); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glBindVertexArray(triangle_vao); + glDrawArrays(GL_POINTS, 0, sizeof(triangle_vertices)/2); + + rect.setZoom(zoom); + rect.setOffset(nav_point[0], nav_point[1]); + rect.render(); + + window->swapBuffer(); + got_event = false; + + while (!got_event) { + if (SDL_WaitEvent(&event)) { + if (event.type == SDL_KEYDOWN) { + if (event.key.keysym.sym == SDLK_w) { + nav_point[1] += 0.05; + } else if (event.key.keysym.sym == SDLK_s) { + nav_point[1] -= 0.05; + } else if (event.key.keysym.sym == SDLK_a) { + nav_point[0] -= 0.05; + } else if (event.key.keysym.sym == SDLK_d) { + nav_point[0] += 0.05; + } else if (event.key.keysym.sym == SDLK_ESCAPE) { + std::cout << "Bye!" << std::endl; + run = false; + } else if (event.key.keysym.sym == SDLK_PLUS) { + zoom += 0.01f; + } else if (event.key.keysym.sym == SDLK_MINUS) { + zoom -= 0.01f; + if (zoom < 0.0f) + zoom = 0.0f; + } + got_event = true; + + } + } + } + + + } + + textured_rect_prog.unload(); + prog.unload(); delete window; } diff --git a/src/openglgraphics.cpp b/src/openglgraphics.cpp new file mode 100644 index 0000000..7127d65 --- /dev/null +++ b/src/openglgraphics.cpp @@ -0,0 +1,13 @@ +#include + + + +OpenGlGraphics::OpenGlGraphics(OpenGlShaderProgram &prog) : shaderprog(prog) +{ + +} + +OpenGlGraphics::~OpenGlGraphics() +{ + +} diff --git a/src/openglshader.cpp b/src/openglshader.cpp index 61749c9..5f1f464 100644 --- a/src/openglshader.cpp +++ b/src/openglshader.cpp @@ -1,4 +1,7 @@ #include +#include +#include +#include OpenGlShaderProgram::OpenGlShaderProgram(std::string vertex_file, std::string geometry_file, std::string fragment_file) { @@ -10,12 +13,16 @@ OpenGlShaderProgram::OpenGlShaderProgram(std::string vertex_file, std::string ge OpenGlShaderProgram::~OpenGlShaderProgram() { - this->unload(); + } -char *load_shader_program_from_file(std::string file_name) +std::string load_shader_program_from_file(std::string &file_name) { - return NULL; + std::ifstream ifs(file_name); + std::string file_content((std::istreambuf_iterator(ifs)), + (std::istreambuf_iterator())); + + return file_content; } int OpenGlShaderProgram::compile() @@ -25,7 +32,8 @@ int OpenGlShaderProgram::compile() char info_log[512]; unsigned int vertex_shader, geometry_shader, fragment_shader; bool vertex_b = false, geo_b = false, frag_b = false; - char *src_code; + std::string src_code; + const char *c_string; if (this->compiled) { glDeleteProgram(shader_program); @@ -37,32 +45,37 @@ int OpenGlShaderProgram::compile() if (!vertex_file.empty()) { vertex_b = true; + src_code = load_shader_program_from_file(this->vertex_file); + c_string = src_code.c_str(); + /* Compile the vertex shader */ vertex_shader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(vertex_shader, 1, &src_code, NULL); - + glShaderSource(vertex_shader, 1, &c_string, NULL); + glCompileShader(vertex_shader); glGetShaderiv(vertex_shader, GL_COMPILE_STATUS, &success); - free(src_code); if (!success) { glGetShaderInfoLog(vertex_shader, 512, NULL, info_log); - fprintf(stderr, "%s\n", info_log); + printf("Error in vertex shader: %s\n", info_log); ret_code = -1; goto delete_vertex; } glAttachShader(this->shader_program, vertex_shader); - } + } else + printf("Empty\n"); if (!this->geometry_file.empty()) { geo_b = true; - /* Compile the vertex shader */ - geometry_shader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(geometry_shader, 1, &src_code, NULL); + src_code = load_shader_program_from_file(this->geometry_file); + c_string = src_code.c_str(); + /* Compile the vertex shader */ + geometry_shader = glCreateShader(GL_GEOMETRY_SHADER); + glShaderSource(geometry_shader, 1, &c_string, NULL); + glCompileShader(geometry_shader); glGetShaderiv(geometry_shader, GL_COMPILE_STATUS, &success); - free(src_code); if (!success) { glGetShaderInfoLog(geometry_shader, 512, NULL, info_log); @@ -78,12 +91,14 @@ int OpenGlShaderProgram::compile() if (!this->fragment_file.empty()) { frag_b = true; - /* Compile the vertex shader */ - fragment_shader = glCreateShader(GL_VERTEX_SHADER); - glShaderSource(fragment_shader, 1, &src_code, NULL); + src_code = load_shader_program_from_file(this->fragment_file); + c_string = src_code.c_str(); + /* Compile the vertex shader */ + fragment_shader = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragment_shader, 1, &c_string, NULL); + glCompileShader(fragment_shader); glGetShaderiv(fragment_shader, GL_COMPILE_STATUS, &success); - free(src_code); if (!success) { glGetShaderInfoLog(fragment_shader, 512, NULL, info_log); @@ -141,3 +156,27 @@ int OpenGlShaderProgram::use() glUseProgram(this->shader_program); return 0; } + +void OpenGlShaderProgram::setUniformFloat(const std::string &uniform, float value) +{ + int loc = this->getUniformLoc(uniform); + if (loc >= 0) { + glUniform1f(loc, value); + } +} + +void OpenGlShaderProgram::setUniformVec2(const std::string &uniform, float *vector) +{ + int loc = this->getUniformLoc(uniform); + if (loc >= 0) { + glUniform2fv(loc, 1, vector); + } +} + +int OpenGlShaderProgram::getUniformLoc(const std::string &uniform) +{ + if (!this->compiled) + return -1; + + return glGetUniformLocation(this->shader_program, uniform.c_str()); +} diff --git a/src/sdlmainwindow.cpp b/src/sdlmainwindow.cpp index 0bf1282..c0eb7aa 100644 --- a/src/sdlmainwindow.cpp +++ b/src/sdlmainwindow.cpp @@ -29,6 +29,11 @@ void SdlMainWindow::swapBuffer() void SdlMainWindow::activateGlContext() { + // OPENGL VERSION + SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + if (this->context == NULL) this->context = SDL_GL_CreateContext(this->window); else diff --git a/src/textured-rectangle.cpp b/src/textured-rectangle.cpp new file mode 100644 index 0000000..d03f715 --- /dev/null +++ b/src/textured-rectangle.cpp @@ -0,0 +1,86 @@ +#include + + + +TexturedRectangle::TexturedRectangle(float x0, float y0, float x1, float y1, OpenGlShaderProgram &shaderprog) : + OpenGlGraphics(shaderprog) +{ + this->pos1[0] = x0; + this->pos1[1] = y0; + this->pos2[0] = x1; + this->pos2[1] = y1; + this->setZoom(1.0f); + this->setOffset(0.0f, 0.0f); + this->vao = 0; +} + +void TexturedRectangle::realize() +{ + GLuint vbo; + GLuint elem_buff; + const unsigned int indices[] = { + 0, 1, 2, + 2, 0, 3 + }; + + float vertices[8] = { + this->pos1[0], this->pos1[1], + this->pos1[0], this->pos2[1], + this->pos2[0], this->pos2[1], + this->pos2[0], this->pos1[1], + }; + + glGenVertexArrays(1, &this->vao); + glBindVertexArray(this->vao); + glGenBuffers(1, &vbo); + glBindBuffer(GL_ARRAY_BUFFER, vbo); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + glGenBuffers(1, &elem_buff); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elem_buff); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW); + + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void*)0); + glEnableVertexAttribArray(0); +} + +void TexturedRectangle::render() +{ + float offset[2]; + + this->shaderprog.use(); + offset[0] = this->getOffsetX(); + offset[1] = this->getOffsetY(); + this->shaderprog.setUniformVec2("pos_offset", offset); + this->shaderprog.setUniformFloat("zoom", this->zoom); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glBindVertexArray(this->vao); + glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); + +} + +void TexturedRectangle::setZoom(float zoom) +{ + this->zoom = zoom; +} + +float TexturedRectangle::getZoom() +{ + return this->zoom; +} + +void TexturedRectangle::setOffset(float x_off, float y_off) +{ + this->x_offset = x_off; + this->y_offset = y_off; +} + +float TexturedRectangle::getOffsetX() +{ + return this->x_offset; +} + +float TexturedRectangle::getOffsetY() +{ + return this->y_offset; +}