From 819ac22d40f632bb03fe19ffe4a2c30fa777026a Mon Sep 17 00:00:00 2001 From: GuillaumeG <48102745+JonathSpirit@users.noreply.github.com> Date: Wed, 20 Oct 2021 15:42:58 +0200 Subject: [PATCH 1/5] Add a first iteration of custom texture support for RadialLight --- include/Candle/RadialLight.hpp | 48 +++++++++- src/RadialLight.cpp | 169 ++++++++++++++++++++++----------- 2 files changed, 161 insertions(+), 56 deletions(-) diff --git a/include/Candle/RadialLight.hpp b/include/Candle/RadialLight.hpp index f3384ce..b6aa20d 100644 --- a/include/Candle/RadialLight.hpp +++ b/include/Candle/RadialLight.hpp @@ -32,7 +32,11 @@ namespace candle{ class RadialLight: public LightSource{ private: static int s_instanceCount; - float m_beamAngle; + float m_beamAngle; + unsigned int m_localRadius; + + sf::Texture* m_lightTextureFade; + sf::Texture* m_lightTexturePlain; void draw(sf::RenderTarget& t, sf::RenderStates st) const override; void resetColor() override; @@ -66,6 +70,48 @@ namespace candle{ */ float getBeamAngle() const; + /** + * @brief Set the light fade texture. + * @details The default texture is generated internally. + * @see getLightFadeTexture + */ + void setLightFadeTexture(sf::Texture& texture); + + /** + * @brief Get the light fade texture. + * @returns The actual light fade texture. + * @see setLightFadeTexture + */ + sf::Texture* getLightFadeTexture(); + + /** + * @brief Set the light plain texture. + * @details The default texture is generated internally. + * @see getLightPlainTexture + */ + void setLightPlainTexture(sf::Texture& texture); + + /** + * @brief Get the light plain texture. + * @returns The actual light plain texture. + * @see setLightPlainTexture + */ + sf::Texture* getLightPlainTexture(); + + /** + * @brief Get the default internally generated light fade texture. + * @returns The default light fade texture. + * @see getLightFadeTexture + */ + std::shared_ptr getDefaultLightFadeTexture() const; + + /** + * @brief Get the default internally generated light plain texture. + * @returns The default light plain texture. + * @see getLightFadeTexture + */ + std::shared_ptr getDefaultLightPlainTexture() const; + /** * @brief Get the local bounding rectangle of the light. * @returns The local bounding rectangle in float. diff --git a/src/RadialLight.cpp b/src/RadialLight.cpp index ff8ea4a..c50bd3c 100644 --- a/src/RadialLight.cpp +++ b/src/RadialLight.cpp @@ -13,41 +13,51 @@ namespace candle{ int RadialLight::s_instanceCount = 0; - const float BASE_RADIUS = 400.0f; + const unsigned int BASE_RADIUS = 400; bool l_texturesReady(false); - std::unique_ptr l_lightTextureFade; - std::unique_ptr l_lightTexturePlain; + std::shared_ptr l_lightTextureFade; + std::shared_ptr l_lightTexturePlain; void initializeTextures(){ #ifdef CANDLE_DEBUG std::cout << "RadialLight: InitializeTextures" << std::endl; #endif - int points = 100; - - l_lightTextureFade.reset(new sf::RenderTexture); - l_lightTexturePlain.reset(new sf::RenderTexture); - l_lightTextureFade->create(BASE_RADIUS*2 + 2, BASE_RADIUS*2 + 2); - l_lightTexturePlain->create(BASE_RADIUS*2 + 2, BASE_RADIUS*2 + 2); - - sf::VertexArray lightShape(sf::TriangleFan, points+2); - float step = sfu::PI*2.f/points; - lightShape[0].position = {BASE_RADIUS + 1, BASE_RADIUS + 1}; - for(int i = 1; i < points+2; i++){ - lightShape[i].position = { - (std::sin(step*(i)) + 1) * BASE_RADIUS + 1, - (std::cos(step*(i)) + 1) * BASE_RADIUS + 1 - }; - lightShape[i].color.a = 0; - } - l_lightTextureFade->clear(sf::Color::Transparent); - l_lightTextureFade->draw(lightShape); - l_lightTextureFade->display(); - l_lightTextureFade->setSmooth(true); - - sfu::setColor(lightShape, sf::Color::White); - l_lightTexturePlain->clear(sf::Color::Transparent); - l_lightTexturePlain->draw(lightShape); - l_lightTexturePlain->display(); + + sf::Image lightImageFade; + sf::Image lightImagePlain; + + //We create an image of the radius*2 + an 2 more pixels + lightImageFade.create(BASE_RADIUS*2+2, BASE_RADIUS*2+2, sf::Color(255,255,255,0)); + lightImagePlain.create(BASE_RADIUS*2+2, BASE_RADIUS*2+2, sf::Color(255,255,255,0)); + + sf::Vector2f center = {BASE_RADIUS, BASE_RADIUS}; + + for (unsigned int y=1; y(255.0f*distanceFromCenter))); + lightImagePlain.setPixel(x,y, sf::Color(255,255,255,255)); + } + } + } + + l_lightTextureFade.reset( new sf::Texture() ); + l_lightTextureFade->loadFromImage(lightImageFade); + l_lightTextureFade->setSmooth(true); + + l_lightTexturePlain.reset( new sf::Texture() ); + l_lightTexturePlain->loadFromImage(lightImagePlain); l_lightTexturePlain->setSmooth(true); } @@ -64,26 +74,17 @@ namespace candle{ // The first time we create a RadialLight, we must create the textures initializeTextures(); l_texturesReady = true; - } - m_polygon.setPrimitiveType(sf::TriangleFan); - m_polygon.resize(6); - m_polygon[0].position = - m_polygon[0].texCoords = {BASE_RADIUS+1, BASE_RADIUS+1}; - m_polygon[1].position = - m_polygon[5].position = - m_polygon[1].texCoords = - m_polygon[5].texCoords = {0.f, 0.f}; - m_polygon[2].position = - m_polygon[2].texCoords = {BASE_RADIUS*2 + 2, 0.f}; - m_polygon[3].position = - m_polygon[3].texCoords = {BASE_RADIUS*2 + 2, BASE_RADIUS*2 + 2}; - m_polygon[4].position = - m_polygon[4].texCoords = {0.f, BASE_RADIUS*2 + 2}; - Transformable::setOrigin(BASE_RADIUS, BASE_RADIUS); + } + + setLightFadeTexture( *l_lightTextureFade.get() ); + setLightPlainTexture( *l_lightTexturePlain.get() ); + setRange(1.0f); setBeamAngle(360.f); // castLight(); - s_instanceCount++; + s_instanceCount++; + + setColor(sf::Color(255,255,255,255)); } RadialLight::~RadialLight(){ @@ -105,9 +106,9 @@ namespace candle{ void RadialLight::draw(sf::RenderTarget& t, sf::RenderStates s) const{ sf::Transform trm = Transformable::getTransform(); - trm.scale(m_range/BASE_RADIUS, m_range/BASE_RADIUS, BASE_RADIUS, BASE_RADIUS); + trm.scale(m_range/m_localRadius, m_range/m_localRadius, m_localRadius, m_localRadius); s.transform *= trm; - s.texture = m_fade ? &l_lightTextureFade->getTexture() : &l_lightTexturePlain->getTexture(); + s.texture = m_fade ? m_lightTextureFade : m_lightTexturePlain; if(s.blendMode == sf::BlendAlpha){ s.blendMode = sf::BlendAdd; } @@ -130,21 +131,79 @@ namespace candle{ return m_beamAngle; } + void RadialLight::setLightFadeTexture(sf::Texture& texture){ + m_lightTextureFade = &texture; + m_localRadius = (texture.getSize().x > texture.getSize().y) ? texture.getSize().x/2+1 : texture.getSize().y/2+1; + + m_polygon.setPrimitiveType(sf::TriangleFan); + m_polygon.resize(6); + m_polygon[0].position = + m_polygon[0].texCoords = {static_cast(m_localRadius), static_cast(m_localRadius)}; + m_polygon[1].position = + m_polygon[5].position = + m_polygon[1].texCoords = + m_polygon[5].texCoords = {0.f, 0.f}; + m_polygon[2].position = + m_polygon[2].texCoords = {static_cast(m_localRadius)*2, 0.f}; + m_polygon[3].position = + m_polygon[3].texCoords = {static_cast(m_localRadius)*2, static_cast(m_localRadius)*2}; + m_polygon[4].position = + m_polygon[4].texCoords = {0.f, static_cast(m_localRadius)*2}; + Transformable::setOrigin(m_localRadius, m_localRadius); + } + + sf::Texture* RadialLight::getLightFadeTexture(){ + return m_lightTextureFade; + } + + void RadialLight::setLightPlainTexture(sf::Texture& texture){ + m_lightTexturePlain = &texture; + m_localRadius = (texture.getSize().x > texture.getSize().y) ? texture.getSize().x/2 : texture.getSize().y/2; + + m_polygon.setPrimitiveType(sf::TriangleFan); + m_polygon.resize(6); + m_polygon[0].position = + m_polygon[0].texCoords = {static_cast(m_localRadius), static_cast(m_localRadius)}; + m_polygon[1].position = + m_polygon[5].position = + m_polygon[1].texCoords = + m_polygon[5].texCoords = {0.f, 0.f}; + m_polygon[2].position = + m_polygon[2].texCoords = {static_cast(m_localRadius)*2, 0.f}; + m_polygon[3].position = + m_polygon[3].texCoords = {static_cast(m_localRadius)*2, static_cast(m_localRadius)*2}; + m_polygon[4].position = + m_polygon[4].texCoords = {0.f, static_cast(m_localRadius)*2}; + Transformable::setOrigin(m_localRadius, m_localRadius); + } + + sf::Texture* RadialLight::getLightPlainTexture(){ + return m_lightTexturePlain; + } + + std::shared_ptr RadialLight::getDefaultLightFadeTexture() const{ + return l_lightTextureFade; + } + + std::shared_ptr RadialLight::getDefaultLightPlainTexture() const{ + return l_lightTexturePlain; + } + sf::FloatRect RadialLight::getLocalBounds() const{ - return sf::FloatRect(0.0f, 0.0f, BASE_RADIUS*2, BASE_RADIUS*2); + return sf::FloatRect(0.0f, 0.0f, m_localRadius*2, m_localRadius*2); } sf::FloatRect RadialLight::getGlobalBounds() const{ - float scaledRange = m_range / BASE_RADIUS; + float scaledRange = m_range / m_localRadius; sf::Transform trm = Transformable::getTransform(); - trm.scale(scaledRange, scaledRange, BASE_RADIUS, BASE_RADIUS); + trm.scale(scaledRange, scaledRange, m_localRadius, m_localRadius); return trm.transformRect( getLocalBounds() ); } void RadialLight::castLight(const EdgeVector::iterator& begin, const EdgeVector::iterator& end){ - float scaledRange = m_range / BASE_RADIUS; + float scaledRange = m_range / m_localRadius; sf::Transform trm = Transformable::getTransform(); - trm.scale(scaledRange, scaledRange, BASE_RADIUS, BASE_RADIUS); + trm.scale(scaledRange, scaledRange, m_localRadius, m_localRadius); std::vector rays; rays.reserve(2 + std::distance(begin, end) * 2 * 3); // 2: beam angle, 4: corners, 2: pnts/sgmnt, 3 rays/pnt @@ -166,7 +225,7 @@ namespace candle{ if(beamAngleBigEnough || angleInBeam(a)){ rays.emplace_back(castPoint, a); } - } + } sf::FloatRect lightBounds = getGlobalBounds(); for(auto it = begin; it != end; it++){ @@ -223,7 +282,7 @@ namespace candle{ std::vector points; points.reserve(rays.size()); for (auto& r: rays){ - points.push_back(tr_i.transformPoint(castRay(begin, end, r, m_range*m_range))); + points.push_back(tr_i.transformPoint(castRay(begin, end, r, m_range*2))); } m_polygon.resize(points.size() + 1 + beamAngleBigEnough); // + center and last m_polygon[0].color = m_color; From 8b6d8a4fff5c23a6432405fa432464d54a281e31 Mon Sep 17 00:00:00 2001 From: GuillaumeG <48102745+JonathSpirit@users.noreply.github.com> Date: Mon, 25 Oct 2021 15:44:46 +0200 Subject: [PATCH 2/5] Adding setTexture on LightSource class, add a map cache --- include/Candle/DirectedLight.hpp | 31 +++++---- include/Candle/LightSource.hpp | 78 ++++++++++++---------- include/Candle/RadialLight.hpp | 32 +-------- src/DirectedLight.cpp | 10 ++- src/LightSource.cpp | 18 ++--- src/RadialLight.cpp | 110 ++++++++++++++++++------------- 6 files changed, 142 insertions(+), 137 deletions(-) diff --git a/include/Candle/DirectedLight.hpp b/include/Candle/DirectedLight.hpp index b8ec030..c08951a 100644 --- a/include/Candle/DirectedLight.hpp +++ b/include/Candle/DirectedLight.hpp @@ -12,51 +12,54 @@ namespace candle{ /** * @brief LightSource that emits light in a single direction. - * @details - * - * A DirectedLight is defined, mainly, by the direction of the rays, the + * @details + * + * A DirectedLight is defined, mainly, by the direction of the rays, the * position of the source, the beam width and the range of the light. You - * can manipulate the first two changing the rotation and + * can manipulate the first two changing the rotation and * position as you would with any sf::Transformable. The range can * be manipulated as with other LightSources, with * @ref LightSource::setRange, and the beam width with @ref setBeamWidth. - * + * * * * * * *

Variables diagram

Demo example
- * + * */ class DirectedLight: public LightSource{ private: - float m_beamWidth; - + float m_beamWidth; + sf::Texture* m_texture; + void draw(sf::RenderTarget& t, sf::RenderStates st) const override; void resetColor() override; public: DirectedLight(); - - void castLight(const EdgeVector::iterator& begin, const EdgeVector::iterator& end) override; - + + void castLight(const EdgeVector::iterator& begin, const EdgeVector::iterator& end) override; + + void setTexture(sf::Texture* texture) override; + /** * @brief Set the width of the beam. - * @details The width specifies the maximum distance allowed from the + * @details The width specifies the maximum distance allowed from the * center of the segment to cast a ray, along a segment normal to the * light direction. * @param width Width of the beam. * @see getBeamWidth */ void setBeamWidth(float width); - + /** * @brief Get the width of the beam. * @returns Width of the beam * @see setBeamWidth */ float getBeamWidth() const; - + }; } diff --git a/include/Candle/LightSource.hpp b/include/Candle/LightSource.hpp index 7d0008f..22a336c 100644 --- a/include/Candle/LightSource.hpp +++ b/include/Candle/LightSource.hpp @@ -20,37 +20,37 @@ namespace candle{ * @brief Typedef with mere semantic purposes. */ typedef sfu::Line Edge; - + /** * @typedef EdgeVector * @brief Typedef to shorten the use of vectors as edge pools */ typedef std::vector EdgeVector; - + /** * @brief This function initializes the Texture used for the RadialLights. * @details This function is called the first time a RadialLight is created - * , so the user shouldn't need to do it. Anyways, it could be - * necessary to do it explicitly if you declare a RadialLight that, for + * , so the user shouldn't need to do it. Anyways, it could be + * necessary to do it explicitly if you declare a RadialLight that, for * some reason, is global or static RadialLight and is not constructed in * a normal order. */ void initializeTextures(); - + /** * @brief Interface for objects that emit light * @details - * + * * LightSources use raycasting algorithms to compute the polygon - * illuminated by the light. The main difference between the + * illuminated by the light. The main difference between the * implementations, @ref RadialLight and @ref DirectedLight, is whether * the constant is the origin or the direction of the rays. - * + * * LightSources manage their colour separating the alpha value from the RGB - * . This is convenient to manipulate color of the light (interpreted as - * the RGB value) and intensity (interpreted as the alpha value) + * . This is convenient to manipulate color of the light (interpreted as + * the RGB value) and intensity (interpreted as the alpha value) * separately. - * + * * By default, they use a sf::BlendAdd mode. This means that you can * specify any other blend mode you want, except sf::BlendAlpha, that * will be changed to the additive mode. @@ -61,7 +61,7 @@ namespace candle{ * @brief Draw the object to a target */ virtual void draw(sf::RenderTarget& t, sf::RenderStates st) const = 0; - + protected: sf::Color m_color; sf::VertexArray m_polygon; @@ -69,50 +69,50 @@ namespace candle{ float m_intensity; // only for fog bool m_fade; -#ifdef CANDLE_DEBUG +#ifdef CANDLE_DEBUG sf::VertexArray m_debug; #endif - + virtual void resetColor() = 0; - + public: /** * @brief Constructor */ LightSource(); - + /** * @brief Set the light intensity. - * @details The @p intensity of the light determines two things: - * how much fog opacity it reduces when drawn in a LightingArea * in + * @details The @p intensity of the light determines two things: + * how much fog opacity it reduces when drawn in a LightingArea * in * FOG mode, and how much presence its color has when drawn normally. - * + * * The default value is 1. - * + * * @param intensity Value from 0 to 1. At 0 the light is * invisible. * @see getIntensity */ void setIntensity(float intensity); - + /** * @brief Get the intensity of the light. * @returns The light intensity. * @see setIntensity */ float getIntensity() const; - + /** * @brief Set the light color. * @details The light color refers only to the RGB values. - * + * * The default value is sf::Color::White - * + * * @param color New color of the light. The alpha value is ignored. * @see getColor */ void setColor(const sf::Color& color); - + /** * @brief Get the plain color of the light. * @details The light color refers only to the RGB values. @@ -120,27 +120,33 @@ namespace candle{ * @see setColor */ sf::Color getColor() const; - + /** * @brief Set the value of the _fade_ flag. * @details when the @p fade flag is set, the light will lose intensity * in the limits of its range. Otherwise, the intensity will remain * constant. - * + * * The default value is true. - * + * * @param fade Value to set the flag. * @see getFade */ virtual void setFade(bool fade); - + /** * @brief Check if the light fades or not. * @returns The value of the _fade_ flag. * @see setFade */ - virtual bool getFade() const; - + virtual bool getFade() const; + + /** + * @brief Set the light texture (nullptr = default texture). + * @details The default texture is generated internally. + */ + virtual void setTexture(sf::Texture* texture) = 0; + /** * @brief Set the range of the illuminated area. * @details The range of the light indicates the how far a light ray @@ -149,21 +155,21 @@ namespace candle{ * @see getRange, setFade */ void setRange(float range); - + /** * @brief Get the range of the illuminated area. * @returns The range of the illuminated area. * @see setRange */ float getRange() const; - + /** - * @brief Modify the polygon of the illuminated area with a + * @brief Modify the polygon of the illuminated area with a * raycasting algorithm. - * @details The algorithm needs to know which edges to use to cast + * @details The algorithm needs to know which edges to use to cast * shadows. They are specified within a range of two iterators of a * vector of edges of type @ref sfu::Line. - * @param begin Iterator to the first sfu::Line of the vector to take + * @param begin Iterator to the first sfu::Line of the vector to take * into account. * @param end Iterator to the first sfu::Line of the vector not to be * taken into account. diff --git a/include/Candle/RadialLight.hpp b/include/Candle/RadialLight.hpp index b6aa20d..34208d5 100644 --- a/include/Candle/RadialLight.hpp +++ b/include/Candle/RadialLight.hpp @@ -52,7 +52,9 @@ namespace candle{ */ virtual ~RadialLight(); - void castLight(const EdgeVector::iterator& begin, const EdgeVector::iterator& end) override; + void castLight(const EdgeVector::iterator& begin, const EdgeVector::iterator& end) override; + + void setTexture(sf::Texture* texture) override; /** * @brief Set the range for which rays may be casted. @@ -70,13 +72,6 @@ namespace candle{ */ float getBeamAngle() const; - /** - * @brief Set the light fade texture. - * @details The default texture is generated internally. - * @see getLightFadeTexture - */ - void setLightFadeTexture(sf::Texture& texture); - /** * @brief Get the light fade texture. * @returns The actual light fade texture. @@ -84,13 +79,6 @@ namespace candle{ */ sf::Texture* getLightFadeTexture(); - /** - * @brief Set the light plain texture. - * @details The default texture is generated internally. - * @see getLightPlainTexture - */ - void setLightPlainTexture(sf::Texture& texture); - /** * @brief Get the light plain texture. * @returns The actual light plain texture. @@ -98,20 +86,6 @@ namespace candle{ */ sf::Texture* getLightPlainTexture(); - /** - * @brief Get the default internally generated light fade texture. - * @returns The default light fade texture. - * @see getLightFadeTexture - */ - std::shared_ptr getDefaultLightFadeTexture() const; - - /** - * @brief Get the default internally generated light plain texture. - * @returns The default light plain texture. - * @see getLightFadeTexture - */ - std::shared_ptr getDefaultLightPlainTexture() const; - /** * @brief Get the local bounding rectangle of the light. * @returns The local bounding rectangle in float. diff --git a/src/DirectedLight.cpp b/src/DirectedLight.cpp index 54f0faa..2108829 100644 --- a/src/DirectedLight.cpp +++ b/src/DirectedLight.cpp @@ -11,7 +11,8 @@ namespace candle{ st.transform *= Transformable::getTransform(); if(st.blendMode == sf::BlendAlpha){ // the default st.blendMode = sf::BlendAdd; - } + } + st.texture = m_texture; t.draw(m_polygon, st); #ifdef CANDLE_DEBUG sf::RenderStates deb_s; @@ -44,7 +45,8 @@ namespace candle{ DirectedLight::DirectedLight(){ m_polygon.setPrimitiveType(sf::Quads); m_polygon.resize(2); - setBeamWidth(10.f); + setBeamWidth(10.f); + m_texture = nullptr; // castLight(); } @@ -54,6 +56,10 @@ namespace candle{ float DirectedLight::getBeamWidth() const{ return m_beamWidth; + } + + void DirectedLight::setTexture(sf::Texture* texture){ + m_texture = texture; } struct LineParam: public sfu::Line{ diff --git a/src/LightSource.cpp b/src/LightSource.cpp index d5c604f..c795077 100644 --- a/src/LightSource.cpp +++ b/src/LightSource.cpp @@ -15,41 +15,41 @@ namespace candle{ , m_debug(sf::Lines, 0) #endif {} - + void LightSource::setIntensity(float intensity){ m_color.a = 255 * intensity; resetColor(); } - + float LightSource::getIntensity() const{ return (float)m_color.a/255.f; } - + void LightSource::setColor(const sf::Color& c){ m_color = {c.r, c.g, c.b, m_color.a}; resetColor(); } - + sf::Color LightSource::getColor() const{ const sf::Color &c = m_color; return {c.r, c.g, c.b, 255}; } - + void LightSource::setFade(bool fade){ m_fade = fade; resetColor(); } - + bool LightSource::getFade() const{ return m_fade; } - + void LightSource::setRange(float r){ m_range = r; } - + float LightSource::getRange() const{ return m_range; } - + } diff --git a/src/RadialLight.cpp b/src/RadialLight.cpp index c50bd3c..3b44d07 100644 --- a/src/RadialLight.cpp +++ b/src/RadialLight.cpp @@ -1,7 +1,8 @@ #ifdef CANDLE_DEBUG #include #endif - + +#include #include #include "Candle/RadialLight.hpp" @@ -14,9 +15,10 @@ namespace candle{ int RadialLight::s_instanceCount = 0; const unsigned int BASE_RADIUS = 400; - bool l_texturesReady(false); - std::shared_ptr l_lightTextureFade; - std::shared_ptr l_lightTexturePlain; + bool l_texturesReady(false); + std::map, std::unique_ptr >> l_lightTexturesCache; + std::unique_ptr l_lightTextureFade; + std::unique_ptr l_lightTexturePlain; void initializeTextures(){ #ifdef CANDLE_DEBUG @@ -32,20 +34,16 @@ namespace candle{ sf::Vector2f center = {BASE_RADIUS, BASE_RADIUS}; - for (unsigned int y=1; y(255.0f*distanceFromCenter))); lightImagePlain.setPixel(x,y, sf::Color(255,255,255,255)); } @@ -76,8 +74,7 @@ namespace candle{ l_texturesReady = true; } - setLightFadeTexture( *l_lightTextureFade.get() ); - setLightPlainTexture( *l_lightTexturePlain.get() ); + setTexture(nullptr); setRange(1.0f); setBeamAngle(360.f); @@ -131,9 +128,57 @@ namespace candle{ return m_beamAngle; } - void RadialLight::setLightFadeTexture(sf::Texture& texture){ - m_lightTextureFade = &texture; - m_localRadius = (texture.getSize().x > texture.getSize().y) ? texture.getSize().x/2+1 : texture.getSize().y/2+1; + void RadialLight::setTexture(sf::Texture* texture){ + if (texture != nullptr){ + //Custom texture + m_lightTexturePlain = texture; + auto cachedTextureIter = l_lightTexturesCache.find(texture); + + if (cachedTextureIter != l_lightTexturesCache.end()){ + m_lightTexturePlain = cachedTextureIter->second.first.get(); + m_lightTextureFade = cachedTextureIter->second.second.get(); + }else{ + sf::Image userTexture = texture->copyToImage(); + + //Put 1px transparent border to avoid bad clamp + sf::Image plainImage; + sf::Image fadeImage; + fadeImage.create(userTexture.getSize().x+2, userTexture.getSize().y+2, sf::Color(255,255,255,0)); + plainImage.create(userTexture.getSize().x+2, userTexture.getSize().y+2, sf::Color(255,255,255,0)); + + sf::Vector2f center = static_cast(userTexture.getSize())/2.0f; + + for (unsigned int y=0; yloadFromImage(plainImage); + fadeTexture->loadFromImage(fadeImage); + + l_lightTexturesCache[texture] = std::make_pair(std::unique_ptr(plainTexture), std::unique_ptr(fadeTexture)); + + m_lightTexturePlain = plainTexture; + m_lightTextureFade = fadeTexture; + } + }else{ + //Default texture + m_lightTexturePlain = l_lightTexturePlain.get(); + m_lightTextureFade = l_lightTextureFade.get(); + } + + m_localRadius = (m_lightTexturePlain->getSize().x > m_lightTexturePlain->getSize().y) ? m_lightTexturePlain->getSize().x/2+1 : m_lightTexturePlain->getSize().y/2+1; m_polygon.setPrimitiveType(sf::TriangleFan); m_polygon.resize(6); @@ -156,39 +201,10 @@ namespace candle{ return m_lightTextureFade; } - void RadialLight::setLightPlainTexture(sf::Texture& texture){ - m_lightTexturePlain = &texture; - m_localRadius = (texture.getSize().x > texture.getSize().y) ? texture.getSize().x/2 : texture.getSize().y/2; - - m_polygon.setPrimitiveType(sf::TriangleFan); - m_polygon.resize(6); - m_polygon[0].position = - m_polygon[0].texCoords = {static_cast(m_localRadius), static_cast(m_localRadius)}; - m_polygon[1].position = - m_polygon[5].position = - m_polygon[1].texCoords = - m_polygon[5].texCoords = {0.f, 0.f}; - m_polygon[2].position = - m_polygon[2].texCoords = {static_cast(m_localRadius)*2, 0.f}; - m_polygon[3].position = - m_polygon[3].texCoords = {static_cast(m_localRadius)*2, static_cast(m_localRadius)*2}; - m_polygon[4].position = - m_polygon[4].texCoords = {0.f, static_cast(m_localRadius)*2}; - Transformable::setOrigin(m_localRadius, m_localRadius); - } - sf::Texture* RadialLight::getLightPlainTexture(){ return m_lightTexturePlain; } - std::shared_ptr RadialLight::getDefaultLightFadeTexture() const{ - return l_lightTextureFade; - } - - std::shared_ptr RadialLight::getDefaultLightPlainTexture() const{ - return l_lightTexturePlain; - } - sf::FloatRect RadialLight::getLocalBounds() const{ return sf::FloatRect(0.0f, 0.0f, m_localRadius*2, m_localRadius*2); } From 121e2f8829e13f26ab1eaa444f33cced6dee176b Mon Sep 17 00:00:00 2001 From: GuillaumeG <48102745+JonathSpirit@users.noreply.github.com> Date: Thu, 25 Nov 2021 09:38:19 +0100 Subject: [PATCH 3/5] Add a cleanupTexture, setSmooth(true) on created textures --- include/Candle/LightSource.hpp | 7 ++++++- src/RadialLight.cpp | 16 ++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/include/Candle/LightSource.hpp b/include/Candle/LightSource.hpp index 22a336c..b202dd8 100644 --- a/include/Candle/LightSource.hpp +++ b/include/Candle/LightSource.hpp @@ -35,7 +35,12 @@ namespace candle{ * some reason, is global or static RadialLight and is not constructed in * a normal order. */ - void initializeTextures(); + void initializeTextures(); + + /** + * @brief This function cleanup texture created by RadialLights. + */ + void cleanupTexture(sf::Texture* texture); /** * @brief Interface for objects that emit light diff --git a/src/RadialLight.cpp b/src/RadialLight.cpp index 3b44d07..2f6244a 100644 --- a/src/RadialLight.cpp +++ b/src/RadialLight.cpp @@ -57,6 +57,20 @@ namespace candle{ l_lightTexturePlain.reset( new sf::Texture() ); l_lightTexturePlain->loadFromImage(lightImagePlain); l_lightTexturePlain->setSmooth(true); + } + + void cleanupTexture(sf::Texture* texture){ + if (texture != nullptr){ + //Custom texture + auto cachedTextureIter = l_lightTexturesCache.find(texture); + + if (cachedTextureIter != l_lightTexturesCache.end()){ + l_lightTexturesCache.erase(cachedTextureIter); + } + }else{ + //Every texture + l_lightTexturesCache.clear(); + } } float module360(float x){ @@ -166,6 +180,8 @@ namespace candle{ sf::Texture* fadeTexture = new sf::Texture(); plainTexture->loadFromImage(plainImage); fadeTexture->loadFromImage(fadeImage); + plainTexture->setSmooth(true); + fadeTexture->setSmooth(true); l_lightTexturesCache[texture] = std::make_pair(std::unique_ptr(plainTexture), std::unique_ptr(fadeTexture)); From c1c4f2f1c342ce86ef2e75dcf5b34e588870dfe8 Mon Sep 17 00:00:00 2001 From: GuillaumeG <48102745+JonathSpirit@users.noreply.github.com> Date: Thu, 25 Nov 2021 10:02:15 +0100 Subject: [PATCH 4/5] Fix non-applied fade effect and add repeated texture --- src/RadialLight.cpp | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/RadialLight.cpp b/src/RadialLight.cpp index 2f6244a..23a9d33 100644 --- a/src/RadialLight.cpp +++ b/src/RadialLight.cpp @@ -154,25 +154,33 @@ namespace candle{ }else{ sf::Image userTexture = texture->copyToImage(); + unsigned int diameter = ((userTexture.getSize().x > userTexture.getSize().y) ? userTexture.getSize().x : userTexture.getSize().y) + 2; + //Put 1px transparent border to avoid bad clamp sf::Image plainImage; sf::Image fadeImage; - fadeImage.create(userTexture.getSize().x+2, userTexture.getSize().y+2, sf::Color(255,255,255,0)); - plainImage.create(userTexture.getSize().x+2, userTexture.getSize().y+2, sf::Color(255,255,255,0)); + fadeImage.create(diameter, diameter, sf::Color(255,255,255,0)); + plainImage.create(diameter, diameter, sf::Color(255,255,255,0)); - sf::Vector2f center = static_cast(userTexture.getSize())/2.0f; + sf::Vector2f center = sf::Vector2f(diameter/2.0f, diameter/2.0f); - for (unsigned int y=0; y(255.0f*distanceFromCenter); + fadeImage.setPixel(x+1,y+1, pixel); + } } } @@ -194,7 +202,7 @@ namespace candle{ m_lightTextureFade = l_lightTextureFade.get(); } - m_localRadius = (m_lightTexturePlain->getSize().x > m_lightTexturePlain->getSize().y) ? m_lightTexturePlain->getSize().x/2+1 : m_lightTexturePlain->getSize().y/2+1; + m_localRadius = m_lightTexturePlain->getSize().x/2+1; m_polygon.setPrimitiveType(sf::TriangleFan); m_polygon.resize(6); From fb556c3a0788afc9e089bc5da3753f40655071a9 Mon Sep 17 00:00:00 2001 From: GuillaumeG <48102745+JonathSpirit@users.noreply.github.com> Date: Thu, 25 Nov 2021 10:12:23 +0100 Subject: [PATCH 5/5] fix silent outOfBound crash --- src/RadialLight.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/RadialLight.cpp b/src/RadialLight.cpp index 23a9d33..e587cf3 100644 --- a/src/RadialLight.cpp +++ b/src/RadialLight.cpp @@ -164,9 +164,9 @@ namespace candle{ sf::Vector2f center = sf::Vector2f(diameter/2.0f, diameter/2.0f); - for (unsigned int y=0; y