diff --git a/src/noggit/TextureManager.cpp b/src/noggit/TextureManager.cpp index a66a0940..524b9dc9 100644 --- a/src/noggit/TextureManager.cpp +++ b/src/noggit/TextureManager.cpp @@ -3,15 +3,9 @@ #include #include #include // LogDebug -#include -#include -#include #include -#include -#include #include -#include #include @@ -260,43 +254,126 @@ void blp_texture::finishLoading() namespace noggit { - QPixmap* render_blp_to_pixmap ( std::string const& blp_filename - , int width - , int height - ) - { - static std::map, QPixmap> cache{}; - std::tuple const curEntry{blp_filename, width, height}; - auto it{cache.find(curEntry)}; - if(it != cache.end()) - return &it->second; + BLPRenderer::BLPRenderer() + { + _cache = {}; opengl::context::save_current_context const context_save (::gl); - QOpenGLContext context; - context.create(); + _context.create(); - QOpenGLFramebufferObjectFormat fmt; - fmt.setSamples(1); - fmt.setInternalTextureFormat(GL_RGBA8); + _fmt.setSamples(1); + _fmt.setInternalTextureFormat(GL_RGBA8); - QOffscreenSurface surface; - surface.create(); + _surface.create(); - context.makeCurrent(&surface); + _context.makeCurrent(&_surface); - opengl::context::scoped_setter const context_set (::gl, &context); + opengl::context::scoped_setter const context_set (::gl, &_context); opengl::scoped::bool_setter cull; opengl::scoped::bool_setter depth; - opengl::scoped::deferred_upload_vertex_arrays<1> vao; - vao.upload(); - opengl::scoped::deferred_upload_buffers<3> buffers; - buffers.upload(); - GLuint const& indices_vbo = buffers[0]; - GLuint const& vertices_vbo = buffers[1]; - GLuint const& texcoords_vbo = buffers[2]; + _vao.upload(); + _buffers.upload(); + + GLuint const& indices_vbo = _buffers[0]; + GLuint const& vertices_vbo = _buffers[1]; + GLuint const& texcoords_vbo = _buffers[2]; + + std::vector vertices = + { + {-1.0f, -1.0f} + ,{-1.0f, 1.0f} + ,{ 1.0f, 1.0f} + ,{ 1.0f, -1.0f} + }; + std::vector texcoords = + { + {0.f, 0.f} + ,{0.f, 1.0f} + ,{1.0f, 1.0f} + ,{1.0f, 0.f} + }; + std::vector indices = {0,1,2, 2,3,0}; + + gl.bufferData(vertices_vbo, vertices, GL_STATIC_DRAW); + gl.bufferData(texcoords_vbo, texcoords, GL_STATIC_DRAW); + gl.bufferData(indices_vbo, indices, GL_STATIC_DRAW); + + + _program.reset(new opengl::program + ( + { + { + GL_VERTEX_SHADER, R"code( + #version 330 core + + in vec4 position; + in vec2 tex_coord; + out vec2 f_tex_coord; + + uniform float width; + uniform float height; + + void main() + { + f_tex_coord = vec2(tex_coord.x * width, -tex_coord.y * height); + gl_Position = vec4(position.x * width / 2, position.y * height / 2, position.z, 1.0); + } + )code" + }, + { + GL_FRAGMENT_SHADER, R"code( + #version 330 core + + uniform sampler2D tex; + + in vec2 f_tex_coord; + + layout(location = 0) out vec4 out_color; + + void main() + { + out_color = vec4(texture(tex, f_tex_coord/2.f + vec2(0.5)).rgb, 1.); + } + )code" + } + } + )); + + opengl::scoped::use_program shader (*_program.get()); + + opengl::scoped::vao_binder const _ (_vao[0]); + + { + opengl::scoped::buffer_binder vertices_binder (vertices_vbo); + shader.attrib("position", 2, GL_FLOAT, GL_FALSE, 0, 0); + } + { + opengl::scoped::buffer_binder texcoords_binder (texcoords_vbo); + shader.attrib("tex_coord", 2, GL_FLOAT, GL_FALSE, 0, 0); + } + + + } + + QPixmap* BLPRenderer::render_blp_to_pixmap ( std::string const& blp_filename + , int width + , int height + ) + { + std::tuple const curEntry{blp_filename, width, height}; + auto it{_cache.find(curEntry)}; + + if(it != _cache.end()) + return &it->second; + + opengl::context::save_current_context const context_save (::gl); + + _context.makeCurrent(&_surface); + + opengl::context::scoped_setter const context_set (::gl, &_context); opengl::texture::set_active_texture(0); blp_texture texture(blp_filename); @@ -307,90 +384,25 @@ namespace noggit float h = static_cast(height); float w = static_cast(width); - float half_h = h * 0.5f; - float half_w = w * 0.5f; - std::vector vertices = - { - {-half_w, -half_h} - ,{-half_w, half_h} - ,{ half_w, half_h} - ,{ half_w, -half_h} - }; - std::vector texcoords = - { - {0.f, 0.f} - ,{0.f, h} - ,{w, h} - ,{w, 0.f} - }; - std::vector indices = {0,1,2, 2,3,0}; - - gl.bufferData(vertices_vbo, vertices, GL_STATIC_DRAW); - gl.bufferData(texcoords_vbo, texcoords, GL_STATIC_DRAW); - gl.bufferData(indices_vbo, indices, GL_STATIC_DRAW); - - QOpenGLFramebufferObject pixel_buffer(width, height, fmt); + QOpenGLFramebufferObject pixel_buffer(width, height, _fmt); pixel_buffer.bind(); gl.viewport(0, 0, w, h); gl.clearColor(.0f, .0f, .0f, 1.f); gl.clear(GL_COLOR_BUFFER_BIT); - - opengl::program program - ( - { - { - GL_VERTEX_SHADER, R"code( -#version 330 core - -in vec4 position; -in vec2 tex_coord; -out vec2 f_tex_coord; - -void main() -{ -f_tex_coord = vec2(tex_coord.x, -tex_coord.y); -gl_Position = position; -} -)code" - }, - { - GL_FRAGMENT_SHADER, - R"code( -#version 330 core - -uniform sampler2D tex; - -in vec2 f_tex_coord; - -layout(location = 0) out vec4 out_color; - -void main() -{ -out_color = vec4(texture(tex, f_tex_coord/2.f + vec2(0.5)).rgb, 1.); -} -)code" - } - } - ); - - opengl::scoped::use_program shader (program); + + opengl::scoped::use_program shader (*_program.get()); shader.uniform("tex", 0); + shader.uniform("width", w); + shader.uniform("height", h); + texture.bind(); - opengl::scoped::vao_binder const _ (vao[0]); - - { - opengl::scoped::buffer_binder vertices_binder (vertices_vbo); - shader.attrib("position", 2, GL_FLOAT, GL_FALSE, 0, 0); - } - { - opengl::scoped::buffer_binder texcoords_binder (texcoords_vbo); - shader.attrib("tex_coord", 2, GL_FLOAT, GL_FALSE, 0, 0); - } - opengl::scoped::buffer_binder indices_binder(indices_vbo); + opengl::scoped::vao_binder const _ (_vao[0]); + + opengl::scoped::buffer_binder indices_binder(_buffers[0]); gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr); @@ -404,7 +416,7 @@ out_color = vec4(texture(tex, f_tex_coord/2.f + vec2(0.5)).rgb, 1.); ("failed rendering " + blp_filename + " to pixmap"); } - return &(cache[curEntry] = std::move(result)); + return &(_cache[curEntry] = std::move(result)); } } diff --git a/src/noggit/TextureManager.h b/src/noggit/TextureManager.h index 085eaf7c..c7df2af9 100644 --- a/src/noggit/TextureManager.h +++ b/src/noggit/TextureManager.h @@ -5,6 +5,13 @@ #include #include #include +#include +#include +#include + +#include +#include +#include #include @@ -12,6 +19,7 @@ #include #include + struct BLPHeader; struct blp_texture : public opengl::texture, AsyncObject @@ -81,8 +89,35 @@ private: namespace noggit { - QPixmap* render_blp_to_pixmap ( std::string const& blp_filename - , int width = -1 - , int height = -1 - ); + + class BLPRenderer + { + private: + BLPRenderer(); + + BLPRenderer( const BLPRenderer&); + BLPRenderer& operator=( BLPRenderer& ); + + std::map, QPixmap> _cache; + + QOpenGLContext _context; + QOpenGLFramebufferObjectFormat _fmt; + QOffscreenSurface _surface; + std::unique_ptr _program; + + opengl::scoped::deferred_upload_vertex_arrays<1> _vao; + opengl::scoped::deferred_upload_buffers<3> _buffers; + + public: + static BLPRenderer& getInstance() + { + static BLPRenderer instance; + return instance; + } + + QPixmap* render_blp_to_pixmap ( std::string const& blp_filename, int width = -1, int height = -1); + + }; + + } diff --git a/src/noggit/ui/About.cpp b/src/noggit/ui/About.cpp index 33c70124..35a5810b 100644 --- a/src/noggit/ui/About.cpp +++ b/src/noggit/ui/About.cpp @@ -23,7 +23,7 @@ namespace noggit new QVBoxLayout (this); auto icon (new QLabel (this)); - icon->setPixmap (*render_blp_to_pixmap ("interface/icons/inv_potion_83.blp")); + icon->setPixmap (*BLPRenderer::getInstance().render_blp_to_pixmap ("interface/icons/inv_potion_83.blp")); layout()->addWidget (icon); //! \todo was Skurri32 layout()->addWidget (new QLabel ("Noggit Studio", this)); diff --git a/src/noggit/ui/CurrentTexture.cpp b/src/noggit/ui/CurrentTexture.cpp index f43a9a15..1a4b9e23 100644 --- a/src/noggit/ui/CurrentTexture.cpp +++ b/src/noggit/ui/CurrentTexture.cpp @@ -56,7 +56,7 @@ namespace noggit _need_update = false; show(); - setPixmap (*render_blp_to_pixmap (_filename, width(), height())); + setPixmap (*BLPRenderer::getInstance().render_blp_to_pixmap (_filename, width(), height())); setToolTip(QString::fromStdString(_filename)); } diff --git a/src/noggit/ui/HelperModels.cpp b/src/noggit/ui/HelperModels.cpp index 53f38464..7a50a1d3 100644 --- a/src/noggit/ui/HelperModels.cpp +++ b/src/noggit/ui/HelperModels.cpp @@ -27,7 +27,7 @@ namespace noggit layout->addLayout (bottom_layout); auto icon (new QLabel (this)); - icon->setPixmap (*render_blp_to_pixmap ("interface/icons/inv_misc_enggizmos_swissarmy.blp")); + icon->setPixmap (*BLPRenderer::getInstance().render_blp_to_pixmap ("interface/icons/inv_misc_enggizmos_swissarmy.blp")); top_layout->addWidget (icon); top_layout->addWidget (new QLabel ("Select a model to add.\nYou should select a chunk first.", this)); diff --git a/src/noggit/ui/SettingsPanel.cpp b/src/noggit/ui/SettingsPanel.cpp index af78a030..41cc4000 100644 --- a/src/noggit/ui/SettingsPanel.cpp +++ b/src/noggit/ui/SettingsPanel.cpp @@ -175,7 +175,7 @@ namespace noggit new QHBoxLayout (warning); auto icon (new QLabel (warning)); icon->setPixmap - (*render_blp_to_pixmap ("interface/gossipframe/availablequesticon.blp")); + (*BLPRenderer::getInstance().render_blp_to_pixmap ("interface/gossipframe/availablequesticon.blp")); warning->layout()->addWidget (icon); warning->layout()->addWidget (new QLabel ("Changes may not take effect until next launch.", warning)); diff --git a/src/noggit/ui/TexturingGUI.cpp b/src/noggit/ui/TexturingGUI.cpp index 1771d99b..21e843ce 100644 --- a/src/noggit/ui/TexturingGUI.cpp +++ b/src/noggit/ui/TexturingGUI.cpp @@ -47,7 +47,7 @@ namespace noggit //! \note The one time Qt is const correct and we don't want that. auto that (const_cast (this)); that->_rendered = true; - that->_pixmap = *render_blp_to_pixmap (data (Qt::DisplayRole).toString().prepend ("tileset/").toStdString(), 256, 256); + that->_pixmap = *BLPRenderer::getInstance().render_blp_to_pixmap (data (Qt::DisplayRole).toString().prepend ("tileset/").toStdString(), 256, 256); } return QIcon(_pixmap); } diff --git a/src/noggit/ui/texture_palette_small.cpp b/src/noggit/ui/texture_palette_small.cpp index 6a1ebd04..672502c2 100644 --- a/src/noggit/ui/texture_palette_small.cpp +++ b/src/noggit/ui/texture_palette_small.cpp @@ -147,7 +147,7 @@ namespace noggit _texture_paths.emplace(display_name.toStdString()); QListWidgetItem* list_item = new QListWidgetItem(_texture_list); - list_item->setIcon(*render_blp_to_pixmap(filename, _texture_list->iconSize().width(), _texture_list->iconSize().height())); + list_item->setIcon(*BLPRenderer::getInstance().render_blp_to_pixmap(filename, _texture_list->iconSize().width(), _texture_list->iconSize().height())); list_item->setToolTip(display_name); list_item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); diff --git a/src/opengl/shader.cpp b/src/opengl/shader.cpp index 35c5299d..702fdf8d 100644 --- a/src/opengl/shader.cpp +++ b/src/opengl/shader.cpp @@ -128,7 +128,7 @@ namespace opengl } } - //! \todo cache lookups? + //! \todo _cache lookups? GLuint program::uniform_location (std::string const& name) const { return gl.getUniformLocation (*_handle, name.c_str());