mirror of
https://github.com/johndoe6345789/SDL3CPlusPlus.git
synced 2026-04-28 23:54:59 +00:00
feat(shader): Update shader handling to support multiple shader keys across various components
This commit is contained in:
@@ -741,7 +741,7 @@ local function create_static_cube(position, scale, color, shader_key)
|
||||
vertices = vertices,
|
||||
indices = cube_indices,
|
||||
compute_model_matrix = compute_model_matrix,
|
||||
shader_key = resolved_shader,
|
||||
shader_keys = {resolved_shader},
|
||||
}
|
||||
end
|
||||
|
||||
@@ -758,7 +758,7 @@ local function create_skybox()
|
||||
vertices = apply_color_to_vertices(skybox_color),
|
||||
indices = (#cube_indices_double_sided > 0) and cube_indices_double_sided or cube_indices,
|
||||
compute_model_matrix = compute_model_matrix,
|
||||
shader_key = "skybox",
|
||||
shader_keys = {"skybox"},
|
||||
}
|
||||
end
|
||||
|
||||
@@ -791,7 +791,7 @@ local function create_physics_cube()
|
||||
vertices = apply_color_to_vertices(physics_state.cube_color),
|
||||
indices = (#cube_indices_double_sided > 0) and cube_indices_double_sided or cube_indices,
|
||||
compute_model_matrix = compute_model_matrix,
|
||||
shader_key = shader_key,
|
||||
shader_keys = {shader_key},
|
||||
}
|
||||
end
|
||||
|
||||
@@ -809,7 +809,7 @@ local function create_spinning_cube()
|
||||
vertices = cube_vertices,
|
||||
indices = (#cube_indices_double_sided > 0) and cube_indices_double_sided or cube_indices,
|
||||
compute_model_matrix = compute_model_matrix,
|
||||
shader_key = shader_key,
|
||||
shader_keys = {shader_key},
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -590,7 +590,7 @@ function get_scene_objects()
|
||||
{
|
||||
vertices = map_mesh.vertices,
|
||||
indices = map_mesh.indices,
|
||||
shader_key = map_shader_key,
|
||||
shader_keys = {map_shader_key},
|
||||
compute_model_matrix = function()
|
||||
return map_model_matrix
|
||||
end,
|
||||
|
||||
@@ -251,7 +251,7 @@ local function createCube(position)
|
||||
vertices = cubeVertices,
|
||||
indices = cubeIndices,
|
||||
compute_model_matrix = computeModel,
|
||||
shader_key = "default",
|
||||
shader_keys = {"default"},
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -155,6 +155,42 @@ void GraphicsService::RenderScene(const std::vector<RenderCommand>& commands,
|
||||
|
||||
// Set the view-projection matrix for the frame
|
||||
backend_->SetViewState(viewState);
|
||||
|
||||
if (commands.empty()) {
|
||||
return;
|
||||
}
|
||||
if (!vertexBuffer_ || !indexBuffer_) {
|
||||
logger_->Error("GraphicsService::RenderScene: Vertex/index buffers not uploaded");
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t commandIndex = 0; commandIndex < commands.size(); ++commandIndex) {
|
||||
const auto& command = commands[commandIndex];
|
||||
if (command.shaderKeys.empty()) {
|
||||
logger_->Error("GraphicsService::RenderScene: Render command missing shader keys");
|
||||
continue;
|
||||
}
|
||||
if (logger_) {
|
||||
logger_->Trace("GraphicsService", "RenderScene",
|
||||
"commandIndex=" + std::to_string(commandIndex) +
|
||||
", shaderKeyCount=" + std::to_string(command.shaderKeys.size()));
|
||||
}
|
||||
for (const auto& shaderKey : command.shaderKeys) {
|
||||
auto it = pipelines_.find(shaderKey);
|
||||
if (it == pipelines_.end()) {
|
||||
logger_->Error("GraphicsService::RenderScene: Missing pipeline for shaderKey=" + shaderKey);
|
||||
continue;
|
||||
}
|
||||
backend_->Draw(device_,
|
||||
it->second,
|
||||
vertexBuffer_,
|
||||
indexBuffer_,
|
||||
command.indexOffset,
|
||||
command.indexCount,
|
||||
command.vertexOffset,
|
||||
command.modelMatrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool GraphicsService::EndFrame() {
|
||||
|
||||
@@ -52,10 +52,10 @@ private:
|
||||
std::shared_ptr<ILogger> logger_;
|
||||
std::shared_ptr<IGraphicsBackend> backend_;
|
||||
std::shared_ptr<IWindowService> windowService_;
|
||||
GraphicsDeviceHandle device_;
|
||||
GraphicsDeviceHandle device_ = nullptr;
|
||||
std::unordered_map<std::string, GraphicsPipelineHandle> pipelines_;
|
||||
GraphicsBufferHandle vertexBuffer_;
|
||||
GraphicsBufferHandle indexBuffer_;
|
||||
GraphicsBufferHandle vertexBuffer_ = nullptr;
|
||||
GraphicsBufferHandle indexBuffer_ = nullptr;
|
||||
// Other state
|
||||
bool initialized_ = false;
|
||||
};
|
||||
|
||||
@@ -237,12 +237,29 @@ std::vector<SceneObject> SceneScriptService::LoadSceneObjects() {
|
||||
object.computeModelMatrixRef = -1;
|
||||
}
|
||||
|
||||
lua_getfield(L, -1, "shader_key");
|
||||
if (lua_isstring(L, -1)) {
|
||||
object.shaderKey = lua_tostring(L, -1);
|
||||
object.shaderKeys.clear();
|
||||
lua_getfield(L, -1, "shader_keys");
|
||||
if (lua_istable(L, -1)) {
|
||||
const size_t count = lua_rawlen(L, -1);
|
||||
object.shaderKeys.reserve(count);
|
||||
for (size_t keyIndex = 1; keyIndex <= count; ++keyIndex) {
|
||||
lua_rawgeti(L, -1, static_cast<int>(keyIndex));
|
||||
if (lua_isstring(L, -1)) {
|
||||
object.shaderKeys.emplace_back(lua_tostring(L, -1));
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (object.shaderKeys.empty()) {
|
||||
lua_getfield(L, -1, "shader_key");
|
||||
if (lua_isstring(L, -1)) {
|
||||
object.shaderKeys.emplace_back(lua_tostring(L, -1));
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
objects.push_back(std::move(object));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
|
||||
@@ -73,12 +73,18 @@ void SceneService::LoadScene(const std::vector<SceneObject>& objects) {
|
||||
}
|
||||
throw std::runtime_error("Scene object missing vertex or index data");
|
||||
}
|
||||
if (obj.shaderKeys.empty()) {
|
||||
if (logger_) {
|
||||
logger_->Error("Scene object missing shader keys");
|
||||
}
|
||||
throw std::runtime_error("Scene object missing shader keys");
|
||||
}
|
||||
|
||||
auto entity = registry_->create();
|
||||
sceneEntities_.push_back(entity);
|
||||
registry_->emplace<SceneTag>(entity);
|
||||
registry_->emplace<MeshComponent>(entity, obj.vertices, obj.indices);
|
||||
registry_->emplace<RenderComponent>(entity, obj.computeModelMatrixRef, obj.shaderKey);
|
||||
registry_->emplace<RenderComponent>(entity, obj.computeModelMatrixRef, obj.shaderKeys);
|
||||
}
|
||||
|
||||
for (const auto entity : sceneEntities_) {
|
||||
@@ -118,7 +124,7 @@ void SceneService::LoadScene(const std::vector<SceneObject>& objects) {
|
||||
drawInfo.indexCount = static_cast<uint32_t>(mesh.indices.size());
|
||||
drawInfo.vertexOffset = static_cast<int32_t>(vertexOffset);
|
||||
drawInfo.computeModelMatrixRef = render.computeModelMatrixRef;
|
||||
drawInfo.shaderKey = render.shaderKey;
|
||||
drawInfo.shaderKeys = render.shaderKeys;
|
||||
drawInfos_.push_back(std::move(drawInfo));
|
||||
}
|
||||
|
||||
@@ -156,7 +162,7 @@ std::vector<RenderCommand> SceneService::GetRenderCommands(float time) const {
|
||||
cmd.indexOffset = drawInfo.indexOffset;
|
||||
cmd.indexCount = drawInfo.indexCount;
|
||||
cmd.vertexOffset = drawInfo.vertexOffset;
|
||||
cmd.shaderKey = drawInfo.shaderKey;
|
||||
cmd.shaderKeys = drawInfo.shaderKeys;
|
||||
cmd.modelMatrix = scriptService_->ComputeModelMatrix(drawInfo.computeModelMatrixRef, time);
|
||||
commands.push_back(cmd);
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ private:
|
||||
|
||||
struct RenderComponent {
|
||||
int computeModelMatrixRef = -1;
|
||||
std::string shaderKey;
|
||||
std::vector<std::string> shaderKeys;
|
||||
};
|
||||
|
||||
struct SceneDrawInfo {
|
||||
@@ -56,7 +56,7 @@ private:
|
||||
uint32_t indexCount = 0;
|
||||
int32_t vertexOffset = 0;
|
||||
int computeModelMatrixRef = -1;
|
||||
std::string shaderKey;
|
||||
std::vector<std::string> shaderKeys;
|
||||
};
|
||||
|
||||
void ClearSceneEntities();
|
||||
|
||||
@@ -34,43 +34,44 @@ std::unordered_map<std::string, ShaderPaths> ShaderScriptService::LoadShaderPath
|
||||
if (configService_) {
|
||||
const auto& materialConfig = configService_->GetMaterialXConfig();
|
||||
const auto& materialOverrides = configService_->GetMaterialXMaterialConfigs();
|
||||
if (!materialOverrides.empty()) {
|
||||
for (const auto& overrideConfig : materialOverrides) {
|
||||
if (!overrideConfig.enabled) {
|
||||
continue;
|
||||
}
|
||||
MaterialXConfig resolvedConfig = materialConfig;
|
||||
resolvedConfig.enabled = true;
|
||||
resolvedConfig.documentPath = overrideConfig.documentPath;
|
||||
resolvedConfig.shaderKey = overrideConfig.shaderKey;
|
||||
resolvedConfig.materialName = overrideConfig.materialName;
|
||||
resolvedConfig.useConstantColor = overrideConfig.useConstantColor;
|
||||
resolvedConfig.constantColor = overrideConfig.constantColor;
|
||||
try {
|
||||
ShaderPaths materialShader = materialxGenerator_.Generate(
|
||||
resolvedConfig,
|
||||
engineService_ ? engineService_->GetScriptDirectory() : std::filesystem::path{});
|
||||
if (!resolvedConfig.shaderKey.empty()) {
|
||||
shaderMap[resolvedConfig.shaderKey] = std::move(materialShader);
|
||||
}
|
||||
} catch (const std::exception& ex) {
|
||||
if (logger_) {
|
||||
logger_->Error("MaterialX shader generation failed for key=" +
|
||||
overrideConfig.shaderKey + ": " + std::string(ex.what()));
|
||||
}
|
||||
}
|
||||
if (materialOverrides.empty()) {
|
||||
if (logger_) {
|
||||
logger_->Error("MaterialX shader generation requires materialx_materials entries");
|
||||
}
|
||||
throw std::runtime_error("MaterialX shader generation requires materialx_materials entries");
|
||||
}
|
||||
if (logger_) {
|
||||
logger_->Trace("ShaderScriptService", "LoadShaderPathsMap",
|
||||
"materialOverrides=" + std::to_string(materialOverrides.size()));
|
||||
}
|
||||
for (const auto& overrideConfig : materialOverrides) {
|
||||
if (!overrideConfig.enabled) {
|
||||
continue;
|
||||
}
|
||||
MaterialXConfig resolvedConfig = materialConfig;
|
||||
resolvedConfig.enabled = true;
|
||||
resolvedConfig.documentPath = overrideConfig.documentPath;
|
||||
resolvedConfig.shaderKey = overrideConfig.shaderKey;
|
||||
resolvedConfig.materialName = overrideConfig.materialName;
|
||||
resolvedConfig.useConstantColor = overrideConfig.useConstantColor;
|
||||
resolvedConfig.constantColor = overrideConfig.constantColor;
|
||||
if (logger_) {
|
||||
logger_->Trace("ShaderScriptService", "LoadShaderPathsMap",
|
||||
"materialKey=" + resolvedConfig.shaderKey +
|
||||
", document=" + resolvedConfig.documentPath.string() +
|
||||
", material=" + resolvedConfig.materialName);
|
||||
}
|
||||
} else if (materialConfig.enabled) {
|
||||
try {
|
||||
ShaderPaths materialShader = materialxGenerator_.Generate(
|
||||
materialConfig,
|
||||
resolvedConfig,
|
||||
engineService_ ? engineService_->GetScriptDirectory() : std::filesystem::path{});
|
||||
if (!materialConfig.shaderKey.empty()) {
|
||||
shaderMap[materialConfig.shaderKey] = std::move(materialShader);
|
||||
if (!resolvedConfig.shaderKey.empty()) {
|
||||
shaderMap[resolvedConfig.shaderKey] = std::move(materialShader);
|
||||
}
|
||||
} catch (const std::exception& ex) {
|
||||
if (logger_) {
|
||||
logger_->Error("MaterialX shader generation failed: " + std::string(ex.what()));
|
||||
logger_->Error("MaterialX shader generation failed for key=" +
|
||||
overrideConfig.shaderKey + ": " + std::string(ex.what()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ struct RenderCommand {
|
||||
uint32_t indexOffset;
|
||||
uint32_t indexCount;
|
||||
int32_t vertexOffset;
|
||||
std::string shaderKey;
|
||||
std::vector<std::string> shaderKeys;
|
||||
std::array<float, 16> modelMatrix;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ struct SceneObject {
|
||||
std::vector<core::Vertex> vertices;
|
||||
std::vector<uint16_t> indices;
|
||||
int computeModelMatrixRef = -1;
|
||||
std::string shaderKey = "default";
|
||||
std::vector<std::string> shaderKeys;
|
||||
};
|
||||
|
||||
} // namespace sdl3cpp::services
|
||||
|
||||
@@ -19,7 +19,7 @@ function get_scene_objects()
|
||||
compute_model_matrix = function(time)
|
||||
return identity_matrix()
|
||||
end,
|
||||
shader_key = "test",
|
||||
shader_keys = {"test"},
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
@@ -78,7 +78,10 @@ int main() {
|
||||
const auto& object = objects.front();
|
||||
Assert(object.vertices.size() == 3, "scene object should yield three vertices", failures);
|
||||
Assert(object.indices.size() == 3, "scene object should yield three indices", failures);
|
||||
Assert(object.shaderKey == "test", "shader key should match fixture", failures);
|
||||
Assert(object.shaderKeys.size() == 1, "shader keys should contain one entry", failures);
|
||||
if (!object.shaderKeys.empty()) {
|
||||
Assert(object.shaderKeys.front() == "test", "shader key should match fixture", failures);
|
||||
}
|
||||
const std::vector<uint16_t> expectedIndices{0, 1, 2};
|
||||
Assert(object.indices == expectedIndices, "indices should be zero-based", failures);
|
||||
Assert(object.computeModelMatrixRef >= 0,
|
||||
|
||||
Reference in New Issue
Block a user