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:
Alexis Maiquez 2022-10-28 18:21:29 +02:00
parent 9ff33ef61f
commit 7b7d699371
11 changed files with 208 additions and 150 deletions

View File

@ -113,16 +113,23 @@ CScene* CScene::fromFile (const std::string& filename, CContainer* container)
return scene; return scene;
} }
const std::vector<CObject*>& CScene::getObjects () const const std::map<uint32_t, CObject*>& CScene::getObjects () const
{ {
return this->m_objects; return this->m_objects;
} }
const std::vector<CObject*>& CScene::getObjectsByRenderOrder () const
{
return this->m_objectsByRenderOrder;
}
void CScene::insertObject (CObject* object) void CScene::insertObject (CObject* object)
{ {
/// TODO: XXXHACK -- TO REMOVE WHEN PARTICLE SUPPORT IS PROPERLY IMPLEMENTED /// TODO: XXXHACK -- TO REMOVE WHEN PARTICLE SUPPORT IS PROPERLY IMPLEMENTED
if (object != nullptr) 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 () CContainer* CScene::getContainer ()

View File

@ -21,7 +21,8 @@ namespace WallpaperEngine::Core
public: public:
static CScene* fromFile (const std::string& filename, CContainer* container); 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 FloatColor& getAmbientColor() const;
const bool isBloom() const; const bool isBloom() const;
@ -95,6 +96,7 @@ namespace WallpaperEngine::Core
Scenes::CProjection* m_orthogonalProjection; Scenes::CProjection* m_orthogonalProjection;
FloatColor m_skylightColor; FloatColor m_skylightColor;
std::vector<CObject*> m_objects; std::map<uint32_t, CObject*> m_objects;
std::vector<CObject*> m_objectsByRenderOrder;
}; };
}; };

View File

@ -91,14 +91,16 @@ CEffect* CEffect::fromJSON (json data, Core::CObject* object, CContainer* contai
if ((*texturesCur).is_null () == true) 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 else
{ {

View File

@ -25,3 +25,8 @@ CContainer* CObject::getContainer () const
{ {
return this->getScene ()->getContainer (); return this->getScene ()->getContainer ();
} }
const int CObject::getId () const
{
return this->m_object->getId ();
}

View File

@ -22,6 +22,7 @@ namespace WallpaperEngine::Render
CScene* getScene () const; CScene* getScene () const;
CContainer* getContainer () const; CContainer* getContainer () const;
const int getId () const;
protected: protected:
CObject (CScene* scene, std::string type, Core::CObject *object); CObject (CScene* scene, std::string type, Core::CObject *object);

View File

@ -24,10 +24,10 @@ CScene::CScene (Core::CScene* scene, CContainer* container, CContext* context) :
for (; cur != end; cur ++) for (; cur != end; cur ++)
{ {
if ((*cur)->is<Core::Objects::CImage> () == false) if ((*cur).second->is<Core::Objects::CImage> () == false)
continue; 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 ()->setWidth (size.x);
scene->getOrthogonalProjection ()->setHeight (size.y); scene->getOrthogonalProjection ()->setHeight (size.y);
@ -42,42 +42,84 @@ CScene::CScene (Core::CScene* scene, CContainer* container, CContext* context) :
// setup framebuffers // setup framebuffers
this->setupFramebuffers (); this->setupFramebuffers ();
auto cur = scene->getObjects ().begin (); // create all objects based off their dependencies
auto end = scene->getObjects ().end (); {
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 ++) for (; cur != end; cur ++)
{ {
CObject* object = nullptr; auto obj = this->m_objects.find ((*cur)->getId ());
if ((*cur)->is<Core::Objects::CImage>() == true) // ignores not created objects like particle systems
{ if (obj == this->m_objects.end ())
object = new Objects::CImage (this, (*cur)->as<Core::Objects::CImage>()); continue;
}
else if ((*cur)->is<Core::Objects::CSound>() == true)
{
object = new Objects::CSound (this, (*cur)->as<Core::Objects::CSound>());
}
if (object != nullptr) this->m_objectsByRenderOrder.emplace_back ((*obj).second);
this->m_objects.emplace_back (object);
} }
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 try
{ {
if ((*objectsCur)->is <Objects::CImage> () == true) image->setup ();
(*objectsCur)->as <Objects::CImage> ()->setup ();
} }
catch (std::runtime_error ex) catch (std::runtime_error ex)
{ {
std::cerr << "Cannot setup image resource: " << std::endl; std::cerr << "Cannot setup image resource: " << std::endl;
std::cerr << ex.what () << 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 CCamera* CScene::getCamera () const
@ -88,8 +130,8 @@ CCamera* CScene::getCamera () const
void CScene::renderFrame (glm::ivec4 viewport) void CScene::renderFrame (glm::ivec4 viewport)
{ {
auto projection = this->getScene ()->getOrthogonalProjection (); auto projection = this->getScene ()->getOrthogonalProjection ();
auto cur = this->m_objects.begin (); auto cur = this->m_objectsByRenderOrder.begin ();
auto end = this->m_objects.end (); auto end = this->m_objectsByRenderOrder.end ();
// ensure the virtual mouse position is up to date // ensure the virtual mouse position is up to date
this->updateMouse (viewport); this->updateMouse (viewport);

View File

@ -32,8 +32,11 @@ namespace WallpaperEngine::Render
static const std::string Type; static const std::string Type;
private: private:
Render::CObject* createObject (Core::CObject* object);
CCamera* m_camera; CCamera* m_camera;
std::vector<CObject*> m_objects; std::map<int, CObject*> m_objects;
std::vector<CObject*> m_objectsByRenderOrder;
glm::vec2 m_mousePosition; glm::vec2 m_mousePosition;
}; };
} }

View File

@ -212,6 +212,10 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) :
void CImage::setup () 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 // generate the main material used to copy the image to the correct texture
this->m_copyMaterial = new Effects::CMaterial ( this->m_copyMaterial = new Effects::CMaterial (
new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)), new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)),

View File

@ -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); glActiveTexture (GL_TEXTURE0);
glBindTexture (GL_TEXTURE_2D, texture->getTextureID (currentTexture)); 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_finalTextures.begin ();
auto cur = this->m_textures.begin (); auto end = this->m_finalTextures.end ();
auto end = this->m_textures.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)); 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_Texture7", 7);
this->addUniform ("g_Texture0Resolution", texture->getResolution ()); this->addUniform ("g_Texture0Resolution", texture->getResolution ());
int lastTextureIndex = 0; // do the real, final texture setup for the whole process
// register the extra texture resolutions
{ {
auto cur = this->m_textures.begin (); auto cur = this->m_textures.begin ();
auto end = this->m_textures.end (); 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; 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 ()); 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_fbos.insert (std::make_pair (index, fbo));
this->m_textures.emplace_back ( this->m_textures.emplace_back (
nullptr fbo
); );
} }
// _rt_texture // _rt_texture
} }
else else
{ {
this->m_textures.emplace_back ( if ((*cur) == "")
this->m_material->getImage ()->getContainer ()->readTexture ((*cur)) {
); this->m_textures.emplace_back (nullptr);
}
else
{
this->m_textures.emplace_back (
this->m_material->getImage ()->getContainer ()->readTexture ((*cur))
);
}
} }
} }
} }

View File

@ -95,6 +95,11 @@ namespace WallpaperEngine::Render::Objects::Effects
std::map<std::string, UniformEntry*> m_uniforms; std::map<std::string, UniformEntry*> m_uniforms;
glm::mat4 m_modelViewProjectionMatrix; 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_fragShader;
Render::Shaders::Compiler* m_vertShader; Render::Shaders::Compiler* m_vertShader;

View File

@ -12,6 +12,7 @@
#include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h> #include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h>
#include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.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/CShaderVariable.h"
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloat.h" #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloat.h"
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableInteger.h" #include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableInteger.h"
@ -667,13 +668,13 @@ namespace WallpaperEngine::Render::Shaders
// if needed // if needed
auto combo = data.find ("combo"); auto combo = data.find ("combo");
auto textureName = data.find ("default"); 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 ()) 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 the texture exists, add the combo
if (this->m_passTextures.size () > index) if (this->m_passTextures.size () > index)
@ -698,16 +699,34 @@ namespace WallpaperEngine::Render::Shaders
} }
else 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 this->m_textures.insert (
char value = name.at (std::string("g_Texture").length ()); std::make_pair (index, texture)
// now convert it to integer );
int index = value - '0'; }
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 // samplers are not saved, we can ignore them for now