dmuratshin 8 years ago
parent
commit
3adb427402

+ 1 - 0
examples/HelloWorld/src/example.h

@@ -2,3 +2,4 @@ void example_preinit();
 void example_init();
 void example_init();
 void example_destroy();
 void example_destroy();
 void example_update();
 void example_update();
+void example_flush();

+ 2 - 1
examples/HelloWorld/src/main.cpp

@@ -35,6 +35,7 @@ int mainloop()
         // Render all actors inside the stage. Actor::render will also be called for all its children
         // Render all actors inside the stage. Actor::render will also be called for all its children
         getStage()->render(clearColor, viewport);
         getStage()->render(clearColor, viewport);
 
 
+        example_flush();
         core::swapDisplayBuffers();
         core::swapDisplayBuffers();
     }
     }
 
 
@@ -68,7 +69,7 @@ void run()
     getStage()->setSize(size);
     getStage()->setSize(size);
 
 
     // DebugActor is a helper actor node. It shows FPS, memory usage and other useful stuff
     // DebugActor is a helper actor node. It shows FPS, memory usage and other useful stuff
-    DebugActor::show();
+    //DebugActor::show();
 
 
     // Initializes our example game. See example.cpp
     // Initializes our example game. See example.cpp
     example_init();
     example_init();

+ 2 - 0
oxygine/SDL/win32/oxygine.vcxproj

@@ -165,6 +165,7 @@
     <ClCompile Include="..\..\src\oxygine\MaskedSprite.cpp" />
     <ClCompile Include="..\..\src\oxygine\MaskedSprite.cpp" />
     <ClCompile Include="..\..\src\oxygine\Material.cpp" />
     <ClCompile Include="..\..\src\oxygine\Material.cpp" />
     <ClCompile Include="..\..\src\oxygine\Image.cpp" />
     <ClCompile Include="..\..\src\oxygine\Image.cpp" />
+    <ClCompile Include="..\..\src\oxygine\MaterialX.cpp" />
     <ClCompile Include="..\..\src\oxygine\minizip\ioapi.c" />
     <ClCompile Include="..\..\src\oxygine\minizip\ioapi.c" />
     <ClCompile Include="..\..\src\oxygine\minizip\ioapi_mem.c" />
     <ClCompile Include="..\..\src\oxygine\minizip\ioapi_mem.c" />
     <ClCompile Include="..\..\src\oxygine\minizip\unzip.c" />
     <ClCompile Include="..\..\src\oxygine\minizip\unzip.c" />
@@ -277,6 +278,7 @@
     <ClInclude Include="..\..\src\oxygine\MaskedRenderer.h" />
     <ClInclude Include="..\..\src\oxygine\MaskedRenderer.h" />
     <ClInclude Include="..\..\src\oxygine\MaskedSprite.h" />
     <ClInclude Include="..\..\src\oxygine\MaskedSprite.h" />
     <ClInclude Include="..\..\src\oxygine\Material.h" />
     <ClInclude Include="..\..\src\oxygine\Material.h" />
+    <ClInclude Include="..\..\src\oxygine\MaterialX.h" />
     <ClInclude Include="..\..\src\oxygine\math\OBBox.h" />
     <ClInclude Include="..\..\src\oxygine\math\OBBox.h" />
     <ClInclude Include="..\..\src\oxygine\Image.h" />
     <ClInclude Include="..\..\src\oxygine\Image.h" />
     <ClInclude Include="..\..\src\oxygine\minizip\ioapi.h" />
     <ClInclude Include="..\..\src\oxygine\minizip\ioapi.h" />

+ 6 - 0
oxygine/SDL/win32/oxygine.vcxproj.filters

@@ -348,6 +348,9 @@
     <ClCompile Include="..\..\src\oxygine\utils\AtlasBuilder.cpp">
     <ClCompile Include="..\..\src\oxygine\utils\AtlasBuilder.cpp">
       <Filter>src\utils</Filter>
       <Filter>src\utils</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="..\..\src\oxygine\MaterialX.cpp">
+      <Filter>src</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\src\oxygine\closure\closure.h">
     <ClInclude Include="..\..\src\oxygine\closure\closure.h">
@@ -749,6 +752,9 @@
     <ClInclude Include="..\..\src\oxygine\utils\AtlasBuilder.h">
     <ClInclude Include="..\..\src\oxygine\utils\AtlasBuilder.h">
       <Filter>src\utils</Filter>
       <Filter>src\utils</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="..\..\src\oxygine\MaterialX.h">
+      <Filter>src</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <None Include="ReadMe.txt" />
     <None Include="ReadMe.txt" />

+ 1 - 0
oxygine/src/oxygine-framework.h

@@ -47,6 +47,7 @@
 #include "oxygine/TweenOutline.h"
 #include "oxygine/TweenOutline.h"
 #include "oxygine/TweenGlow.h"
 #include "oxygine/TweenGlow.h"
 #include "oxygine/TweenAlphaFade.h"
 #include "oxygine/TweenAlphaFade.h"
+#include "oxygine/MaterialX.h"
 
 
 
 
 //closure/
 //closure/

+ 4 - 0
oxygine/src/oxygine/ColorRectSprite.cpp

@@ -13,6 +13,10 @@ namespace oxygine
 
 
     ColorRectSprite::ColorRectSprite()
     ColorRectSprite::ColorRectSprite()
     {
     {
+        STDMatData data;
+        data._base = STDRenderer::white;
+
+        _mat = mc().add(data);
     }
     }
 
 
     ColorRectSprite::~ColorRectSprite()
     ColorRectSprite::~ColorRectSprite()

+ 44 - 0
oxygine/src/oxygine/MaterialX.cpp

@@ -0,0 +1,44 @@
+#include "MaterialX.h"
+#include "STDRenderer.h"
+#include "core/UberShaderProgram.h"
+#include "STDRenderer.h"
+
+namespace oxygine
+{
+    spMaterialX currentMat;
+
+    bool STDMatData::operator==(const STDMatData& b) const
+    {
+        if (_base != b._base)
+            return false;
+        if (_alpha != b._alpha)
+            return false;
+        if (_blend != b._blend)
+            return false;
+        if (_flags != b._flags)
+            return false;
+        return true;
+    }
+
+    STDMatData::STDMatData() : _blend(blend_alpha), _flags(0)
+    {
+
+    }
+
+    void STDMatData::init(size_t& hash)
+    {
+        hash_combine(hash, _base.get());
+        hash_combine(hash, _alpha.get());
+        hash_combine(hash, _blend);
+        hash_combine(hash, _flags);
+    }
+
+    void STDMatData::apply()
+    {
+        STDRenderer::getCurrent()->setShaderFlags(_flags);
+        STDRenderer::getCurrent()->setTextureNew(UberShaderProgram::SAMPLER_BASE, _base);
+        STDRenderer::getCurrent()->setTextureNew(UberShaderProgram::SAMPLER_ALPHA, _alpha);
+        STDRenderer::getCurrent()->setBlendMode(_blend);
+    }
+
+}

+ 146 - 0
oxygine/src/oxygine/MaterialX.h

@@ -0,0 +1,146 @@
+#pragma once
+#include "core/ref_counter.h"
+#include "core/Renderer.h"
+
+namespace oxygine
+{
+
+    class MaterialX : public ref_counter
+    {
+    public:
+
+        typedef bool(*compare)(const MaterialX* a, const MaterialX* b);
+
+        MaterialX() {}
+        MaterialX(compare cmp) : _hash(0), _compare(cmp) {}
+        MaterialX(const MaterialX& other)
+        {
+            _hash = other._hash;
+            _compare = other._compare;
+        }
+
+        size_t _hash;
+        compare _compare;
+
+        virtual void apply() = 0;
+
+        virtual MaterialX* clone() const = 0;
+    };
+
+    typedef intrusive_ptr<MaterialX> spMaterialX;
+
+
+
+    template<class T>
+    class MaterialTX : public MaterialX
+    {
+    public:
+
+        typedef bool(*fcmp)(const MaterialTX<T>& a, const MaterialTX<T>& b);
+
+        T _data;
+
+        MaterialTX(const T& data) : _data(data)
+        {
+            _data.init(_hash);
+
+            fcmp fn = &MaterialTX<T>::cmp;
+            _compare = (compare)(fn);
+
+            hash_combine(_hash, _compare);
+        }
+
+        template<class T>
+        static bool cmp(const MaterialTX<T>& a, const MaterialTX<T>& b)
+        {
+            return a._data == b._data;
+        }
+
+        void apply() override
+        {
+            _data.apply();
+        }
+
+        MaterialTX<T>* clone() const override
+        {
+            MaterialTX<T>* copy = new MaterialTX<T>(*this);
+            return copy;
+        }
+    };
+
+
+
+    inline void hash_combine(std::size_t& seed) { }
+
+    template <typename T, typename... Rest>
+    inline void hash_combine(std::size_t& seed, const T& v, Rest... rest)
+    {
+        std::hash<T> hasher;
+        seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+        hash_combine(seed, rest...);
+    }
+
+    class STDMatData
+    {
+    public:
+        STDMatData();
+
+        spNativeTexture _base;
+        spNativeTexture _alpha;
+        blend_mode      _blend;
+        int             _flags;
+
+        void init(size_t& hash);
+
+        void apply();
+
+        bool operator == (const STDMatData& b) const;
+    };
+
+    typedef intrusive_ptr< MaterialTX<STDMatData> > spSTDMaterialX;
+
+    class MaterialCache
+    {
+    public:
+
+        typedef std::vector<spMaterialX> materials;
+        materials _materials;
+
+        template<class T>
+        intrusive_ptr< MaterialTX<T> > add(const T& other)
+        {
+            MaterialTX<T> mat(other);
+            return add2(mat);
+        }
+
+        template<class T>
+        intrusive_ptr<T> add2(const T& other)
+        {
+            for (auto m : _materials)
+            {
+                if (m->_compare != other._compare)
+                    continue;
+                if (m->_hash != other._hash)
+                    continue;
+                bool same = m->_compare(m.get(), &other);
+                if (same)
+                    return (T*)m.get();
+            }
+
+            T* copy = other.clone();
+            _materials.push_back(copy);
+
+            return copy;
+        }
+    };
+
+    inline MaterialCache& mc()
+    {
+        static MaterialCache cache;
+        return cache;
+    }
+
+
+    extern spMaterialX currentMat;
+
+}

+ 9 - 35
oxygine/src/oxygine/STDMaterial.cpp

@@ -136,30 +136,11 @@ namespace oxygine
 
 
     void STDMaterial::doRender(Sprite* sprite, const RenderState& rs)
     void STDMaterial::doRender(Sprite* sprite, const RenderState& rs)
     {
     {
-        Material::setCurrent(rs.material);
+        Color color = rs.getFinalColor(sprite->getColor());
+        if (sprite->getBlendMode() == blend_premultiplied_alpha)
+            color = color.premultiplied();
 
 
-        const AnimationFrame& frame = sprite->getAnimFrame();
-        const Diffuse& df = frame.getDiffuse();
-
-        const spNativeTexture& base = df.base;
-
-
-#ifdef EMSCRIPTEN
-        STDRenderer::getCurrent()->setTexture(df.base, df.alpha, df.premultiplied);//preload
-        if (base && base->getHandle())
-#else
-        if (base)
-#endif
-        {
-            STDRenderer* r = STDRenderer::getCurrent();
-            r->setBlendMode(sprite->getBlendMode());
-#ifndef EMSCRIPTEN
-            r->setTexture(df.base, df.alpha, df.premultiplied);//preload
-#endif
-
-            r->setTransform(rs.transform);
-            r->draw(rs.getFinalColor(sprite->getColor()), frame.getSrcRect(), sprite->getDestRect());
-        }
+        STDRenderer::getCurrent()->draw(sprite->_mat, rs.transform, color.rgba(), sprite->getAnimFrame().getSrcRect(), sprite->getDestRect());
     }
     }
 
 
     void STDMaterial::doRender(TextField* tf, const RenderState& rs)
     void STDMaterial::doRender(TextField* tf, const RenderState& rs)
@@ -170,9 +151,6 @@ namespace oxygine
         if (!root)
         if (!root)
             return;
             return;
 
 
-        Material::setCurrent(this);
-
-
 
 
         text::DrawContext dc;
         text::DrawContext dc;
 
 
@@ -182,13 +160,12 @@ namespace oxygine
         dc.color = tf->getStyle().color * dc.primary;
         dc.color = tf->getStyle().color * dc.primary;
         dc.renderer = renderer;
         dc.renderer = renderer;
 
 
-        renderer->setBlendMode(tf->getBlendMode());
+        //renderer->setBlendMode(tf->getBlendMode());
         renderer->setTransform(rs.transform);
         renderer->setTransform(rs.transform);
 
 
         int sdfSize;
         int sdfSize;
         if (tf->getFont()->isSDF(sdfSize))
         if (tf->getFont()->isSDF(sdfSize))
         {
         {
-
             if (tf->getFontSize())
             if (tf->getFontSize())
                 scale = scale * tf->getFontSize() / sdfSize;
                 scale = scale * tf->getFontSize() / sdfSize;
 
 
@@ -209,14 +186,11 @@ namespace oxygine
 
 
     void STDMaterial::doRender(ColorRectSprite* sprite, const RenderState& rs)
     void STDMaterial::doRender(ColorRectSprite* sprite, const RenderState& rs)
     {
     {
-        Material::setCurrent(this);
+        Color color = rs.getFinalColor(sprite->getColor());
+        if (sprite->getBlendMode() == blend_premultiplied_alpha)
+            color = color.premultiplied();
 
 
-        STDRenderer* renderer = STDRenderer::getCurrent();
-
-        renderer->setBlendMode(sprite->getBlendMode());
-        renderer->setTexture(STDRenderer::white);
-        renderer->setTransform(rs.transform);
-        renderer->draw(rs.getFinalColor(sprite->getColor()), RectF(0, 0, 1, 1), sprite->getDestRect());
+        STDRenderer::getCurrent()->draw(sprite->_mat, rs.transform, color.rgba(), sprite->getAnimFrame().getSrcRect(), sprite->getDestRect());
     }
     }
 
 
     void STDMaterial::doRender(ProgressBar*, const RenderState& rs)
     void STDMaterial::doRender(ProgressBar*, const RenderState& rs)

+ 127 - 0
oxygine/src/oxygine/STDRenderer.cpp

@@ -284,6 +284,8 @@ namespace oxygine
         _program = 0;
         _program = 0;
         _vertices.clear();
         _vertices.clear();
         _transform.identity();
         _transform.identity();
+        for (int i = 0; i < MAX_TEXTURES; ++i)
+            _textures[i] = 0;
         resetSettings();
         resetSettings();
 
 
         xbegin();
         xbegin();
@@ -301,6 +303,8 @@ namespace oxygine
         OX_ASSERT(_drawing);
         OX_ASSERT(_drawing);
         drawBatch();
         drawBatch();
 
 
+        flush();
+
         if (_prevRT)
         if (_prevRT)
         {
         {
             _driver->setRenderTarget(_prevRT);
             _driver->setRenderTarget(_prevRT);
@@ -412,6 +416,7 @@ namespace oxygine
         _uberShader = &uberShader;
         _uberShader = &uberShader;
         _transform.identity();
         _transform.identity();
         _drawing = false;
         _drawing = false;
+        _baseShaderFlags = 0;
     }
     }
 
 
     void STDRenderer::setBlendMode(blend_mode blend)
     void STDRenderer::setBlendMode(blend_mode blend)
@@ -576,6 +581,128 @@ namespace oxygine
         addVertices(v, sizeof(v));
         addVertices(v, sizeof(v));
     }
     }
 
 
+    void STDRenderer::draw(const spMaterialX& mat, unsigned int color, const RectF& srcRect, const RectF& destRect)
+    {
+        vertexPCT2 v[4];
+        fillQuadT(v, srcRect, destRect, _transform, color);
+        add(mat, v);
+    }
+
+    void STDRenderer::draw(const spMaterialX& mat, const AffineTransform& tr, unsigned int color, const RectF& srcRect, const RectF& destRect)
+    {
+        vertexPCT2 v[4];
+        fillQuadT(v, srcRect, destRect, tr, color);
+        add(mat, v);
+    }
+
+
+    void STDRenderer::setTextureNew(int sampler, spNativeTexture t)
+    {
+        if (_textures[sampler] == t)
+            return;
+        _textures[sampler] = t;
+        _driver->setTexture(sampler, t);
+    }
+
+    void STDRenderer::setShaderFlags(int flags)
+    {
+        ShaderProgram* sp = STDRenderer::uberShader.getShaderProgram(_baseShaderFlags | flags);
+        if (_program != sp)
+        {
+            _driver->setShaderProgram(sp);
+            _program = sp;
+        }
+
+        _driver->setUniform("mat", STDRenderer::getCurrent()->getViewProjection());
+    }
+
+    void STDRenderer::add(spMaterialX mat, vertexPCT2 vert[4])
+    {
+        batch& b = add(mat);
+
+        b.vertices.insert(b.vertices.end(), vert, vert + 4);
+        for (int i = 0; i < 4; ++i)
+        {
+            b.bbox.unite(Vector2(vert[i].x, vert[i].y));
+        }
+    }
+
+    STDRenderer::batch& STDRenderer::add(spMaterialX mat)
+    {
+        if (_batches.empty() || _batches.back().mat != mat)
+        {
+            batch b;
+            b.mat = mat;
+            b.bbox = RectF::invalidated();
+            _batches.push_back(b);
+            return _batches.back();
+        }
+        return _batches.back();
+    }
+
+    void STDRenderer::process()
+    {
+        for (int i = 0; i < (int)_batches.size() - 1; ++i)
+            process(i);
+    }
+
+    void STDRenderer::process(int j)
+    {
+        batch& my = _batches[j];
+        for (int i = j + 1; i < (int)_batches.size(); ++i)
+        {
+            batch& c = _batches[i];
+            if (c.mat == my.mat)
+            {
+                bool fail = false;
+                for (int n = i - 1; n > j; --n)
+                {
+                    batch& c2 = _batches[n];
+                    if (c2.bbox.isIntersecting(c.bbox))
+                    {
+                        fail = true;
+                        break;
+                    }
+                }
+
+                if (!fail)
+                {
+                    my.vertices.insert(my.vertices.end(), c.vertices.begin(), c.vertices.end());
+                    _batches.erase(_batches.begin() + i);
+
+                    //continue search
+                    --i;
+                }
+            }
+        }
+    }
+
+    void STDRenderer::flush()
+    {
+        process();
+
+        size_t num = _batches.size();
+        for (size_t i = 0; i < num; ++i)
+        {
+            batch& c = _batches[i];
+
+            size_t indices = (c.vertices.size() * 3) / 2;
+            if (!indices)
+                continue;
+
+            c.mat->apply();
+
+            IVideoDriver::instance->draw(IVideoDriver::PT_TRIANGLES, STDRenderer::getCurrent()->getVertexDeclaration(),
+                                         &c.vertices.front(), (unsigned int)c.vertices.size(),
+                                         &STDRenderer::indices16.front(), (unsigned int)indices);
+
+        }
+
+        log::messageln("batches %d", _batches.size());
+        _batches.clear();
+    }
+
+
     void STDRenderer::setUberShaderProgram(UberShaderProgram* pr)
     void STDRenderer::setUberShaderProgram(UberShaderProgram* pr)
     {
     {
         if (_uberShader == pr)
         if (_uberShader == pr)

+ 25 - 0
oxygine/src/oxygine/STDRenderer.h

@@ -43,6 +43,7 @@ namespace oxygine
         unsigned int    getShaderFlags() const;
         unsigned int    getShaderFlags() const;
         const VertexDeclaration* getVertexDeclaration() const { return _vdecl; }
         const VertexDeclaration* getVertexDeclaration() const { return _vdecl; }
 
 
+        void setShaderFlags(int);
         void setViewProj(const Matrix& viewProj);
         void setViewProj(const Matrix& viewProj);
         void setVertexDeclaration(const VertexDeclaration* decl);
         void setVertexDeclaration(const VertexDeclaration* decl);
         void setUberShaderProgram(UberShaderProgram* pr);
         void setUberShaderProgram(UberShaderProgram* pr);
@@ -54,6 +55,7 @@ namespace oxygine
         /**Sets World transformation.*/
         /**Sets World transformation.*/
         void setTransform(const Transform& world);
         void setTransform(const Transform& world);
         void draw(const Color&, const RectF& srcRect, const RectF& destRect);
         void draw(const Color&, const RectF& srcRect, const RectF& destRect);
+        void setTextureNew(int sampler, spNativeTexture t);
 
 
         /**Draws existing batch immediately.*/
         /**Draws existing batch immediately.*/
         void drawBatch();
         void drawBatch();
@@ -65,6 +67,9 @@ namespace oxygine
         void applySimpleMode(bool basePremultiplied);
         void applySimpleMode(bool basePremultiplied);
         /**used in pair with applySimpleMode/applySDF, fast, don't have excess checks*/
         /**used in pair with applySimpleMode/applySDF, fast, don't have excess checks*/
         void draw(const spNativeTexture& texture, unsigned int color, const RectF& src, const RectF& dest) override;
         void draw(const spNativeTexture& texture, unsigned int color, const RectF& src, const RectF& dest) override;
+        void draw(const spMaterialX& mat, unsigned int color, const RectF& src, const RectF& dest) override;
+        void draw(const spMaterialX& mat, const AffineTransform& transform, unsigned int color, const RectF& src, const RectF& dest);
+        void add(spMaterialX mat, vertexPCT2 vert[4]);
 
 
         /**Begins rendering into RenderTexture or into primary framebuffer if rt is null*/
         /**Begins rendering into RenderTexture or into primary framebuffer if rt is null*/
         void begin();
         void begin();
@@ -74,6 +79,9 @@ namespace oxygine
         /**initializes View + Projection matrices where TopLeft is (0,0) and RightBottom is (width, height). use flipU = true for render to texture*/
         /**initializes View + Projection matrices where TopLeft is (0,0) and RightBottom is (width, height). use flipU = true for render to texture*/
         void initCoordinateSystem(int width, int height, bool flipU = false);
         void initCoordinateSystem(int width, int height, bool flipU = false);
         void resetSettings();
         void resetSettings();
+        void process();
+        void process(int);
+        void flush();
 
 
         virtual void addVertices(const void* data, unsigned int size);
         virtual void addVertices(const void* data, unsigned int size);
 
 
@@ -90,6 +98,23 @@ namespace oxygine
         void setViewProjTransform(const Matrix& viewProj);
         void setViewProjTransform(const Matrix& viewProj);
 
 
     protected:
     protected:
+
+        struct batch
+        {
+            spMaterialX mat;
+            std::vector<vertexPCT2> vertices;
+            RectF bbox;
+        };
+
+        typedef std::vector<batch> batches;
+        batches _batches;
+
+        enum { MAX_TEXTURES = 4 };
+        spNativeTexture _textures[MAX_TEXTURES];
+
+        batch& add(spMaterialX mat);
+
+        int _baseShaderFlags;
         Transform _transform;
         Transform _transform;
 
 
         STDRenderer* _previous;
         STDRenderer* _previous;

+ 9 - 0
oxygine/src/oxygine/Sprite.cpp

@@ -6,6 +6,7 @@
 #include "Stage.h"
 #include "Stage.h"
 #include "Serialize.h"
 #include "Serialize.h"
 #include "Material.h"
 #include "Material.h"
+#include "core/UberShaderProgram.h"
 
 
 namespace oxygine
 namespace oxygine
 {
 {
@@ -222,6 +223,14 @@ namespace oxygine
         _setSize(_frame.getSize().mult(_localScale));
         _setSize(_frame.getSize().mult(_localScale));
 
 
 
 
+
+        STDMatData data = _mat->_data;
+        data._base = _frame.getDiffuse().base;
+        data._alpha = _frame.getDiffuse().alpha;
+        data._flags = _frame.getDiffuse().premultiplied ? 0 : UberShaderProgram::ALPHA_PREMULTIPLY;
+
+        _mat = mc().add(data);
+
         animFrameChanged(_frame);
         animFrameChanged(_frame);
     }
     }
 
 

+ 1 - 1
oxygine/src/oxygine/TextField.cpp

@@ -328,7 +328,7 @@ namespace oxygine
                 _root = new text::TextNode(_text.c_str());
                 _root = new text::TextNode(_text.c_str());
             }
             }
 
 
-            text::Aligner rd(_style, font, scale, getSize());
+            text::Aligner rd(_style, _mat->_data , font, scale, getSize());
             rd.begin();
             rd.begin();
             _root->resize(rd);
             _root->resize(rd);
             rd.end();
             rd.end();

+ 16 - 0
oxygine/src/oxygine/VisualStyle.cpp

@@ -14,6 +14,10 @@ namespace oxygine
 
 
     VStyleActor::VStyleActor()
     VStyleActor::VStyleActor()
     {
     {
+        STDMatData data;
+        data._blend = blend_premultiplied_alpha;
+
+        _mat = mc().add(data);
     }
     }
 
 
     void VStyleActor::copyFrom(const VStyleActor& src, cloneOptions opt)
     void VStyleActor::copyFrom(const VStyleActor& src, cloneOptions opt)
@@ -83,4 +87,16 @@ namespace oxygine
         setColor(Color(r, g, b, a));
         setColor(Color(r, g, b, a));
     }
     }
 
 
+    void VStyleActor::setBlendMode(blend_mode mode)
+    {
+        _vstyle.setBlendMode(mode);
+
+        STDMatData data = _mat->_data;
+        data._blend = mode;
+
+        _mat = mc().add(data);
+
+        blendModeChanged(mode);
+    }
+
 }
 }

+ 6 - 2
oxygine/src/oxygine/VisualStyle.h

@@ -1,7 +1,7 @@
 #pragma once
 #pragma once
 #include "oxygine-include.h"
 #include "oxygine-include.h"
 #include "Actor.h"
 #include "Actor.h"
-
+#include "MaterialX.h"
 namespace oxygine
 namespace oxygine
 {
 {
     class VisualStyle
     class VisualStyle
@@ -41,15 +41,19 @@ namespace oxygine
 
 
         void                    setColor(const Color& color);
         void                    setColor(const Color& color);
         void                    setColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
         void                    setColor(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
-        void                    setBlendMode(blend_mode mode) { _vstyle.setBlendMode(mode); blendModeChanged(mode); }
+        void                    setBlendMode(blend_mode mode);
 
 
         typedef Property<Color, const Color&, VStyleActor, &VStyleActor::getColor, &VStyleActor::setColor> TweenColor;
         typedef Property<Color, const Color&, VStyleActor, &VStyleActor::getColor, &VStyleActor::setColor> TweenColor;
 
 
         bool getBounds(RectF& b) const  override { b = getDestRect();  return true; }
         bool getBounds(RectF& b) const  override { b = getDestRect();  return true; }
 
 
+        spSTDMaterialX _mat;
+
     protected:
     protected:
         virtual void blendModeChanged(blend_mode) {}
         virtual void blendModeChanged(blend_mode) {}
         VisualStyle _vstyle;
         VisualStyle _vstyle;
+
+
     };
     };
 
 
 }
 }

+ 4 - 0
oxygine/src/oxygine/core/Renderer.h

@@ -214,11 +214,15 @@ namespace oxygine
         ++pv;
         ++pv;
     }
     }
 
 
+    class MaterialX;
+    typedef intrusive_ptr<MaterialX> spMaterialX;
+
     class IElementRenderer
     class IElementRenderer
     {
     {
     public:
     public:
         virtual ~IElementRenderer() {}
         virtual ~IElementRenderer() {}
         virtual void draw(const spNativeTexture& texture, unsigned int color, const RectF& src, const RectF& dest) = 0;
         virtual void draw(const spNativeTexture& texture, unsigned int color, const RectF& src, const RectF& dest) = 0;
+        virtual void draw(const spMaterialX& mat, unsigned int color, const RectF& src, const RectF& dest) = 0;
     };
     };
 
 
     /**Returns View matrix where Left Top corner is (0,0), and right bottom is (w,h)*/
     /**Returns View matrix where Left Top corner is (0,0), and right bottom is (w,h)*/

+ 1 - 1
oxygine/src/oxygine/text_utils/Aligner.cpp

@@ -8,7 +8,7 @@ namespace oxygine
     {
     {
 #define GSCALE 1
 #define GSCALE 1
 
 
-        Aligner::Aligner(const TextStyle& Style, const Font* font, float gscale, const Vector2& size): width((int)size.x), height((int)size.y), _x(0), _y(0), _lineWidth(0), bounds(0, 0, 0, 0), style(Style), _scale(gscale), _font(font)
+        Aligner::Aligner(const TextStyle& Style, const STDMatData& md, const Font* font, float gscale, const Vector2& size): width((int)size.x), height((int)size.y), _x(0), _y(0), _lineWidth(0), bounds(0, 0, 0, 0), style(Style), _scale(gscale), _font(font), data(md)
         {
         {
             //log::messageln("gscale %f, adjScale %f globscale %f, %d %f", gscale, _globalScale, _fontSize, fs);
             //log::messageln("gscale %f, adjScale %f globscale %f, %d %f", gscale, _globalScale, _fontSize, fs);
             _line.reserve(50);
             _line.reserve(50);

+ 5 - 1
oxygine/src/oxygine/text_utils/Aligner.h

@@ -6,12 +6,14 @@
 #include "../TextStyle.h"
 #include "../TextStyle.h"
 #include "../Font.h"
 #include "../Font.h"
 #include "../core/NativeTexture.h"
 #include "../core/NativeTexture.h"
+#include "../MaterialX.h"
 
 
 namespace oxygine
 namespace oxygine
 {
 {
     struct glyph;
     struct glyph;
     class Font;
     class Font;
 
 
+
     namespace text
     namespace text
     {
     {
         struct Symbol
         struct Symbol
@@ -22,12 +24,13 @@ namespace oxygine
             int code;
             int code;
             glyph gl;
             glyph gl;
             RectF destRect;
             RectF destRect;
+            spMaterialX materialX;
         };
         };
 
 
         class Aligner
         class Aligner
         {
         {
         public:
         public:
-            Aligner(const TextStyle& style, const Font* font, float gscale, const Vector2& size);
+            Aligner(const TextStyle& style, const STDMatData& md, const Font* font, float gscale, const Vector2& size);
             ~Aligner();
             ~Aligner();
 
 
 
 
@@ -47,6 +50,7 @@ namespace oxygine
             int height;
             int height;
             int options;
             int options;
 
 
+            const STDMatData& data;
 
 
             const Font* _font;
             const Font* _font;
 
 

+ 8 - 2
oxygine/src/oxygine/text_utils/Node.cpp

@@ -153,9 +153,9 @@ namespace oxygine
             for (size_t i = 0; i < _data.size(); ++i)
             for (size_t i = 0; i < _data.size(); ++i)
             {
             {
                 const Symbol& s = _data[i];
                 const Symbol& s = _data[i];
-                if (!s.gl.texture)
+                if (!s.materialX)
                     continue;
                     continue;
-                dc.renderer->draw(s.gl.texture, dc.color.rgba(), s.gl.src, s.destRect);
+                dc.renderer->draw(s.materialX, dc.color.rgba(), s.gl.src, s.destRect);
             }
             }
 
 
             drawChildren(dc);
             drawChildren(dc);
@@ -198,6 +198,12 @@ namespace oxygine
                                 i += rd.putSymbol(s);
                                 i += rd.putSymbol(s);
                             }
                             }
                         }
                         }
+
+                        STDMatData data = rd.data;
+                        data._base = gl->texture;
+
+
+                        s.materialX = mc().add(data);
                     }
                     }
                     ++i;
                     ++i;
                     if (i < 0)
                     if (i < 0)