From 77125540e699ecc0936c2c90806f45c1b41804a2 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Fri, 16 Oct 2020 07:44:13 +0300 Subject: [PATCH] Implement texture rendering in gfx::painter --- libs/gfx/include/psemek/gfx/painter.hpp | 3 + libs/gfx/source/painter.cpp | 85 ++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/libs/gfx/include/psemek/gfx/painter.hpp b/libs/gfx/include/psemek/gfx/painter.hpp index 52f1ce4b..63aac7db 100644 --- a/libs/gfx/include/psemek/gfx/painter.hpp +++ b/libs/gfx/include/psemek/gfx/painter.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -57,6 +58,8 @@ namespace psemek::gfx geom::vector text_size(std::string_view str, font f = font::font_9x12, float scale = 1.f); void text(geom::point const & p, std::string_view str, text_options const & opts); + void texture(texture_2d const & texture, geom::box const & box); + // 3D void axes(geom::point const & p, float length, float width); void sphere(geom::point const & p, float radius, color const & c, int quality = 6); diff --git a/libs/gfx/source/painter.cpp b/libs/gfx/source/painter.cpp index 00fa6f9a..85e87f61 100644 --- a/libs/gfx/source/painter.cpp +++ b/libs/gfx/source/painter.cpp @@ -74,6 +74,38 @@ void main() } )"; +static const char texture_vertex_source[] = +R"(#version 330 + +uniform mat4 u_transform; + +layout (location = 0) in vec4 in_position; +layout (location = 1) in vec2 in_texcoord; + +out vec2 texcoord; + +void main() +{ + gl_Position = u_transform * in_position; + texcoord = in_texcoord; +} +)"; + +static const char texture_fragment_source[] = +R"(#version 330 + +uniform sampler2D u_texture; + +in vec2 texcoord; + +out vec4 out_color; + +void main() +{ + out_color = texture(u_texture, texcoord); +} +)"; + namespace psemek::gfx { @@ -92,10 +124,18 @@ namespace psemek::gfx geom::point texcoord; }; + struct texture_vertex + { + geom::point position; + geom::point texcoord; + }; + gfx::program program{vertex_source, fragment_source}; gfx::program text_program{text_vertex_source, text_fragment_source}; + gfx::program texture_program{texture_vertex_source, texture_fragment_source}; gfx::mesh mesh; gfx::mesh text_mesh; + gfx::mesh texture_mesh; std::vector vertices; std::vector indices; @@ -103,12 +143,22 @@ namespace psemek::gfx std::vector text_vertices; std::vector text_indices; - gfx::texture_2d font_texture; + struct texture_render_data + { + std::vector vertices; + std::vector indices; + texture_2d const * texture; + }; + + std::vector textures; + + texture_2d font_texture; impl() { mesh.setup, gfx::normalized>(); text_mesh.setup, gfx::normalized, geom::point>(); + texture_mesh.setup, gfx::normalized>>(); util::memory_istream font_data(resource::font_9x12); font_texture.load(gfx::read_pbm(font_data)); @@ -231,6 +281,24 @@ namespace psemek::gfx text3d(geom::point{p[0], p[1], 0.f}, str, opts, geom::matrix::identity()); } + void painter::texture(gfx::texture_2d const & texture, geom::box const & box) + { + impl::texture_render_data data; + data.texture = &texture; + + data.indices = {0, 1, 2, 2, 1, 3}; + + std::uint16_t lo = 0; + std::uint16_t hi = 65535; + + data.vertices.push_back({{box[0].min, box[1].min, 0.f}, {lo, lo}}); + data.vertices.push_back({{box[0].max, box[1].min, 0.f}, {hi, lo}}); + data.vertices.push_back({{box[0].min, box[1].max, 0.f}, {lo, hi}}); + data.vertices.push_back({{box[0].max, box[1].max, 0.f}, {hi, hi}}); + + impl().textures.push_back(data); + } + void painter::axes(geom::point const & p, float length, float width) { geom::vector const d[3] @@ -450,6 +518,10 @@ namespace psemek::gfx void painter::render(geom::matrix const & transform) { + gl::ActiveTexture(gl::TEXTURE0); + + gl::Disable(gl::CULL_FACE); + impl().mesh.load(impl().vertices, impl().indices, gl::TRIANGLES, gl::STREAM_DRAW); impl().vertices.clear(); impl().indices.clear(); @@ -468,6 +540,17 @@ namespace psemek::gfx impl().text_program["u_texture_size"] = impl().font_texture.size(); impl().font_texture.bind(); impl().text_mesh.draw(); + + impl().texture_program.bind(); + impl().texture_program["u_transform"] = transform; + impl().texture_program["u_texture"] = 0; + for (auto const & data : impl().textures) + { + impl().texture_mesh.load(data.vertices, data.indices, gl::TRIANGLES, gl::STREAM_DRAW); + data.texture->bind(); + impl().texture_mesh.draw(); + } + impl().textures.clear(); } }