|
@@ -307,19 +307,70 @@ void ShaderUnit::preprocessIncludes () {
|
|
|
|
|
|
|
|
void ShaderUnit::preprocessRequires () {
|
|
void ShaderUnit::preprocessRequires () {
|
|
|
size_t start = 0, end = 0;
|
|
size_t start = 0, end = 0;
|
|
|
- // comment out requires
|
|
|
|
|
|
|
+
|
|
|
while ((start = this->m_preprocessed.find ("#require", end)) != std::string::npos) {
|
|
while ((start = this->m_preprocessed.find ("#require", end)) != std::string::npos) {
|
|
|
- // TODO: CHECK FOR ERRORS HERE
|
|
|
|
|
const size_t lineEnd = this->m_preprocessed.find_first_of ('\n', start);
|
|
const size_t lineEnd = this->m_preprocessed.find_first_of ('\n', start);
|
|
|
- sLog.out ("Shader has a require block ", this->m_preprocessed.substr (start, lineEnd - start));
|
|
|
|
|
- // replace the first two letters with a comment so the filelength doesn't change
|
|
|
|
|
|
|
+
|
|
|
|
|
+ const size_t nameStart = start + std::string ("#require ").length ();
|
|
|
|
|
+
|
|
|
|
|
+ if (nameStart >= lineEnd) {
|
|
|
|
|
+ sLog.error ("Malformed #require directive (no module name) in shader ", this->m_file);
|
|
|
|
|
+ end = lineEnd;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ std::string moduleName = this->m_preprocessed.substr (nameStart, lineEnd - nameStart);
|
|
|
|
|
+
|
|
|
|
|
+ while (!moduleName.empty () && (moduleName.back () == ' ' || moduleName.back () == '\r')) {
|
|
|
|
|
+ moduleName.pop_back ();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (moduleName.empty ()) {
|
|
|
|
|
+ sLog.error ("Malformed #require directive (empty module name) in shader ", this->m_file);
|
|
|
|
|
+ end = lineEnd;
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sLog.out ("Resolving require module: ", moduleName, " in shader ", this->m_file);
|
|
|
|
|
+
|
|
|
|
|
+ std::string moduleCode = this->resolveRequireModule (moduleName);
|
|
|
|
|
+
|
|
|
|
|
+ // comment out the #require directive
|
|
|
this->m_preprocessed = this->m_preprocessed.replace (start, 2, "//");
|
|
this->m_preprocessed = this->m_preprocessed.replace (start, 2, "//");
|
|
|
|
|
|
|
|
- // go to the end of the line
|
|
|
|
|
- end = lineEnd;
|
|
|
|
|
|
|
+ if (!moduleCode.empty ()) {
|
|
|
|
|
+ // insert the generated code directly into m_preprocessed at the #require location
|
|
|
|
|
+ // (m_includes was already consumed by preprocessIncludes, so appending there would be lost)
|
|
|
|
|
+ this->m_preprocessed.insert (start, moduleCode);
|
|
|
|
|
+ end = start + moduleCode.length ();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ end = lineEnd;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+std::string ShaderUnit::resolveRequireModule (const std::string& moduleName) const {
|
|
|
|
|
+ if (moduleName == "LightingV1") {
|
|
|
|
|
+ return this->generateLightingV1 ();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sLog.error ("Unknown #require module: ", moduleName, " in shader ", this->m_file);
|
|
|
|
|
+ return "";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+std::string ShaderUnit::generateLightingV1 () const {
|
|
|
|
|
+ // PerformLighting_V1 is dynamically generated by Wallpaper Engine based on the scene's
|
|
|
|
|
+ // light sources. Since linux-wallpaperengine does not yet support light objects, we
|
|
|
|
|
+ // generate a stub that returns no dynamic light contribution.
|
|
|
|
|
+ return "// begin of generated module LightingV1\n"
|
|
|
|
|
+ "vec3 PerformLighting_V1(vec3 worldPos, vec3 albedo, vec3 normal, vec3 viewDir,\n"
|
|
|
|
|
+ " vec3 specularTint, vec3 baseReflectance, float roughness, float metallic)\n"
|
|
|
|
|
+ "{\n"
|
|
|
|
|
+ " return vec3(0.0);\n"
|
|
|
|
|
+ "}\n"
|
|
|
|
|
+ "// end of generated module LightingV1\n";
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void ShaderUnit::parseComboConfiguration (const std::string& content, const int defaultValue) {
|
|
void ShaderUnit::parseComboConfiguration (const std::string& content, const int defaultValue) {
|
|
|
// TODO: SUPPORT REQUIRES SO WE PROPERLY FOLLOW THE REQUIRED CHAIN
|
|
// TODO: SUPPORT REQUIRES SO WE PROPERLY FOLLOW THE REQUIRED CHAIN
|
|
|
const auto data = JSON::parse (content);
|
|
const auto data = JSON::parse (content);
|