feat(materialx): Add vertex data block handling in shader generation

This commit is contained in:
2026-01-06 16:43:34 +00:00
parent 9f2faa389d
commit 7ec101cbf6

View File

@@ -10,11 +10,73 @@
#include <MaterialXGenShader/Util.h>
#include <MaterialXRender/Util.h>
#include <optional>
#include <stdexcept>
#include <string>
namespace sdl3cpp::services::impl {
namespace mx = MaterialX;
namespace {
bool HasVertexDataBlock(const std::string& source) {
return source.find("VertexData") != std::string::npos
&& source.find("vd;") != std::string::npos;
}
std::optional<std::string> ExtractVertexDataBlock(const std::string& source) {
const std::string marker = "VertexData";
const std::string instance = "vd;";
size_t blockPos = source.find(marker);
if (blockPos == std::string::npos) {
return std::nullopt;
}
size_t instancePos = source.find(instance, blockPos);
if (instancePos == std::string::npos) {
return std::nullopt;
}
size_t lineStart = source.rfind('\n', blockPos);
if (lineStart == std::string::npos) {
lineStart = 0;
} else {
++lineStart;
}
size_t lineEnd = source.find('\n', instancePos);
if (lineEnd == std::string::npos) {
lineEnd = source.size();
}
return source.substr(lineStart, lineEnd - lineStart);
}
std::string ToVertexOutputBlock(std::string block) {
const std::string inToken = " in VertexData";
const std::string outToken = " out VertexData";
size_t tokenPos = block.find(inToken);
if (tokenPos != std::string::npos) {
block.replace(tokenPos, inToken.size(), outToken);
return block;
}
tokenPos = block.find("in VertexData");
if (tokenPos != std::string::npos) {
block.replace(tokenPos, std::string("in VertexData").size(), "out VertexData");
}
return block;
}
void InsertAfterVersion(std::string& source, const std::string& block) {
size_t lineEnd = source.find('\n');
if (lineEnd == std::string::npos) {
source.append("\n");
source.append(block);
source.append("\n");
return;
}
++lineEnd;
source.insert(lineEnd, block + "\n");
}
} // namespace
MaterialXShaderGenerator::MaterialXShaderGenerator(std::shared_ptr<ILogger> logger)
: logger_(std::move(logger)) {}
@@ -159,6 +221,27 @@ ShaderPaths MaterialXShaderGenerator::Generate(const MaterialXConfig& config,
ShaderPaths paths;
paths.vertexSource = shader->getSourceCode(mx::Stage::VERTEX);
paths.fragmentSource = shader->getSourceCode(mx::Stage::PIXEL);
const bool vertexHasBlock = HasVertexDataBlock(paths.vertexSource);
const bool fragmentHasBlock = HasVertexDataBlock(paths.fragmentSource);
if (!vertexHasBlock && fragmentHasBlock) {
auto fragmentBlock = ExtractVertexDataBlock(paths.fragmentSource);
if (fragmentBlock) {
std::string vertexBlock = ToVertexOutputBlock(*fragmentBlock);
InsertAfterVersion(paths.vertexSource, vertexBlock);
if (logger_) {
logger_->Trace("MaterialXShaderGenerator", "Generate",
"vertexDataBlock=inserted");
}
} else if (logger_) {
logger_->Trace("MaterialXShaderGenerator", "Generate",
"vertexDataBlock=missing");
}
} else if (logger_) {
logger_->Trace("MaterialXShaderGenerator", "Generate",
"vertexDataBlock=" + std::string(vertexHasBlock ? "present" : "absent") +
", fragmentVertexDataBlock=" + std::string(fragmentHasBlock ? "present" : "absent"));
}
return paths;
}