From fa70f6d465aa7946ab497dc6ac0d685a9bce23bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Wed, 14 Feb 2024 09:55:44 +0100 Subject: [PATCH] material transparency map, paint tool improvements --- Editor/MaterialWindow.cpp | 6 ++ Editor/PaintToolWindow.cpp | 61 ++++++++++++++++++- WickedEngine/shaders/ShaderInterop_Renderer.h | 1 + WickedEngine/shaders/objectHF.hlsli | 6 ++ WickedEngine/shaders/shadowPS_alphatest.hlsl | 12 +++- .../shaders/shadowPS_transparent.hlsl | 7 +++ WickedEngine/shaders/surfaceHF.hlsli | 14 +++++ WickedEngine/wiScene.h | 2 +- WickedEngine/wiScene_BindLua.cpp | 1 + WickedEngine/wiScene_Components.h | 1 + WickedEngine/wiScene_Serializers.cpp | 12 ++++ WickedEngine/wiVersion.cpp | 2 +- 12 files changed, 121 insertions(+), 4 deletions(-) diff --git a/Editor/MaterialWindow.cpp b/Editor/MaterialWindow.cpp index c41a407f8..201aca902 100644 --- a/Editor/MaterialWindow.cpp +++ b/Editor/MaterialWindow.cpp @@ -596,6 +596,9 @@ void MaterialWindow::Create(EditorComponent* _editor) case MaterialComponent::ANISOTROPYMAP: textureSlotComboBox.AddItem("Anisotropy map"); break; + case MaterialComponent::TRANSPARENCYMAP: + textureSlotComboBox.AddItem("Transparency map"); + break; default: break; } @@ -648,6 +651,9 @@ void MaterialWindow::Create(EditorComponent* _editor) case MaterialComponent::ANISOTROPYMAP: tooltiptext = "RG: The anisotropy texture. Red and green channels represent the anisotropy direction in [-1, 1] tangent, bitangent space.\nThe vector is rotated by anisotropyRotation, and multiplied by anisotropyStrength, to obtain the final anisotropy direction and strength."; break; + case MaterialComponent::TRANSPARENCYMAP: + tooltiptext = "R: transparency."; + break; default: break; } diff --git a/Editor/PaintToolWindow.cpp b/Editor/PaintToolWindow.cpp index ed74a1de9..c6812254c 100644 --- a/Editor/PaintToolWindow.cpp +++ b/Editor/PaintToolWindow.cpp @@ -207,6 +207,9 @@ void PaintToolWindow::Create(EditorComponent* _editor) textureSlotComboBox.AddItem("ClearcoatMap (R)", MaterialComponent::CLEARCOATMAP); textureSlotComboBox.AddItem("ClearcoatRoughMap (R)", MaterialComponent::CLEARCOATROUGHNESSMAP); textureSlotComboBox.AddItem("ClearcoatNormMap (R)", MaterialComponent::CLEARCOATNORMALMAP); + textureSlotComboBox.AddItem("SpecularMap (RGBA)", MaterialComponent::SPECULARMAP); + textureSlotComboBox.AddItem("AnisotropyMap (RG)", MaterialComponent::ANISOTROPYMAP); + textureSlotComboBox.AddItem("TransparencyMap (R)", MaterialComponent::TRANSPARENCYMAP); textureSlotComboBox.SetSelected(0); AddWidget(&textureSlotComboBox); @@ -248,6 +251,13 @@ void PaintToolWindow::Create(EditorComponent* _editor) if (wi::helper::saveTextureToMemoryFile(editTexture.texture, "PNG", texturefiledata)) { material->textures[sel].resource.SetFileData(texturefiledata); + // Register into resource manager: + material->textures[sel].resource = wi::resourcemanager::Load( + material->textures[sel].name, + wi::resourcemanager::Flags::IMPORT_RETAIN_FILEDATA, + texturefiledata.data(), + texturefiledata.size() + ); } else { @@ -476,12 +486,61 @@ void PaintToolWindow::Update(float dt) if (mesh == nullptr || (mesh->vertex_uvset_0.empty() && mesh->vertex_uvset_1.empty())) break; - MaterialComponent* material = selected.subsetIndex >= 0 && selected.subsetIndex < (int)mesh->subsets.size() ? scene.materials.GetComponent(mesh->subsets[selected.subsetIndex].materialID) : nullptr; + Entity materialID = mesh->subsets[selected.subsetIndex].materialID; + MaterialComponent* material = selected.subsetIndex >= 0 && selected.subsetIndex < (int)mesh->subsets.size() ? scene.materials.GetComponent(materialID) : nullptr; if (material == nullptr) break; int uvset = 0; TextureSlot editTexture = GetEditTextureSlot(*material, &uvset); + + // Missing texture will be created a blank one: + if (!editTexture.texture.IsValid()) + { + std::string texturename = "painttool/"; + const NameComponent* materialname = scene.names.GetComponent(materialID); + if (materialname != nullptr) + { + texturename += materialname->name; + texturename += "_"; + } + texturename += std::to_string(wi::random::GetRandom(std::numeric_limits::max())); + texturename += ".PNG"; + uint64_t sel = textureSlotComboBox.GetItemUserData(textureSlotComboBox.GetSelected()); + material->textures[sel].name = texturename; + + TextureDesc desc; + desc.width = 1024; + desc.height = 1024; + desc.format = Format::R8G8B8A8_UNORM; + desc.bind_flags = BindFlag::SHADER_RESOURCE | BindFlag::UNORDERED_ACCESS; + wi::vector whitedata(desc.width * desc.height); + std::fill(whitedata.begin(), whitedata.end(), wi::Color::White()); + SubresourceData initdata; + initdata.data_ptr = whitedata.data(); + initdata.row_pitch = desc.width * GetFormatStride(desc.format); + Texture texture; + GraphicsDevice* device = GetDevice(); + device->CreateTexture(&desc, &initdata, &texture); + device->SetName(&texture, texturename.c_str()); + // This part must be AFTER mip level subresource creation: + int srgb_subresource = -1; + { + Format srgb_format = GetFormatSRGB(desc.format); + srgb_subresource = device->CreateSubresource( + &texture, + SubresourceType::SRV, + 0, -1, + 0, -1, + &srgb_format + ); + } + material->textures[sel].resource.SetTexture(texture, srgb_subresource); + editTexture = GetEditTextureSlot(*material, &uvset); + + wi::backlog::post("Paint Tool created default texture: " + texturename); + } + if (!editTexture.texture.IsValid()) break; const TextureDesc& desc = editTexture.texture.GetDesc(); diff --git a/WickedEngine/shaders/ShaderInterop_Renderer.h b/WickedEngine/shaders/ShaderInterop_Renderer.h index b9ffb2ae0..dbc7de137 100644 --- a/WickedEngine/shaders/ShaderInterop_Renderer.h +++ b/WickedEngine/shaders/ShaderInterop_Renderer.h @@ -91,6 +91,7 @@ enum TEXTURESLOT CLEARCOATNORMALMAP, SPECULARMAP, ANISOTROPYMAP, + TRANSPARENCYMAP, TEXTURESLOT_COUNT }; diff --git a/WickedEngine/shaders/objectHF.hlsli b/WickedEngine/shaders/objectHF.hlsli index 8c83f6ae8..cb38d372c 100644 --- a/WickedEngine/shaders/objectHF.hlsli +++ b/WickedEngine/shaders/objectHF.hlsli @@ -547,6 +547,12 @@ float4 main(PixelInput input, in bool is_frontface : SV_IsFrontFace) : SV_Target { surface.baseColor *= GetMaterial().textures[BASECOLORMAP].Sample(sampler_objectshader, uvsets); } + + [branch] + if (GetMaterial().textures[TRANSPARENCYMAP].IsValid()) + { + surface.baseColor.a *= GetMaterial().textures[TRANSPARENCYMAP].Sample(sampler_objectshader, uvsets).r; + } #endif // OBJECTSHADER_USE_UVSETS diff --git a/WickedEngine/shaders/shadowPS_alphatest.hlsl b/WickedEngine/shaders/shadowPS_alphatest.hlsl index f1b6e16c9..1f2d6097e 100644 --- a/WickedEngine/shaders/shadowPS_alphatest.hlsl +++ b/WickedEngine/shaders/shadowPS_alphatest.hlsl @@ -3,9 +3,19 @@ void main(PixelInput input) { + float alpha = 1; + [branch] if (GetMaterial().textures[BASECOLORMAP].IsValid()) { - clip(GetMaterial().textures[BASECOLORMAP].Sample(sampler_point_wrap, input.GetUVSets()).a - GetMaterial().alphaTest); + alpha = GetMaterial().textures[BASECOLORMAP].Sample(sampler_point_wrap, input.GetUVSets()).a; } + + [branch] + if (GetMaterial().textures[TRANSPARENCYMAP].IsValid()) + { + alpha *= GetMaterial().textures[TRANSPARENCYMAP].Sample(sampler_point_wrap, input.GetUVSets()).r; + } + + clip(alpha - GetMaterial().alphaTest); } diff --git a/WickedEngine/shaders/shadowPS_transparent.hlsl b/WickedEngine/shaders/shadowPS_transparent.hlsl index 4c859f569..aa57a2a89 100644 --- a/WickedEngine/shaders/shadowPS_transparent.hlsl +++ b/WickedEngine/shaders/shadowPS_transparent.hlsl @@ -16,6 +16,13 @@ float4 main(PixelInput input) : SV_TARGET { color = 1; } + + [branch] + if (GetMaterial().textures[TRANSPARENCYMAP].IsValid()) + { + color.a *= GetMaterial().textures[TRANSPARENCYMAP].Sample(sampler_objectshader, uvsets).r; + } + color *= input.color; clip(color.a - GetMaterial().alphaTest); diff --git a/WickedEngine/shaders/surfaceHF.hlsli b/WickedEngine/shaders/surfaceHF.hlsli index 6fd388043..6a2a715d0 100644 --- a/WickedEngine/shaders/surfaceHF.hlsli +++ b/WickedEngine/shaders/surfaceHF.hlsli @@ -528,6 +528,20 @@ struct Surface baseColor.a *= baseColorMap.a; } } + + [branch] + if (material.textures[TRANSPARENCYMAP].IsValid()) + { +#ifdef SURFACE_LOAD_QUAD_DERIVATIVES + baseColor.a *= material.textures[TRANSPARENCYMAP].SampleGrad(sam, uvsets, uvsets_dx, uvsets_dy).r; +#else + float lod = 0; +#ifdef SURFACE_LOAD_MIPCONE + lod = compute_texture_lod(material.textures[TRANSPARENCYMAP].GetTexture(), material.textures[TRANSPARENCYMAP].GetUVSet() == 0 ? lod_constant0 : lod_constant1, ray_direction, surf_normal, cone_width); +#endif // SURFACE_LOAD_MIPCONE + baseColor.a *= material.textures[TRANSPARENCYMAP].SampleLevel(sam, uvsets, lod).r; +#endif // SURFACE_LOAD_QUAD_DERIVATIVES + } [branch] if (geometry.vb_col >= 0 && material.IsUsingVertexColors()) diff --git a/WickedEngine/wiScene.h b/WickedEngine/wiScene.h index dbdb2b78f..d16a5ea3c 100644 --- a/WickedEngine/wiScene.h +++ b/WickedEngine/wiScene.h @@ -30,7 +30,7 @@ namespace wi::scene wi::ecs::ComponentManager& layers = componentLibrary.Register("wi::scene::Scene::layers"); wi::ecs::ComponentManager& transforms = componentLibrary.Register("wi::scene::Scene::transforms"); wi::ecs::ComponentManager& hierarchy = componentLibrary.Register("wi::scene::Scene::hierarchy"); - wi::ecs::ComponentManager& materials = componentLibrary.Register("wi::scene::Scene::materials", 2); // version = 2 + wi::ecs::ComponentManager& materials = componentLibrary.Register("wi::scene::Scene::materials", 3); // version = 3 wi::ecs::ComponentManager& meshes = componentLibrary.Register("wi::scene::Scene::meshes", 2); // version = 2 wi::ecs::ComponentManager& impostors = componentLibrary.Register("wi::scene::Scene::impostors"); wi::ecs::ComponentManager& objects = componentLibrary.Register("wi::scene::Scene::objects", 3); // version = 3 diff --git a/WickedEngine/wiScene_BindLua.cpp b/WickedEngine/wiScene_BindLua.cpp index 1aac29af5..75a539f94 100644 --- a/WickedEngine/wiScene_BindLua.cpp +++ b/WickedEngine/wiScene_BindLua.cpp @@ -341,6 +341,7 @@ TextureSlot = { CLEARCOATNORMALMAP = 11, SPECULARMAP = 12, ANISOTROPYMAP = 13, + TRANSPARENCYMAP = 14, } SHADERTYPE_PBR = 0 diff --git a/WickedEngine/wiScene_Components.h b/WickedEngine/wiScene_Components.h index 868eb5c3d..32b334f0f 100644 --- a/WickedEngine/wiScene_Components.h +++ b/WickedEngine/wiScene_Components.h @@ -204,6 +204,7 @@ namespace wi::scene CLEARCOATNORMALMAP, SPECULARMAP, ANISOTROPYMAP, + TRANSPARENCYMAP, TEXTURESLOT_COUNT }; diff --git a/WickedEngine/wiScene_Serializers.cpp b/WickedEngine/wiScene_Serializers.cpp index 854e7c3a4..e3496ebea 100644 --- a/WickedEngine/wiScene_Serializers.cpp +++ b/WickedEngine/wiScene_Serializers.cpp @@ -231,6 +231,12 @@ namespace wi::scene anisotropy_strength = parallaxOcclusionMapping; // old version fix } + if (seri.GetVersion() >= 3) + { + archive >> textures[TRANSPARENCYMAP].name; + archive >> textures[TRANSPARENCYMAP].uvset; + } + for (auto& x : textures) { if (!x.name.empty()) @@ -369,6 +375,12 @@ namespace wi::scene archive << wi::helper::GetPathRelative(dir, textures[ANISOTROPYMAP].name); archive << textures[ANISOTROPYMAP].uvset; } + + if (seri.GetVersion() >= 2) + { + archive << wi::helper::GetPathRelative(dir, textures[TRANSPARENCYMAP].name); + archive << textures[TRANSPARENCYMAP].uvset; + } } } void MeshComponent::Serialize(wi::Archive& archive, EntitySerializer& seri) diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index ee6b36939..6c79381ab 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 376; + const int revision = 377; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);