~ shader precompilation should be done in order to ensure that the vertex shader has information discovered by the fragment shader (like new combos) should fix some effects on backgrounds

+ added partial support for shader constant values from the scene.json

Signed-off-by: Alexis Maiquez <almamu@almamu.com>
This commit is contained in:
Alexis Maiquez 2021-08-08 08:41:03 +02:00
parent 8d0eb6d63c
commit 537acb97bd
3 changed files with 86 additions and 23 deletions

View File

@ -42,12 +42,18 @@ CPass::CPass (Irrlicht::CContext* context, CMaterial* material, Core::Objects::I
irr::io::path fragPath = this->m_context->resolveFragmentShader (pass->getShader ());
// register fragment shader
this->m_fragShader = new Render::Shaders::Compiler (
this->m_context, fragPath, Render::Shaders::Compiler::Type::Type_Pixel, pass->getCombos (), false
this->m_context, fragPath, Render::Shaders::Compiler::Type::Type_Pixel,
pass->getCombos (), pass->getConstants (), false
);
// compile fragment shader
this->m_fragShader->precompile ();
// register vertex shader, combos come from the fragment as it can sometimes define them
this->m_vertShader = new Render::Shaders::Compiler (
this->m_context, vertPath, Render::Shaders::Compiler::Type::Type_Vertex, this->m_fragShader->getCombos (), false
this->m_context, vertPath, Render::Shaders::Compiler::Type::Type_Vertex,
this->m_fragShader->getCombos (), pass->getConstants (), false
);
// compile vertex shader
this->m_vertShader->precompile ();
this->setupTextures ();
// initialize material data and compile shader used for this pass
this->m_irrlichtMaterial.Wireframe = false;
@ -56,8 +62,8 @@ CPass::CPass (Irrlicht::CContext* context, CMaterial* material, Core::Objects::I
this->m_irrlichtMaterial.setFlag (irr::video::EMF_BLEND_OPERATION, true);
this->m_irrlichtMaterial.MaterialType = (irr::video::E_MATERIAL_TYPE)
this->m_context->getDevice ()->getVideoDriver ()->getGPUProgrammingServices ()->addHighLevelShaderMaterial (
this->m_vertShader->precompile ().c_str (), "main", irr::video::EVST_VS_2_0,
this->m_fragShader->precompile ().c_str (), "main", irr::video::EPST_PS_2_0,
this->m_vertShader->getCompiled ().c_str (), "main", irr::video::EVST_VS_2_0,
this->m_fragShader->getCompiled ().c_str (), "main", irr::video::EPST_PS_2_0,
this, irr::video::EMT_TRANSPARENT_ALPHA_CHANNEL, 0, irr::video::EGSL_DEFAULT
);

View File

@ -9,6 +9,9 @@
// shader compiler
#include <WallpaperEngine/Render/Shaders/Compiler.h>
#include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantVector3.h>
#include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantInteger.h>
#include <WallpaperEngine/Core/Objects/Effects/Constants/CShaderConstantFloat.h>
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariable.h"
#include "WallpaperEngine/Render/Shaders/Variables/CShaderVariableFloat.h"
@ -21,14 +24,21 @@ using namespace WallpaperEngine::Core;
namespace WallpaperEngine::Render::Shaders
{
Compiler::Compiler (Irrlicht::CContext* context, irr::io::path& file, Type type, std::map<std::string, int> combos, bool recursive) :
m_combos (std::move(combos)),
Compiler::Compiler (
Irrlicht::CContext* context,
irr::io::path& file,
Type type,
std::map<std::string, int> combos,
const std::map<std::string, CShaderConstant*>& constants,
bool recursive) :
m_combos (combos),
m_recursive (recursive),
m_type (type),
m_file (file),
m_error (""),
m_errorInfo (""),
m_context (context)
m_context (context),
m_constants (constants)
{
this->m_content =WallpaperEngine::FileSystem::loadFullFile (file);
}
@ -209,9 +219,11 @@ namespace WallpaperEngine::Render::Shaders
// now compile the new shader
// do not include the default header (as it's already included in the parent)
Compiler loader (this->m_context, shader, this->m_type, this->m_combos, true);
Compiler loader (this->m_context, shader, this->m_type, this->m_combos, this->m_constants, true);
return loader.precompile ();
loader.precompile ();
return loader.getCompiled ();
}
std::string Compiler::lookupReplaceSymbol (std::string symbol)
@ -233,7 +245,12 @@ namespace WallpaperEngine::Render::Shaders
return symbol;
}
std::string Compiler::precompile()
std::string& Compiler::getCompiled ()
{
return this->m_compiledContent;
}
void Compiler::precompile()
{
#define BREAK_IF_ERROR if (this->m_error == true) { throw std::runtime_error ("ERROR PRE-COMPILING SHADER" + this->m_errorInfo); }
// parse the shader and find #includes and such things and translate them to the correct name
@ -475,10 +492,11 @@ namespace WallpaperEngine::Render::Shaders
if (this->m_recursive == false)
{
std::cout << "======================== COMPILED SHADER " << this->m_file.c_str () << " ========================" << std::endl;
std::cout << this->m_compiledContent << std::endl;
std::cout << finalCode << std::endl;
}
return finalCode;
// store the final final code here
this->m_compiledContent = finalCode;
#undef BREAK_IF_ERROR
}
@ -526,16 +544,19 @@ namespace WallpaperEngine::Render::Shaders
auto range = data.find ("range");
// this is not a real parameter
if (material == data.end () || defvalue == data.end ())
if (material == data.end ())
return;
auto constant = this->m_constants.find (*material);
if (constant == this->m_constants.end () && defvalue == data.end ())
{
if (type != "sampler2D")
throw std::runtime_error ("cannot parse parameter info for " + name);
return;
throw std::runtime_error ("cannot parse parameter data");
}
Variables::CShaderVariable* parameter = nullptr;
// TODO: SUPPORT VALUES FOR ALL THESE TYPES
if (type == "vec4")
{
parameter = new Variables::CShaderVariableVector4 (
@ -545,7 +566,9 @@ namespace WallpaperEngine::Render::Shaders
else if (type == "vec3")
{
parameter = new Variables::CShaderVariableVector3 (
WallpaperEngine::Core::ato3vf (*defvalue)
constant == this->m_constants.end ()
? WallpaperEngine::Core::ato3vf (*defvalue)
: *(*constant).second->as <CShaderConstantVector3> ()->getValue ()
);
}
else if (type == "vec2")
@ -556,11 +579,29 @@ namespace WallpaperEngine::Render::Shaders
}
else if (type == "float")
{
parameter = new Variables::CShaderVariableFloat ((*defvalue).get <irr::f32> ());
irr::f32 value = 0;
if (constant == this->m_constants.end ())
value = (*defvalue).get <irr::f32> ();
else if ((*constant).second->is <CShaderConstantFloat> () == true)
value = *(*constant).second->as <CShaderConstantFloat> ()->getValue ();
else if ((*constant).second->is <CShaderConstantInteger> () == true)
value = *(*constant).second->as <CShaderConstantInteger> ()->getValue ();
parameter = new Variables::CShaderVariableFloat (value);
}
else if (type == "int")
{
parameter = new Variables::CShaderVariableInteger ((*defvalue).get <irr::s32> ());
irr::s32 value = 0;
if (constant == this->m_constants.end ())
value = (*defvalue).get <irr::s32> ();
else if ((*constant).second->is <CShaderConstantFloat> () == true)
value = *(*constant).second->as <CShaderConstantFloat> ()->getValue ();
else if ((*constant).second->is <CShaderConstantInteger> () == true)
value = *(*constant).second->as <CShaderConstantInteger> ()->getValue ();
parameter = new Variables::CShaderVariableInteger (value);
}
else if (type == "sampler2D")
{

View File

@ -16,6 +16,7 @@
namespace WallpaperEngine::Render::Shaders
{
using json = nlohmann::json;
using namespace WallpaperEngine::Core::Objects::Effects::Constants;
/**
* A basic shader loader that adds basic function definitions to every loaded shader
@ -50,18 +51,29 @@ namespace WallpaperEngine::Render::Shaders
* @param file The file to load
* @param type The type of shader
* @param combos Settings for the shader
* @param constants Default values for shader variables
* @param recursive Whether the compiler should add base definitions or not
*/
Compiler (Irrlicht::CContext* context, irr::io::path& file, Type type, std::map<std::string, int> combos, bool recursive = false);
Compiler (
Irrlicht::CContext* context,
irr::io::path& file,
Type type,
std::map<std::string, int> combos,
const std::map<std::string, CShaderConstant*>& constants,
bool recursive = false
);
/**
* Performs the actual pre-compilation/pre-processing over the shader files
* This step is kinda big, replaces variables names on sVariableReplacement,
* ensures #include directives are correctly handled
* and takes care of attribute comments for the wallpaper engine specifics
*
* @return The shader contents ready to be used by OpenGL
*/
std::string precompile ();
void precompile ();
/**
* @return The compiled shader's text (if available)
*/
std::string& getCompiled ();
/**
* Searches the list of parameters available for the parameter with the given value
*
@ -225,6 +237,10 @@ namespace WallpaperEngine::Render::Shaders
* The combos the shader should be generated with
*/
std::map <std::string, int> m_combos;
/**
* The shader constants with values for variables inside the shader
*/
const std::map<std::string, CShaderConstant*>& m_constants;
/**
* Whether this compilation is a recursive one or not
*/