diff --git a/assets/shaders/deferred_frag.nzsl b/assets/shaders/deferred_frag.nzsl index 8626c0d4b..b82b7fd79 100644 --- a/assets/shaders/deferred_frag.nzsl +++ b/assets/shaders/deferred_frag.nzsl @@ -9,20 +9,29 @@ option HasAlphaTexture: bool = false; option AlphaTest: bool = false; [layout(std140)] -struct BasicSettings +struct MaterialSettings { + [tag("AlphaTestThreshold")] AlphaThreshold: f32, + + [tag("BaseColor")] BaseColor: vec4[f32] } +[tag("Material")] external { - [binding(0)] settings: uniform[BasicSettings], - [binding(1)] MaterialBaseColorMap: sampler2D[f32], - [binding(2)] MaterialAlphaMap: sampler2D[f32], - [binding(3)] TextureOverlay: sampler2D[f32], - [binding(4)] instanceData: uniform[InstanceData], - [binding(5)] viewerData: uniform[ViewerData], + [tag("Settings"), binding(0)] settings: uniform[MaterialSettings], + [tag("BaseColorMap"), binding(1)] MaterialBaseColorMap: sampler2D[f32], + [tag("AlphaMap"), binding(2)] MaterialAlphaMap: sampler2D[f32], +} + +[tag("Engine")] +external +{ + [tag("TextureOverlay"), binding(3)] TextureOverlay: sampler2D[f32], + [tag("InstanceData"), binding(4)] instanceData: uniform[InstanceData], + [tag("ViewerData"), binding(5)] viewerData: uniform[ViewerData], } struct InputData diff --git a/assets/shaders/deferred_vert.nzsl b/assets/shaders/deferred_vert.nzsl index 18c36f43d..4cfd53c1e 100644 --- a/assets/shaders/deferred_vert.nzsl +++ b/assets/shaders/deferred_vert.nzsl @@ -5,17 +5,29 @@ import InstanceData from Engine.InstanceData; import ViewerData from Engine.ViewerData; [layout(std140)] -struct BasicSettings +struct MaterialSettings { + [tag("AlphaTestThreshold")] AlphaThreshold: f32, + + [tag("BaseColor")] BaseColor: vec4[f32] } +[tag("Material")] external { - [binding(0)] settings: uniform[BasicSettings], - [binding(4)] instanceData: uniform[InstanceData], - [binding(5)] viewerData: uniform[ViewerData], + [tag("Settings"), binding(0)] settings: uniform[MaterialSettings], + [tag("BaseColorMap"), binding(1)] MaterialBaseColorMap: sampler2D[f32], + [tag("AlphaMap"), binding(2)] MaterialAlphaMap: sampler2D[f32], +} + +[tag("Engine")] +external +{ + [tag("TextureOverlay"), binding(3)] TextureOverlay: sampler2D[f32], + [tag("InstanceData"), binding(4)] instanceData: uniform[InstanceData], + [tag("ViewerData"), binding(5)] viewerData: uniform[ViewerData], } struct InputData diff --git a/examples/DeferredShading/main.cpp b/examples/DeferredShading/main.cpp index 22bc3105a..f50eca77d 100644 --- a/examples/DeferredShading/main.cpp +++ b/examples/DeferredShading/main.cpp @@ -192,60 +192,49 @@ int main() std::shared_ptr coneMeshGfx = Nz::GraphicalMesh::BuildFromMesh(*coneMesh); - auto customSettings = Nz::BasicMaterial::GetSettings()->GetBuilderData(); - customSettings.shaders.clear(); - customSettings.shaders.emplace_back(std::make_shared(nzsl::ShaderStageType::Fragment, nzsl::ParseFromFile(shaderDir / "deferred_frag.nzsl"))); - customSettings.shaders.emplace_back(std::make_shared(nzsl::ShaderStageType::Vertex, nzsl::ParseFromFile(shaderDir / "deferred_vert.nzsl"))); + Nz::MaterialSettings settings; + Nz::PredefinedMaterials::AddBasicSettings(settings); - auto customMatSettings = std::make_shared(std::move(customSettings)); + Nz::MaterialPass customForwardPass; + customForwardPass.states.depthBuffer = true; + customForwardPass.shaders.emplace_back(std::make_shared(nzsl::ShaderStageType::Fragment, nzsl::ParseFromFile(shaderDir / "deferred_frag.nzsl"))); + customForwardPass.shaders.emplace_back(std::make_shared(nzsl::ShaderStageType::Vertex, nzsl::ParseFromFile(shaderDir / "deferred_vert.nzsl"))); + settings.AddPass("ForwardPass", customForwardPass); - std::shared_ptr spaceshipMat = std::make_shared(); + Nz::MaterialPass customDepthPass = customForwardPass; + customDepthPass.options[Nz::CRC32("DepthPass")] = true; + settings.AddPass("DepthPass", customDepthPass); - std::shared_ptr spaceshipMatPass = std::make_shared(customMatSettings); - spaceshipMatPass->EnableDepthBuffer(true); + auto deferredMaterial = std::make_shared(std::move(settings), "BasicMaterial"); + + std::shared_ptr spaceshipMat = deferredMaterial->CreateInstance(); + spaceshipMat->SetTextureProperty("AlphaMap", Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams)); + spaceshipMat->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams)); + + std::shared_ptr flareMaterial = deferredMaterial->CreateInstance(); + flareMaterial->UpdatePassStates("ForwardPass", [](Nz::RenderStates& renderStates) { - Nz::BasicMaterial basicMat(*spaceshipMatPass); - basicMat.EnableAlphaTest(false); - basicMat.SetAlphaMap(Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams)); - basicMat.SetBaseColorMap(Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams)); - } - spaceshipMat->AddPass("ForwardPass", spaceshipMatPass); + renderStates.depthClamp = true; + renderStates.depthWrite = false; + renderStates.blending = true; + renderStates.blend.modeColor = Nz::BlendEquation::Add; + renderStates.blend.modeAlpha = Nz::BlendEquation::Add; + renderStates.blend.srcColor = Nz::BlendFunc::SrcAlpha; + renderStates.blend.dstColor = Nz::BlendFunc::InvSrcAlpha; + renderStates.blend.srcAlpha = Nz::BlendFunc::One; + renderStates.blend.dstAlpha = Nz::BlendFunc::One; + return true; + }); + flareMaterial->UpdatePassFlags("ForwardPass", Nz::MaterialPassFlag::SortByDistance); + flareMaterial->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "flare1.png", texParams)); - std::shared_ptr flareMaterial = std::make_shared(); - std::shared_ptr flareMaterialPass; - { - flareMaterialPass = std::make_shared(Nz::BasicMaterial::GetSettings()); - flareMaterialPass->EnableDepthBuffer(true); - flareMaterialPass->EnableDepthWrite(false); - flareMaterialPass->EnableDepthClamp(true); + Nz::TextureSamplerInfo planeSampler; + planeSampler.anisotropyLevel = 16; + planeSampler.wrapModeU = Nz::SamplerWrap::Repeat; + planeSampler.wrapModeV = Nz::SamplerWrap::Repeat; - flareMaterialPass->EnableFlag(Nz::MaterialPassFlag::SortByDistance); - - flareMaterialPass->EnableBlending(true); - flareMaterialPass->SetBlendEquation(Nz::BlendEquation::Add, Nz::BlendEquation::Add); - flareMaterialPass->SetBlendFunc(Nz::BlendFunc::SrcAlpha, Nz::BlendFunc::InvSrcAlpha, Nz::BlendFunc::One, Nz::BlendFunc::Zero); - - Nz::BasicMaterial Osef(*flareMaterialPass); - Osef.SetBaseColorMap(Nz::Texture::LoadFromFile(resourceDir / "flare1.png", texParams)); - - flareMaterial->AddPass("ForwardPass", flareMaterialPass); - } - - std::shared_ptr planeMat = std::make_shared(); - - std::shared_ptr planeMatPass = std::make_shared(customMatSettings); - planeMatPass->EnableDepthBuffer(true); - { - Nz::BasicMaterial basicMat(*planeMatPass); - basicMat.SetBaseColorMap(Nz::Texture::LoadFromFile(resourceDir / "dev_grey.png", texParams)); - - Nz::TextureSamplerInfo planeSampler; - planeSampler.anisotropyLevel = 16; - planeSampler.wrapModeU = Nz::SamplerWrap::Repeat; - planeSampler.wrapModeV = Nz::SamplerWrap::Repeat; - basicMat.SetBaseColorSampler(planeSampler); - } - planeMat->AddPass("ForwardPass", planeMatPass); + std::shared_ptr planeMat = deferredMaterial->CreateInstance(); + planeMat->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "dev_grey.png", texParams), planeSampler); Nz::Model spaceshipModel(std::move(gfxMesh), spaceship->GetAABB()); for (std::size_t i = 0; i < spaceshipModel.GetSubMeshCount(); ++i) @@ -537,7 +526,7 @@ int main() std::shared_ptr godRaysShaderBinding = godraysPipelineInfo.pipelineLayout->AllocateShaderBinding(0); /* - uniformExposure = 0.0034f; + uniformExposure = 0.0034f; uniformDecay = 1.0f; uniformDensity = 0.84f; uniformWeight = 5.65f; @@ -588,7 +577,7 @@ int main() meshPrimitiveParams.vertexDeclaration }); - stencilPipelineInfo.colorWrite = false; + stencilPipelineInfo.colorWriteMask = 0; stencilPipelineInfo.depthBuffer = true; stencilPipelineInfo.depthWrite = false; stencilPipelineInfo.faceCulling = false; @@ -1466,15 +1455,15 @@ int main() { builder.PreTransferBarrier(); - modelInstance1.UpdateBuffers(uploadPool, builder); - modelInstance2.UpdateBuffers(uploadPool, builder); - planeInstance.UpdateBuffers(uploadPool, builder); + modelInstance1.OnTransfer(frame, builder); + modelInstance2.OnTransfer(frame, builder); + planeInstance.OnTransfer(frame, builder); Nz::EulerAnglesf flareRotation(0.f, 0.f, elapsedTime * 10.f); flareInstance.UpdateWorldMatrix(Nz::Matrix4f::Transform(viewerPos + flarePosition, flareRotation)); - flareInstance.UpdateBuffers(uploadPool, builder); + flareInstance.OnTransfer(frame, builder); - viewerInstance.UpdateBuffers(uploadPool, builder); + viewerInstance.OnTransfer(frame, builder); // Update light buffer if (!spotLights.empty() && (lightUpdate || lightAnimation)) @@ -1527,9 +1516,9 @@ int main() builder.CopyBuffer(lightScatteringAllocation, godRaysUBO.get()); } - spaceshipMatPass->Update(frame, builder); - planeMatPass->Update(frame, builder); - flareMaterialPass->Update(frame, builder); + spaceshipMat->OnTransfer(frame, builder); + planeMat->OnTransfer(frame, builder); + flareMaterial->OnTransfer(frame, builder); builder.PostTransferBarrier(); } diff --git a/examples/GraphicsTest/main.cpp b/examples/GraphicsTest/main.cpp index f7882be5d..c981fe90b 100644 --- a/examples/GraphicsTest/main.cpp +++ b/examples/GraphicsTest/main.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include #include #include @@ -19,7 +21,7 @@ int main() if (std::getchar() == 'y') rendererConfig.preferredAPI = Nz::RenderAPI::Vulkan; else - rendererConfig.preferredAPI = Nz::RenderAPI::OpenGL; + rendererConfig.preferredAPI = Nz::RenderAPI::Vulkan; Nz::Modules nazara(rendererConfig); @@ -61,30 +63,25 @@ int main() texParams.renderDevice = device; texParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB; - std::shared_ptr material = std::make_shared(); + std::shared_ptr diffuseTexture = Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams); - std::shared_ptr forwardPass = std::make_shared(Nz::PhongLightingMaterial::GetSettings()); - forwardPass->EnableDepthBuffer(true); - forwardPass->EnableFaceCulling(true); + std::shared_ptr material = Nz::Graphics::Instance()->GetDefaultMaterials().basicMaterial; - material->AddPass("ForwardPass", forwardPass); + std::shared_ptr materialInstance = std::make_shared(material); + materialInstance->SetTextureProperty(0, diffuseTexture); + materialInstance->SetValueProperty(0, Nz::Color::White); - std::shared_ptr normalMap = Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/normal.png", texParams); - - Nz::PhongLightingMaterial phongMat(*forwardPass); - phongMat.EnableAlphaTest(false); - phongMat.SetAlphaMap(Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams)); - phongMat.SetBaseColorMap(Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams)); - phongMat.SetNormalMap(Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/normal.png", texParams)); + std::shared_ptr materialInstance2 = std::make_shared(material); + materialInstance2->SetValueProperty(0, Nz::Color::Green); Nz::Model model(std::move(gfxMesh), spaceshipMesh->GetAABB()); for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i) - model.SetMaterial(i, material); + model.SetMaterial(i, materialInstance); Nz::Vector2ui windowSize = window.GetSize(); Nz::Camera camera(window.GetRenderTarget()); - //camera.UpdateClearColor(Nz::Color::Gray); + camera.UpdateClearColor(Nz::Color::Gray); Nz::ViewerInstance& viewerInstance = camera.GetViewerInstance(); viewerInstance.UpdateTargetSize(Nz::Vector2f(window.GetSize())); @@ -138,18 +135,18 @@ int main() case Nz::WindowEventType::KeyPressed: if (event.key.virtualKey == Nz::Keyboard::VKey::A) - phongMat.EnableAlphaTest(!phongMat.IsAlphaTestEnabled()); - else if (event.key.virtualKey == Nz::Keyboard::VKey::N) { - if (phongMat.GetNormalMap()) - phongMat.SetNormalMap({}); - else - phongMat.SetNormalMap(normalMap); + for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i) + model.SetMaterial(i, materialInstance); + } + else if (event.key.virtualKey == Nz::Keyboard::VKey::B) + { + for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i) + model.SetMaterial(i, materialInstance2); } else if (event.key.virtualKey == Nz::Keyboard::VKey::Space) { modelInstance->UpdateWorldMatrix(Nz::Matrix4f::Translate(viewerPos)); - framePipeline.InvalidateWorldInstance(worldInstanceIndex1); } break; @@ -227,8 +224,6 @@ int main() viewerInstance.UpdateViewMatrix(Nz::Matrix4f::TransformInverse(viewerPos, camAngles)); viewerInstance.UpdateEyePosition(viewerPos); - framePipeline.InvalidateViewer(cameraIndex); - framePipeline.Render(frame); frame.Present(); diff --git a/examples/PhysicallyBasedRendering/main.cpp b/examples/PhysicallyBasedRendering/main.cpp index a14f9052e..d2ce93912 100644 --- a/examples/PhysicallyBasedRendering/main.cpp +++ b/examples/PhysicallyBasedRendering/main.cpp @@ -55,27 +55,22 @@ int main() Nz::TextureParams srgbTexParams = texParams; srgbTexParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB; - std::shared_ptr material = std::make_shared(); - - std::shared_ptr forwardPass = std::make_shared(Nz::PhysicallyBasedMaterial::GetSettings()); - forwardPass->EnableDepthBuffer(true); - forwardPass->EnableFaceCulling(true); - - material->AddPass("ForwardPass", forwardPass); - std::shared_ptr normalMap = Nz::Texture::LoadFromFile(resourceDir / "Rusty/rustediron2_normal.png", texParams); - Nz::PhysicallyBasedMaterial pbrMat(*forwardPass); - pbrMat.EnableAlphaTest(false); - pbrMat.SetAlphaMap(Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams)); - pbrMat.SetBaseColorMap(Nz::Texture::LoadFromFile(resourceDir / "Rusty/rustediron2_basecolor.png", srgbTexParams)); - pbrMat.SetMetallicMap(Nz::Texture::LoadFromFile(resourceDir / "Rusty/rustediron2_metallic.png", texParams)); - pbrMat.SetRoughnessMap(Nz::Texture::LoadFromFile(resourceDir / "Rusty/rustediron2_roughness.png", texParams)); - pbrMat.SetNormalMap(normalMap); + std::shared_ptr material = Nz::Graphics::Instance()->GetDefaultMaterials().pbrMaterial; + + std::shared_ptr materialInstance = std::make_shared(material); + materialInstance->SetTextureProperty("AlphaMap", Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams)); + materialInstance->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "Rusty/rustediron2_basecolor.png", texParams)); + materialInstance->SetTextureProperty("MetallicMap", Nz::Texture::LoadFromFile(resourceDir / "Rusty/rustediron2_metallic.png", texParams)); + materialInstance->SetTextureProperty("RoughnessMap", Nz::Texture::LoadFromFile(resourceDir / "Rusty/rustediron2_roughness.png", texParams)); + + std::size_t normalMapProperty = materialInstance->FindTextureProperty("NormalMap"); + materialInstance->SetTextureProperty(normalMapProperty, normalMap); Nz::Model model(std::move(gfxMesh), sphereMesh->GetAABB()); for (std::size_t i = 0; i < model.GetSubMeshCount(); ++i) - model.SetMaterial(i, material); + model.SetMaterial(i, materialInstance); Nz::Vector2ui windowSize = window.GetSize(); @@ -129,10 +124,10 @@ int main() case Nz::WindowEventType::KeyPressed: if (event.key.virtualKey == Nz::Keyboard::VKey::N) { - if (pbrMat.GetNormalMap()) - pbrMat.SetNormalMap({}); + if (materialInstance->GetTextureProperty(normalMapProperty)) + materialInstance->SetTextureProperty(normalMapProperty, {}); else - pbrMat.SetNormalMap(normalMap); + materialInstance->SetTextureProperty(normalMapProperty, normalMap); } break; @@ -207,8 +202,6 @@ int main() viewerInstance.UpdateViewMatrix(Nz::Matrix4f::TransformInverse(viewerPos, camAngles)); viewerInstance.UpdateEyePosition(viewerPos); - framePipeline.InvalidateViewer(cameraIndex); - framePipeline.Render(frame); frame.Present(); diff --git a/examples/Physics2DDemo/main.cpp b/examples/Physics2DDemo/main.cpp index c766c5404..e5e6a2e5e 100644 --- a/examples/Physics2DDemo/main.cpp +++ b/examples/Physics2DDemo/main.cpp @@ -52,7 +52,7 @@ int main() Nz::Vector2ui windowSize = window.GetSize(); - physSytem.GetPhysWorld().SetGravity({ 0.f, -9.81f }); + physSytem.GetPhysWorld().SetGravity({ 0.f, -98.1f }); entt::entity viewer = registry.create(); { @@ -62,11 +62,6 @@ int main() cameraComponent.UpdateClearColor(Nz::Color(0.5f, 0.5f, 0.5f)); } - std::shared_ptr material = std::make_shared(); - - std::shared_ptr materialPass = std::make_shared(Nz::BasicMaterial::GetSettings()); - material->AddPass("ForwardPass", materialPass); - Nz::TextureSamplerInfo samplerInfo; samplerInfo.anisotropyLevel = 8; @@ -74,9 +69,8 @@ int main() texParams.renderDevice = device; texParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB; - Nz::BasicMaterial basicMat(*materialPass); - basicMat.SetBaseColorMap(Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams)); - basicMat.SetBaseColorSampler(samplerInfo); + std::shared_ptr material = Nz::Graphics::Instance()->GetDefaultMaterials().phongMaterial->CreateInstance(); + material->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams)); for (std::size_t y = 0; y < 10; ++y) { @@ -99,12 +93,7 @@ int main() entt::entity groundEntity = registry.create(); { - std::shared_ptr whiteMaterial = std::make_shared(); - - std::shared_ptr materialPass = std::make_shared(Nz::BasicMaterial::GetSettings()); - whiteMaterial->AddPass("ForwardPass", materialPass); - - std::shared_ptr sprite = std::make_shared(whiteMaterial); + std::shared_ptr sprite = std::make_shared(Nz::Graphics::Instance()->GetDefaultMaterials().basicDefault); sprite->SetSize({ 800.f, 20.f }); sprite->SetOrigin({ 400.f, 10.f, 0.f }); @@ -158,13 +147,6 @@ int main() } } - if (updateClock.GetMilliseconds() > 1000 / 60) - { - float updateTime = updateClock.Restart() / 1'000'000.f; - - physSytem.Update(1000.f / 60.f); - } - systemGraph.Update(); fps++; diff --git a/examples/PhysicsDemo/main.cpp b/examples/PhysicsDemo/main.cpp index 7617c9701..274568910 100644 --- a/examples/PhysicsDemo/main.cpp +++ b/examples/PhysicsDemo/main.cpp @@ -56,22 +56,6 @@ int main() const Nz::Boxf& spaceshipAABB = spaceshipMesh->GetAABB(); std::shared_ptr gfxMesh = Nz::GraphicalMesh::BuildFromMesh(*spaceshipMesh); - // Texture - std::shared_ptr material = std::make_shared(); - - std::shared_ptr depthPass = std::make_shared(Nz::DepthMaterial::GetSettings()); - depthPass->EnableDepthBuffer(true); - depthPass->EnableDepthClamp(true); - depthPass->EnableFaceCulling(true); - - std::shared_ptr materialPass = std::make_shared(Nz::PhongLightingMaterial::GetSettings()); - materialPass->EnableDepthBuffer(true); - materialPass->EnableDepthClamp(true); - materialPass->EnableFaceCulling(true); - - material->AddPass("DepthPass", depthPass); - material->AddPass("ForwardPass", materialPass); - Nz::TextureSamplerInfo samplerInfo; samplerInfo.anisotropyLevel = 8; @@ -79,35 +63,15 @@ int main() texParams.renderDevice = device; texParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB; - Nz::BasicMaterial basicMat(*materialPass); - basicMat.EnableAlphaTest(false); - basicMat.SetAlphaMap(Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams)); - basicMat.SetBaseColorMap(Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams)); - basicMat.SetBaseColorSampler(samplerInfo); - - Nz::DepthMaterial basicMatDepth(*depthPass); - basicMatDepth.SetAlphaMap(Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams)); + std::shared_ptr material = Nz::Graphics::Instance()->GetDefaultMaterials().phongMaterial->CreateInstance(); + material->SetTextureProperty("AlphaMap", Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams)); + material->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams)); std::shared_ptr model = std::make_shared(std::move(gfxMesh), spaceshipAABB); for (std::size_t i = 0; i < model->GetSubMeshCount(); ++i) model->SetMaterial(i, material); - std::shared_ptr spriteMaterial = std::make_shared(); - - std::shared_ptr spriteMaterialPass = std::make_shared(Nz::BasicMaterial::GetSettings()); - spriteMaterialPass->EnableDepthBuffer(true); - spriteMaterialPass->EnableDepthWrite(false); - spriteMaterialPass->EnableDepthClamp(true); - - spriteMaterialPass->EnableFlag(Nz::MaterialPassFlag::SortByDistance); - - spriteMaterialPass->EnableBlending(true); - spriteMaterialPass->SetBlendEquation(Nz::BlendEquation::Add, Nz::BlendEquation::Add); - spriteMaterialPass->SetBlendFunc(Nz::BlendFunc::SrcAlpha, Nz::BlendFunc::InvSrcAlpha, Nz::BlendFunc::One, Nz::BlendFunc::Zero); - - spriteMaterial->AddPass("ForwardPass", spriteMaterialPass); - - std::shared_ptr sprite = std::make_shared(spriteMaterial); + std::shared_ptr sprite = std::make_shared(); sprite->Update(Nz::SimpleTextDrawer::Draw("Voix ambiguë d'un cœur qui, au zéphyr, préfère les jattes de kiwis", 72), 0.01f); Nz::VertexMapper vertexMapper(*spaceshipMesh->GetSubMesh(0)); @@ -134,16 +98,16 @@ int main() auto shipCollider = std::make_shared(vertices, vertexMapper.GetVertexCount(), 0.01f); - std::shared_ptr colliderMat = std::make_shared(); - - std::shared_ptr colliderMatPass = std::make_shared(Nz::BasicMaterial::GetSettings()); - colliderMatPass->EnableDepthBuffer(true); - colliderMatPass->SetPrimitiveMode(Nz::PrimitiveMode::LineList); - - colliderMat->AddPass("ForwardPass", colliderMatPass); - - Nz::BasicMaterial colliderBasicMat(*colliderMatPass); - colliderBasicMat.SetBaseColor(Nz::Color::Green); + std::shared_ptr colliderMat = Nz::Graphics::Instance()->GetDefaultMaterials().basicMaterial->CreateInstance(); + colliderMat->SetValueProperty("BaseColor", Nz::Color::Green); + for (std::string_view passName : { "DepthPass", "ForwardPass" }) + { + colliderMat->UpdatePassStates(passName, [](Nz::RenderStates& states) + { + states.primitiveMode = Nz::PrimitiveMode::LineList; + return true; + }); + } std::shared_ptr colliderModel; { @@ -245,9 +209,8 @@ int main() case Nz::WindowEventType::KeyPressed: if (event.key.virtualKey == Nz::Keyboard::VKey::A) { - //canvas2D.Resize({ 1920.f, 1080.f }); - basicMat.EnableAlphaTest(!basicMat.IsAlphaTestEnabled()); - basicMatDepth.EnableAlphaTest(!basicMatDepth.IsAlphaTestEnabled()); + bool alphaTestEnabled = std::get(*material->GetValueProperty("AlphaTest")); + material->SetValueProperty("AlphaTest", !alphaTestEnabled); } else if (event.key.virtualKey == Nz::Keyboard::VKey::B) { diff --git a/examples/Showcase/main.cpp b/examples/Showcase/main.cpp index 3c4ba130c..40a7ec346 100644 --- a/examples/Showcase/main.cpp +++ b/examples/Showcase/main.cpp @@ -111,13 +111,18 @@ int main() const Nz::Boxf& bobAABB = bobMesh->GetAABB(); std::shared_ptr bobGfxMesh = Nz::GraphicalMesh::BuildFromMesh(*bobMesh); + std::shared_ptr material = Nz::Graphics::Instance()->GetDefaultMaterials().basicMaterial; + std::shared_ptr bobModel = std::make_shared(std::move(bobGfxMesh), bobAABB); - std::vector> materials(bobMesh->GetMaterialCount()); + std::vector> materials(bobMesh->GetMaterialCount()); + for (std::size_t i = 0; i < bobMesh->GetMaterialCount(); ++i) { + materials[i] = std::make_shared(material); + std::string matPath = bobMesh->GetMaterialData(i).GetStringParameter(Nz::MaterialData::BaseColorTexturePath).GetValueOr(""); if (!matPath.empty()) - materials[i] = Nz::Material::LoadFromFile(matPath); + materials[i]->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(matPath, texParams)); } for (std::size_t i = 0; i < bobMesh->GetSubMeshCount(); ++i) @@ -148,7 +153,7 @@ int main() auto& bobNode = bobEntity.emplace(); //bobNode.SetRotation(Nz::EulerAnglesf(-90.f, -90.f, 0.f)); //bobNode.SetScale(1.f / 40.f * 0.5f); - //bobNode.SetPosition(bobNode.GetScale() * Nz::Vector3f(0.f, -bobAABB.height / 2.f + bobAABB.y, 0.f)); + //bobNode.SetPosition(Nz::Vector3f(0.f, -1.f, 0.f)); auto& bobGfx = bobEntity.emplace(); bobGfx.AttachRenderable(bobModel, 0xFFFFFFFF); @@ -173,24 +178,12 @@ int main() Nz::TextureParams srgbTexParams = texParams; srgbTexParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB; - std::shared_ptr material = std::make_shared(); - - std::shared_ptr forwardPass = std::make_shared(Nz::BasicMaterial::GetSettings()); - forwardPass->EnableDepthBuffer(true); - forwardPass->EnableFaceCulling(true); - - material->AddPass("ForwardPass", forwardPass); - - std::shared_ptr normalMap = Nz::Texture::LoadFromFile(resourceDir / "Rusty/rustediron2_normal.png", texParams); - - Nz::BasicMaterial pbrMat(*forwardPass); - pbrMat.EnableAlphaTest(false); - pbrMat.SetAlphaMap(Nz::Texture::LoadFromFile(resourceDir / "alphatile.png", texParams)); - pbrMat.SetBaseColorMap(Nz::Texture::LoadFromFile(resourceDir / "Rusty/rustediron2_basecolor.png", srgbTexParams)); + std::shared_ptr sphereMat = std::make_shared(material); + sphereMat->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "Rusty/rustediron2_basecolor.png", srgbTexParams)); std::shared_ptr sphereModel = std::make_shared(std::move(gfxMesh), sphereMesh->GetAABB()); for (std::size_t i = 0; i < sphereModel->GetSubMeshCount(); ++i) - sphereModel->SetMaterial(i, material); + sphereModel->SetMaterial(i, sphereMat); auto& sphereNode = registry.emplace(sphereEntity); sphereNode.SetScale(0.1f); @@ -229,32 +222,24 @@ int main() std::shared_ptr planeMeshGfx = Nz::GraphicalMesh::BuildFromMesh(planeMesh); - std::shared_ptr planeMat = std::make_shared(); + Nz::TextureSamplerInfo planeSampler; + planeSampler.anisotropyLevel = 16; + planeSampler.wrapModeU = Nz::SamplerWrap::Repeat; + planeSampler.wrapModeV = Nz::SamplerWrap::Repeat; - std::shared_ptr planeMatPass = std::make_shared(Nz::BasicMaterial::GetSettings()); - planeMatPass->EnableDepthBuffer(true); - { - Nz::BasicMaterial basicMat(*planeMatPass); - basicMat.SetBaseColorMap(Nz::Texture::LoadFromFile(resourceDir / "dev_grey.png", texParams)); - - Nz::TextureSamplerInfo planeSampler; - planeSampler.anisotropyLevel = 16; - planeSampler.wrapModeU = Nz::SamplerWrap::Repeat; - planeSampler.wrapModeV = Nz::SamplerWrap::Repeat; - basicMat.SetBaseColorSampler(planeSampler); - } - planeMat->AddPass("ForwardPass", planeMatPass); + std::shared_ptr planeMat = std::make_shared(material); + planeMat->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "dev_grey.png", texParams), planeSampler); std::shared_ptr planeModel = std::make_shared(std::move(planeMeshGfx), planeMesh.GetAABB()); planeModel->SetMaterial(0, planeMat); + auto& planeGfx = registry.emplace(planeEntity); + planeGfx.AttachRenderable(planeModel, 0xFFFFFFFF); + auto& planeNode = registry.emplace(planeEntity); auto& planeBody = registry.emplace(planeEntity, &physSytem.GetPhysWorld()); planeBody.SetGeom(std::make_shared(Nz::Vector3f(planeSize.x, 0.5f, planeSize.y), Nz::Vector3f(0.f, -0.25f, 0.f))); - - auto& planeGfx = registry.emplace(planeEntity); - planeGfx.AttachRenderable(planeModel, 0xFFFFFFFF); } window.EnableEventPolling(true); @@ -266,6 +251,8 @@ int main() Nz::EulerAnglesf camAngles = Nz::EulerAnglesf(-30.f, 0.f, 0.f); Nz::UInt64 lastTime = Nz::GetElapsedMicroseconds(); Nz::UInt64 fps = 0; + bool paused = false; + while (window.IsOpen()) { Nz::UInt64 now = Nz::GetElapsedMicroseconds(); @@ -282,7 +269,12 @@ int main() break; case Nz::WindowEventType::KeyPressed: + { + if (event.type == Nz::WindowEventType::KeyPressed && event.key.virtualKey == Nz::Keyboard::VKey::P) + paused = !paused; + break; + } case Nz::WindowEventType::MouseMoved: { @@ -329,20 +321,23 @@ int main() if (Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::Right) || Nz::Keyboard::IsKeyPressed(Nz::Keyboard::VKey::D)) playerBody.AddForce(Nz::Vector3f::Right() * 25.f * mass, Nz::CoordSys::Local); - incr += updateTime * bobAnim->GetSequence(0)->frameRate * 1.5f; - while (incr >= 1.f) + if (!paused) { - incr -= 1.f; + incr += updateTime * bobAnim->GetSequence(0)->frameRate * 1.5f; + while (incr >= 1.f) + { + incr -= 1.f; - currentFrame = nextFrame; - nextFrame++; - if (nextFrame >= bobAnim->GetFrameCount()) - nextFrame = 0; + currentFrame = nextFrame; + nextFrame++; + if (nextFrame >= bobAnim->GetFrameCount()) + nextFrame = 0; + } + + std::cout << currentFrame << std::endl; + + bobAnim->AnimateSkeleton(skeleton.get(), currentFrame, nextFrame, incr); } - - std::cout << currentFrame << std::endl; - - bobAnim->AnimateSkeleton(skeleton.get(), currentFrame, nextFrame, incr); //for (std::size_t i = 0; i < skeleton.GetJointCount(); ++i) // matrices[i] = skeleton.GetJoint(i)->GetSkinningMatrix(); diff --git a/examples/Tut01/main.cpp b/examples/Tut01/main.cpp index 70c79b443..186cfc69d 100644 --- a/examples/Tut01/main.cpp +++ b/examples/Tut01/main.cpp @@ -33,20 +33,7 @@ int main() textDrawer.SetOutlineThickness(4.f); textDrawer.SetText("Hello world !"); - std::shared_ptr material = std::make_shared(); - - std::shared_ptr materialPass = std::make_shared(Nz::BasicMaterial::GetSettings()); - materialPass->EnableDepthBuffer(true); - materialPass->EnableDepthWrite(false); - materialPass->EnableScissorTest(true); - materialPass->EnableBlending(true); - materialPass->SetBlendEquation(Nz::BlendEquation::Add, Nz::BlendEquation::Add); - materialPass->SetBlendFunc(Nz::BlendFunc::SrcAlpha, Nz::BlendFunc::InvSrcAlpha, Nz::BlendFunc::One, Nz::BlendFunc::One); - - material = std::make_shared(); - material->AddPass("ForwardPass", materialPass); - - std::shared_ptr textSprite = std::make_shared(material); + std::shared_ptr textSprite = std::make_shared(); textSprite->Update(textDrawer); entt::entity textEntity = registry.create(); diff --git a/examples/Tut02/main.cpp b/examples/Tut02/main.cpp index 2ab8343ba..82896c5fc 100644 --- a/examples/Tut02/main.cpp +++ b/examples/Tut02/main.cpp @@ -33,20 +33,7 @@ int main() textDrawer.SetOutlineThickness(4.f); textDrawer.SetText("Press a key"); - std::shared_ptr material = std::make_shared(); - - std::shared_ptr materialPass = std::make_shared(Nz::BasicMaterial::GetSettings()); - materialPass->EnableDepthBuffer(true); - materialPass->EnableDepthWrite(false); - materialPass->EnableScissorTest(true); - materialPass->EnableBlending(true); - materialPass->SetBlendEquation(Nz::BlendEquation::Add, Nz::BlendEquation::Add); - materialPass->SetBlendFunc(Nz::BlendFunc::SrcAlpha, Nz::BlendFunc::InvSrcAlpha, Nz::BlendFunc::One, Nz::BlendFunc::One); - - material = std::make_shared(); - material->AddPass("ForwardPass", materialPass); - - std::shared_ptr textSprite = std::make_shared(material); + std::shared_ptr textSprite = std::make_shared(); textSprite->Update(textDrawer); entt::entity textEntity = registry.create(); diff --git a/examples/WidgetDemo/main.cpp b/examples/WidgetDemo/main.cpp index 5f501a9ff..054b04181 100644 --- a/examples/WidgetDemo/main.cpp +++ b/examples/WidgetDemo/main.cpp @@ -66,10 +66,7 @@ int main() labelWidget->UpdateText(Nz::SimpleTextDrawer::Draw("You clicked the button " + std::to_string(++clickCount) + " times", 72)); }); - std::shared_ptr material = std::make_shared(); - - std::shared_ptr materialPass = std::make_shared(Nz::BasicMaterial::GetSettings()); - material->AddPass("ForwardPass", materialPass); + std::shared_ptr material = Nz::Graphics::Instance()->GetDefaultMaterials().basicMaterial; Nz::TextureSamplerInfo samplerInfo; samplerInfo.anisotropyLevel = 8; @@ -78,15 +75,14 @@ int main() texParams.renderDevice = device; texParams.loadFormat = Nz::PixelFormat::RGBA8_SRGB; - Nz::BasicMaterial basicMat(*materialPass); - basicMat.SetBaseColorMap(Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams)); - basicMat.SetBaseColorSampler(samplerInfo); + std::shared_ptr materialInstance = material->CreateInstance(); + materialInstance->SetTextureProperty("BaseColorMap", Nz::Texture::LoadFromFile(resourceDir / "Spaceship/Texture/diffuse.png", texParams)); - Nz::ImageWidget* imageWidget = canvas2D.Add(material); + Nz::ImageWidget* imageWidget = canvas2D.Add(materialInstance); imageWidget->SetPosition(1200.f, 200.f); imageWidget->Resize(imageWidget->GetPreferredSize() / 4.f); - Nz::ImageButtonWidget* imageButtonWidget = canvas2D.Add(material); + Nz::ImageButtonWidget* imageButtonWidget = canvas2D.Add(materialInstance); imageButtonWidget->SetPosition(1400, 500.f); imageButtonWidget->Resize(imageButtonWidget->GetPreferredSize() / 4.f); diff --git a/include/Nazara/Core/StringExt.inl b/include/Nazara/Core/StringExt.inl index 07d7d53e6..5a7325a2f 100644 --- a/include/Nazara/Core/StringExt.inl +++ b/include/Nazara/Core/StringExt.inl @@ -13,7 +13,7 @@ namespace Nz inline bool EndsWith(const std::string_view& str, const std::string_view& s) { //FIXME: Replace with proper C++20 value once it's available -#if __cplusplus > 201703L +#if NAZARA_CPP_VER > 201703L // C++20 return str.ends_with(s); #else @@ -53,7 +53,7 @@ namespace Nz inline bool StartsWith(const std::string_view& str, const std::string_view& s) { //FIXME: Replace with proper C++20 value once it's available -#if __cplusplus > 201703L +#if NAZARA_CPP_VER > 201703L // C++20 return str.starts_with(s); #else diff --git a/include/Nazara/Graphics.hpp b/include/Nazara/Graphics.hpp index c235a51ae..a51bd4d8a 100644 --- a/include/Nazara/Graphics.hpp +++ b/include/Nazara/Graphics.hpp @@ -32,11 +32,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include @@ -56,15 +54,16 @@ #include #include #include +#include #include #include #include #include #include -#include -#include #include +#include #include +#include #include #include #include @@ -72,6 +71,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +80,7 @@ #include #include #include +#include #include #include #include diff --git a/include/Nazara/Graphics/BasicMaterial.hpp b/include/Nazara/Graphics/BasicMaterial.hpp deleted file mode 100644 index ae8f77634..000000000 --- a/include/Nazara/Graphics/BasicMaterial.hpp +++ /dev/null @@ -1,123 +0,0 @@ -// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) -// This file is part of the "Nazara Engine - Graphics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_GRAPHICS_BASICMATERIAL_HPP -#define NAZARA_GRAPHICS_BASICMATERIAL_HPP - -#include -#include - -namespace nzsl -{ - class FieldOffsets; -} - -namespace Nz -{ - class NAZARA_GRAPHICS_API BasicMaterial - { - friend class MaterialPipeline; - - public: - struct BasicUniformOffsets; - - BasicMaterial(MaterialPass& material); - ~BasicMaterial() = default; - - inline void EnableAlphaTest(bool alphaTest); - - inline const std::shared_ptr& GetAlphaMap() const; - inline const TextureSamplerInfo& GetAlphaSampler() const; - float GetAlphaTestThreshold() const; - Color GetBaseColor() const; - inline const std::shared_ptr& GetBaseColorMap() const; - inline const TextureSamplerInfo& GetBaseColorSampler() const; - - inline bool IsAlphaTestEnabled() const; - - inline bool HasAlphaMap() const; - inline bool HasAlphaTest() const; - inline bool HasAlphaTestThreshold() const; - inline bool HasBaseColor() const; - inline bool HasBaseColorMap() const; - - inline void SetAlphaMap(std::shared_ptr alphaMap); - inline void SetAlphaSampler(TextureSamplerInfo alphaSampler); - void SetAlphaTestThreshold(float alphaThreshold); - void SetBaseColor(const Color& baseColor); - inline void SetBaseColorMap(std::shared_ptr baseColorMap); - inline void SetBaseColorSampler(TextureSamplerInfo baseColorSampler); - - static inline const BasicUniformOffsets& GetOffsets(); - static inline const std::shared_ptr& GetSettings(); - - struct BasicUniformOffsets - { - std::size_t alphaThreshold; - std::size_t baseColor; - std::size_t totalSize; - }; - - protected: - struct NoInit {}; - - inline BasicMaterial(MaterialPass& material, NoInit); - - struct BasicOptionIndexes - { - std::size_t alphaTest; - std::size_t hasAlphaMap; - std::size_t hasBaseColorMap; - }; - - struct BasicTextureIndexes - { - std::size_t alpha; - std::size_t baseColor; - }; - - struct BasicBuildOptions - { - // Common - std::vector defaultValues; - std::size_t* uniformBlockIndex = nullptr; - std::vector> shaders; - - // Basic - BasicUniformOffsets basicOffsets; - BasicOptionIndexes* basicOptionIndexes = nullptr; - BasicTextureIndexes* basicTextureIndexes = nullptr; - }; - - inline MaterialPass& GetMaterial(); - inline const MaterialPass& GetMaterial() const; - - static MaterialSettings::Builder Build(BasicBuildOptions& options); - static std::vector> BuildShaders(); - static std::pair BuildUniformOffsets(); - - std::size_t m_uniformBlockIndex; - BasicOptionIndexes m_basicOptionIndexes; - BasicTextureIndexes m_basicTextureIndexes; - BasicUniformOffsets m_basicUniformOffsets; - - static std::shared_ptr s_basicMaterialSettings; - static std::size_t s_uniformBlockIndex; - static BasicOptionIndexes s_basicOptionIndexes; - static BasicTextureIndexes s_basicTextureIndexes; - static BasicUniformOffsets s_basicUniformOffsets; - - private: - static bool Initialize(); - static void Uninitialize(); - - MaterialPass& m_material; - }; -} - -#include - -#endif // NAZARA_GRAPHICS_BASICMATERIAL_HPP diff --git a/include/Nazara/Graphics/BasicMaterial.inl b/include/Nazara/Graphics/BasicMaterial.inl deleted file mode 100644 index 31d2e8803..000000000 --- a/include/Nazara/Graphics/BasicMaterial.inl +++ /dev/null @@ -1,149 +0,0 @@ -// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) -// This file is part of the "Nazara Engine - Graphics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include - -namespace Nz -{ - inline BasicMaterial::BasicMaterial(MaterialPass& material, NoInit) : - m_material(material) - { - } - - /*! - * \brief Enable/Disable alpha test for this material - * - * When enabled, all objects using this material will be rendered using alpha testing, - * rejecting pixels if their alpha component is under a defined threshold. - * This allows some kind of transparency with a much cheaper cost as it doesn't prevent any optimization (as deferred rendering or batching). - * - * \param alphaTest Defines if this material will use alpha testing - * - * \remark Invalidates the pipeline - * - * \see IsAlphaTestEnabled - * \see SetAlphaThreshold - */ - inline void BasicMaterial::EnableAlphaTest(bool alphaTest) - { - NazaraAssert(HasAlphaTest(), "Material has no alpha test option"); - m_material.SetOptionValue(m_basicOptionIndexes.alphaTest, alphaTest); - } - - inline const std::shared_ptr& BasicMaterial::GetAlphaMap() const - { - NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot"); - return m_material.GetTexture(m_basicTextureIndexes.alpha); - } - - inline const TextureSamplerInfo& BasicMaterial::GetAlphaSampler() const - { - NazaraAssert(HasAlphaMap(), "Material has no alpha texture slot"); - return m_material.GetTextureSampler(m_basicTextureIndexes.alpha); - } - - inline const std::shared_ptr& BasicMaterial::GetBaseColorMap() const - { - NazaraAssert(HasBaseColorMap(), "Material has no alpha texture slot"); - return m_material.GetTexture(m_basicTextureIndexes.baseColor); - } - - inline const TextureSamplerInfo& BasicMaterial::GetBaseColorSampler() const - { - NazaraAssert(HasBaseColorMap(), "Material has no alpha texture slot"); - return m_material.GetTextureSampler(m_basicTextureIndexes.baseColor); - } - - inline bool BasicMaterial::IsAlphaTestEnabled() const - { - NazaraAssert(HasAlphaTest(), "Material has no alpha test option"); - const auto& optionOpt = m_material.GetOptionValue(m_basicOptionIndexes.alphaTest); - if (std::holds_alternative(optionOpt)) - return false; - - return std::get(optionOpt); - } - - inline bool BasicMaterial::HasAlphaMap() const - { - return m_basicTextureIndexes.alpha != MaterialSettings::InvalidIndex; - } - - inline bool BasicMaterial::HasAlphaTest() const - { - return m_basicOptionIndexes.alphaTest != MaterialSettings::InvalidIndex; - } - - inline bool BasicMaterial::HasAlphaTestThreshold() const - { - return m_basicUniformOffsets.alphaThreshold != MaterialSettings::InvalidIndex; - } - - inline bool BasicMaterial::HasBaseColor() const - { - return m_basicUniformOffsets.baseColor != MaterialSettings::InvalidIndex; - } - - inline bool BasicMaterial::HasBaseColorMap() const - { - return m_basicTextureIndexes.baseColor != MaterialSettings::InvalidIndex; - } - - inline void BasicMaterial::SetAlphaMap(std::shared_ptr alphaMap) - { - NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); - bool hasAlphaMap = (alphaMap != nullptr); - m_material.SetTexture(m_basicTextureIndexes.alpha, std::move(alphaMap)); - - if (m_basicOptionIndexes.hasBaseColorMap != MaterialSettings::InvalidIndex) - m_material.SetOptionValue(m_basicOptionIndexes.hasAlphaMap, hasAlphaMap); - } - - inline void BasicMaterial::SetAlphaSampler(TextureSamplerInfo alphaSampler) - { - NazaraAssert(HasAlphaMap(), "Material has no alpha map slot"); - m_material.SetTextureSampler(m_basicTextureIndexes.alpha, std::move(alphaSampler)); - } - - inline void BasicMaterial::SetBaseColorMap(std::shared_ptr baseColorMap) - { - NazaraAssert(HasBaseColorMap(), "Material has no diffuse map slot"); - bool hasBaseColorMap = (baseColorMap != nullptr); - m_material.SetTexture(m_basicTextureIndexes.baseColor, std::move(baseColorMap)); - - if (m_basicOptionIndexes.hasBaseColorMap != MaterialSettings::InvalidIndex) - m_material.SetOptionValue(m_basicOptionIndexes.hasBaseColorMap, hasBaseColorMap); - } - - inline void BasicMaterial::SetBaseColorSampler(TextureSamplerInfo diffuseSampler) - { - NazaraAssert(HasBaseColorMap(), "Material has no diffuse map slot"); - m_material.SetTextureSampler(m_basicTextureIndexes.baseColor, std::move(diffuseSampler)); - } - - inline MaterialPass& BasicMaterial::GetMaterial() - { - return m_material; - } - - inline const MaterialPass& BasicMaterial::GetMaterial() const - { - return m_material; - } - - inline const std::shared_ptr& BasicMaterial::GetSettings() - { - return s_basicMaterialSettings; - } - - inline auto BasicMaterial::GetOffsets() -> const BasicUniformOffsets& - { - return s_basicUniformOffsets; - } -} - -#include diff --git a/include/Nazara/Graphics/DepthMaterial.hpp b/include/Nazara/Graphics/DepthMaterial.hpp deleted file mode 100644 index eb84f590d..000000000 --- a/include/Nazara/Graphics/DepthMaterial.hpp +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) -// This file is part of the "Nazara Engine - Graphics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#pragma once - -#ifndef NAZARA_GRAPHICS_DEPTHMATERIAL_HPP -#define NAZARA_GRAPHICS_DEPTHMATERIAL_HPP - -#include -#include - -namespace Nz -{ - class NAZARA_GRAPHICS_API DepthMaterial : public BasicMaterial - { - friend class MaterialPipeline; - - public: - using BasicMaterial::BasicMaterial; - ~DepthMaterial() = default; - - static inline const std::shared_ptr& GetSettings(); - - protected: - static std::vector> BuildShaders(); - - private: - static bool Initialize(); - static void Uninitialize(); - - static std::shared_ptr s_depthMaterialSettings; - }; -} - -#include - -#endif // NAZARA_GRAPHICS_DEPTHMATERIAL_HPP diff --git a/include/Nazara/Graphics/DepthPipelinePass.hpp b/include/Nazara/Graphics/DepthPipelinePass.hpp index 58d771201..ab96c9b5e 100644 --- a/include/Nazara/Graphics/DepthPipelinePass.hpp +++ b/include/Nazara/Graphics/DepthPipelinePass.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -24,7 +25,6 @@ namespace Nz class ElementRendererRegistry; class FrameGraph; class FramePipeline; - class Material; class NAZARA_GRAPHICS_API DepthPipelinePass : public FramePipelinePass { @@ -32,17 +32,17 @@ namespace Nz DepthPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer); DepthPipelinePass(const DepthPipelinePass&) = delete; DepthPipelinePass(DepthPipelinePass&&) = delete; - ~DepthPipelinePass(); + ~DepthPipelinePass() = default; inline void InvalidateCommandBuffers(); inline void InvalidateElements(); void Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector& visibleRenderables, std::size_t visibilityHash); - void RegisterMaterial(const Material& material); + void RegisterMaterialInstance(const MaterialInstance& materialInstance); void RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t depthBufferIndex); - void UnregisterMaterial(const Material& material); + void UnregisterMaterialInstance(const MaterialInstance& materialInstance); DepthPipelinePass& operator=(const DepthPipelinePass&) = delete; DepthPipelinePass& operator=(DepthPipelinePass&&) = delete; @@ -52,8 +52,8 @@ namespace Nz { std::size_t usedCount = 1; - NazaraSlot(MaterialPass, OnMaterialPassPipelineInvalidated, onMaterialPipelineInvalidated); - NazaraSlot(MaterialPass, OnMaterialPassShaderBindingInvalidated, onMaterialShaderBindingInvalidated); + NazaraSlot(MaterialInstance, OnMaterialInstancePipelineInvalidated, onMaterialInstancePipelineInvalidated); + NazaraSlot(MaterialInstance, OnMaterialInstanceShaderBindingInvalidated, onMaterialInstanceShaderBindingInvalidated); }; std::size_t m_depthPassIndex; @@ -61,7 +61,7 @@ namespace Nz std::vector> m_elementRendererData; std::vector m_renderStates; std::vector m_renderElements; - std::unordered_map m_materialPasses; + std::unordered_map m_materialInstances; RenderQueue m_renderQueue; RenderQueueRegistry m_renderQueueRegistry; AbstractViewer* m_viewer; diff --git a/include/Nazara/Graphics/Enums.hpp b/include/Nazara/Graphics/Enums.hpp index 06c744183..7419aefa8 100644 --- a/include/Nazara/Graphics/Enums.hpp +++ b/include/Nazara/Graphics/Enums.hpp @@ -41,6 +41,27 @@ namespace Nz Volume }; + enum class MaterialPropertyType + { + Bool, + Bool2, + Bool3, + Bool4, + Color, + Float, + Float2, + Float3, + Float4, + Int, + Int2, + Int3, + Int4, + UInt, + UInt2, + UInt3, + UInt4 + }; + enum class MaterialLightingType { None, @@ -69,7 +90,7 @@ namespace Nz Perspective }; - enum class PredefinedShaderBinding + enum class EngineShaderBinding { InstanceDataUbo, LightDataUbo, @@ -80,7 +101,7 @@ namespace Nz Max = ViewerDataUbo }; - constexpr std::size_t PredefinedShaderBindingCount = static_cast(PredefinedShaderBinding::Max) + 1; + constexpr std::size_t PredefinedShaderBindingCount = static_cast(EngineShaderBinding::Max) + 1; } #endif // NAZARA_GRAPHICS_ENUMS_HPP diff --git a/include/Nazara/Graphics/ForwardFramePipeline.hpp b/include/Nazara/Graphics/ForwardFramePipeline.hpp index f335c123c..7470526ff 100644 --- a/include/Nazara/Graphics/ForwardFramePipeline.hpp +++ b/include/Nazara/Graphics/ForwardFramePipeline.hpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -42,12 +43,7 @@ namespace Nz ForwardFramePipeline(ForwardFramePipeline&&) = delete; ~ForwardFramePipeline(); - void InvalidateSkeletalInstance(std::size_t skeletalInstanceIndex) override; - void InvalidateViewer(std::size_t viewerIndex) override; - void InvalidateWorldInstance(std::size_t renderableIndex) override; - std::size_t RegisterLight(std::shared_ptr light, UInt32 renderMask) override; - void RegisterMaterialPass(MaterialPass* materialPass) override; std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) override; std::size_t RegisterSkeleton(SkeletonInstancePtr skeletonInstance) override; std::size_t RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder) override; @@ -56,7 +52,6 @@ namespace Nz void Render(RenderFrame& renderFrame) override; void UnregisterLight(std::size_t lightIndex) override; - void UnregisterMaterialPass(MaterialPass* material) override; void UnregisterRenderable(std::size_t renderableIndex) override; void UnregisterSkeleton(std::size_t skeletonIndex) override; void UnregisterViewer(std::size_t viewerIndex) override; @@ -73,6 +68,9 @@ namespace Nz private: BakedFrameGraph BuildFrameGraph(); + void RegisterMaterialInstance(MaterialInstance* materialPass); + void UnregisterMaterialInstance(MaterialInstance* material); + struct ViewerData; struct LightData @@ -83,11 +81,11 @@ namespace Nz NazaraSlot(Light, OnLightDataInvalided, onLightInvalidated); }; - struct MaterialPassData + struct MaterialInstanceData { std::size_t usedCount = 0; - NazaraSlot(MaterialPass, OnMaterialPassInvalidated, onMaterialPassInvalided); + NazaraSlot(TransferInterface, OnTransferRequired, onTransferRequired); }; struct RenderableData @@ -109,6 +107,13 @@ namespace Nz ShaderBindingPtr blitShaderBinding; }; + struct SkeletonInstanceData + { + SkeletonInstancePtr skeleton; + + NazaraSlot(TransferInterface, OnTransferRequired, onTransferRequired); + }; + struct ViewerData { std::size_t forwardColorAttachment; @@ -122,27 +127,33 @@ namespace Nz RenderQueueRegistry forwardRegistry; RenderQueue forwardRenderQueue; ShaderBindingPtr blitShaderBinding; + + NazaraSlot(TransferInterface, OnTransferRequired, onTransferRequired); + }; + + struct WorldInstanceData + { + WorldInstancePtr worldInstance; + + NazaraSlot(TransferInterface, OnTransferRequired, onTransferRequired); }; - std::unordered_map m_activeMaterialPasses; std::unordered_map m_renderTargets; - std::unordered_set m_invalidatedMaterialPasses; + std::unordered_map m_materialInstances; std::vector m_renderStates; std::vector m_visibleRenderables; std::vector m_visibleLights; + robin_hood::unordered_set m_transferSet; BakedFrameGraph m_bakedFrameGraph; - Bitset m_invalidatedSkeletonInstances; - Bitset m_invalidatedViewerInstances; - Bitset m_invalidatedWorldInstances; Bitset m_removedSkeletonInstances; Bitset m_removedViewerInstances; Bitset m_removedWorldInstances; ElementRendererRegistry& m_elementRegistry; MemoryPool m_renderablePool; MemoryPool m_lightPool; - MemoryPool m_skeletonInstances; + MemoryPool m_skeletonInstances; MemoryPool m_viewerPool; - MemoryPool m_worldInstances; + MemoryPool m_worldInstances; RenderFrame* m_currentRenderFrame; bool m_rebuildFrameGraph; }; diff --git a/include/Nazara/Graphics/ForwardPipelinePass.hpp b/include/Nazara/Graphics/ForwardPipelinePass.hpp index 90fc3aef1..9a95009e4 100644 --- a/include/Nazara/Graphics/ForwardPipelinePass.hpp +++ b/include/Nazara/Graphics/ForwardPipelinePass.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -27,7 +28,6 @@ namespace Nz class FrameGraph; class FramePipeline; class Light; - class Material; class NAZARA_GRAPHICS_API ForwardPipelinePass : public FramePipelinePass { @@ -35,17 +35,17 @@ namespace Nz ForwardPipelinePass(FramePipeline& owner, ElementRendererRegistry& elementRegistry, AbstractViewer* viewer); ForwardPipelinePass(const ForwardPipelinePass&) = delete; ForwardPipelinePass(ForwardPipelinePass&&) = delete; - ~ForwardPipelinePass(); + ~ForwardPipelinePass() = default; inline void InvalidateCommandBuffers(); inline void InvalidateElements(); void Prepare(RenderFrame& renderFrame, const Frustumf& frustum, const std::vector& visibleRenderables, const std::vector& visibleLights, std::size_t visibilityHash); - void RegisterMaterial(const Material& material); + void RegisterMaterialInstance(const MaterialInstance& material); void RegisterToFrameGraph(FrameGraph& frameGraph, std::size_t colorBufferIndex, std::size_t depthBufferIndex, bool hasDepthPrepass); - void UnregisterMaterial(const Material& material); + void UnregisterMaterialInstance(const MaterialInstance& material); ForwardPipelinePass& operator=(const ForwardPipelinePass&) = delete; ForwardPipelinePass& operator=(ForwardPipelinePass&&) = delete; @@ -57,8 +57,8 @@ namespace Nz { std::size_t usedCount = 1; - NazaraSlot(MaterialPass, OnMaterialPassPipelineInvalidated, onMaterialPipelineInvalidated); - NazaraSlot(MaterialPass, OnMaterialPassShaderBindingInvalidated, onMaterialShaderBindingInvalidated); + NazaraSlot(MaterialInstance, OnMaterialInstancePipelineInvalidated, onMaterialInstancePipelineInvalidated); + NazaraSlot(MaterialInstance, OnMaterialInstanceShaderBindingInvalidated, onMaterialInstanceShaderBindingInvalidated); }; using LightKey = std::array; @@ -86,7 +86,7 @@ namespace Nz std::vector> m_elementRendererData; std::vector m_renderStates; std::vector m_renderElements; - std::unordered_map m_materialPasses; + std::unordered_map m_materialInstances; std::unordered_map m_lightPerRenderElement; std::unordered_map m_lightBufferPerLights; std::vector m_lightDataBuffers; diff --git a/include/Nazara/Graphics/FramePipeline.hpp b/include/Nazara/Graphics/FramePipeline.hpp index 3fa694222..726a32cbc 100644 --- a/include/Nazara/Graphics/FramePipeline.hpp +++ b/include/Nazara/Graphics/FramePipeline.hpp @@ -21,7 +21,6 @@ namespace Nz class AbstractViewer; class InstancedRenderable; class Light; - class MaterialPass; class RenderFrame; class NAZARA_GRAPHICS_API FramePipeline @@ -34,12 +33,7 @@ namespace Nz inline DebugDrawer& GetDebugDrawer(); - virtual void InvalidateSkeletalInstance(std::size_t skeletalInstanceIndex) = 0; - virtual void InvalidateViewer(std::size_t viewerIndex) = 0; - virtual void InvalidateWorldInstance(std::size_t worldInstance) = 0; - virtual std::size_t RegisterLight(std::shared_ptr light, UInt32 renderMask) = 0; - virtual void RegisterMaterialPass(MaterialPass* materialPass) = 0; virtual std::size_t RegisterRenderable(std::size_t worldInstanceIndex, std::size_t skeletonInstanceIndex, const InstancedRenderable* instancedRenderable, UInt32 renderMask, const Recti& scissorBox) = 0; virtual std::size_t RegisterSkeleton(SkeletonInstancePtr skeletonInstance) = 0; virtual std::size_t RegisterViewer(AbstractViewer* viewerInstance, Int32 renderOrder) = 0; @@ -48,7 +42,6 @@ namespace Nz virtual void Render(RenderFrame& renderFrame) = 0; virtual void UnregisterLight(std::size_t lightIndex) = 0; - virtual void UnregisterMaterialPass(MaterialPass* materialPass) = 0; virtual void UnregisterRenderable(std::size_t renderableIndex) = 0; virtual void UnregisterSkeleton(std::size_t skeletonIndex) = 0; virtual void UnregisterViewer(std::size_t viewerIndex) = 0; diff --git a/include/Nazara/Graphics/Graphics.hpp b/include/Nazara/Graphics/Graphics.hpp index 142c1d6c3..356c5594d 100644 --- a/include/Nazara/Graphics/Graphics.hpp +++ b/include/Nazara/Graphics/Graphics.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -43,8 +44,10 @@ namespace Nz inline const DefaultTextures& GetDefaultTextures() const; inline MaterialPassRegistry& GetMaterialPassRegistry(); inline const MaterialPassRegistry& GetMaterialPassRegistry() const; - MaterialLoader& GetMaterialLoader(); - const MaterialLoader& GetMaterialLoader() const; + inline MaterialInstanceLoader& GetMaterialInstanceLoader(); + inline const MaterialInstanceLoader& GetMaterialInstanceLoader() const; + inline MaterialLoader& GetMaterialLoader(); + inline const MaterialLoader& GetMaterialLoader() const; inline PixelFormat GetPreferredDepthStencilFormat() const; inline const std::shared_ptr& GetRenderDevice() const; inline const RenderPassCache& GetRenderPassCache() const; @@ -59,8 +62,13 @@ namespace Nz struct DefaultMaterials { - std::shared_ptr depthMaterial; - std::shared_ptr noDepthMaterial; + std::shared_ptr basicMaterial; + std::shared_ptr phongMaterial; + std::shared_ptr pbrMaterial; + + std::shared_ptr basicDefault; + std::shared_ptr basicNoDepth; + std::shared_ptr basicTransparent; }; struct DefaultTextures @@ -86,6 +94,7 @@ namespace Nz std::shared_ptr m_blitPipelineLayout; DefaultMaterials m_defaultMaterials; DefaultTextures m_defaultTextures; + MaterialInstanceLoader m_materialInstanceLoader; MaterialLoader m_materialLoader; MaterialPassRegistry m_materialPassRegistry; PixelFormat m_preferredDepthStencilFormat; diff --git a/include/Nazara/Graphics/Graphics.inl b/include/Nazara/Graphics/Graphics.inl index c3f385cf8..4b18d58c8 100644 --- a/include/Nazara/Graphics/Graphics.inl +++ b/include/Nazara/Graphics/Graphics.inl @@ -37,6 +37,16 @@ namespace Nz return m_materialPassRegistry; } + inline MaterialInstanceLoader& Graphics::GetMaterialInstanceLoader() + { + return m_materialInstanceLoader; + } + + inline const MaterialInstanceLoader& Graphics::GetMaterialInstanceLoader() const + { + return m_materialInstanceLoader; + } + inline MaterialLoader& Graphics::GetMaterialLoader() { return m_materialLoader; diff --git a/include/Nazara/Graphics/InstancedRenderable.hpp b/include/Nazara/Graphics/InstancedRenderable.hpp index 4438f0350..ffef3f987 100644 --- a/include/Nazara/Graphics/InstancedRenderable.hpp +++ b/include/Nazara/Graphics/InstancedRenderable.hpp @@ -18,7 +18,7 @@ namespace Nz { class CommandBufferBuilder; class ElementRendererRegistry; - class Material; + class MaterialInstance; class RenderElement; class SkeletonInstance; class WorldInstance; @@ -36,7 +36,7 @@ namespace Nz virtual void BuildElement(ElementRendererRegistry& registry, const ElementData& elementData, std::size_t passIndex, std::vector& elements) const = 0; inline const Boxf& GetAABB() const; - virtual const std::shared_ptr& GetMaterial(std::size_t i) const = 0; + virtual const std::shared_ptr& GetMaterial(std::size_t i) const = 0; virtual std::size_t GetMaterialCount() const = 0; inline int GetRenderLayer() const; @@ -47,7 +47,7 @@ namespace Nz NazaraSignal(OnAABBUpdate, InstancedRenderable* /*instancedRenderable*/, const Boxf& /*aabb*/); NazaraSignal(OnElementInvalidated, InstancedRenderable* /*instancedRenderable*/); - NazaraSignal(OnMaterialInvalidated, InstancedRenderable* /*instancedRenderable*/, std::size_t /*materialIndex*/, const std::shared_ptr& /*newMaterial*/); + NazaraSignal(OnMaterialInvalidated, InstancedRenderable* /*instancedRenderable*/, std::size_t /*materialIndex*/, const std::shared_ptr& /*newMaterial*/); struct ElementData { diff --git a/include/Nazara/Graphics/LinearSlicedSprite.hpp b/include/Nazara/Graphics/LinearSlicedSprite.hpp index 55998603b..eb2d1d098 100644 --- a/include/Nazara/Graphics/LinearSlicedSprite.hpp +++ b/include/Nazara/Graphics/LinearSlicedSprite.hpp @@ -23,7 +23,7 @@ namespace Nz enum class Orientation; struct Section; - LinearSlicedSprite(std::shared_ptr material, Orientation orientation); + LinearSlicedSprite(std::shared_ptr material, Orientation orientation); LinearSlicedSprite(const LinearSlicedSprite&) = delete; LinearSlicedSprite(LinearSlicedSprite&&) noexcept = default; ~LinearSlicedSprite() = default; @@ -35,7 +35,7 @@ namespace Nz inline void Clear(); inline const Color& GetColor() const; - const std::shared_ptr& GetMaterial(std::size_t i = 0) const override; + const std::shared_ptr& GetMaterial(std::size_t i = 0) const override; std::size_t GetMaterialCount() const override; inline Orientation GetOrientation() const; inline const Section& GetSection(std::size_t sectionIndex) const; @@ -46,7 +46,7 @@ namespace Nz inline void RemoveSection(std::size_t sectionIndex); inline void SetColor(const Color& color); - inline void SetMaterial(std::shared_ptr material); + inline void SetMaterial(std::shared_ptr material); inline void SetSection(std::size_t sectionIndex, float size, float textureCoord); inline void SetSectionSize(std::size_t sectionIndex, float size); inline void SetSectionTextureCoord(std::size_t sectionIndex, float textureCoord); @@ -76,7 +76,7 @@ namespace Nz std::array m_sections; std::array m_vertices; - std::shared_ptr m_material; + std::shared_ptr m_material; std::size_t m_sectionCount; std::size_t m_spriteCount; Color m_color; diff --git a/include/Nazara/Graphics/LinearSlicedSprite.inl b/include/Nazara/Graphics/LinearSlicedSprite.inl index 007dccc90..fa5e78a1c 100644 --- a/include/Nazara/Graphics/LinearSlicedSprite.inl +++ b/include/Nazara/Graphics/LinearSlicedSprite.inl @@ -71,7 +71,7 @@ namespace Nz UpdateVertices(); } - inline void LinearSlicedSprite::SetMaterial(std::shared_ptr material) + inline void LinearSlicedSprite::SetMaterial(std::shared_ptr material) { assert(material); diff --git a/include/Nazara/Graphics/Material.hpp b/include/Nazara/Graphics/Material.hpp index 048900ec4..ba02b03c0 100644 --- a/include/Nazara/Graphics/Material.hpp +++ b/include/Nazara/Graphics/Material.hpp @@ -14,50 +14,91 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include namespace Nz { struct NAZARA_GRAPHICS_API MaterialParams : ResourceParameters { - MaterialLightingType lightingType = MaterialLightingType::None; - bool IsValid() const; }; class Material; - class MaterialPass; + class MaterialInstance; + class RenderPipelineLayout; using MaterialLibrary = ObjectLibrary; using MaterialLoader = ResourceLoader; using MaterialManager = ResourceManager; using MaterialSaver = ResourceSaver; - class NAZARA_GRAPHICS_API Material : public Resource + class NAZARA_GRAPHICS_API Material : public Resource, public std::enable_shared_from_this { public: - Material() = default; + struct TextureData; + struct UniformBlockData; + + Material(MaterialSettings settings, const std::string& referenceModuleName); + Material(MaterialSettings settings, const nzsl::Ast::ModulePtr& referenceModule); ~Material() = default; - inline void AddPass(std::size_t passIndex, std::shared_ptr pass); - void AddPass(std::string passName, std::shared_ptr pass); + std::shared_ptr CreateInstance() const; - const std::shared_ptr& FindPass(const std::string& passName) const; + std::shared_ptr GetDefaultInstance() const; - template void ForEachPass(F&& callback); + inline std::size_t FindTextureByTag(const std::string& tag) const; + inline std::size_t FindUniformBlockByTag(const std::string& tag) const; - inline const std::shared_ptr& GetPass(std::size_t passIndex) const; - - inline bool HasPass(std::size_t passIndex) const; - - inline void RemovePass(std::size_t passIndex); - void RemovePass(const std::string& passName); + inline UInt32 GetEngineBindingIndex(EngineShaderBinding shaderBinding) const; + inline const std::shared_ptr& GetRenderPipelineLayout() const; + inline const MaterialSettings& GetSettings() const; + inline const TextureData& GetTextureData(std::size_t textureIndex) const; + inline std::size_t GetTextureCount() const; + inline const UniformBlockData& GetUniformBlockData(std::size_t uniformBlockIndex) const; + inline std::size_t GetUniformBlockCount() const; + static std::shared_ptr Build(const ParameterList& materialData); static std::shared_ptr LoadFromFile(const std::filesystem::path& filePath, const MaterialParams& params = MaterialParams()); static std::shared_ptr LoadFromMemory(const void* data, std::size_t size, const MaterialParams& params = MaterialParams()); static std::shared_ptr LoadFromStream(Stream& stream, const MaterialParams& params = MaterialParams()); + static inline ImageType ToImageType(nzsl::ImageType imageType); + + static constexpr UInt32 InvalidBindingIndex = std::numeric_limits::max(); + static constexpr std::size_t InvalidIndex = std::numeric_limits::max(); + + struct TextureData + { + UInt32 bindingSet; + UInt32 bindingIndex; + ImageType imageType; + }; + + struct UniformBlockData + { + UInt32 bindingSet; + UInt32 bindingIndex; + std::size_t structIndex; + std::unique_ptr bufferPool; + }; + private: - std::vector> m_passes; + std::array m_engineShaderBindings; + std::shared_ptr m_renderPipelineLayout; + std::unordered_map m_optionValues; + std::unordered_map m_textureByTag; + std::unordered_map m_uniformBlockByTag; + std::vector m_textures; + std::vector m_uniformBlocks; + mutable std::weak_ptr m_defaultInstance; + MaterialSettings m_settings; + ShaderReflection m_reflection; }; } diff --git a/include/Nazara/Graphics/Material.inl b/include/Nazara/Graphics/Material.inl index 76f3e1daf..34d7d0d38 100644 --- a/include/Nazara/Graphics/Material.inl +++ b/include/Nazara/Graphics/Material.inl @@ -7,49 +7,75 @@ namespace Nz { - inline void Material::AddPass(std::size_t passIndex, std::shared_ptr pass) + inline std::size_t Material::FindTextureByTag(const std::string& tag) const { - if (passIndex >= m_passes.size()) - m_passes.resize(passIndex + 1); + auto it = m_textureByTag.find(tag); + if (it == m_textureByTag.end()) + return InvalidIndex; - m_passes[passIndex] = std::move(pass); + return it->second; } - template - void Material::ForEachPass(F&& callback) + inline std::size_t Material::FindUniformBlockByTag(const std::string& tag) const { - for (std::size_t i = 0; i < m_passes.size(); ++i) - { - if (m_passes[i]) - callback(i, m_passes[i]); - } + auto it = m_uniformBlockByTag.find(tag); + if (it == m_uniformBlockByTag.end()) + return InvalidIndex; + + return it->second; } - inline const std::shared_ptr& Material::GetPass(std::size_t passIndex) const + inline UInt32 Material::GetEngineBindingIndex(EngineShaderBinding shaderBinding) const { - if (passIndex >= m_passes.size()) + return m_engineShaderBindings[UnderlyingCast(shaderBinding)]; + } + + inline const std::shared_ptr& Material::GetRenderPipelineLayout() const + { + return m_renderPipelineLayout; + } + + inline const MaterialSettings& Material::GetSettings() const + { + return m_settings; + } + + inline auto Material::GetTextureData(std::size_t textureIndex) const -> const TextureData& + { + assert(textureIndex < m_textures.size()); + return m_textures[textureIndex]; + } + + inline std::size_t Material::GetTextureCount() const + { + return m_textures.size(); + } + + inline auto Material::GetUniformBlockData(std::size_t uniformBlockIndex) const -> const UniformBlockData& + { + assert(uniformBlockIndex < m_uniformBlocks.size()); + return m_uniformBlocks[uniformBlockIndex]; + } + + inline std::size_t Material::GetUniformBlockCount() const + { + return m_uniformBlocks.size(); + } + + inline ImageType Material::ToImageType(nzsl::ImageType imageType) + { + switch (imageType) { - static std::shared_ptr dummy; - return dummy; + case nzsl::ImageType::E1D: return ImageType::E1D; + case nzsl::ImageType::E1D_Array: return ImageType::E1D_Array; + case nzsl::ImageType::E2D: return ImageType::E2D; + case nzsl::ImageType::E2D_Array: return ImageType::E2D_Array; + case nzsl::ImageType::E3D: return ImageType::E3D; + case nzsl::ImageType::Cubemap: return ImageType::Cubemap; } - return m_passes[passIndex]; - } - - inline bool Material::HasPass(std::size_t passIndex) const - { - if (passIndex >= m_passes.size()) - return false; - - return m_passes[passIndex] != nullptr; - } - - inline void Material::RemovePass(std::size_t passIndex) - { - if (passIndex >= m_passes.size()) - return; - - m_passes[passIndex].reset(); + NazaraError("invalid image type 0x" + NumberToString(UnderlyingCast(imageType), 16)); + return ImageType::E2D; } } diff --git a/include/Nazara/Graphics/MaterialInstance.hpp b/include/Nazara/Graphics/MaterialInstance.hpp new file mode 100644 index 000000000..43aaa6045 --- /dev/null +++ b/include/Nazara/Graphics/MaterialInstance.hpp @@ -0,0 +1,165 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#pragma once + +#ifndef NAZARA_GRAPHICS_MATERIALINSTANCE_HPP +#define NAZARA_GRAPHICS_MATERIALINSTANCE_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Nz +{ + struct NAZARA_GRAPHICS_API MaterialInstanceParams : ResourceParameters + { + MaterialLightingType lightingType = MaterialLightingType::None; + + bool IsValid() const; + }; + + class Material; + class MaterialInstance; + class MaterialPipeline; + class Texture; + + using MaterialInstanceLibrary = ObjectLibrary; + using MaterialInstanceLoader = ResourceLoader; + using MaterialInstanceManager = ResourceManager; + using MaterialInstanceSaver = ResourceSaver; + + class NAZARA_GRAPHICS_API MaterialInstance : public TransferInterface + { + struct CopyToken {}; + + public: + MaterialInstance(std::shared_ptr parent); + MaterialInstance(const MaterialInstance&) = delete; + MaterialInstance(const MaterialInstance& material, CopyToken); + MaterialInstance(MaterialInstance&&) = delete; + ~MaterialInstance(); + + inline std::shared_ptr Clone() const; + + void DisablePass(std::string_view passName); + inline void DisablePass(std::size_t passIndex); + void EnablePass(std::string_view passName, bool enable = true); + inline void EnablePass(std::size_t passIndex, bool enable = true); + + void FillShaderBinding(std::vector& bindings) const; + + inline std::size_t FindTextureProperty(std::string_view propertyName) const; + inline std::size_t FindValueProperty(std::string_view propertyName) const; + + inline const std::shared_ptr& GetParentMaterial() const; + inline MaterialPassFlags GetPassFlags(std::size_t passIndex) const; + const std::shared_ptr& GetPipeline(std::size_t passIndex) const; + + inline const std::shared_ptr* GetTextureProperty(std::string_view propertyName) const; + inline const std::shared_ptr& GetTextureProperty(std::size_t textureIndex) const; + inline const std::shared_ptr& GetTexturePropertyOverride(std::size_t textureIndex) const; + + inline const TextureSamplerInfo* GetTextureSamplerProperty(std::string_view propertyName) const; + inline const TextureSamplerInfo& GetTextureSamplerProperty(std::size_t textureIndex) const; + + inline const MaterialSettings::Value* GetValueProperty(std::string_view propertyName) const; + inline const MaterialSettings::Value& GetValueProperty(std::size_t valueIndex) const; + inline const MaterialSettings::Value& GetValuePropertyOverride(std::size_t valueIndex) const; + + bool HasPass(std::string_view passName) const; + inline bool HasPass(std::size_t passIndex) const; + + void OnTransfer(RenderFrame& renderFrame, CommandBufferBuilder& builder) override; + + inline void SetTextureProperty(std::string_view propertyName, std::shared_ptr texture); + inline void SetTextureProperty(std::string_view propertyName, std::shared_ptr texture, const TextureSamplerInfo& samplerInfo); + void SetTextureProperty(std::size_t textureIndex, std::shared_ptr texture); + void SetTextureProperty(std::size_t textureIndex, std::shared_ptr texture, const TextureSamplerInfo& samplerInfo); + + inline void SetTextureSamplerProperty(std::string_view propertyName, const TextureSamplerInfo& samplerInfo); + void SetTextureSamplerProperty(std::size_t textureIndex, const TextureSamplerInfo& samplerInfo); + + inline void SetValueProperty(std::string_view propertyName, const MaterialSettings::Value& value); + void SetValueProperty(std::size_t valueIndex, const MaterialSettings::Value& value); + + void UpdateOptionValue(UInt32 optionHash, const nzsl::Ast::ConstantSingleValue& value); + void UpdatePassFlags(std::string_view passName, MaterialPassFlags materialFlags); + inline void UpdatePassFlags(std::size_t passName, MaterialPassFlags materialFlags); + void UpdatePassStates(std::string_view passName, FunctionRef stateUpdater); + template void UpdatePassStates(std::size_t passIndex, F&& stateUpdater); + void UpdateTextureBinding(std::size_t textureBinding, std::shared_ptr texture, std::shared_ptr textureSampler); + void UpdateUniformBufferData(std::size_t uniformBufferIndex, std::size_t offset, std::size_t size, const void* data); + + MaterialInstance& operator=(const MaterialInstance&) = delete; + MaterialInstance& operator=(MaterialInstance&&) = delete; + + static constexpr std::size_t InvalidPropertyIndex = MaterialSettings::InvalidPropertyIndex; + + NazaraSignal(OnMaterialInstancePipelineInvalidated, const MaterialInstance* /*matInstance*/, std::size_t /*passIndex*/); + NazaraSignal(OnMaterialInstanceShaderBindingInvalidated, const MaterialInstance* /*matInstance*/); + + private: + inline void InvalidatePassPipeline(std::size_t passIndex); + inline void InvalidateShaderBinding(); + + struct PassShader + { + std::shared_ptr shader; + + NazaraSlot(UberShader, OnShaderUpdated, onShaderUpdated); + }; + + struct PassData + { + mutable MaterialPipelineInfo pipelineInfo; + mutable std::shared_ptr pipeline; + std::vector shaders; + MaterialPassFlags flags; + bool enabled = false; + }; + + struct TextureBinding + { + std::shared_ptr texture; + std::shared_ptr sampler; + }; + + struct TextureProperty + { + std::shared_ptr texture; + TextureSamplerInfo samplerInfo; + }; + + struct UniformBuffer + { + std::size_t bufferIndex; + std::vector values; + RenderBufferView bufferView; + bool dataInvalidated = true; + }; + + std::shared_ptr m_parent; + std::unordered_map m_optionValuesOverride; + std::vector m_valueOverride; + std::vector m_passes; + std::vector m_textureBinding; + std::vector m_textureOverride; + std::vector m_uniformBuffers; + const MaterialSettings& m_materialSettings; + }; +} + +#include + +#endif // NAZARA_GRAPHICS_MATERIALINSTANCE_HPP diff --git a/include/Nazara/Graphics/MaterialInstance.inl b/include/Nazara/Graphics/MaterialInstance.inl new file mode 100644 index 000000000..20daebf1c --- /dev/null +++ b/include/Nazara/Graphics/MaterialInstance.inl @@ -0,0 +1,216 @@ +// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) +// This file is part of the "Nazara Engine - Graphics module" +// For conditions of distribution and use, see copyright notice in Config.hpp + +#include +#include +#include + +namespace Nz +{ + inline std::shared_ptr MaterialInstance::Clone() const + { + return std::make_shared(*this, CopyToken{}); + } + + inline void MaterialInstance::DisablePass(std::size_t passIndex) + { + EnablePass(passIndex, false); + } + + inline void MaterialInstance::EnablePass(std::size_t passIndex, bool enable) + { + assert(passIndex < m_passes.size()); + if (m_passes[passIndex].enabled != enable) + { + m_passes[passIndex].enabled = enable; + InvalidatePassPipeline(passIndex); + } + } + + inline std::size_t MaterialInstance::FindTextureProperty(std::string_view propertyName) const + { + return m_materialSettings.FindTextureProperty(propertyName); + } + + inline std::size_t MaterialInstance::FindValueProperty(std::string_view propertyName) const + { + return m_materialSettings.FindValueProperty(propertyName); + } + + inline const std::shared_ptr& MaterialInstance::GetParentMaterial() const + { + return m_parent; + } + + inline MaterialPassFlags MaterialInstance::GetPassFlags(std::size_t passIndex) const + { + assert(passIndex < m_passes.size()); + return m_passes[passIndex].flags; + } + + inline const std::shared_ptr* MaterialInstance::GetTextureProperty(std::string_view propertyName) const + { + std::size_t propertyIndex = FindTextureProperty(propertyName); + if (propertyIndex == MaterialSettings::InvalidPropertyIndex) + { + NazaraError("material has no texture property named " + std::string(propertyName)); + return nullptr; + } + + return &GetTextureProperty(propertyIndex); + } + + inline const std::shared_ptr& MaterialInstance::GetTextureProperty(std::size_t textureIndex) const + { + if (const std::shared_ptr& textureOverride = GetTexturePropertyOverride(textureIndex)) + return textureOverride; + else + return m_materialSettings.GetTextureProperty(textureIndex).defaultTexture; + } + + inline const std::shared_ptr& MaterialInstance::GetTexturePropertyOverride(std::size_t textureIndex) const + { + assert(textureIndex < m_textureOverride.size()); + return m_textureOverride[textureIndex].texture; + } + + inline const TextureSamplerInfo* MaterialInstance::GetTextureSamplerProperty(std::string_view propertyName) const + { + std::size_t propertyIndex = FindTextureProperty(propertyName); + if (propertyIndex == MaterialSettings::InvalidPropertyIndex) + { + NazaraError("material has no texture property named " + std::string(propertyName)); + return nullptr; + } + + return &GetTextureSamplerProperty(propertyIndex); + } + + inline const TextureSamplerInfo& MaterialInstance::GetTextureSamplerProperty(std::size_t textureIndex) const + { + assert(textureIndex < m_textureOverride.size()); + return m_textureOverride[textureIndex].samplerInfo; + } + + inline const MaterialSettings::Value* MaterialInstance::GetValueProperty(std::string_view propertyName) const + { + std::size_t propertyIndex = FindValueProperty(propertyName); + if (propertyIndex == MaterialSettings::InvalidPropertyIndex) + { + NazaraError("material has no value property named " + std::string(propertyName)); + return nullptr; + } + + return &GetValueProperty(propertyIndex); + } + + inline const MaterialSettings::Value& MaterialInstance::GetValueProperty(std::size_t valueIndex) const + { + if (const MaterialSettings::Value& valueOverride = GetValuePropertyOverride(valueIndex); !std::holds_alternative(valueOverride)) + return valueOverride; + else + return m_materialSettings.GetValueProperty(valueIndex).defaultValue; + } + + inline const MaterialSettings::Value& MaterialInstance::GetValuePropertyOverride(std::size_t valueIndex) const + { + assert(valueIndex < m_valueOverride.size()); + return m_valueOverride[valueIndex]; + } + + inline bool MaterialInstance::HasPass(std::size_t passIndex) const + { + return passIndex < m_passes.size() && m_passes[passIndex].enabled; + } + + inline void MaterialInstance::SetTextureProperty(std::string_view propertyName, std::shared_ptr texture) + { + std::size_t propertyIndex = FindTextureProperty(propertyName); + if (propertyIndex == MaterialSettings::InvalidPropertyIndex) + { + NazaraError("material has no texture property named " + std::string(propertyName)); + return; + } + + return SetTextureProperty(propertyIndex, std::move(texture)); + } + + inline void MaterialInstance::SetTextureProperty(std::string_view propertyName, std::shared_ptr texture, const TextureSamplerInfo& samplerInfo) + { + std::size_t propertyIndex = FindTextureProperty(propertyName); + if (propertyIndex == MaterialSettings::InvalidPropertyIndex) + { + NazaraError("material has no texture property named " + std::string(propertyName)); + return; + } + + return SetTextureProperty(propertyIndex, std::move(texture), samplerInfo); + } + + inline void MaterialInstance::SetTextureSamplerProperty(std::string_view propertyName, const TextureSamplerInfo& samplerInfo) + { + std::size_t propertyIndex = FindTextureProperty(propertyName); + if (propertyIndex == MaterialSettings::InvalidPropertyIndex) + { + NazaraError("material has no texture property named " + std::string(propertyName)); + return; + } + + return SetTextureSamplerProperty(propertyIndex, samplerInfo); + } + + inline void MaterialInstance::SetValueProperty(std::string_view propertyName, const MaterialSettings::Value& value) + { + std::size_t propertyIndex = FindValueProperty(propertyName); + if (propertyIndex == MaterialSettings::InvalidPropertyIndex) + { + NazaraError("material has no value property named " + std::string(propertyName)); + return; + } + + return SetValueProperty(propertyIndex, value); + } + + inline void MaterialInstance::UpdatePassFlags(std::size_t passIndex, MaterialPassFlags materialFlags) + { + assert(passIndex < m_passes.size()); + if (m_passes[passIndex].flags != materialFlags) + { + m_passes[passIndex].flags = materialFlags; + InvalidatePassPipeline(passIndex); + } + } + + template + void MaterialInstance::UpdatePassStates(std::size_t passIndex, F&& stateUpdater) + { + assert(passIndex < m_passes.size()); + using Ret = std::invoke_result_t; + if constexpr (std::is_same_v) + { + if (!stateUpdater(static_cast(m_passes[passIndex].pipelineInfo))) + return; + } + else if constexpr (std::is_void_v) + stateUpdater(static_cast(m_passes[passIndex].pipelineInfo)); + else + static_assert(AlwaysFalse(), "callback must either return a bool or nothing"); + + InvalidatePassPipeline(passIndex); + } + + inline void MaterialInstance::InvalidatePassPipeline(std::size_t passIndex) + { + assert(passIndex < m_passes.size()); + m_passes[passIndex].pipeline.reset(); + OnMaterialInstancePipelineInvalidated(this, passIndex); + } + + inline void MaterialInstance::InvalidateShaderBinding() + { + OnMaterialInstanceShaderBindingInvalidated(this); + } +} + +#include diff --git a/include/Nazara/Graphics/MaterialPass.hpp b/include/Nazara/Graphics/MaterialPass.hpp index aef9c18b2..db0d80a00 100644 --- a/include/Nazara/Graphics/MaterialPass.hpp +++ b/include/Nazara/Graphics/MaterialPass.hpp @@ -10,10 +10,6 @@ #include #include #include -#include -#include -#include -#include #include #include #include @@ -24,145 +20,19 @@ #include #include #include +#include #include #include namespace Nz { - class CommandBufferBuilder; - class RenderFrame; - - class NAZARA_GRAPHICS_API MaterialPass + struct MaterialPass { - public: - MaterialPass(std::shared_ptr settings); - MaterialPass(const MaterialPass&) = delete; - MaterialPass(MaterialPass&&) = delete; - inline ~MaterialPass(); - - inline void Configure(std::shared_ptr pipeline); - inline void Configure(const MaterialPipelineInfo& pipelineInfo); - - inline void EnableBlending(bool blending); - inline void EnableColorWrite(bool colorWrite); - inline void EnableDepthBuffer(bool depthBuffer); - inline void EnableDepthClamp(bool depthClamp); - inline void EnableDepthWrite(bool depthWrite); - inline void EnableFaceCulling(bool faceCulling); - inline void EnableFlag(MaterialPassFlag flag, bool enable = true); - inline void EnableScissorTest(bool scissorTest); - inline void EnableStencilTest(bool stencilTest); - - inline void EnsurePipelineUpdate() const; - - void FillShaderBinding(std::vector& bindings) const; - - inline RendererComparison GetDepthCompareFunc() const; - inline BlendEquation GetBlendAlphaModeEquation() const; - inline BlendEquation GetBlendColorModeEquation() const; - inline BlendFunc GetBlendDstAlphaFunc() const; - inline BlendFunc GetBlendDstColorFunc() const; - inline BlendFunc GetBlendSrcAlphaFunc() const; - inline BlendFunc GetBlendSrcColorFunc() const; - inline FaceSide GetFaceCulling() const; - inline FaceFilling GetFaceFilling() const; - inline MaterialPassFlags GetFlags() const; - inline float GetLineWidth() const; - inline const nzsl::Ast::ConstantSingleValue& GetOptionValue(std::size_t optionIndex) const; - inline const std::shared_ptr& GetPipeline() const; - inline const MaterialPipelineInfo& GetPipelineInfo() const; - inline float GetPointSize() const; - inline PrimitiveMode GetPrimitiveMode() const; - inline const std::shared_ptr& GetSettings() const; - inline const std::shared_ptr& GetShader(nzsl::ShaderStageType shaderStage) const; - inline const std::shared_ptr& GetTexture(std::size_t textureIndex) const; - inline const TextureSamplerInfo& GetTextureSampler(std::size_t textureIndex) const; - inline const std::shared_ptr& GetUniformBuffer(std::size_t bufferIndex) const; - inline const std::vector& GetUniformBufferConstData(std::size_t bufferIndex) const; - inline std::vector& GetUniformBufferData(std::size_t bufferIndex); - - inline bool HasTexture(std::size_t textureIndex) const; - - inline bool IsBlendingEnabled() const; - inline bool IsColorWriteEnabled() const; - inline bool IsDepthBufferEnabled() const; - inline bool IsDepthClampEnabled() const; - inline bool IsDepthWriteEnabled() const; - inline bool IsFaceCullingEnabled() const; - inline bool IsFlagEnabled(MaterialPassFlag flag) const; - inline bool IsScissorTestEnabled() const; - inline bool IsStencilTestEnabled() const; - - inline void SetDepthCompareFunc(RendererComparison depthFunc); - inline void SetBlendEquation(BlendEquation colorMode, BlendEquation alphaMode); - inline void SetBlendFunc(BlendFunc srcColor, BlendFunc dstColor, BlendFunc srcAlpha, BlendFunc dstAlpha); - inline void SetFaceCulling(FaceSide faceSide); - inline void SetFaceFilling(FaceFilling filling); - inline void SetLineWidth(float lineWidth); - inline void SetOptionValue(std::size_t optionIndex, nzsl::Ast::ConstantSingleValue value); - inline void SetPointSize(float pointSize); - inline void SetPrimitiveMode(PrimitiveMode mode); - inline void SetSharedUniformBuffer(std::size_t sharedUboIndex, std::shared_ptr uniformBuffer); - inline void SetSharedUniformBuffer(std::size_t sharedUboIndex, std::shared_ptr uniformBuffer, UInt64 offset, UInt64 size); - inline void SetTexture(std::size_t textureIndex, std::shared_ptr texture); - inline void SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo); - - void Update(RenderFrame& renderFrame, CommandBufferBuilder& builder); - - MaterialPass& operator=(const MaterialPass&) = delete; - MaterialPass& operator=(MaterialPass&&) = delete; - - // Signals: - NazaraSignal(OnMaterialPassInvalidated, const MaterialPass* /*materialPass*/); - NazaraSignal(OnMaterialPassPipelineInvalidated, const MaterialPass* /*materialPass*/); - NazaraSignal(OnMaterialPassShaderBindingInvalidated, const MaterialPass* /*materialPass*/); - NazaraSignal(OnMaterialPassRelease, const MaterialPass* /*materialPass*/); - - private: - inline void InvalidatePipeline(); - inline void InvalidateShaderBinding(); - inline void InvalidateTextureSampler(std::size_t textureIndex); - inline void InvalidateUniformData(std::size_t uniformBufferIndex); - void UpdatePipeline() const; - - struct MaterialTexture - { - mutable std::shared_ptr sampler; - std::shared_ptr texture; - TextureSamplerInfo samplerInfo; - }; - - struct ShaderEntry - { - NazaraSlot(UberShader, OnShaderUpdated, onShaderUpdated); - }; - - struct ShaderUniformBuffer - { - std::shared_ptr buffer; //< kept for ownership - RenderBufferView bufferView; - }; - - struct UniformBuffer - { - std::shared_ptr buffer; - std::vector data; - bool dataInvalidated = true; - }; - - std::array m_optionValues; - std::shared_ptr m_settings; - std::vector m_textures; - std::vector m_shaders; - std::vector m_sharedUniformBuffers; - std::vector m_uniformBuffers; - mutable std::shared_ptr m_pipeline; - mutable MaterialPipelineInfo m_pipelineInfo; - MaterialPassFlags m_flags; - mutable bool m_pipelineUpdated; + MaterialPassFlags flags; + RenderStates states; + std::unordered_map options; + std::vector> shaders; }; } -#include - #endif // NAZARA_GRAPHICS_MATERIALPASS_HPP diff --git a/include/Nazara/Graphics/MaterialPass.inl b/include/Nazara/Graphics/MaterialPass.inl deleted file mode 100644 index e5e8a1697..000000000 --- a/include/Nazara/Graphics/MaterialPass.inl +++ /dev/null @@ -1,683 +0,0 @@ -// Copyright (C) 2022 Jérôme "Lynix" Leclercq (lynix680@gmail.com) -// This file is part of the "Nazara Engine - Graphics module" -// For conditions of distribution and use, see copyright notice in Config.hpp - -#include -#include -#include -#include - -namespace Nz -{ - /*! - * \brief Destructs the object and calls OnMaterialRelease - * - * \see OnMaterialRelease - */ - inline MaterialPass::~MaterialPass() - { - OnMaterialPassRelease(this); - } - - /*! - * \brief Reset material pipeline state - * - * Sets the material pipeline - * - * \remark pipeline must be valid - * - * \see Configure - */ - inline void MaterialPass::Configure(std::shared_ptr pipeline) - { - NazaraAssert(pipeline, "Invalid material pipeline"); - - m_pipeline = std::move(pipeline); - m_pipelineInfo = m_pipeline->GetInfo(); - m_pipelineUpdated = true; - } - - /*! - * \brief Reset material pipeline state - * - * Sets the material pipeline using pipeline info - * - * \remark pipeline must be valid - * - * \see Configure - */ - inline void MaterialPass::Configure(const MaterialPipelineInfo& pipelineInfo) - { - m_pipelineInfo = pipelineInfo; - - InvalidatePipeline(); - } - - /*! - * \brief Enable/Disable blending for this material - * - * When enabled, all objects using this material will be rendered using blending, obeying the dstBlend and srcBlend parameters - * This is useful with translucent objects, but will reduces performance as it prevents some optimizations (as deferred rendering) - * - * \param blending Defines if this material will use blending - * - * \remark Invalidates the pipeline - * - * \see IsBlendingEnabled - * \see SetDstBlend - * \see SetSrcBlend - */ - inline void MaterialPass::EnableBlending(bool blending) - { - m_pipelineInfo.blending = blending; - - InvalidatePipeline(); - } - - /*! - * \brief Enable/Disable color writing for this material - * - * \param colorWrite Defines if this material will use color writing - * - * \remark Invalidates the pipeline - * - * \see IsColorWritingEnabled - */ - inline void MaterialPass::EnableColorWrite(bool colorWrite) - { - m_pipelineInfo.colorWrite = colorWrite; - - InvalidatePipeline(); - } - - /*! - * \brief Enable/Disable depth buffer for this material - * - * When enabled, all objects using this material will be rendered using a depth buffer, if the RenderTarget has one. - * This will enable Depth Test, preventing further fragments to render on top of closer ones. - * - * This parameter is required for depth writing. - * - * In order to enable depth writing without enabling depth test, set the depth comparison function to RendererComparison::Never - * - * \param depthBuffer Defines if this material will use depth buffer - * - * \remark Invalidates the pipeline - * - * \see EnableDepthWrite - * \see IsDepthBufferEnabled - * \see SetDepthFunc - */ - inline void MaterialPass::EnableDepthBuffer(bool depthBuffer) - { - m_pipelineInfo.depthBuffer = depthBuffer; - - InvalidatePipeline(); - } - - /*! - * \brief Enable/Disable depth clamp for this material - * - * When enabled, all fragments generated by this material will be clamped to znear or zfar - * instead of being clipped out when outside this range. - * - * This can be useful to prevent clipping near or far primitives. - * - * \param depthClamp Defines if this material will use depth clamping - * - * \remark Invalidates the pipeline - * \remark Depth clamping requires RenderDeviceFeatures::depthClamping to be true - * - * \see IsDepthClampEnabled - */ - inline void MaterialPass::EnableDepthClamp(bool depthClamp) - { - m_pipelineInfo.depthClamp = depthClamp; - - InvalidatePipeline(); - } - - /*! - * \brief Enable/Disable depth writing for this material - * - * When enabled, and if depth buffer is enabled and present, all fragments generated with this material will write - * to the depth buffer if they pass depth test. - * - * This is usually disabled with translucent objects, as depth test is wanted to prevent them from rendering on top of opaque objects but - * not depth writing (which could make other translucent fragments to fail depth test) - * - * \param depthBuffer Defines if this material will use depth write - * - * \remark Invalidates the pipeline - * - * \see EnableDepthBuffer - * \see IsDepthWriteEnabled - */ - inline void MaterialPass::EnableDepthWrite(bool depthWrite) - { - m_pipelineInfo.depthWrite = depthWrite; - - InvalidatePipeline(); - } - - /*! - * \brief Enable/Disable face culling for this material - * - * When enabled, the material prevents front and/or back faces from rendering. - * This is commonly used as an optimization to prevent processing of hidden faces by the rendering device. - * - * Use SetFaceCulling to control which side will be eliminated. - * - * \param faceCulling Defines if this material will use face culling - * - * \remark Invalidates the pipeline - * - * \see IsFaceCullingEnabled - * \see SetFaceCulling - */ - inline void MaterialPass::EnableFaceCulling(bool faceCulling) - { - m_pipelineInfo.faceCulling = faceCulling; - - InvalidatePipeline(); - } - - inline void MaterialPass::EnableFlag(MaterialPassFlag flag, bool enable) - { - if (enable) - m_flags |= flag; - else - m_flags &= ~flag; - } - - /*! - * \brief Enable/Disable scissor test for this material - * - * When enabled, the material prevents fragments out of the scissor box to be rendered. - * This can be useful with GUI, where widgets must not be rendered outside of their parent rendering area. - * - * \param scissorTest Defines if this material will use scissor test - * - * \remark Invalidates the pipeline - * - * \see IsScissorTestEnabled - */ - inline void MaterialPass::EnableScissorTest(bool scissorTest) - { - m_pipelineInfo.scissorTest = scissorTest; - - InvalidatePipeline(); - } - - /*! - * \brief Enable/Disable stencil test for this material - * - * When enabled, all fragments must pass the stencil test to be rendered. - * - * \param scissorTest Defines if this material will use stencil test - * - * \remark Invalidates the pipeline - * - * \see IsStencilTestEnabled - */ - inline void MaterialPass::EnableStencilTest(bool stencilTest) - { - m_pipelineInfo.stencilTest = stencilTest; - - InvalidatePipeline(); - } - - /*! - * \brief Ensures the pipeline gets updated - * - * When the pipeline gets invalidated, it's not updated until required (per example by calling GetPipeline). - * Using this function forces the pipeline update, making GetPipeline thread-safe as long as the pipeline does not get invalidated. - * - * \see GetPipeline - */ - inline void MaterialPass::EnsurePipelineUpdate() const - { - if (!m_pipelineUpdated) - UpdatePipeline(); - } - - /*! - * \brief Gets the function to compare depth - * - * \return Function comparing the depth of two materials - * - * \see EnableDepthTest - * \see SetAmbientColor - */ - inline RendererComparison MaterialPass::GetDepthCompareFunc() const - { - return m_pipelineInfo.depthCompare; - } - - inline BlendEquation MaterialPass::GetBlendAlphaModeEquation() const - { - return m_pipelineInfo.blend.modeAlpha; - } - - inline BlendEquation MaterialPass::GetBlendColorModeEquation() const - { - return m_pipelineInfo.blend.modeColor; - } - - inline BlendFunc MaterialPass::GetBlendDstAlphaFunc() const - { - return m_pipelineInfo.blend.dstAlpha; - } - - inline BlendFunc MaterialPass::GetBlendDstColorFunc() const - { - return m_pipelineInfo.blend.dstColor; - } - - inline BlendFunc MaterialPass::GetBlendSrcAlphaFunc() const - { - return m_pipelineInfo.blend.srcAlpha; - } - - inline BlendFunc MaterialPass::GetBlendSrcColorFunc() const - { - return m_pipelineInfo.blend.srcColor; - } - - /*! - * \brief Gets the face culling - * - * \return Current face culling side - * - * \see SetFaceCulling - */ - inline FaceSide MaterialPass::GetFaceCulling() const - { - return m_pipelineInfo.cullingSide; - } - - /*! - * \brief Gets the face filling - * \return Current face filling - */ - inline FaceFilling MaterialPass::GetFaceFilling() const - { - return m_pipelineInfo.faceFilling; - } - - inline MaterialPassFlags MaterialPass::GetFlags() const - { - return m_flags; - } - - /*! - * \brief Gets the line width of this material - * \return Line width - */ - inline float MaterialPass::GetLineWidth() const - { - return m_pipelineInfo.lineWidth; - } - - inline const nzsl::Ast::ConstantSingleValue& MaterialPass::GetOptionValue(std::size_t optionIndex) const - { - assert(optionIndex < m_optionValues.size()); - return m_optionValues[optionIndex]; - } - - /*! - * \brief Gets the render states - * \return Constant reference to the render states - */ - inline const std::shared_ptr& MaterialPass::GetPipeline() const - { - EnsurePipelineUpdate(); - - return m_pipeline; - } - - /*! - * \brief Gets the pipeline informations - * \return Constant reference to the pipeline info - */ - inline const MaterialPipelineInfo& MaterialPass::GetPipelineInfo() const - { - return m_pipelineInfo; - } - - /*! - * \brief Gets the point size of this material - * \return Point size - */ - inline float MaterialPass::GetPointSize() const - { - return m_pipelineInfo.pointSize; - } - - inline PrimitiveMode MaterialPass::GetPrimitiveMode() const - { - return m_pipelineInfo.primitiveMode; - } - - inline const std::shared_ptr& MaterialPass::GetSettings() const - { - return m_settings; - } - - /*! - * \brief Gets the über-shader used by this material - * \return Constant pointer to the über-shader used - */ - inline const std::shared_ptr& MaterialPass::GetShader(nzsl::ShaderStageType shaderStage) const - { - return m_pipelineInfo.shaders[UnderlyingCast(shaderStage)].uberShader; - } - - inline const std::shared_ptr& MaterialPass::GetTexture(std::size_t textureIndex) const - { - NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - return m_textures[textureIndex].texture; - } - - inline const TextureSamplerInfo& MaterialPass::GetTextureSampler(std::size_t textureIndex) const - { - NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - return m_textures[textureIndex].samplerInfo; - } - - inline const std::shared_ptr& MaterialPass::GetUniformBuffer(std::size_t bufferIndex) const - { - NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index"); - return m_uniformBuffers[bufferIndex].buffer; - } - - inline const std::vector& MaterialPass::GetUniformBufferConstData(std::size_t bufferIndex) const - { - NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index"); - return m_uniformBuffers[bufferIndex].data; - } - - inline std::vector& MaterialPass::GetUniformBufferData(std::size_t bufferIndex) - { - NazaraAssert(bufferIndex < m_uniformBuffers.size(), "Invalid uniform buffer index"); - UniformBuffer& uboEntry = m_uniformBuffers[bufferIndex]; - InvalidateUniformData(bufferIndex); - - return uboEntry.data; - } - - inline bool MaterialPass::HasTexture(std::size_t textureIndex) const - { - return GetTexture(textureIndex) != nullptr; - } - - /*! - * \brief Checks whether this material has blending enabled - * \return true If it is the case - */ - inline bool MaterialPass::IsBlendingEnabled() const - { - return m_pipelineInfo.blending; - } - - /*! - * \brief Checks whether this material has color write enabled - * \return true If it is the case - */ - inline bool MaterialPass::IsColorWriteEnabled() const - { - return m_pipelineInfo.colorWrite; - } - - /*! - * \brief Checks whether this material has depth buffer enabled - * \return true If it is the case - */ - inline bool MaterialPass::IsDepthBufferEnabled() const - { - return m_pipelineInfo.depthBuffer; - } - - /*! - * \brief Checks whether this material has depth clamping enabled - * \return true If it is the case - */ - inline bool MaterialPass::IsDepthClampEnabled() const - { - return m_pipelineInfo.depthClamp; - } - - /*! - * \brief Checks whether this material has depth writing enabled - * \return true If it is the case - */ - inline bool MaterialPass::IsDepthWriteEnabled() const - { - return m_pipelineInfo.depthWrite; - } - - /*! - * \brief Checks whether this material has face culling enabled - * \return true If it is the case - */ - inline bool MaterialPass::IsFaceCullingEnabled() const - { - return m_pipelineInfo.faceCulling; - } - - inline bool MaterialPass::IsFlagEnabled(MaterialPassFlag flag) const - { - return m_flags.Test(flag); - } - - /*! - * \brief Checks whether this material has scissor test enabled - * \return true If it is the case - */ - inline bool MaterialPass::IsScissorTestEnabled() const - { - return m_pipelineInfo.scissorTest; - } - - /*! - * \brief Checks whether this material has stencil test enabled - * \return true If it is the case - */ - inline bool MaterialPass::IsStencilTestEnabled() const - { - return m_pipelineInfo.stencilTest; - } - - /*! - * \brief Sets the depth functor - * - * \param depthFunc - * - * \remark Invalidates the pipeline - */ - inline void MaterialPass::SetDepthCompareFunc(RendererComparison depthFunc) - { - m_pipelineInfo.depthCompare = depthFunc; - - InvalidatePipeline(); - } - - inline void MaterialPass::SetBlendEquation(BlendEquation colorMode, BlendEquation alphaMode) - { - m_pipelineInfo.blend.modeAlpha = alphaMode; - m_pipelineInfo.blend.modeColor = colorMode; - - InvalidatePipeline(); - } - - inline void MaterialPass::SetBlendFunc(BlendFunc srcColor, BlendFunc dstColor, BlendFunc srcAlpha, BlendFunc dstAlpha) - { - m_pipelineInfo.blend.dstAlpha = dstAlpha; - m_pipelineInfo.blend.dstColor = dstColor; - m_pipelineInfo.blend.srcAlpha = srcAlpha; - m_pipelineInfo.blend.srcColor = srcColor; - - InvalidatePipeline(); - } - - /*! - * \brief Sets the face culling - * - * \param faceSide Face to cull - * - * \remark Invalidates the pipeline - */ - inline void MaterialPass::SetFaceCulling(FaceSide faceSide) - { - m_pipelineInfo.cullingSide = faceSide; - - InvalidatePipeline(); - } - - /*! - * \brief Sets the face filling - * - * \param filling Face to fill - * - * \remark Invalidates the pipeline - */ - inline void MaterialPass::SetFaceFilling(FaceFilling filling) - { - m_pipelineInfo.faceFilling = filling; - - InvalidatePipeline(); - } - - /*! - * \brief Sets the line width for this material - * - * This parameter is used when rendering lines, to define the width (in pixels) the line will take on the framebuffer - * - * \param lineWidth Width of the line - * - * \remark Invalidates the pipeline - * - * \see GetLineWidth - */ - inline void MaterialPass::SetLineWidth(float lineWidth) - { - m_pipelineInfo.lineWidth = lineWidth; - - InvalidatePipeline(); - } - - inline void MaterialPass::SetOptionValue(std::size_t optionIndex, nzsl::Ast::ConstantSingleValue value) - { - assert(optionIndex < m_optionValues.size()); - if (m_optionValues[optionIndex] != value) - { - m_optionValues[optionIndex] = std::move(value); - InvalidatePipeline(); - } - } - - /*! - * \brief Sets the point size for this material - * - * This parameter is used when rendering points, to define the size (in pixels) the point will take on the framebuffer - * - * \param pointSize Size of the point - * - * \remark Invalidates the pipeline - * - * \see GetPointSize - */ - inline void MaterialPass::SetPointSize(float pointSize) - { - m_pipelineInfo.pointSize = pointSize; - - InvalidatePipeline(); - } - - - inline void MaterialPass::SetPrimitiveMode(PrimitiveMode mode) - { - m_pipelineInfo.primitiveMode = mode; - - InvalidatePipeline(); - } - - inline void MaterialPass::SetSharedUniformBuffer(std::size_t sharedUboIndex, std::shared_ptr uniformBuffer) - { - if (uniformBuffer) - { - UInt64 size = uniformBuffer->GetSize(); - return SetSharedUniformBuffer(sharedUboIndex, std::move(uniformBuffer), 0, size); - } - else - return SetSharedUniformBuffer(sharedUboIndex, std::move(uniformBuffer), 0, 0); - } - - inline void MaterialPass::SetSharedUniformBuffer(std::size_t sharedUboIndex, std::shared_ptr uniformBuffer, UInt64 offset, UInt64 size) - { - NazaraAssert(sharedUboIndex < m_sharedUniformBuffers.size(), "Invalid shared uniform buffer index"); - - RenderBufferView bufferView(uniformBuffer.get(), offset, size); - - if (m_sharedUniformBuffers[sharedUboIndex].bufferView != bufferView) - { - m_sharedUniformBuffers[sharedUboIndex].bufferView = bufferView; - m_sharedUniformBuffers[sharedUboIndex].buffer = std::move(uniformBuffer); - - InvalidateShaderBinding(); - } - } - - inline void MaterialPass::SetTexture(std::size_t textureIndex, std::shared_ptr texture) - { - NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - if (m_textures[textureIndex].texture != texture) - { - m_textures[textureIndex].texture = std::move(texture); - - InvalidateShaderBinding(); - } - } - - inline void MaterialPass::SetTextureSampler(std::size_t textureIndex, TextureSamplerInfo samplerInfo) - { - NazaraAssert(textureIndex < m_textures.size(), "Invalid texture index"); - if (m_textures[textureIndex].samplerInfo != samplerInfo) - { - m_textures[textureIndex].samplerInfo = std::move(samplerInfo); - - InvalidateTextureSampler(textureIndex); - } - } - - inline void MaterialPass::InvalidatePipeline() - { - m_pipelineUpdated = false; - - OnMaterialPassPipelineInvalidated(this); - } - - inline void MaterialPass::InvalidateShaderBinding() - { - OnMaterialPassShaderBindingInvalidated(this); - } - - inline void MaterialPass::InvalidateTextureSampler(std::size_t textureIndex) - { - assert(textureIndex < m_textures.size()); - m_textures[textureIndex].sampler.reset(); - - InvalidateShaderBinding(); - } - - inline void MaterialPass::InvalidateUniformData(std::size_t uniformBufferIndex) - { - assert(uniformBufferIndex < m_uniformBuffers.size()); - UniformBuffer& uboEntry = m_uniformBuffers[uniformBufferIndex]; - uboEntry.dataInvalidated = true; - - OnMaterialPassInvalidated(this); - } -} - -#include diff --git a/include/Nazara/Graphics/MaterialPassRegistry.hpp b/include/Nazara/Graphics/MaterialPassRegistry.hpp index 270f38483..cc964499c 100644 --- a/include/Nazara/Graphics/MaterialPassRegistry.hpp +++ b/include/Nazara/Graphics/MaterialPassRegistry.hpp @@ -8,6 +8,8 @@ #define NAZARA_GRAPHICS_MATERIALPASSREGISTRY_HPP #include +#include +#include #include #include @@ -21,7 +23,7 @@ namespace Nz MaterialPassRegistry(MaterialPassRegistry&&) = default; ~MaterialPassRegistry() = default; - inline std::size_t GetPassIndex(const std::string& passName) const; + inline std::size_t GetPassIndex(std::string_view passName) const; inline std::size_t RegisterPass(std::string passName); @@ -29,7 +31,8 @@ namespace Nz MaterialPassRegistry& operator=(MaterialPassRegistry&&) = default; private: - std::unordered_map m_passIndex; + std::list m_passNames; //< in order to allow std::string_view as a key in C++17 (keep std::string stable as well because of SSO) + std::unordered_map m_passIndex; }; } diff --git a/include/Nazara/Graphics/MaterialPassRegistry.inl b/include/Nazara/Graphics/MaterialPassRegistry.inl index b16b00e11..5a8cf516d 100644 --- a/include/Nazara/Graphics/MaterialPassRegistry.inl +++ b/include/Nazara/Graphics/MaterialPassRegistry.inl @@ -8,11 +8,11 @@ namespace Nz { - std::size_t MaterialPassRegistry::GetPassIndex(const std::string& passName) const + std::size_t MaterialPassRegistry::GetPassIndex(std::string_view passName) const { auto it = m_passIndex.find(passName); if (it == m_passIndex.end()) - throw std::runtime_error("pass " + passName + " must be registered before being used"); + throw std::runtime_error("pass " + std::string(passName) + " must be registered before being used"); return it->second; } @@ -22,8 +22,10 @@ namespace Nz if (m_passIndex.find(passName) != m_passIndex.end()) throw std::runtime_error("pass " + passName + " is already registered"); + m_passNames.push_back(std::move(passName)); + std::size_t passIndex = m_passIndex.size(); - m_passIndex.emplace(std::move(passName), passIndex); + m_passIndex.emplace(m_passNames.back(), passIndex); return passIndex; } diff --git a/include/Nazara/Graphics/MaterialPipeline.hpp b/include/Nazara/Graphics/MaterialPipeline.hpp index 419385208..5e60371ed 100644 --- a/include/Nazara/Graphics/MaterialPipeline.hpp +++ b/include/Nazara/Graphics/MaterialPipeline.hpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include @@ -33,10 +33,9 @@ namespace Nz std::shared_ptr uberShader; }; - std::array optionValues; - std::size_t optionCount = 0; - std::vector shaders; - std::shared_ptr settings; + std::shared_ptr pipelineLayout; + std::vector