Ignore composelayers for now

Added support for color blend mode
Main pass' blendmode should be normal
Last pass' blendmode should be the first's
Fixed order of glClear's so _rt_FullFrameBuffer is the right color at the right time
Simplified effect and pass creation code a bit more
Non-visible images should render the full chain into the pingpong framebuffers instead of to screen
Fixed an integer division not producing float numbers

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
Alexis Maiquez 2022-11-03 13:14:52 +01:00
parent 261bc696df
commit 5521e90155
12 changed files with 161 additions and 105 deletions

View File

@ -68,6 +68,10 @@ CObject* CObject::fromJSON (json data, CContainer* container)
if (image_it != data.end () && (*image_it).is_null () == false) if (image_it != data.end () && (*image_it).is_null () == false)
{ {
// composelayer should be ignored for now, or artifacts will appear
if (*image_it == "models/util/composelayer.json")
return nullptr;
object = Objects::CImage::fromJSON ( object = Objects::CImage::fromJSON (
data, data,
container, container,

View File

@ -19,14 +19,16 @@ CImage::CImage (
std::string alignment, std::string alignment,
const glm::vec3& color, const glm::vec3& color,
float alpha, float alpha,
float brightness) : float brightness,
uint32_t colorBlendMode) :
CObject (visible, id, std::move(name), Type, origin, scale, angles), CObject (visible, id, std::move(name), Type, origin, scale, angles),
m_size (size), m_size (size),
m_material (material), m_material (material),
m_alignment (std::move(alignment)), m_alignment (std::move(alignment)),
m_color (color), m_color (color),
m_alpha (alpha), m_alpha (alpha),
m_brightness (brightness) m_brightness (brightness),
m_colorBlendMode (colorBlendMode)
{ {
} }
@ -46,6 +48,7 @@ WallpaperEngine::Core::CObject* CImage::fromJSON (
auto alpha = jsonFindDefault <float> (data, "alpha", 1.0); auto alpha = jsonFindDefault <float> (data, "alpha", 1.0);
auto color_val = jsonFindDefault <std::string> (data, "color", "1.0 1.0 1.0"); auto color_val = jsonFindDefault <std::string> (data, "color", "1.0 1.0 1.0");
auto brightness_val = jsonFindDefault <float> (data, "brightness", 1.0); auto brightness_val = jsonFindDefault <float> (data, "brightness", 1.0);
auto colorBlendMode_val = jsonFindDefault <uint32_t> (data, "colorBlendMode", 0);
json content = json::parse (WallpaperEngine::FileSystem::loadFullFile ((*image_it).get <std::string> (), container)); json content = json::parse (WallpaperEngine::FileSystem::loadFullFile ((*image_it).get <std::string> (), container));
@ -63,7 +66,8 @@ WallpaperEngine::Core::CObject* CImage::fromJSON (
alignment, alignment,
WallpaperEngine::Core::aToVector3 (color_val), WallpaperEngine::Core::aToVector3 (color_val),
alpha, alpha,
brightness_val brightness_val,
colorBlendMode_val
); );
} }
@ -97,4 +101,9 @@ const float CImage::getBrightness () const
return this->m_brightness; return this->m_brightness;
} }
const uint32_t CImage::getColorBlendMode () const
{
return this->m_colorBlendMode;
}
const std::string CImage::Type = "image"; const std::string CImage::Type = "image";

View File

@ -34,6 +34,7 @@ namespace WallpaperEngine::Core::Objects
const float getAlpha () const; const float getAlpha () const;
const glm::vec3& getColor () const; const glm::vec3& getColor () const;
const float getBrightness () const; const float getBrightness () const;
const uint32_t getColorBlendMode () const;
protected: protected:
CImage ( CImage (
@ -48,7 +49,8 @@ namespace WallpaperEngine::Core::Objects
std::string alignment, std::string alignment,
const glm::vec3& color, const glm::vec3& color,
float alpha, float alpha,
float brightness float brightness,
uint32_t colorBlendMode
); );
static const std::string Type; static const std::string Type;
@ -60,5 +62,6 @@ namespace WallpaperEngine::Core::Objects
float m_alpha; float m_alpha;
float m_brightness; float m_brightness;
glm::vec3 m_color; glm::vec3 m_color;
uint32_t m_colorBlendMode;
}; };
}; };

View File

@ -139,6 +139,11 @@ const std::string& CPass::getDepthWrite ()const
return this->m_depthwrite; return this->m_depthwrite;
} }
void CPass::setBlendingMode (std::string mode)
{
this->m_blending = mode;
}
void CPass::insertConstant (const std::string& name, CShaderConstant* constant) void CPass::insertConstant (const std::string& name, CShaderConstant* constant)
{ {
this->m_constants.insert (std::pair <std::string, CShaderConstant*> (name, constant)); this->m_constants.insert (std::pair <std::string, CShaderConstant*> (name, constant));

View File

@ -28,6 +28,7 @@ namespace WallpaperEngine::Core::Objects::Images::Materials
const std::string& getCullingMode () const; const std::string& getCullingMode () const;
const std::string& getDepthTest () const; const std::string& getDepthTest () const;
const std::string& getDepthWrite () const; const std::string& getDepthWrite () const;
void setBlendingMode (std::string mode);
void insertCombo (const std::string& name, int value); void insertCombo (const std::string& name, int value);
void insertConstant (const std::string& name, Effects::Constants::CShaderConstant* constant); void insertConstant (const std::string& name, Effects::Constants::CShaderConstant* constant);

View File

@ -39,6 +39,11 @@ CScene::CScene (Core::CScene* scene, CContainer* container, CContext* context) :
scene->getOrthogonalProjection ()->getHeight () scene->getOrthogonalProjection ()->getHeight ()
); );
// set clear color
FloatColor clearColor = this->getScene ()->getClearColor ();
glClearColor (clearColor.r, clearColor.g, clearColor.b, 1.0f);
// setup framebuffers // setup framebuffers
this->setupFramebuffers (); this->setupFramebuffers ();
@ -136,21 +141,15 @@ void CScene::renderFrame (glm::ivec4 viewport)
// ensure the virtual mouse position is up to date // ensure the virtual mouse position is up to date
this->updateMouse (viewport); this->updateMouse (viewport);
// clear screen
FloatColor clearColor = this->getScene ()->getClearColor ();
glClearColor (clearColor.r, clearColor.g, clearColor.b, 0.0f);
// use the scene's framebuffer by default // use the scene's framebuffer by default
glBindFramebuffer (GL_FRAMEBUFFER, this->getWallpaperFramebuffer()); glBindFramebuffer (GL_FRAMEBUFFER, this->getWallpaperFramebuffer());
// ensure we render over the whole screen // ensure we render over the whole screen
glViewport (0, 0, projection->getWidth (), projection->getHeight ()); glViewport (0, 0, projection->getWidth (), projection->getHeight ());
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
for (; cur != end; cur ++) for (; cur != end; cur ++)
(*cur)->render (); (*cur)->render ();
// ensure we render over the whole screen
glViewport (0, 0, projection->getWidth (), projection->getHeight ());
} }
void CScene::updateMouse (glm::ivec4 viewport) void CScene::updateMouse (glm::ivec4 viewport)

View File

@ -94,8 +94,8 @@ CImage::CImage (CScene* scene, Core::Objects::CImage* image) :
this->m_texture->getRealWidth (), this->m_texture->getRealHeight () this->m_texture->getRealWidth (), this->m_texture->getRealHeight ()
); );
GLfloat realWidth = this->m_texture->getRealWidth () / 2; GLfloat realWidth = this->m_texture->getRealWidth () / 2.0f;
GLfloat realHeight = this->m_texture->getRealHeight () / 2; GLfloat realHeight = this->m_texture->getRealHeight () / 2.0f;
// build a list of vertices, these might need some change later (or maybe invert the camera) // build a list of vertices, these might need some change later (or maybe invert the camera)
GLfloat sceneSpacePosition [] = { GLfloat sceneSpacePosition [] = {
@ -216,12 +216,24 @@ void CImage::setup ()
if (this->m_initialized) if (this->m_initialized)
return; return;
// TODO: SUPPORT PASSTHROUGH (IT'S A SHADER)
{
// generate the main material used to render the image // generate the main material used to render the image
this->m_material = new Effects::CMaterial ( this->m_material = new Effects::CMaterial (
new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)), new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)),
this->m_image->getMaterial () this->m_image->getMaterial ()
); );
// add blendmode to the combos
auto cur = this->m_material->getPasses ().begin ();
auto end = this->m_material->getPasses ().end ();
for (; cur != end; cur ++)
this->m_passes.push_back (*cur);
}
// prepare the passes list
if (this->getImage ()->getEffects ().empty () == false) if (this->getImage ()->getEffects ().empty () == false)
{ {
// generate the effects used by this material // generate the effects used by this material
@ -229,19 +241,10 @@ void CImage::setup ()
auto end = this->getImage ()->getEffects ().end (); auto end = this->getImage ()->getEffects ().end ();
for (; cur != end; cur ++) for (; cur != end; cur ++)
this->m_effects.emplace_back (new CEffect (this, *cur));
}
// prepare the passes list
if (this->getEffects ().empty () == false)
{ {
auto effectCur = this->getEffects ().begin (); auto effect = new CEffect (this, *cur);
auto effectEnd = this->getEffects ().end (); auto materialCur = effect->getMaterials ().begin ();
auto materialEnd = effect->getMaterials ().end ();
for (; effectCur != effectEnd; effectCur ++)
{
auto materialCur = (*effectCur)->getMaterials ().begin ();
auto materialEnd = (*effectCur)->getMaterials ().end ();
for (; materialCur != materialEnd; materialCur ++) for (; materialCur != materialEnd; materialCur ++)
{ {
@ -251,19 +254,43 @@ void CImage::setup ()
for (; passCur != passEnd; passCur ++) for (; passCur != passEnd; passCur ++)
this->m_passes.push_back (*passCur); this->m_passes.push_back (*passCur);
} }
this->m_effects.push_back (effect);
} }
} }
// add the final passes too if (this->m_image->getColorBlendMode () > 0)
if (this->m_material->getPasses ().empty () == false)
{ {
auto cur = this->m_material->getPasses ().begin (); auto material = Core::Objects::Images::CMaterial::fromFile ("materials/util/effectpassthrough.json", this->getContainer ());
auto end = this->m_material->getPasses ().end ();
// effectpasshthrough only has one pass
(*material->getPasses ().begin ())->insertCombo ("BLENDMODE", this->m_image->getColorBlendMode ());
// generate the main material used to render the image
this->m_colorBlendMaterial = new Effects::CMaterial(
new CEffect (this, new Core::Objects::CEffect ("", "", "", "", this->m_image)),
material
);
// add blendmode to the combos
auto cur = this->m_colorBlendMaterial->getPasses ().begin ();
auto end = this->m_colorBlendMaterial->getPasses ().end ();
for (; cur != end; cur ++) for (; cur != end; cur ++)
this->m_passes.push_back (*cur); this->m_passes.push_back (*cur);
} }
// if there's more than one pass the blendmode has to be moved from the beginning to the end
if (this->m_passes.size () > 1)
{
auto first = this->m_passes.begin ();
auto last = this->m_passes.rbegin ();
(*last)->getPass ()->setBlendingMode ((*first)->getPass ()->getBlendingMode ());
(*first)->getPass ()->setBlendingMode ("normal");
}
{
// calculate full animation time (if any) // calculate full animation time (if any)
this->m_animationTime = 0.0f; this->m_animationTime = 0.0f;
@ -272,6 +299,7 @@ void CImage::setup ()
for (; cur != end; cur++) for (; cur != end; cur++)
this->m_animationTime += (*cur)->frametime; this->m_animationTime += (*cur)->frametime;
}
this->m_initialized = true; this->m_initialized = true;
} }
@ -299,8 +327,8 @@ void CImage::render ()
return; return;
// reset the framebuffers so the drawing always happens on the same order // reset the framebuffers so the drawing always happens on the same order
this->m_currentMainFBO = this->m_subFBO; this->m_currentMainFBO = this->m_mainFBO;
this->m_currentSubFBO = this->m_mainFBO; this->m_currentSubFBO = this->m_subFBO;
glColorMask (true, true, true, true); glColorMask (true, true, true, true);
@ -334,12 +362,8 @@ void CImage::render ()
} }
// determine if it's the last element in the list as this is a screen-copy-like process // determine if it's the last element in the list as this is a screen-copy-like process
else if (std::next (cur) == end) else if (std::next (cur) == end && this->getImage ()->isVisible () == true)
{ {
// do not draw to screen if the image is not visible
if (this->getImage ()->isVisible () == false)
return;
spacePosition = *this->getSceneSpacePosition (); spacePosition = *this->getSceneSpacePosition ();
drawTo = this->getScene ()->getFBO (); drawTo = this->getScene ()->getFBO ();
projection = this->m_modelViewProjectionScreen; projection = this->m_modelViewProjectionScreen;

View File

@ -79,6 +79,7 @@ namespace WallpaperEngine::Render::Objects
std::vector<CEffect*> m_effects; std::vector<CEffect*> m_effects;
Effects::CMaterial* m_material; Effects::CMaterial* m_material;
Effects::CMaterial* m_colorBlendMaterial;
std::vector <Effects::CPass*> m_passes; std::vector <Effects::CPass*> m_passes;
double m_animationTime; double m_animationTime;

View File

@ -289,6 +289,11 @@ const CMaterial* CPass::getMaterial () const
return this->m_material; return this->m_material;
} }
Core::Objects::Images::Materials::CPass* CPass::getPass ()
{
return this->m_pass;
}
GLuint CPass::compileShader (Render::Shaders::Compiler* shader, GLuint type) GLuint CPass::compileShader (Render::Shaders::Compiler* shader, GLuint type)
{ {
// reserve shaders in OpenGL // reserve shaders in OpenGL
@ -464,6 +469,7 @@ void CPass::setupUniforms ()
if (bindCur != bindEnd) if (bindCur != bindEnd)
{ {
this->m_finalTextures.insert (std::make_pair ((*bindCur).first, nullptr)); this->m_finalTextures.insert (std::make_pair ((*bindCur).first, nullptr));
bindCur ++;
} }
if (cur != end) if (cur != end)
@ -472,28 +478,68 @@ void CPass::setupUniforms ()
this->m_finalTextures.insert (std::make_pair (index, *cur)); this->m_finalTextures.insert (std::make_pair (index, *cur));
index ++; 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 ++; cur ++;
}
if (fragCur != fragEnd) if (fragCur != fragEnd)
{
std::string textureName = (*fragCur).second;
try
{
// resolve the texture first
ITexture* textureRef = nullptr;
if (textureName.find ("_rt_") == 0)
{
textureRef = this->getMaterial ()->getEffect ()->findFBO (textureName);
if (textureRef == nullptr)
textureRef = this->getMaterial ()->getImage ()->getScene ()->findFBO (textureName);
}
else
textureRef = this->getMaterial ()->getImage ()->getContainer ()->readTexture (textureName);
this->m_finalTextures.insert (std::make_pair ((*fragCur).first, textureRef));
}
catch (std::runtime_error& ex)
{
std::cerr << "Cannot resolve texture " << textureName << " for fragment shader: " << ex.what () << std::endl;
}
fragCur ++; fragCur ++;
}
if (vertCur != vertEnd) if (vertCur != vertEnd)
{
std::string textureName = (*vertCur).second;
try
{
// resolve the texture first
ITexture* textureRef = nullptr;
if (textureName.find ("_rt_") == 0)
{
textureRef = this->getMaterial ()->getEffect ()->findFBO (textureName);
if (textureRef == nullptr)
textureRef = this->getMaterial ()->getImage ()->getScene ()->findFBO (textureName);
}
else
textureRef = this->getMaterial ()->getImage ()->getContainer ()->readTexture (textureName);
this->m_finalTextures.insert (std::make_pair ((*vertCur).first, textureRef));
}
catch (std::runtime_error& ex)
{
std::cerr << "Cannot resolve texture " << textureName << " for vertex shader: " << ex.what () << std::endl;
}
vertCur ++; vertCur ++;
} }
} }
}
{ {
auto cur = this->m_finalTextures.begin (); auto cur = this->m_finalTextures.begin ();

View File

@ -24,6 +24,7 @@ namespace WallpaperEngine::Render::Objects::Effects
void render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texcoord, glm::mat4 projection); void render (CFBO* drawTo, ITexture* input, GLuint position, GLuint texcoord, glm::mat4 projection);
const CMaterial* getMaterial () const; const CMaterial* getMaterial () const;
Core::Objects::Images::Materials::CPass* getPass ();
private: private:
enum UniformType enum UniformType

View File

@ -711,47 +711,10 @@ namespace WallpaperEngine::Render::Shaders
this->m_foundCombos->insert (std::make_pair <std::string, bool> (*combo, true)); this->m_foundCombos->insert (std::make_pair <std::string, bool> (*combo, true));
} }
}
if (textureName != data.end ()) if (textureName != data.end ())
{ this->m_textures.insert (std::make_pair (index, *textureName));
// also ensure that the textureName is loaded and we know about it
ITexture* texture = this->m_container->readTexture ((*textureName).get <std::string> ());
this->m_textures.insert (
std::make_pair (index, texture)
);
}
}
else
{
// 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> ());
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)
);
}
}
// samplers are not saved, we can ignore them for now // samplers are not saved, we can ignore them for now
return; return;
@ -798,7 +761,7 @@ namespace WallpaperEngine::Render::Shaders
return this->m_combos; return this->m_combos;
} }
const std::map <int, ITexture*>& Compiler::getTextures () const const std::map <int, std::string>& Compiler::getTextures () const
{ {
return this->m_textures; return this->m_textures;
} }

View File

@ -91,7 +91,7 @@ namespace WallpaperEngine::Render::Shaders
/** /**
* @return The list of textures inferred from the shader's code * @return The list of textures inferred from the shader's code
*/ */
const std::map <int, ITexture*>& getTextures () const; const std::map <int, std::string>& getTextures () const;
private: private:
/** /**
@ -263,7 +263,7 @@ namespace WallpaperEngine::Render::Shaders
/** /**
* List of textures that the shader expects (inferred from sampler2D and it's JSON data) * List of textures that the shader expects (inferred from sampler2D and it's JSON data)
*/ */
std::map<int, ITexture*> m_textures; std::map<int, std::string> m_textures;
bool m_includesProcessed = false; bool m_includesProcessed = false;
}; };
} }