diff --git a/rect.f.glsl b/rect.f.glsl new file mode 100644 index 0000000..bf332db --- /dev/null +++ b/rect.f.glsl @@ -0,0 +1,12 @@ +#version 130 + +/* Interpolated color */ +in vec4 i_color; + +/* Fragment color */ +out vec4 frag_color; + +void main(void) +{ + frag_color = i_color; +} diff --git a/rect.v.glsl b/rect.v.glsl new file mode 100644 index 0000000..f865f5b --- /dev/null +++ b/rect.v.glsl @@ -0,0 +1,31 @@ +#version 130 + +/* Viewport width and height */ +uniform ivec2 viewport_size; +/* Position offset */ +uniform ivec2 position; +/* Rectangle size */ +uniform ivec2 size; + +/* Vertex coordinates: x, y */ +in vec2 coords; +/* Vertex color */ +in vec4 color; + +/* Interpolated color */ +out vec4 i_color; + +/** + * Map coordinates such that: + * (0 .. viewport_size.[xy]) => (-1.0 .. 1.0) + */ +vec2 map_to_screen(vec2 position) +{ + return 2.0 * position / viewport_size - 1.0; +} + +void main(void) +{ + gl_Position = vec4(map_to_screen(vec2(position) + coords * size), 0, 1); + i_color = color; +} diff --git a/src/RectShader.cc b/src/RectShader.cc new file mode 100644 index 0000000..c43da5e --- /dev/null +++ b/src/RectShader.cc @@ -0,0 +1,13 @@ +#include "RectShader.h" + +RectShader::RectShader() +{ + m_program = glcxx::Program::create( + glcxx::Shader::create_from_file(GL_VERTEX_SHADER, "rect.v.glsl"), + glcxx::Shader::create_from_file(GL_FRAGMENT_SHADER, "rect.f.glsl"), + "coords", 0); + + m_uniforms.viewport_size = m_program->get_uniform_location("viewport_size"); + m_uniforms.position = m_program->get_uniform_location("position"); + m_uniforms.size = m_program->get_uniform_location("size"); +} diff --git a/src/RectShader.h b/src/RectShader.h new file mode 100644 index 0000000..f4f9939 --- /dev/null +++ b/src/RectShader.h @@ -0,0 +1,40 @@ +#ifndef RECTSHADER_H +#define RECTSHADER_H + +#include "glcxx.hpp" +#include + +class RectShader +{ +public: + RectShader(); + + void use() { m_program->use(); } + + void set_viewport_size(int width, int height) + { + glUniform2i(m_uniforms.viewport_size, width, height); + } + + void set_position(int x, int y) + { + glUniform2i(m_uniforms.position, x, y); + } + + void set_size(int x, int y) + { + glUniform2i(m_uniforms.size, x, y); + } + +protected: + std::shared_ptr m_program; + + struct + { + GLint viewport_size; + GLint position; + GLint size; + } m_uniforms; +}; + +#endif diff --git a/src/main.cc b/src/main.cc index 7def1e6..38f2b5d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -4,17 +4,21 @@ #include "GL3/gl3w.h" #include #include "TextShader.h" +#include "RectShader.h" using namespace std; std::shared_ptr text_shader; +std::shared_ptr rect_shader; +std::shared_ptr rect_array; +std::shared_ptr rect_buffer; #define WIDTH 800 #define HEIGHT 800 bool init(void) { - glClearColor (0.0, 0.0, 0.0, 0.0); + glClearColor(0.0, 0.0, 0.0, 0.0); glEnable(GL_CULL_FACE); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -25,6 +29,26 @@ bool init(void) text_shader->use(); text_shader->set_texture(0); text_shader->set_viewport_size(WIDTH, HEIGHT); + + rect_shader = std::make_shared(); + rect_shader->use(); + rect_shader->set_viewport_size(WIDTH, HEIGHT); + rect_shader->set_position(0, 0); + rect_shader->set_size(WIDTH, HEIGHT); + GLfloat rect_buffer_data[] = { + 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, + 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, + 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, + }; + rect_array = glcxx::Array::create(); + rect_array->bind(); + rect_buffer = glcxx::Buffer::create(GL_ARRAY_BUFFER, GL_STATIC_DRAW, + rect_buffer_data, sizeof(rect_buffer_data)); + glEnableVertexAttribArray(0); + glEnableVertexAttribArray(1); + glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), 0); + glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (void *)(2 * sizeof(GLfloat))); } catch (glcxx::Error & e) { @@ -38,6 +62,10 @@ void display(SDL_Window * window) { glClear(GL_COLOR_BUFFER_BIT); + rect_array->bind(); + rect_shader->use(); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + SDL_GL_SwapWindow(window); }