feat: take into account project properties for shader values

feat: proper parsing of combo values in shaders
fix: shader units weren't linked as they should
chore: more support for detecting shader things automatically
This commit is contained in:
Almamu 2025-04-17 02:56:26 +02:00
parent fe065f72b7
commit beb186050b
21 changed files with 378 additions and 164 deletions

View File

@ -192,9 +192,7 @@ if(X11_SUPPORT_FOUND)
src/WallpaperEngine/Render/Drivers/Output/CX11Output.cpp
src/WallpaperEngine/Render/Drivers/Output/CX11Output.h
src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.cpp
src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h
src/WallpaperEngine/Render/Shaders/CShaderUnit.cpp
src/WallpaperEngine/Render/Shaders/CShaderUnit.h)
src/WallpaperEngine/Render/Drivers/Detectors/CX11FullScreenDetector.h)
SET(X11_INCLUDES
${X11_INCLUDE_DIR}
${XRANDR_INCLUDE_DIR})
@ -318,8 +316,10 @@ add_executable(
src/WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector4.h
src/WallpaperEngine/Render/Shaders/Variables/CShaderVariableVector4.cpp
src/WallpaperEngine/Render/Shaders/CShader.h
src/WallpaperEngine/Render/Shaders/CShader.cpp
src/WallpaperEngine/Render/Shaders/CShader.h
src/WallpaperEngine/Render/Shaders/CShader.cpp
src/WallpaperEngine/Render/Shaders/CShaderUnit.cpp
src/WallpaperEngine/Render/Shaders/CShaderUnit.h
src/WallpaperEngine/Render/Shaders/CGLSLContext.cpp
src/WallpaperEngine/Render/Shaders/CGLSLContext.h
@ -451,12 +451,16 @@ add_executable(
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.cpp
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.cpp
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector2.h
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector2.cpp
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector3.h
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector3.cpp
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.cpp
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.cpp
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.h
src/WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.cpp
src/WallpaperEngine/Core/Objects/Particles/CControlPoint.cpp
src/WallpaperEngine/Core/Objects/Particles/CControlPoint.h

View File

@ -191,12 +191,12 @@ Core::CProject* CWallpaperApplication::loadBackground (const std::string& bg) {
void CWallpaperApplication::setupPropertiesForProject (const Core::CProject* project) {
// show properties if required
for (const auto cur : project->getProperties ()) {
for (const auto [key, cur] : project->getProperties ()) {
// update the value of the property
auto override = this->m_context.settings.general.properties.find (cur->getName ());
auto override = this->m_context.settings.general.properties.find (key);
if (override != this->m_context.settings.general.properties.end ()) {
sLog.out ("Applying override value for ", cur->getName ());
sLog.out ("Applying override value for ", key);
cur->update (override->second);
}

View File

@ -14,12 +14,16 @@ using namespace WallpaperEngine::Assets;
static int backgroundId = -1;
CProject::CProject (std::string title, std::string type, std::string workshopid, const CContainer* container) :
CProject::CProject (
std::string title, std::string type, std::string workshopid, const CContainer* container,
const std::map<std::string, const Projects::CProperty*> properties
) :
m_workshopid(std::move(workshopid)),
m_title (std::move(title)),
m_type (std::move(type)),
m_wallpaper (nullptr),
m_container (container) {}
m_container (container),
m_properties (properties) {}
CProject* CProject::fromFile (const std::string& filename, const CContainer* container) {
json content = json::parse (container->readFileAsString (filename));
@ -36,14 +40,32 @@ CProject* CProject::fromFile (const std::string& filename, const CContainer* con
const auto file = jsonFindRequired <std::string> (content, "file", "Project's main file missing");
auto general = content.find ("general");
const CWallpaper* wallpaper;
std::map<std::string, const Projects::CProperty*> properties;
std::transform (type.begin (), type.end (), type.begin (), tolower);
if (general != content.end ()) {
const auto properties_it = general->find ("properties");
if (properties_it != general->end ()) {
for (const auto& cur : properties_it->items ()) {
const auto property = Projects::CProperty::fromJSON (cur.value (), cur.key ());
if (property == nullptr) {
continue;
}
properties.insert (std::pair (property->getName (), property));
}
}
}
auto* project = new CProject (
jsonFindRequired <std::string> (content, "title", "Project title missing"),
type,
jsonFindDefault <std::string> (content, "workshopid", std::to_string (backgroundId--)),
container
container,
properties
);
if (type == "scene")
@ -57,17 +79,6 @@ CProject* CProject::fromFile (const std::string& filename, const CContainer* con
project->setWallpaper (wallpaper);
if (general != content.end ()) {
const auto properties = general->find ("properties");
if (properties != general->end ()) {
for (const auto& cur : properties->items ()) {
const auto property = Projects::CProperty::fromJSON (cur.value (), cur.key ());
if (property != nullptr)
project->insertProperty (property);
}
}
}
return project;
}
@ -87,7 +98,7 @@ const std::string& CProject::getType () const {
return this->m_type;
}
const std::vector<const Projects::CProperty*>& CProject::getProperties () const {
const std::map<std::string, const Projects::CProperty*>& CProject::getProperties () const {
return this->m_properties;
}
@ -98,7 +109,3 @@ const std::string& CProject::getWorkshopId () const {
const CContainer* CProject::getContainer () const {
return this->m_container;
}
void CProject::insertProperty (const Projects::CProperty* property) {
this->m_properties.push_back (property);
}

View File

@ -20,19 +20,20 @@ class CProject {
[[nodiscard]] const std::string& getTitle () const;
[[nodiscard]] const std::string& getType () const;
[[nodiscard]] const std::vector<const Projects::CProperty*>& getProperties () const;
[[nodiscard]] const std::map<std::string, const Projects::CProperty*>& getProperties () const;
[[nodiscard]] const std::string& getWorkshopId () const;
const CContainer* getContainer () const;
protected:
CProject (std::string title, std::string type, std::string workshopid, const CContainer* container);
CProject (
std::string title, std::string type, std::string workshopid, const CContainer* container,
std::map<std::string, const Projects::CProperty*> properties);
void setWallpaper (const CWallpaper* wallpaper);
void insertProperty (const Projects::CProperty* property);
private:
std::vector<const Projects::CProperty*> m_properties;
std::map<std::string, const Projects::CProperty*> m_properties;
const std::string m_workshopid;
const std::string m_title;

View File

@ -8,7 +8,10 @@
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector2.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector3.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.h"
#include "WallpaperEngine/Core/UserSettings/CUserSettingBoolean.h"
#include "WallpaperEngine/Logging/CLog.h"
@ -53,7 +56,7 @@ const CEffect* CEffect::fromJSON (
fbos = CEffect::fbosFromJSON (fbos_it);
if (effectpasses_it != data.end ()) {
overrides = overridesFromJSON (effectpasses_it, material);
overrides = overridesFromJSON (effectpasses_it, material, project);
}
return new CEffect (
@ -83,39 +86,70 @@ std::map<std::string, int> CEffect::combosFromJSON (const json::const_iterator&
}
std::map<std::string, const Core::Objects::Effects::Constants::CShaderConstant*> CEffect::constantsFromJSON (
const json::const_iterator& constants_it
const json::const_iterator& constants_it, const CProject& project
) {
std::map<std::string, const Core::Objects::Effects::Constants::CShaderConstant*> constants;
for (auto& cur : constants_it->items ()) {
auto val = cur.value ();
Effects::Constants::CShaderConstant* constant;
Effects::Constants::CShaderConstant* constant = nullptr;
// if the constant is an object, that means the constant has some extra information
// for the UI, take the value, which is what we need
// TODO: SUPPORT USER SETTINGS HERE
if (cur.value ().is_object ()) {
auto user = cur.value ().find ("user");
auto it = cur.value ().find ("value");
if (it == cur.value ().end ()) {
sLog.error ("Found object for shader constant without \"value\" member");
if (user == cur.value ().end () && it == cur.value ().end ()) {
sLog.error (R"(Found object for shader constant without "value" and "user" setting)");
continue;
}
val = it.value ();
if (user != cur.value ().end ()) {
// look for a property with the correct name
const auto& properties = project.getProperties ();
const auto property = properties.find (*user);
if (property == properties.end ()) {
sLog.exception ("Shader constant pointing to non-existant project property: ", user->get <std::string> ());
}
constant = new Effects::Constants::CShaderConstantProperty (property->second);
} else {
val = it.value ();
}
}
if (val.is_number_float ()) {
constant = new Effects::Constants::CShaderConstantFloat (val.get<float> ());
} else if (val.is_number_integer ()) {
constant = new Effects::Constants::CShaderConstantInteger (val.get<int> ());
} else if (val.is_string ()) {
// try a vector 4 first, then a vector3 and then a vector 2
constant = new Effects::Constants::CShaderConstantVector4 (WallpaperEngine::Core::aToVector4 (val));
} else {
sLog.exception ("unknown shader constant type ", val);
// TODO: REFACTOR THIS SO IT'S NOT SO DEEP INTO THE FUNCTION
if (constant == nullptr) {
if (val.is_number_float ()) {
constant = new Effects::Constants::CShaderConstantFloat (val.get<float> ());
} else if (val.is_number_integer ()) {
constant = new Effects::Constants::CShaderConstantInteger (val.get<int> ());
} else if (val.is_string ()) {
// count the amount of spaces to determine which type of vector we have
std::string value = val;
size_t spaces =
std::count_if (value.begin (), value.end (), [&] (const auto& item) { return item == ' '; });
if (spaces == 1) {
constant =
new Effects::Constants::CShaderConstantVector2 (WallpaperEngine::Core::aToVector2 (value));
} else if (spaces == 2) {
constant =
new Effects::Constants::CShaderConstantVector3 (WallpaperEngine::Core::aToVector3 (value));
} else if (spaces == 3) {
constant =
new Effects::Constants::CShaderConstantVector4 (WallpaperEngine::Core::aToVector4 (value));
} else {
sLog.exception ("unknown shader constant type ", value);
}
} else {
sLog.exception ("unknown shader constant type ", val);
}
}
constants.insert (std::pair (cur.key (), constant));
@ -187,7 +221,7 @@ std::vector<const Images::CMaterial*> CEffect::materialsFromJSON (
}
std::map<int, Images::CMaterial::OverrideInfo> CEffect::overridesFromJSON (
const json::const_iterator& passes_it, const Images::CMaterial* material
const json::const_iterator& passes_it, const Images::CMaterial* material, const CProject& project
) {
std::map<int, Images::CMaterial::OverrideInfo> result;
@ -205,7 +239,7 @@ std::map<int, Images::CMaterial::OverrideInfo> CEffect::overridesFromJSON (
}
if (constants_it != cur.end ()) {
override.constants = CEffect::constantsFromJSON (constants_it);
override.constants = CEffect::constantsFromJSON (constants_it, project);
}
if (textures_it != cur.end ()) {

View File

@ -66,7 +66,7 @@ class CEffect {
protected:
static std::map<std::string, const Core::Objects::Effects::Constants::CShaderConstant*> constantsFromJSON (
const json::const_iterator& constants_it);
const json::const_iterator& constants_it, const CProject& project);
static std::map<std::string, int> combosFromJSON (const json::const_iterator& combos_it);
static std::vector<const Effects::CFBO*> fbosFromJSON (const json::const_iterator& fbos_it);
static std::vector<std::string> dependenciesFromJSON (const json::const_iterator& dependencies_it);
@ -74,7 +74,7 @@ class CEffect {
const json::const_iterator& passes_it, const std::string& name, const CContainer* container,
std::map<int, Images::CMaterial::OverrideInfo>);
static std::map<int, Images::CMaterial::OverrideInfo> overridesFromJSON (
const json::const_iterator& passes_it, const Images::CMaterial* material);
const json::const_iterator& passes_it, const Images::CMaterial* material, const CProject& project);
private:
/** Effect's name */

View File

@ -11,17 +11,17 @@ class CShaderConstant {
public:
explicit CShaderConstant (std::string type);
template <class T> const T* as () const {
template <class T> [[nodiscard]] const T* as () const {
assert (is<T> ());
return reinterpret_cast<const T*> (this);
}
template <class T> T* as () {
template <class T> [[nodiscard]] T* as () {
assert (is<T> ());
return reinterpret_cast<T*> (this);
}
template <class T> bool is () const {
template <class T> [[nodiscard]] bool is () const {
return this->m_type == T::Type;
}

View File

@ -0,0 +1,17 @@
#include "CShaderConstantProperty.h"
using namespace WallpaperEngine::Core::Objects::Effects::Constants;
CShaderConstantProperty::CShaderConstantProperty (const CProperty* property) :
CShaderConstant (Type),
m_property (property) {}
const CProperty* CShaderConstantProperty::getProperty () const {
return this->m_property;
}
std::string CShaderConstantProperty::toString () const {
return "no string representation yet!";
}
const std::string CShaderConstantProperty::Type = "property";

View File

@ -0,0 +1,37 @@
#pragma once
#include "WallpaperEngine/Core/Projects/CProperty.h"
#include "CShaderConstant.h"
#include <string>
namespace WallpaperEngine::Core::Objects::Effects::Constants {
using namespace WallpaperEngine::Core::Projects;
/**
* Shader constant that comes from a property
*/
class CShaderConstantProperty : public CShaderConstant {
public:
// TODO: SUPPORT DEFAULT VALUE?
explicit CShaderConstantProperty (const CProperty* property);
/**
* @return The property this points to
*/
[[nodiscard]] const CProperty* getProperty () const;
/**
* Type string indicator
*/
static const std::string Type;
[[nodiscard]] std::string toString () const override;
protected:
/**
* The backing property
*/
const CProperty* m_property;
};
} // namespace WallpaperEngine::Core::Objects::Effects::Constants

View File

@ -66,24 +66,21 @@ bool CUserSettingBoolean::getDefaultValue () const {
return this->m_default;
}
bool CUserSettingBoolean::processValue (const std::vector<const Projects::CProperty*>& properties) const {
bool CUserSettingBoolean::processValue (const std::map<std::string, const Projects::CProperty*>& properties) const {
if (!this->m_hasSource && !this->m_hasCondition)
return this->getDefaultValue ();
for (const auto cur : properties) {
if (cur->getName () != this->m_source)
continue;
const auto property = properties.find (this->m_source);
if (property != properties.end ()) {
if (!this->m_hasCondition) {
if (cur->is<CPropertyBoolean> ())
return cur->as<CPropertyBoolean> ()->getValue ();
sLog.exception ("Property without condition must match type boolean");
if (property->second->is<CPropertyBoolean> ())
return property->second->as<CPropertyBoolean> ()->getValue ();
}
// TODO: properly validate this as the combos might be more than just strings?
if (cur->is<CPropertyCombo> ())
return cur->as<CPropertyCombo> ()->getValue () == this->m_expectedValue;
if (property->second->is<CPropertyCombo> ())
return property->second->as<CPropertyCombo> ()->getValue () == this->m_expectedValue;
sLog.exception ("Boolean property with condition doesn't match against combo value");
}

View File

@ -15,7 +15,7 @@ class CUserSettingBoolean : public CUserSettingValue {
static const CUserSettingBoolean* fromScalar (const bool value);
static std::string Type;
[[nodiscard]] bool processValue (const std::vector<const Projects::CProperty*>& properties) const;
[[nodiscard]] bool processValue (const std::map<std::string, const Projects::CProperty*>& properties) const;
[[nodiscard]] bool getDefaultValue () const;
private:

View File

@ -63,17 +63,16 @@ double CUserSettingFloat::getDefaultValue () const {
return this->m_default;
}
double CUserSettingFloat::processValue (const std::vector<const Projects::CProperty*>& properties) const {
double CUserSettingFloat::processValue (const std::map<std::string, const Projects::CProperty*>& properties) const {
if (!this->m_hasSource && !this->m_hasCondition)
return this->getDefaultValue ();
for (const auto cur : properties) {
if (cur->getName () != this->m_source)
continue;
const auto property = properties.find (this->m_source);
if (property != properties.end ()) {
if (!this->m_hasCondition) {
if (cur->is<CPropertySlider> ())
return cur->as<CPropertySlider> ()->getValue ();
if (property->second->is<CPropertySlider> ())
return property->second->as<CPropertySlider> ()->getValue ();
sLog.exception ("Property without condition must match type (slider)");
}

View File

@ -15,7 +15,7 @@ class CUserSettingFloat : public CUserSettingValue {
static const CUserSettingFloat* fromScalar (const double value);
static std::string Type;
[[nodiscard]] double processValue (const std::vector<const Projects::CProperty*>& properties) const;
[[nodiscard]] double processValue (const std::map<std::string, const Projects::CProperty*>& properties) const;
[[nodiscard]] double getDefaultValue () const;
private:

View File

@ -64,20 +64,19 @@ const glm::vec3& CUserSettingVector3::getDefaultValue () const {
return this->m_default;
}
const glm::vec3& CUserSettingVector3::processValue (const std::vector<const Projects::CProperty*>& properties) const {
const glm::vec3& CUserSettingVector3::processValue (const std::map<std::string, const Projects::CProperty*>& properties) const {
if (!this->m_hasSource && !this->m_hasCondition)
return this->getDefaultValue ();
for (const auto cur : properties) {
if (cur->getName () != this->m_source)
continue;
const auto property = properties.find (this->m_source);
if (property != properties.end ()) {
if (!this->m_hasCondition) {
if (cur->is<CPropertyColor> ())
return cur->as<CPropertyColor> ()->getValue ();
if (cur->is<CPropertySlider> ())
return {cur->as<CPropertySlider> ()->getValue (), cur->as<CPropertySlider> ()->getValue (),
cur->as<CPropertySlider> ()->getValue ()};
if (property->second->is<CPropertyColor> ())
return property->second->as<CPropertyColor> ()->getValue ();
if (property->second->is<CPropertySlider> ())
return {property->second->as<CPropertySlider> ()->getValue (), property->second->as<CPropertySlider> ()->getValue (),
property->second->as<CPropertySlider> ()->getValue ()};
sLog.exception ("Property without condition must match type (vector3)");
}

View File

@ -17,7 +17,7 @@ class CUserSettingVector3 : public CUserSettingValue {
static const CUserSettingVector3* fromScalar (const glm::vec3 value);
static std::string Type;
[[nodiscard]] const glm::vec3& processValue (const std::vector<const Projects::CProperty*>& properties) const;
[[nodiscard]] const glm::vec3& processValue (const std::map<std::string, const Projects::CProperty*>& properties) const;
[[nodiscard]] const glm::vec3& getDefaultValue () const;
private:

View File

@ -103,12 +103,10 @@ CImage::CImage (Wallpapers::CScene* scene, const Core::Objects::CImage* image) :
this->m_currentMainFBO = this->m_mainFBO =
scene->createFBO (nameA.str (), ITexture::TextureFormat::ARGB8888, this->m_texture->getFlags (), 1,
this->m_texture->getRealWidth (), this->m_texture->getRealHeight (),
this->m_texture->getRealWidth (), this->m_texture->getRealHeight ());
size.x, size.y, size.x, size.y);
this->m_currentSubFBO = this->m_subFBO =
scene->createFBO (nameB.str (), ITexture::TextureFormat::ARGB8888, this->m_texture->getFlags (), 1,
this->m_texture->getRealWidth (), this->m_texture->getRealHeight (),
this->m_texture->getRealWidth (), this->m_texture->getRealHeight ());
size.x, size.y, size.x, size.y);
// build a list of vertices, these might need some change later (or maybe invert the camera)
GLfloat sceneSpacePosition [] = {this->m_pos.x, this->m_pos.y, 0.0f, this->m_pos.x, this->m_pos.w, 0.0f,

View File

@ -2,6 +2,12 @@
#include "WallpaperEngine/Render/CFBO.h"
#include <sstream>
#include "WallpaperEngine/Core/Projects/CProperty.h"
#include "WallpaperEngine/Core/Projects/CPropertyColor.h"
#include "WallpaperEngine/Core/Projects/CPropertyCombo.h"
#include "WallpaperEngine/Core/Projects/CPropertySlider.h"
#include "WallpaperEngine/Core/Projects/CPropertyBoolean.h"
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloat.h"
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableInteger.h"
@ -12,7 +18,10 @@
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstant.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector2.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector3.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector4.h"
#include "WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantProperty.h"
#include "WallpaperEngine/Logging/CLog.h"
using namespace WallpaperEngine::Core::Objects::Effects::Constants;
@ -613,7 +622,7 @@ template <typename T> void CPass::addUniform (const std::string& name, UniformTy
T* newValue = new T (value);
// uniform found, add it to the list
this->m_uniforms.insert (std::make_pair (name, new UniformEntry (id, name, type, newValue, 1)));
this->m_uniforms.insert_or_assign (name, new UniformEntry (id, name, type, newValue, 1));
}
template <typename T> void CPass::addUniform (const std::string& name, UniformType type, T* value, int count) {
@ -625,7 +634,7 @@ template <typename T> void CPass::addUniform (const std::string& name, UniformTy
return;
// uniform found, add it to the list
this->m_uniforms.insert (std::make_pair (name, new UniformEntry (id, name, type, value, count)));
this->m_uniforms.insert_or_assign (name, new UniformEntry (id, name, type, value, count));
}
template <typename T> void CPass::addUniform (const std::string& name, UniformType type, T** value) {
@ -637,8 +646,8 @@ template <typename T> void CPass::addUniform (const std::string& name, UniformTy
return;
// uniform found, add it to the list
this->m_referenceUniforms.insert (
std::make_pair (name, new ReferenceUniformEntry (id, name, type, reinterpret_cast<const void**> (value))));
this->m_referenceUniforms.insert_or_assign (
name, new ReferenceUniformEntry (id, name, type, reinterpret_cast<const void**> (value)));
}
void CPass::setupTextures () {
@ -672,6 +681,18 @@ void CPass::setupTextures () {
}
void CPass::setupShaderVariables () {
for (const auto& cur : this->m_shader->getVertex ().getParameters ())
if (this->m_uniforms.find (cur->getName ()) == this->m_uniforms.end ())
this->addUniform (cur);
for (const auto& cur : this->m_shader->getVertex ().getParameters ())
if (this->m_uniforms.find (cur->getName ()) == this->m_uniforms.end ())
this->addUniform (cur);
if (this->getMaterial ()->getImage ()->getImage ()->getName ()== "Blur") {
sLog.out("girl!");
}
// find variables in the shaders and set the value with the constants if possible
for (const auto& [name, value] : this->m_pass->getConstants ()) {
const auto parameters = this->m_shader->findParameter (name);
@ -708,20 +729,25 @@ void CPass::setupShaderVariables () {
auto* val = value->as<CShaderConstantVector4> ();
this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y, val->getValue ()->z});
} else if (value->is<CShaderConstantVector3> () && var->is<CShaderVariableVector2> ()) {
auto* val = value->as<CShaderConstantVector3> ();
this->addUniform (var->getName (), {val->getValue ()->x, val->getValue ()->y});
} else if (value->is<CShaderConstantProperty> ()) {
const auto property = value->as<CShaderConstantProperty> ();
// resolve the property to a current setting
// resolve property to a user setting and store that value instead
// properties have different kinds of values
sLog.out("property!");
} else {
sLog.exception ("Constant ", name,
" type does not match pixel/vertex shader variable and cannot be converted (",
value->getType (), " to ", var->getType ());
}
}
for (const auto& cur : this->m_shader->getVertex ().getParameters ())
if (this->m_uniforms.find (cur->getName ()) == this->m_uniforms.end ())
this->addUniform (cur);
for (const auto& cur : this->m_shader->getVertex ().getParameters ())
if (this->m_uniforms.find (cur->getName ()) == this->m_uniforms.end ())
this->addUniform (cur);
}
// define some basic methods for the template
@ -741,6 +767,65 @@ void CPass::addUniform (CShaderVariable* value) {
else if (value->is<CShaderVariableVector4> ())
this->addUniform (value->getName (),
static_cast<const glm::vec4*> (value->as<CShaderVariableVector4> ()->getValue ()));
else
sLog.exception ("Trying to add an uniform from an unknown type: ", value->getName ());
}
void CPass::addUniform (CShaderVariable* value, CProperty* setting) {
// TODO: CHECK THIS? CAN WE KEEP A REF SO THE VALUES ARE AUTOMATICALLY UPDATED?
// TODO: MAYBE PROVIDE PUBLIC CASTS FOR EVERYTHING INSTEAD OF MANUALLY DOING IT EVERYWHERE
if (value->is<CShaderVariableVector2> ()) {
if (setting->is<CPropertySlider> ()) {
const auto slider = setting->as<CPropertySlider> ();
// sliders have to be converted to vector2
this->addUniform (value->getName (), {slider->getValue (), slider->getValue ()});
} else if (setting->is<CPropertyColor> ()) {
const auto color = setting->as<CPropertyColor> ();
// colors are vec3, we just need vec2
this->addUniform (value->getName (), {color->getValue ().x, color->getValue ().y});
} else {
sLog.error ("Cannot convert setting ", setting->getName (), " to ", value->getName (), ". Using default value");
this->addUniform (value);
}
} else if (value->is<CShaderVariableFloat> ()) {
if (setting->is<CPropertySlider> ()) {
const auto slider = setting->as<CPropertySlider> ();
this->addUniform (value->getName (), slider->getValue ());
} else if (setting->is<CPropertyColor>()) {
const auto color = setting->as<CPropertyColor> ();
this->addUniform (value->getName (), &color->getValue ().x);
} else {
sLog.error ("Cannot convert setting ", setting->getName (), " to ", value->getName (), ". Using default value");
this->addUniform (value);
}
} else if (value->is<CShaderVariableVector3> ()) {
if (setting->is<CPropertySlider> ()) {
const auto slider = setting->as<CPropertySlider> ();
this->addUniform (value->getName (), {slider->getValue (), slider->getValue (), slider->getValue ()});
} else if (setting->is<CPropertyColor>()) {
const auto color = setting->as<CPropertyColor> ();
this->addUniform (value->getName (), color->getValue ());
} else {
sLog.error ("Cannot convert setting ", setting->getName (), " to ", value->getName (), ". Using default value");
this->addUniform (value);
}
} else if (value->is<CShaderVariableVector4> ()) {
if (setting->is<CPropertySlider> ()) {
const auto slider = setting->as<CPropertySlider> ();
this->addUniform (value->getName (), {slider->getValue (), slider->getValue (), slider->getValue (), slider->getValue ()});
} else {
sLog.error ("Cannot convert setting ", setting->getName (), " to ", value->getName (), ". Using default value");
this->addUniform (value);
}
} else {
sLog.error ("Cannot convert setting ", setting->getName (), " to ", value->getName (), ". Using default value");
this->addUniform (value);
}
}
void CPass::addUniform (const std::string& name, CShaderConstant* value) {
@ -749,8 +834,14 @@ void CPass::addUniform (const std::string& name, CShaderConstant* value) {
this->addUniform (name, value->as<CShaderConstantFloat> ()->getValue ());
else if (value->is<CShaderConstantInteger> ())
this->addUniform (name, value->as<CShaderConstantInteger> ()->getValue ());
else if (value->is<CShaderConstantVector2> ())
this->addUniform (name, value->as<CShaderConstantVector2> ()->getValue ());
else if (value->is<CShaderConstantVector3> ())
this->addUniform (name, value->as<CShaderConstantVector3> ()->getValue ());
else if (value->is<CShaderConstantVector4> ())
this->addUniform (name, value->as<CShaderConstantVector4> ()->getValue ());
else
sLog.exception ("Trying to add an uniform from an unknown type: ", name);
}
void CPass::addUniform (const std::string& name, const CShaderConstant* value) {
@ -759,8 +850,14 @@ void CPass::addUniform (const std::string& name, const CShaderConstant* value) {
this->addUniform (name, value->as<CShaderConstantFloat> ()->getValue ());
else if (value->is<CShaderConstantInteger> ())
this->addUniform (name, value->as<CShaderConstantInteger> ()->getValue ());
else if (value->is<CShaderConstantVector2> ())
this->addUniform (name, value->as<CShaderConstantVector2> ()->getValue ());
else if (value->is<CShaderConstantVector3> ())
this->addUniform (name, value->as<CShaderConstantVector3> ()->getValue ());
else if (value->is<CShaderConstantVector4> ())
this->addUniform (name, value->as<CShaderConstantVector4> ()->getValue ());
else
sLog.exception ("Trying to add an uniform from an unknown type: ", name);
}
void CPass::addUniform (const std::string& name, int value) {
this->addUniform (name, UniformType::Integer, value);

View File

@ -10,12 +10,13 @@
#include "WallpaperEngine/Render/Objects/Effects/CMaterial.h"
#include "WallpaperEngine/Render/Shaders/CShader.h"
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
#include "WallpaperEngine/Core/UserSettings/CUserSettingValue.h"
#include "WallpaperEngine/Render/Helpers/CContextAware.h"
namespace WallpaperEngine::Render::Objects::Effects {
using namespace WallpaperEngine::Assets;
using namespace WallpaperEngine::Render::Shaders::Variables;
using namespace WallpaperEngine::Core::Projects;
using namespace WallpaperEngine::Core::Objects::Effects::Constants;
class CMaterial;
@ -108,6 +109,7 @@ class CPass final : public Helpers::CContextAware {
void setupAttributes ();
void addAttribute (const std::string& name, GLint type, GLint elements, const GLuint* value);
void addUniform (CShaderVariable* value);
void addUniform (CShaderVariable* value, CProperty* setting);
void addUniform (const std::string& name, CShaderConstant* value);
void addUniform (const std::string& name, const CShaderConstant* value);
void addUniform (const std::string& name, int value);

View File

@ -18,11 +18,11 @@ using namespace WallpaperEngine::Assets;
namespace WallpaperEngine::Render::Shaders {
CShader::CShader (
const CContainer* container, std::string filename, std::map<std::string, int> combos,
const CContainer* container, std::string filename, const std::map<std::string, int>& combos,
const std::map<int, std::string>& textures, const std::map<std::string, const CShaderConstant*>& constants
) :
m_file (std::move (filename)),
m_combos (std::move(combos)),
m_combos (combos),
m_passTextures (textures),
m_vertex (
CGLSLContext::UnitType_Vertex, filename, container->readVertexShader (filename),
@ -30,6 +30,9 @@ CShader::CShader (
m_fragment (
CGLSLContext::UnitType_Fragment, filename, container->readFragmentShader (filename),
container, constants, textures, combos) {
// link shaders between them
this->m_vertex.linkToUnit (&this->m_fragment);
this->m_fragment.linkToUnit (&this->m_vertex);
}

View File

@ -43,7 +43,7 @@ class CShader {
*/
CShader (
const CContainer* container, std::string filename,
std::map<std::string, int> combos,const std::map<int, std::string>& textures,
const std::map<std::string, int>& combos,const std::map<int, std::string>& textures,
const std::map<std::string, const CShaderConstant*>& constants);
/**
* @return The vertex's shader coude for OpenGL to use
@ -93,7 +93,7 @@ class CShader {
/**
* The combos the shader should be generated with
*/
std::map<std::string, int> m_combos;
const std::map<std::string, int>& m_combos;
/**
* The list of textures the pass knows about
*/

View File

@ -79,6 +79,16 @@ void CShaderUnit::preprocess () {
this->preprocessVariables ();
this->preprocessIncludes ();
this->preprocessRequires ();
// replace gl_FragColor with the equivalent
std::string from = "gl_FragColor";
std::string to = "out_FragColor";
size_t start_pos = 0;
while ((start_pos = this->m_preprocessed.find (from, start_pos)) != std::string::npos) {
this->m_preprocessed.replace (start_pos, from.length (), to);
start_pos += to.length (); // Handles case where 'to' is a substring of 'from'
}
}
void CShaderUnit::preprocessVariables () {
@ -344,6 +354,9 @@ void CShaderUnit::parseComboConfiguration (const std::string& content, int defau
void CShaderUnit::parseParameterConfiguration (const std::string& type, const std::string& name,
const std::string& content) {
if (name == "g_Speed") {
sLog.out("speed!");
}
json data = json::parse (content);
const auto material = data.find ("material");
const auto defvalue = data.find ("default");
@ -365,37 +378,23 @@ void CShaderUnit::parseParameterConfiguration (const std::string& type, const st
// TODO: SUPPORT VALUES FOR ALL THESE TYPES
if (type == "vec4") {
parameter = new Variables::CShaderVariableVector4 (
constant == this->m_constants.end () ? WallpaperEngine::Core::aToVector4 (*defvalue)
: *constant->second->as<CShaderConstantVector4> ()->getValue ());
parameter = new Variables::CShaderVariableVector4(WallpaperEngine::Core::aToVector4 (*defvalue));
} else if (type == "vec3") {
parameter = new Variables::CShaderVariableVector3 (
constant == this->m_constants.end () ? WallpaperEngine::Core::aToVector3 (*defvalue)
: *constant->second->as<CShaderConstantVector4> ()->getValue ());
parameter = new Variables::CShaderVariableVector3 (WallpaperEngine::Core::aToVector3 (*defvalue));
} else if (type == "vec2") {
parameter = new Variables::CShaderVariableVector2 (WallpaperEngine::Core::aToVector2 (*defvalue));
} else if (type == "float") {
float value = 0;
if (constant == this->m_constants.end ())
value = defvalue->get<float> ();
else if (constant->second->is<CShaderConstantFloat> ())
value = *constant->second->as<CShaderConstantFloat> ()->getValue ();
else if (constant->second->is<CShaderConstantInteger> ())
value = *constant->second->as<CShaderConstantInteger> ()->getValue ();
parameter = new Variables::CShaderVariableFloat (value);
if (defvalue->is_string ()) {
parameter = new Variables::CShaderVariableFloat (strtof32 ((defvalue->get<std::string> ()).c_str (), nullptr));
} else {
parameter = new Variables::CShaderVariableFloat (*defvalue);
}
} else if (type == "int") {
int value = 0;
if (constant == this->m_constants.end ())
value = defvalue->get<int> ();
else if (constant->second->is<CShaderConstantFloat> ())
value = *constant->second->as<CShaderConstantFloat> ()->getValue ();
else if (constant->second->is<CShaderConstantInteger> ())
value = *constant->second->as<CShaderConstantInteger> ()->getValue ();
parameter = new Variables::CShaderVariableInteger (value);
if (defvalue->is_string ()) {
parameter = new Variables::CShaderVariableInteger (strtol((defvalue->get<std::string> ()).c_str (), nullptr, 10));
} else {
parameter = new Variables::CShaderVariableInteger (*defvalue);
}
} else if (type == "sampler2D" || type == "sampler2DComparison") {
// samplers can have special requirements, check what sampler we're working with and create definitions
// if needed
@ -410,55 +409,75 @@ void CShaderUnit::parseParameterConfiguration (const std::string& type, const st
if (combo != data.end ()) {
// if the texture exists (and is not null), add to the combo
auto texture = this->m_textures.find (index);
bool comboValue = true;
bool isRequired = false;
int comboValue = 1;
if (textureName == data.end () && texture == this->m_textures.end ()) {
// is this required?
if (require == data.end ()) {
// if no require information we assume this one is always required, so signal it as such
//sLog.exception ("Shader ", this->m_file, " requires a texture that is not present");
comboValue = false;
}
// some require conditions are set, validate these
if (requireany == data.end () || !requireany->get<bool> ()) {
// all values have to exist for this to be required
for (const auto& item : require->items ()) {
const std::string& macro = item.key ();
const auto it = this->m_combos.find (macro);
// these can not exist and that'd be fine, we just care about the values
if (it != this->m_combos.end () && it->second == item.value ()) {
continue;
}
comboValue = false;
break;
}
} else {
comboValue = false;
if (texture != this->m_textures.end ()) {
// nothing extra to do, the texture exists, the combo must be set
// these tend to not have default value
isRequired = true;
} else if (require != data.end ()) {
// this is required based on certain conditions
if (requireany != data.end () && requireany->get <bool> ()) {
// any of the values set are valid, check for them
for (const auto& item : require->items ()) {
const std::string& macro = item.key ();
const auto it = this->m_combos.find (macro);
// these can not exist and that'd be fine, we just care about the values
// if any of the values matched, this option is required
if (it == this->m_combos.end () || it->second != item.value ()) {
continue;
isRequired = true;
break;
}
}
} else {
isRequired = true;
comboValue = true;
// all values must match for it to be required
for (const auto& item : require->items ()) {
const std::string& macro = item.key ();
const auto it = this->m_combos.find (macro);
// these can not exist and that'd be fine, we just care about the values
if (it != this->m_combos.end () && it->second == item.value ()) {
isRequired = false;
break;
}
}
}
}
// add the new combo to the list
this->m_discoveredCombos.insert (std::make_pair (*combo, comboValue));
if (isRequired && texture == this->m_textures.end ()) {
if (defvalue == data.end ()) {
isRequired = false;
} else {
// is the combo registered already?
// if not, add it with the default value
const auto combo_it = this->m_combos.find (*combo);
// textures linked to combos need to be tracked too
if (this->m_usedCombos.find (*combo) == this->m_usedCombos.end ())
this->m_usedCombos.insert (std::make_pair (*combo, true));
// there's already a combo providing this value, so it doesn't need to be added
if (combo_it != this->m_combos.end ()) {
isRequired = false;
// otherwise a default value must be used
} else if (defvalue->is_string ()) {
comboValue = strtol (defvalue->get <std::string> ().c_str (), nullptr, 10);
} else if (defvalue->is_number()) {
comboValue = *defvalue;
} else {
sLog.exception ("Cannot determine default value for combo ", combo->get <std::string> (), " because it's not specified by the shader and is not given a default value: ", this->m_file);
}
}
}
if (isRequired) {
// add the new combo to the list
this->m_discoveredCombos.insert (std::make_pair (*combo, comboValue));
// textures linked to combos need to be tracked too
if (this->m_usedCombos.find (*combo) == this->m_usedCombos.end ())
this->m_usedCombos.insert (std::make_pair (*combo, true));
}
}
if (textureName != data.end ())
@ -471,7 +490,7 @@ void CShaderUnit::parseParameterConfiguration (const std::string& type, const st
return;
}
if (material != data.end ()) {
if (material != data.end () && parameter != nullptr) {
parameter->setIdentifierName (*material);
parameter->setName (name);