mirror of
https://github.com/Almamu/linux-wallpaperengine.git
synced 2025-09-14 05:46:48 +08:00
Implemented proper dependency detection for images
Simplified texture decision graph and preload it so render is quicker Improved material detecion on shaders Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
parent
9ff33ef61f
commit
7b7d699371
@ -113,16 +113,23 @@ CScene* CScene::fromFile (const std::string& filename, CContainer* container)
|
||||
return scene;
|
||||
}
|
||||
|
||||
const std::vector<CObject*>& CScene::getObjects () const
|
||||
const std::map<uint32_t, CObject*>& CScene::getObjects () const
|
||||
{
|
||||
return this->m_objects;
|
||||
}
|
||||
const std::vector<CObject*>& CScene::getObjectsByRenderOrder () const
|
||||
{
|
||||
return this->m_objectsByRenderOrder;
|
||||
}
|
||||
|
||||
void CScene::insertObject (CObject* object)
|
||||
{
|
||||
/// TODO: XXXHACK -- TO REMOVE WHEN PARTICLE SUPPORT IS PROPERLY IMPLEMENTED
|
||||
if (object != nullptr)
|
||||
this->m_objects.push_back (object);
|
||||
{
|
||||
this->m_objects.insert (std::make_pair (object->getId (), object));
|
||||
this->m_objectsByRenderOrder.emplace_back (object);
|
||||
}
|
||||
}
|
||||
|
||||
CContainer* CScene::getContainer ()
|
||||
|
@ -21,7 +21,8 @@ namespace WallpaperEngine::Core
|
||||
public:
|
||||
static CScene* fromFile (const std::string& filename, CContainer* container);
|
||||
|
||||
const std::vector<CObject*>& getObjects () const;
|
||||
const std::map<uint32_t, CObject*>& getObjects () const;
|
||||
const std::vector<CObject*>& getObjectsByRenderOrder () const;
|
||||
|
||||
const FloatColor& getAmbientColor() const;
|
||||
const bool isBloom() const;
|
||||
@ -95,6 +96,7 @@ namespace WallpaperEngine::Core
|
||||
Scenes::CProjection* m_orthogonalProjection;
|
||||
FloatColor m_skylightColor;
|
||||
|
||||
std::vector<CObject*> m_objects;
|
||||
std::map<uint32_t, CObject*> m_objects;
|
||||
std::vector<CObject*> m_objectsByRenderOrder;
|
||||
};
|
||||
};
|
||||
|
@ -91,14 +91,16 @@ CEffect* CEffect::fromJSON (json data, Core::CObject* object, CContainer* contai
|
||||
|
||||
if ((*texturesCur).is_null () == true)
|
||||
{
|
||||
if (object->is <CImage> () == false)
|
||||
if (textureNumber == 0)
|
||||
{
|
||||
throw std::runtime_error ("unexpected null texture for non-image object");
|
||||
CImage* image = object->as <CImage> ();
|
||||
|
||||
texture = (*(*image->getMaterial ()->getPasses ().begin ())->getTextures ().begin ());
|
||||
}
|
||||
else
|
||||
{
|
||||
texture = "";
|
||||
}
|
||||
|
||||
CImage* image = object->as <CImage> ();
|
||||
|
||||
texture = (*(*image->getMaterial ()->getPasses ().begin ())->getTextures ().begin ());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -24,4 +24,9 @@ CScene* CObject::getScene () const
|
||||
CContainer* CObject::getContainer () const
|
||||
{
|
||||
return this->getScene ()->getContainer ();
|
||||
}
|
||||
|
||||
const int CObject::getId () const
|
||||
{
|
||||
return this->m_object->getId ();
|
||||
}
|
@ -22,6 +22,7 @@ namespace WallpaperEngine::Render
|
||||
|
||||
CScene* getScene () const;
|
||||
CContainer* getContainer () const;
|
||||
const int getId () const;
|
||||
|
||||
protected:
|
||||
CObject (CScene* scene, std::string type, Core::CObject *object);
|
||||
|
@ -24,10 +24,10 @@ CScene::CScene (Core::CScene* scene, CContainer* container, CContext* context) :
|
||||
|
||||
for (; cur != end; cur ++)
|
||||
{
|
||||
if ((*cur)->is<Core::Objects::CImage> () == false)
|
||||
if ((*cur).second->is<Core::Objects::CImage> () == false)
|
||||
continue;
|
||||
|
||||
glm::vec2 size = (*cur)->as <Core::Objects::CImage> ()->getSize ();
|
||||
glm::vec2 size = (*cur).second->as <Core::Objects::CImage> ()->getSize ();
|
||||
|
||||
scene->getOrthogonalProjection ()->setWidth (size.x);
|
||||
scene->getOrthogonalProjection ()->setHeight (size.y);
|
||||
@ -42,42 +42,84 @@ CScene::CScene (Core::CScene* scene, CContainer* container, CContext* context) :
|
||||
// setup framebuffers
|
||||
this->setupFramebuffers ();
|
||||
|
||||
auto cur = scene->getObjects ().begin ();
|
||||
auto end = scene->getObjects ().end ();
|
||||
// create all objects based off their dependencies
|
||||
{
|
||||
|
||||
auto cur = scene->getObjects ().begin ();
|
||||
auto end = scene->getObjects ().end ();
|
||||
|
||||
for (; cur != end; cur++)
|
||||
this->createObject ((*cur).second);
|
||||
}
|
||||
|
||||
// now setup the render order
|
||||
auto cur = scene->getObjectsByRenderOrder ().begin ();
|
||||
auto end = scene->getObjectsByRenderOrder ().end ();
|
||||
|
||||
for (; cur != end; cur ++)
|
||||
{
|
||||
CObject* object = nullptr;
|
||||
auto obj = this->m_objects.find ((*cur)->getId ());
|
||||
|
||||
if ((*cur)->is<Core::Objects::CImage>() == true)
|
||||
{
|
||||
object = new Objects::CImage (this, (*cur)->as<Core::Objects::CImage>());
|
||||
}
|
||||
else if ((*cur)->is<Core::Objects::CSound>() == true)
|
||||
{
|
||||
object = new Objects::CSound (this, (*cur)->as<Core::Objects::CSound>());
|
||||
}
|
||||
// ignores not created objects like particle systems
|
||||
if (obj == this->m_objects.end ())
|
||||
continue;
|
||||
|
||||
if (object != nullptr)
|
||||
this->m_objects.emplace_back (object);
|
||||
this->m_objectsByRenderOrder.emplace_back ((*obj).second);
|
||||
}
|
||||
|
||||
auto objectsCur = this->m_objects.begin ();
|
||||
auto objectsEnd = this->m_objects.end ();
|
||||
}
|
||||
|
||||
for (; objectsCur != objectsEnd; objectsCur ++)
|
||||
Render::CObject* CScene::createObject (Core::CObject* object)
|
||||
{
|
||||
Render::CObject* renderObject = nullptr;
|
||||
|
||||
// ensure the item is not loaded already
|
||||
auto current = this->m_objects.find (object->getId ());
|
||||
|
||||
if (current != this->m_objects.end ())
|
||||
return (*current).second;
|
||||
|
||||
// check dependencies too!
|
||||
auto depCur = object->getDependencies ().begin ();
|
||||
auto depEnd = object->getDependencies ().end ();
|
||||
|
||||
for (; depCur != depEnd; depCur ++)
|
||||
{
|
||||
// self-dependency is a possibility...
|
||||
if ((*depCur) == object->getId ())
|
||||
continue;
|
||||
|
||||
auto dep = this->getScene ()->getObjects ().find (*depCur);
|
||||
|
||||
if (dep != this->getScene ()->getObjects ().end ())
|
||||
this->createObject ((*dep).second);
|
||||
}
|
||||
|
||||
if (object->is<Core::Objects::CImage>() == true)
|
||||
{
|
||||
Objects::CImage* image = new Objects::CImage (this, object->as<Core::Objects::CImage>());
|
||||
|
||||
try
|
||||
{
|
||||
if ((*objectsCur)->is <Objects::CImage> () == true)
|
||||
(*objectsCur)->as <Objects::CImage> ()->setup ();
|
||||
image->setup ();
|
||||
}
|
||||
catch (std::runtime_error ex)
|
||||
{
|
||||
std::cerr << "Cannot setup image resource: " << std::endl;
|
||||
std::cerr << ex.what () << std::endl;
|
||||
}
|
||||
|
||||
renderObject = image;
|
||||
}
|
||||
else if (object->is<Core::Objects::CSound>() == true)
|
||||
{
|
||||
renderObject = new Objects::CSound (this, object->as<Core::Objects::CSound>());
|
||||
}
|
||||
|
||||
if (renderObject != nullptr)
|
||||
this->m_objects.insert (std::make_pair (renderObject->getId (), renderObject));
|
||||
|
||||
return renderObject;
|
||||
}
|
||||
|
||||
CCamera* CScene::getCamera () const
|
||||
@ -88,8 +130,8 @@ CCamera* CScene::getCamera () const
|
||||
void CScene::renderFrame (glm::ivec4 viewport)
|
||||
{
|
||||
auto projection = this->getScene ()->getOrthogonalProjection ();
|
||||
auto cur = this->m_objects.begin ();
|
||||
auto end = this->m_objects.end ();
|
||||
auto cur = this->m_objectsByRenderOrder.begin ();
|
||||
auto end = this->m_objectsByRenderOrder.end ();
|
||||
|
||||
// ensure the virtual mouse position is up to date
|
||||
this->updateMouse (viewport);
|
||||
|
@ -32,8 +32,11 @@ namespace WallpaperEngine::Render
|
||||
static const std::string Type;
|
||||
|
||||
private:
|
||||
Render::CObject* createObject (Core::CObject* object);
|
||||
|
||||
CCamera* m_camera;
|
||||
std::vector<CObject*> m_objects;
|
||||
std::map<int, CObject*> m_objects;
|
||||
std::vector<CObject*> m_objectsByRenderOrder;
|
||||
glm::vec2 m_mousePosition;
|
||||
};
|
||||
}
|
||||
|
@ -212,6 +212,10 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) :
|
||||
|
||||
void CImage::setup ()
|
||||
{
|
||||
// do not double-init stuff, that's bad!
|
||||
if (this->m_initialized)
|
||||
return;
|
||||
|
||||
// generate the main material used to copy the image to the correct texture
|
||||
this->m_copyMaterial = new Effects::CMaterial (
|
||||
new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)),
|
||||
|
@ -170,68 +170,22 @@ void CPass::render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texco
|
||||
}
|
||||
}
|
||||
|
||||
// first texture is a bit special as we have to take what comes from the chain first
|
||||
glActiveTexture (GL_TEXTURE0);
|
||||
glBindTexture (GL_TEXTURE_2D, texture->getTextureID (currentTexture));
|
||||
int lastTextureIndex = 0;
|
||||
|
||||
// first bind the textures to their sampler place
|
||||
// continue on the map from the second texture
|
||||
if (this->m_finalTextures.empty () == false)
|
||||
{
|
||||
// set texture slots for the shader
|
||||
auto cur = this->m_textures.begin ();
|
||||
auto end = this->m_textures.end ();
|
||||
auto cur = this->m_finalTextures.begin ();
|
||||
auto end = this->m_finalTextures.end ();
|
||||
|
||||
for (int index = 1; cur != end; cur ++, index ++)
|
||||
for (; cur != end; cur ++)
|
||||
{
|
||||
texture = this->resolveTexture ((*cur), index, input);
|
||||
texture = this->resolveTexture ((*cur).second, (*cur).first, input);
|
||||
|
||||
glActiveTexture (GL_TEXTURE0 + index);
|
||||
glActiveTexture (GL_TEXTURE0 + (*cur).first);
|
||||
glBindTexture (GL_TEXTURE_2D, texture->getTextureID (0));
|
||||
// increase the number of textures counter
|
||||
lastTextureIndex ++;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// load the extra textures needed (if any) from the shader
|
||||
auto cur = this->m_fragShader->getTextures ().begin ();
|
||||
auto end = this->m_fragShader->getTextures ().end ();
|
||||
|
||||
for (; cur != end; cur ++)
|
||||
{
|
||||
if ((*cur).first <= lastTextureIndex)
|
||||
continue;
|
||||
|
||||
texture = this->resolveTexture ((*cur).second, (*cur).first, input);
|
||||
|
||||
if (texture == nullptr)
|
||||
continue;
|
||||
|
||||
// set the active texture index
|
||||
glActiveTexture (GL_TEXTURE0 + (*cur).first);
|
||||
// bind the correct texture here
|
||||
glBindTexture(GL_TEXTURE_2D, texture->getTextureID (0));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// load the extra textures needed (if any) from the shader
|
||||
auto cur = this->m_vertShader->getTextures ().begin ();
|
||||
auto end = this->m_vertShader->getTextures ().end ();
|
||||
|
||||
for (; cur != end; cur ++)
|
||||
{
|
||||
if ((*cur).first <= lastTextureIndex)
|
||||
continue;
|
||||
|
||||
texture = this->resolveTexture ((*cur).second, (*cur).first, input);
|
||||
|
||||
if (texture == nullptr)
|
||||
continue;
|
||||
|
||||
// set the active texture index
|
||||
glActiveTexture (GL_TEXTURE0 + (*cur).first);
|
||||
// bind the correct texture here
|
||||
glBindTexture(GL_TEXTURE_2D, texture->getTextureID (0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,62 +410,69 @@ void CPass::setupUniforms ()
|
||||
this->addUniform ("g_Texture7", 7);
|
||||
this->addUniform ("g_Texture0Resolution", texture->getResolution ());
|
||||
|
||||
int lastTextureIndex = 0;
|
||||
// register the extra texture resolutions
|
||||
// do the real, final texture setup for the whole process
|
||||
{
|
||||
auto cur = this->m_textures.begin ();
|
||||
auto end = this->m_textures.end ();
|
||||
auto fragCur = this->m_fragShader->getTextures ().begin ();
|
||||
auto fragEnd = this->m_fragShader->getTextures ().end ();
|
||||
auto vertCur = this->m_vertShader->getTextures ().begin ();
|
||||
auto vertEnd = this->m_vertShader->getTextures ().end ();
|
||||
auto bindCur = this->m_material->getMaterial ()->getTextureBinds ().begin ();
|
||||
auto bindEnd = this->m_material->getMaterial ()->getTextureBinds ().end ();
|
||||
|
||||
for (int index = 1; cur != end; cur ++, index ++)
|
||||
int index = 1;
|
||||
|
||||
// technically m_textures should have the right amount of textures
|
||||
// but better be safe than sorry
|
||||
while (bindCur != bindEnd || cur != end || fragCur != fragEnd || vertCur != vertEnd)
|
||||
{
|
||||
if (bindCur != bindEnd)
|
||||
{
|
||||
this->m_finalTextures.insert (std::make_pair ((*bindCur).first, nullptr));
|
||||
}
|
||||
|
||||
if (cur != end)
|
||||
{
|
||||
if ((*cur) != nullptr)
|
||||
this->m_finalTextures.insert (std::make_pair (index, *cur));
|
||||
|
||||
index ++;
|
||||
}
|
||||
|
||||
if (fragCur != fragEnd && (*fragCur).second != nullptr)
|
||||
{
|
||||
this->m_finalTextures.insert (std::make_pair ((*fragCur).first, (*fragCur).second));
|
||||
}
|
||||
|
||||
if (vertCur != vertEnd && (*vertCur).second != nullptr)
|
||||
{
|
||||
this->m_finalTextures.insert (std::make_pair ((*vertCur).first, (*vertCur).second));
|
||||
}
|
||||
|
||||
if (bindCur != bindEnd)
|
||||
bindCur ++;
|
||||
if (cur != end)
|
||||
cur ++;
|
||||
if (fragCur != fragEnd)
|
||||
fragCur ++;
|
||||
if (vertCur != vertEnd)
|
||||
vertCur ++;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto cur = this->m_finalTextures.begin ();
|
||||
auto end = this->m_finalTextures.end ();
|
||||
|
||||
for (; cur != end; cur ++)
|
||||
{
|
||||
std::ostringstream namestream;
|
||||
|
||||
namestream << "g_Texture" << index << "Resolution";
|
||||
namestream << "g_Texture" << (*cur).first << "Resolution";
|
||||
|
||||
texture = this->resolveTexture ((*cur), index, texture);
|
||||
texture = this->resolveTexture ((*cur).second, (*cur).first, texture);
|
||||
this->addUniform (namestream.str (), texture->getResolution ());
|
||||
lastTextureIndex ++;
|
||||
}
|
||||
}
|
||||
|
||||
// registers the extra texture resolutions from the shader
|
||||
{
|
||||
auto cur = this->m_fragShader->getTextures ().begin ();
|
||||
auto end = this->m_fragShader->getTextures ().end ();
|
||||
|
||||
for (; cur != end; cur ++)
|
||||
{
|
||||
if ((*cur).first <= lastTextureIndex)
|
||||
continue;
|
||||
|
||||
std::ostringstream namestream;
|
||||
|
||||
namestream << "g_Texture" << (*cur).first << "Resolution";
|
||||
|
||||
texture = this->resolveTexture ((*cur).second, (*cur).first, texture);
|
||||
if (texture != nullptr)
|
||||
this->addUniform (namestream.str (), texture->getResolution ());
|
||||
}
|
||||
}
|
||||
|
||||
// registers the extra texture resolutions from the shader
|
||||
{
|
||||
auto cur = this->m_vertShader->getTextures ().begin ();
|
||||
auto end = this->m_vertShader->getTextures ().end ();
|
||||
|
||||
for (; cur != end; cur ++)
|
||||
{
|
||||
if ((*cur).first <= lastTextureIndex)
|
||||
continue;
|
||||
|
||||
std::ostringstream namestream;
|
||||
|
||||
namestream << "g_Texture" << (*cur).first << "Resolution";
|
||||
|
||||
texture = this->resolveTexture ((*cur).second, (*cur).first, texture);
|
||||
|
||||
if (texture != nullptr)
|
||||
this->addUniform (namestream.str (), texture->getResolution ());
|
||||
}
|
||||
}
|
||||
|
||||
@ -599,16 +560,23 @@ void CPass::setupTextures ()
|
||||
{
|
||||
this->m_fbos.insert (std::make_pair (index, fbo));
|
||||
this->m_textures.emplace_back (
|
||||
nullptr
|
||||
fbo
|
||||
);
|
||||
}
|
||||
// _rt_texture
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_textures.emplace_back (
|
||||
this->m_material->getImage ()->getContainer ()->readTexture ((*cur))
|
||||
);
|
||||
if ((*cur) == "")
|
||||
{
|
||||
this->m_textures.emplace_back (nullptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_textures.emplace_back (
|
||||
this->m_material->getImage ()->getContainer ()->readTexture ((*cur))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -95,6 +95,11 @@ namespace WallpaperEngine::Render::Objects::Effects
|
||||
std::map<std::string, UniformEntry*> m_uniforms;
|
||||
glm::mat4 m_modelViewProjectionMatrix;
|
||||
|
||||
/**
|
||||
* Contains the final map of textures to be used
|
||||
*/
|
||||
std::map <int, ITexture*> m_finalTextures;
|
||||
|
||||
Render::Shaders::Compiler* m_fragShader;
|
||||
Render::Shaders::Compiler* m_vertShader;
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h>
|
||||
#include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h>
|
||||
|
||||
#include "WallpaperEngine/Assets/CAssetLoadException.h"
|
||||
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
|
||||
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloat.h"
|
||||
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableInteger.h"
|
||||
@ -667,13 +668,13 @@ namespace WallpaperEngine::Render::Shaders
|
||||
// if needed
|
||||
auto combo = data.find ("combo");
|
||||
auto textureName = data.find ("default");
|
||||
// extract the texture number from the name
|
||||
char value = name.at (std::string("g_Texture").length ());
|
||||
// now convert it to integer
|
||||
int index = value - '0';
|
||||
|
||||
if (combo != data.end ())
|
||||
{
|
||||
// extract the texture number from the name
|
||||
char value = name.at (std::string("g_Texture").length ());
|
||||
// now convert it to integer
|
||||
int index = value - '0';
|
||||
|
||||
// if the texture exists, add the combo
|
||||
if (this->m_passTextures.size () > index)
|
||||
@ -698,16 +699,34 @@ namespace WallpaperEngine::Render::Shaders
|
||||
}
|
||||
else
|
||||
{
|
||||
// material name is not resolved on compile time, but passes will do it after
|
||||
// check for texture name too
|
||||
if (textureName != data.end ())
|
||||
{
|
||||
try
|
||||
{
|
||||
// also ensure that the textureName is loaded and we know about it
|
||||
ITexture* texture = this->m_container->readTexture ((*textureName).get <std::string> ());
|
||||
|
||||
// extract the texture number from the name
|
||||
char value = name.at (std::string("g_Texture").length ());
|
||||
// now convert it to integer
|
||||
int index = value - '0';
|
||||
this->m_textures.insert (
|
||||
std::make_pair (index, texture)
|
||||
);
|
||||
}
|
||||
catch (CAssetLoadException& ex)
|
||||
{
|
||||
// cannot resolve texture
|
||||
// TODO: TAKE CARE OF FBOS
|
||||
this->m_textures.insert (
|
||||
std::make_pair (index, nullptr)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this->m_textures.insert (
|
||||
std::make_pair (index, nullptr)
|
||||
);
|
||||
}
|
||||
|
||||
this->m_textures.insert (
|
||||
std::make_pair (index, nullptr)
|
||||
);
|
||||
}
|
||||
|
||||
// samplers are not saved, we can ignore them for now
|
||||
|
Loading…
Reference in New Issue
Block a user