diff --git a/android/Android.mk b/android/Android.mk index 0015323c9..bc4fe1670 100644 --- a/android/Android.mk +++ b/android/Android.mk @@ -141,7 +141,8 @@ include $(CLEAR_VARS) LOCAL_MODULE := graphics_engine LOCAL_PATH := . LOCAL_CPP_FEATURES += rtti -LOCAL_SRC_FILES := $(wildcard ../lib/graphics_engine/src/*.c) +LOCAL_SRC_FILES := $(wildcard ../lib/graphics_engine/src/*.c) \ + $(wildcard ../lib/graphics_engine/src/*.cpp) LOCAL_CFLAGS := -I../lib/graphics_engine/include include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) diff --git a/lib/graphics_engine/CMakeLists.txt b/lib/graphics_engine/CMakeLists.txt index c34b4bc85..a00226949 100644 --- a/lib/graphics_engine/CMakeLists.txt +++ b/lib/graphics_engine/CMakeLists.txt @@ -1,5 +1,8 @@ include_directories("${PROJECT_SOURCE_DIR}/lib/graphics_engine/include") +include_directories("${PROJECT_SOURCE_DIR}/lib/irrlicht/include") add_library(graphics_engine STATIC src/gl.c src/vulkan.c + src/ge_main.cpp + src/ge_texture.cpp ) diff --git a/lib/graphics_engine/include/ge_main.hpp b/lib/graphics_engine/include/ge_main.hpp new file mode 100644 index 000000000..4d496d22e --- /dev/null +++ b/lib/graphics_engine/include/ge_main.hpp @@ -0,0 +1,19 @@ +#ifndef HEADER_GE_MAIN_HPP +#define HEADER_GE_MAIN_HPP + +#include + +namespace GE +{ +struct GEConfig +{ +bool m_disable_npot_texture; +}; + +void init(irr::video::IVideoDriver* driver); +irr::video::IVideoDriver* getDriver(); +GEConfig* getGEConfig(); +void deinit(); +} + +#endif diff --git a/lib/graphics_engine/include/ge_texture.hpp b/lib/graphics_engine/include/ge_texture.hpp new file mode 100644 index 000000000..668ff0e6a --- /dev/null +++ b/lib/graphics_engine/include/ge_texture.hpp @@ -0,0 +1,16 @@ +#ifndef HEADER_GE_TEXTURE_HPP +#define HEADER_GE_TEXTURE_HPP + +#include +#include +#include + +namespace GE +{ +irr::video::ITexture* createFontTexture(const std::string& name); +irr::video::ITexture* createTexture(irr::video::IImage* img); +irr::video::IImage* getResizedImage(const std::string& path); +irr::video::ITexture* createTexture(const std::string& path); +}; // GE + +#endif diff --git a/lib/graphics_engine/src/ge_main.cpp b/lib/graphics_engine/src/ge_main.cpp new file mode 100644 index 000000000..3be5e21e6 --- /dev/null +++ b/lib/graphics_engine/src/ge_main.cpp @@ -0,0 +1,27 @@ +#include "ge_main.hpp" + +namespace GE +{ +irr::video::IVideoDriver* g_driver = NULL; +GEConfig g_config = {}; + +void init(irr::video::IVideoDriver* driver) +{ + g_driver = driver; +} + +irr::video::IVideoDriver* getDriver() +{ + return g_driver; +} + +GEConfig* getGEConfig() +{ + return &g_config; +} + +void deinit() +{ +} + +} diff --git a/lib/graphics_engine/src/ge_texture.cpp b/lib/graphics_engine/src/ge_texture.cpp new file mode 100644 index 000000000..4d787c299 --- /dev/null +++ b/lib/graphics_engine/src/ge_texture.cpp @@ -0,0 +1,45 @@ +#include "ge_main.hpp" +#include "ge_texture.hpp" + +#include +#include + +namespace GE +{ +using namespace irr; +video::IImage* getResizedImage(const std::string& path) +{ + video::IImage* image = getDriver()->createImageFromFile(path.c_str()); + if (image == NULL) + return NULL; + + core::dimension2du img_size = image->getDimension(); + bool has_npot = !getGEConfig()->m_disable_npot_texture && + getDriver()->queryFeature(video::EVDF_TEXTURE_NPOT); + + core::dimension2du tex_size = img_size.getOptimalSize(!has_npot); + const core::dimension2du& max_size = getDriver()->getDriverAttributes(). + getAttributeAsDimension2d("MAX_TEXTURE_SIZE"); + + if (tex_size.Width > max_size.Width) + tex_size.Width = max_size.Width; + if (tex_size.Height > max_size.Height) + tex_size.Height = max_size.Height; + + if (image->getColorFormat() != video::ECF_A8R8G8B8 || + tex_size != img_size) + { + video::IImage* new_texture = getDriver()->createImage( + video::ECF_A8R8G8B8, tex_size); + if (tex_size != img_size) + image->copyToScaling(new_texture); + else + image->copyTo(new_texture); + image->drop(); + return new_texture; + } + + return image; +} + +} diff --git a/lib/irrlicht/include/ITexture.h b/lib/irrlicht/include/ITexture.h index 126d3aea0..9935c7ebd 100644 --- a/lib/irrlicht/include/ITexture.h +++ b/lib/irrlicht/include/ITexture.h @@ -192,11 +192,15 @@ public: //! Get name of texture (in most cases this is the filename) const io::SNamedPath& getName() const { return NamedPath; } + void setName(const char* name) { NamedPath = io::SNamedPath(name); } + //! return open gl texture name virtual u64 getTextureHandler() const = 0; virtual u32 getTextureSize() const { return 0; } + virtual void updateTexture(void* data, ECOLOR_FORMAT format, u32 w, u32 h, u32 x, u32 y) {} + protected: //! Helper function, helps to get the desired texture creation format from the flags. diff --git a/src/graphics/abstract_renderer.hpp b/src/graphics/abstract_renderer.hpp index 63e882ec3..53f4365fa 100644 --- a/src/graphics/abstract_renderer.hpp +++ b/src/graphics/abstract_renderer.hpp @@ -66,8 +66,6 @@ public: virtual void resetPostProcessing() {} virtual void giveBoost(unsigned int cam_index) {} - virtual void addSkyBox(const std::vector &texture, - const std::vector &spherical_harmonics_textures) {} virtual void removeSkyBox() {} //FIXME: these three methods should not appear in the public Renderer interface diff --git a/src/graphics/central_settings.cpp b/src/graphics/central_settings.cpp index 14a0770ec..91ab40369 100644 --- a/src/graphics/central_settings.cpp +++ b/src/graphics/central_settings.cpp @@ -24,6 +24,7 @@ #include "graphics/glwrap.hpp" #include "graphics/graphics_restrictions.hpp" #include "guiengine/engine.hpp" +#include bool CentralVideoSettings::m_supports_sp = true; @@ -94,6 +95,9 @@ void CentralVideoSettings::init() std::string card((char*)(glGetString(GL_RENDERER))); std::string vendor((char*)(glGetString(GL_VENDOR))); GraphicsRestrictions::init(driver, card, vendor); + GE::getGEConfig()->m_disable_npot_texture = + GraphicsRestrictions::isDisabled( + GraphicsRestrictions::GR_NPOT_TEXTURES); if (GraphicsRestrictions::isDisabled(GraphicsRestrictions::GR_FORCE_LEGACY_DEVICE)) { diff --git a/src/graphics/irr_driver.cpp b/src/graphics/irr_driver.cpp index 9a6f5cd68..d41c490b7 100644 --- a/src/graphics/irr_driver.cpp +++ b/src/graphics/irr_driver.cpp @@ -95,6 +95,10 @@ #endif #endif +#ifndef SERVER_ONLY +#include +#endif + #ifdef ENABLE_RECORDER #include #include @@ -622,6 +626,9 @@ void IrrDriver::initDevice() m_scene_manager = m_device->getSceneManager(); m_gui_env = m_device->getGUIEnvironment(); m_video_driver = m_device->getVideoDriver(); +#ifndef SERVER_ONLY + GE::init(m_video_driver); +#endif B3DMeshLoader* b3dl = new B3DMeshLoader(m_scene_manager); m_scene_manager->addExternalMeshLoader(b3dl); @@ -1588,12 +1595,6 @@ scene::IAnimatedMeshSceneNode *IrrDriver::addAnimatedMesh(scene::IAnimatedMesh * scene::ISceneNode *IrrDriver::addSkyBox(const std::vector &texture, const std::vector &spherical_harmonics_textures) { -#ifndef SERVER_ONLY - assert(texture.size() == 6); - - m_renderer->addSkyBox(texture, spherical_harmonics_textures); - -#endif return m_scene_manager->addSkyBoxSceneNode(texture[0], texture[1], texture[2], texture[3], texture[4], texture[5]); diff --git a/src/graphics/shader_based_renderer.cpp b/src/graphics/shader_based_renderer.cpp index a6b45c245..f8950f87c 100644 --- a/src/graphics/shader_based_renderer.cpp +++ b/src/graphics/shader_based_renderer.cpp @@ -657,8 +657,8 @@ void ShaderBasedRenderer::giveBoost(unsigned int cam_index) } // ---------------------------------------------------------------------------- -void ShaderBasedRenderer::addSkyBox(const std::vector &texture, - const std::vector &spherical_harmonics_textures) +void ShaderBasedRenderer::addSkyBox(const std::vector &texture, + const std::vector &spherical_harmonics_textures) { m_skybox = new Skybox(texture); if(spherical_harmonics_textures.size() == 6) diff --git a/src/graphics/shader_based_renderer.hpp b/src/graphics/shader_based_renderer.hpp index 442c21f3a..8029e32f5 100644 --- a/src/graphics/shader_based_renderer.hpp +++ b/src/graphics/shader_based_renderer.hpp @@ -87,8 +87,8 @@ public: void resetPostProcessing() OVERRIDE; void giveBoost(unsigned int cam_index) OVERRIDE; - void addSkyBox(const std::vector &texture, - const std::vector &spherical_harmonics_textures) OVERRIDE; + void addSkyBox(const std::vector &texture, + const std::vector &spherical_harmonics_textures); void removeSkyBox() OVERRIDE; const SHCoefficients* getSHCoefficients() const OVERRIDE; GLuint getRenderTargetTexture(TypeRTT which) const OVERRIDE; diff --git a/src/graphics/skybox.cpp b/src/graphics/skybox.cpp index 5971c8426..e75a54477 100644 --- a/src/graphics/skybox.cpp +++ b/src/graphics/skybox.cpp @@ -147,8 +147,8 @@ void Skybox::generateCubeMapFromTextures() unsigned size = 0; for (unsigned i = 0; i < 6; i++) { - size = std::max(size, m_skybox_textures[i]->getSize().Width); - size = std::max(size, m_skybox_textures[i]->getSize().Height); + size = std::max(size, m_skybox_textures[i]->getDimension().Width); + size = std::max(size, m_skybox_textures[i]->getDimension().Height); } const unsigned texture_permutation[] = { 2, 3, 0, 1, 5, 4 }; @@ -158,9 +158,18 @@ void Skybox::generateCubeMapFromTextures() for (unsigned i = 0; i < 6; i++) { unsigned idx = texture_permutation[i]; - video::IImage* img = static_cast - (m_skybox_textures[idx])->getTextureImage(); - assert(img != NULL); + video::IImage* img = m_skybox_textures[idx]; +#if defined(USE_GLES2) + uint8_t* data = (uint8_t*)img->lock(); + for (unsigned int j = 0; j < + img->getDimension().Width * img->getDimension().Height; j++) + { + uint8_t tmp_val = data[j * 4]; + data[j * 4] = data[j * 4 + 2]; + data[j * 4 + 2] = tmp_val; + } +#endif + img->copyToScaling(rgba[i], size, size); if (i == 2 || i == 3) @@ -176,6 +185,7 @@ void Skybox::generateCubeMapFromTextures() } delete[] tmp; } + img->drop(); glBindTexture(GL_TEXTURE_CUBE_MAP, m_cube_map); @@ -315,8 +325,9 @@ Out of legacy the sequence of textures maps to: - 6th texture maps to GL_TEXTURE_CUBE_MAP_POSITIVE_Z * \param skybox_textures sequence of 6 textures. */ -Skybox::Skybox(const std::vector &skybox_textures) +Skybox::Skybox(const std::vector &skybox_textures) { + m_cube_map = 0; m_skybox_textures = skybox_textures; #if !defined(USE_GLES2) @@ -341,11 +352,10 @@ Skybox::~Skybox() // ---------------------------------------------------------------------------- void Skybox::render(const scene::ICameraSceneNode *camera) const { - if (m_skybox_textures.empty()) + if (m_cube_map == 0) return; glEnable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); - assert(m_skybox_textures.size() == 6); if (CVS->isDeferredEnabled()) { diff --git a/src/graphics/skybox.hpp b/src/graphics/skybox.hpp index 6957c4465..8c3056207 100644 --- a/src/graphics/skybox.hpp +++ b/src/graphics/skybox.hpp @@ -28,8 +28,8 @@ class Skybox { private: - /** The 6 skybox textures */ - std::vector m_skybox_textures; + /** The 6 skybox images */ + std::vector m_skybox_textures; /** The skybox texture id */ GLuint m_cube_map; @@ -42,7 +42,7 @@ private: void generateSpecularCubemap (); public: - Skybox(const std::vector &skybox_textures); + Skybox(const std::vector &skybox_textures); ~Skybox(); void render(const irr::scene::ICameraSceneNode *camera) const; diff --git a/src/graphics/spherical_harmonics.cpp b/src/graphics/spherical_harmonics.cpp index f97db763b..76b994516 100644 --- a/src/graphics/spherical_harmonics.cpp +++ b/src/graphics/spherical_harmonics.cpp @@ -22,7 +22,6 @@ #include "graphics/central_settings.hpp" #endif #include "graphics/irr_driver.hpp" -#include "graphics/stk_texture.hpp" #include "utils/log.hpp" #include @@ -514,7 +513,7 @@ printf( "#### SH ; Coeffs B ; %f %f %f %f %f %f %f %f\n", m_SH_coeff->blue_SH_co } // projectSH // ---------------------------------------------------------------------------- -SphericalHarmonics::SphericalHarmonics(const std::vector &spherical_harmonics_textures) +SphericalHarmonics::SphericalHarmonics(const std::vector &spherical_harmonics_textures) { m_SH_coeff = new SHCoefficients; setTextures(spherical_harmonics_textures); @@ -539,7 +538,7 @@ SphericalHarmonics::~SphericalHarmonics() /** Compute spherical harmonics coefficients from 6 textures */ -void SphericalHarmonics::setTextures(const std::vector &spherical_harmonics_textures) +void SphericalHarmonics::setTextures(const std::vector &spherical_harmonics_textures) { assert(spherical_harmonics_textures.size() == 6); @@ -551,8 +550,8 @@ void SphericalHarmonics::setTextures(const std::vector &spher for (unsigned i = 0; i < 6; i++) { - sh_w = std::max(sh_w, m_spherical_harmonics_textures[i]->getSize().Width); - sh_h = std::max(sh_h, m_spherical_harmonics_textures[i]->getSize().Height); + sh_w = std::max(sh_w, m_spherical_harmonics_textures[i]->getDimension().Width); + sh_h = std::max(sh_h, m_spherical_harmonics_textures[i]->getDimension().Height); } for (unsigned i = 0; i < 6; i++) @@ -561,19 +560,8 @@ void SphericalHarmonics::setTextures(const std::vector &spher for (unsigned i = 0; i < 6; i++) { unsigned idx = texture_permutation[i]; - video::IImage* img = static_cast - (m_spherical_harmonics_textures[idx])->getTextureImage(); - assert(img != NULL); - img->copyToScaling(sh_rgba[i], sh_w, sh_h); -#if defined(USE_GLES2) - // Code here assume color format is BGRA - for (unsigned int j = 0; j < sh_w * sh_h; j++) - { - char tmp_val = sh_rgba[i][j * 4]; - sh_rgba[i][j * 4] = sh_rgba[i][j * 4 + 2]; - sh_rgba[i][j * 4 + 2] = tmp_val; - } -#endif + m_spherical_harmonics_textures[idx]->copyToScaling(sh_rgba[i], sh_w, sh_h); + m_spherical_harmonics_textures[idx]->drop(); } //for (unsigned i = 0; i < 6; i++) generateSphericalHarmonics(sh_rgba, sh_w); diff --git a/src/graphics/spherical_harmonics.hpp b/src/graphics/spherical_harmonics.hpp index 3e6fd7695..17592755a 100644 --- a/src/graphics/spherical_harmonics.hpp +++ b/src/graphics/spherical_harmonics.hpp @@ -41,7 +41,7 @@ class SphericalHarmonics { private: /** The 6 spherical harmonics textures */ - std::vector m_spherical_harmonics_textures; + std::vector m_spherical_harmonics_textures; /** Ambient light is used for tracks without spherical harmonics textures */ irr::video::SColor m_ambient; @@ -52,11 +52,11 @@ private: void generateSphericalHarmonics(unsigned char *sh_rgba[6], unsigned int edge_size); public: - SphericalHarmonics(const std::vector &spherical_harmonics_textures); + SphericalHarmonics(const std::vector &spherical_harmonics_textures); SphericalHarmonics(const irr::video::SColor &ambient); ~SphericalHarmonics(); - void setTextures(const std::vector &spherical_harmonics_textures); + void setTextures(const std::vector &spherical_harmonics_textures); void setAmbientLight(const irr::video::SColor &ambient); inline const SHCoefficients* getCoefficients() const { return m_SH_coeff; } diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index 6a666e3c9..a39ee89de 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -40,6 +40,7 @@ #include "graphics/particle_kind.hpp" #include "graphics/particle_kind_manager.hpp" #include "graphics/render_target.hpp" +#include "graphics/shader_based_renderer.hpp" #include "graphics/shader_files_manager.hpp" #include "graphics/stk_tex_manager.hpp" #include "graphics/sp/sp_base.hpp" @@ -95,6 +96,11 @@ #include #include +#ifndef SERVER_ONLY +#include +#include +#endif + using namespace irr; @@ -412,20 +418,13 @@ void Track::cleanup() for(unsigned int i=0; idrop(); - if(m_sky_textures[i]->getReferenceCount()==1) - irr_driver->removeTexture(m_sky_textures[i]); + video::ITexture* tex = (video::ITexture*)m_sky_textures[i]; + tex->drop(); + if (tex->getReferenceCount() == 1) + irr_driver->removeTexture(tex); } m_sky_textures.clear(); - for (unsigned int i = 0; idrop(); - if (m_spherical_harmonics_textures[i]->getReferenceCount() == 1) - irr_driver->removeTexture(m_spherical_harmonics_textures[i]); - } - m_spherical_harmonics_textures.clear(); - if(m_cache_track) material_manager->makeMaterialsPermanent(); else @@ -2094,10 +2093,23 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) #ifndef SERVER_ONLY if(m_sky_type==SKY_BOX && m_sky_textures.size() == 6) { - //if (m_spherical_harmonics_textures.size() > 0) - m_all_nodes.push_back(irr_driver->addSkyBox(m_sky_textures, m_spherical_harmonics_textures)); - //else - // m_all_nodes.push_back(irr_driver->addSkyBox(m_sky_textures, m_sky_textures)); + if (CVS->isGLSL()) + { + std::vector sky; + for (void* t : m_sky_textures) + sky.push_back((video::IImage*)t); + std::vector sh; + for (void* t : m_spherical_harmonics_textures) + sh.push_back((video::IImage*)t); + SP::getRenderer()->addSkyBox(sky, sh); + } + else + { + std::vector textures; + for (void* t : m_sky_textures) + textures.push_back((video::ITexture*)t); + m_all_nodes.push_back(irr_driver->addSkyBox(textures, {})); + } } else if(m_sky_type==SKY_COLOR) { @@ -2253,15 +2265,7 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) #ifndef SERVER_ONLY if (CVS->isGLSL()) { - for (video::ITexture* t : m_sky_textures) - { - t->drop(); - } m_sky_textures.clear(); - for (video::ITexture* t : m_spherical_harmonics_textures) - { - t->drop(); - } m_spherical_harmonics_textures.clear(); } #endif // !SERVER_ONLY @@ -2430,27 +2434,28 @@ void Track::handleSky(const XMLNode &xml_node, const std::string &filename) std::string s; xml_node.get("texture", &s); std::vector v = StringUtils::split(s, ' '); - for(unsigned int i=0; iisGLSL()) { - t = STKTexManager::getInstance()->getTexture(v[i], - (TexConfig*)NULL/*tex_config*/, true/*no_upload*/); + video::IImage* img = getSkyTexture(v[i]); + obj = img; } else #endif // !SERVER_ONLY { - t = irr_driver->getTexture(v[i]); - } - if (t) - { -#ifndef SERVER_ONLY - if (!CVS->isGLSL()) -#endif // !SERVER_ONLY + video::ITexture* t = irr_driver->getTexture(v[i]); + if (t) + { t->grab(); - m_sky_textures.push_back(t); + obj = t; + } + } + if (obj) + { + m_sky_textures.push_back(obj); } else { @@ -2458,6 +2463,7 @@ void Track::handleSky(const XMLNode &xml_node, const std::string &filename) v[i].c_str()); } } // for iisGLSL()) + video::IImage* img = getSkyTexture(v[i]); + if (img) { - t = STKTexManager::getInstance()->getTexture(v[i], - (TexConfig*)NULL/*tex_config*/, true/*no_upload*/); - } - else -#endif // !SERVER_ONLY - { - t = irr_driver->getTexture(v[i]); - } - if (t) - { -#ifndef SERVER_ONLY - if (!CVS->isGLSL()) -#endif // !SERVER_ONLY - t->grab(); - m_spherical_harmonics_textures.push_back(t); + m_spherical_harmonics_textures.push_back(img); } else { @@ -2502,6 +2495,8 @@ void Track::handleSky(const XMLNode &xml_node, const std::string &filename) v[i].c_str()); } } // for isearchTexture(path).c_str(); + if (relative_path.empty()) + return NULL; + path = file_manager->getFileSystem()->getAbsolutePath(relative_path) + .c_str(); + } + return GE::getResizedImage(path); +#endif +} // getSkyTexture diff --git a/src/tracks/track.hpp b/src/tracks/track.hpp index 7c7b9ca79..4eb1270bd 100644 --- a/src/tracks/track.hpp +++ b/src/tracks/track.hpp @@ -253,9 +253,9 @@ private: /** A list of the textures for the sky to use. It contains one texture * in case of a dome, and 6 textures for a box. */ - std::vector m_sky_textures; + std::vector m_sky_textures; - std::vector m_spherical_harmonics_textures; + std::vector m_spherical_harmonics_textures; /** Used if m_sky_type is SKY_COLOR only */ irr::video::SColor m_sky_color; @@ -405,6 +405,7 @@ private: void handleSky(const XMLNode &root, const std::string &filename); void freeCachedMeshVertexBuffer(); void copyFromMainProcess(); + video::IImage* getSkyTexture(std::string path) const; public: /** Static function to get the current track. NULL if no current