diff --git a/Engine_Master_UPC/ComponentFactory.cpp b/Engine_Master_UPC/ComponentFactory.cpp index 705a0cba..d9eca84e 100644 --- a/Engine_Master_UPC/ComponentFactory.cpp +++ b/Engine_Master_UPC/ComponentFactory.cpp @@ -18,6 +18,7 @@ #include "ComponentSoundListener.h" #include "ComponentSoundSource.h" #include "PlayerRenderBufferComponent.h" +#include "LineRendererComponent.h" #include "DamageHighlightComponent.h" #include "DissolveComponent.h" #include "SpectralComponent.h" @@ -108,6 +109,9 @@ std::unique_ptr ComponentFactory::createWithUID(ComponentType type, U case ComponentType::PLAYER_RENDER_BUFFER: return std::make_unique(id, owner); + case ComponentType::LINE_RENDERER: + return std::make_unique(id, owner); + case ComponentType::DAMAGE_HIGHLIGHT: return std::make_unique(id, owner); diff --git a/Engine_Master_UPC/ComponentType.h b/Engine_Master_UPC/ComponentType.h index 4bf534f0..059ec547 100644 --- a/Engine_Master_UPC/ComponentType.h +++ b/Engine_Master_UPC/ComponentType.h @@ -25,6 +25,7 @@ X(SOUND_SOURCE) \ X(PREFAB_INSTANCE) \ X(PLAYER_RENDER_BUFFER) \ + X(LINE_RENDERER) \ X(DAMAGE_HIGHLIGHT) \ X(FLOW_MAP) \ X(DISSOLVE) \ diff --git a/Engine_Master_UPC/Engine.vcxproj b/Engine_Master_UPC/Engine.vcxproj index 9068ed59..ae8ab228 100644 --- a/Engine_Master_UPC/Engine.vcxproj +++ b/Engine_Master_UPC/Engine.vcxproj @@ -312,6 +312,8 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + + @@ -815,6 +817,8 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; + + @@ -1142,6 +1146,22 @@ $(SolutionDir)3rdParty\RecastNavigation\DebugUtils\Include; Pixel 6.0 + + Pixel + 6.0 + Pixel + 6.0 + Pixel + 6.0 + + + Vertex + 6.0 + Vertex + 6.0 + Vertex + 6.0 + Pixel 6.0 diff --git a/Engine_Master_UPC/Engine.vcxproj.filters b/Engine_Master_UPC/Engine.vcxproj.filters index 60320064..0598db9e 100644 --- a/Engine_Master_UPC/Engine.vcxproj.filters +++ b/Engine_Master_UPC/Engine.vcxproj.filters @@ -852,6 +852,21 @@ Source\Rendering\Post Processing + + + + + + + + D3D12\Rendering\Pass + + + GameEntity\Components + + + D3D12\Rendering\Pass + Source\Rendering @@ -1782,6 +1797,20 @@ Source\Rendering\Post Processing + + + + + + + D3D12\Rendering\Pass + + + GameEntity\Components + + + D3D12\Rendering\Pass + Source\Rendering diff --git a/Engine_Master_UPC/LineRendererComponent.cpp b/Engine_Master_UPC/LineRendererComponent.cpp new file mode 100644 index 00000000..29e5e6ab --- /dev/null +++ b/Engine_Master_UPC/LineRendererComponent.cpp @@ -0,0 +1,528 @@ +#include "Globals.h" +#include "LineRendererComponent.h" +#include "JsonArchive.h" + +#include "GameObject.h" +#include "Transform.h" + +#include "Application.h" +#include "ModuleInput.h" +#include "imgui_bezier.h" +#include "imgui_color_gradient.h" +#include "ModuleTime.h" +#include "ModuleScene.h" + +#include + +#include "ModuleAssets.h" +#include "ModuleResources.h" + +class Scene; + +LineRendererComponent::LineRendererComponent(UID id, GameObject* owner) : Component(id, ComponentType::LINE_RENDERER, owner) +{ + //Create two points to start + CreatePoint(); + CreatePoint(); + + m_color.clearMarks(); // because it has default values that we don't want + + m_color.addMark(0.f, ImColor(1.f, 1.f, 1.f, 1.f)); + m_color.addAlphaMark(0.f, 1.0f); + m_color.addMark(1.f, ImColor(1.f, 1.f, 1.f, 1.f)); + m_color.addAlphaMark(1.f, 1.0f); + m_color.setEditAlpha(true); +} + +void LineRendererComponent::drawUi() +{ + ImGui::Text("Line Renderer"); + + // LINE RENDERER INTERFACE + + // point controller // + + //ImGui::Begin("Render Points"); + + ImGui::BeginChild("List", ImVec2(220, 210), true); + + // Add button + if (ImGui::Button("Add")) + { + CreatePoint(); + m_selectedPoint = (int)m_points.size() - 1; + } + + ImGui::SameLine(); + + // Remove button + if (ImGui::Button("Remove")) + { + if (m_selectedPoint >= 0 && + m_selectedPoint < (int)m_points.size()) + { + m_points.erase(m_points.begin() + m_selectedPoint); + + if (m_points.empty()) + m_selectedPoint = -1; + else if (m_selectedPoint >= (int)m_points.size()) + m_selectedPoint = (int)m_points.size() - 1; + } + } + + ImGui::Separator(); + + if (ImGui::BeginListBox("Points", ImVec2(0, 160))) + { + for (int i = 0; i < (int)m_points.size(); i++) + { + bool selected = (m_selectedPoint == i); + + std::string label = "Point " + std::to_string(i); + + if (ImGui::Selectable(label.c_str(), selected)) + m_selectedPoint = i; + + if (selected) + ImGui::SetItemDefaultFocus(); + } + + ImGui::EndListBox(); + } + + ImGui::EndChild(); + + ImGui::SameLine(); + + ImGui::BeginChild("Inspector", ImVec2(0, 210), true); + + if (m_selectedPoint >= 0 && m_selectedPoint < (int)m_points.size()) + { + auto& point = *m_points[m_selectedPoint]; + bool disableTransform = (point.transformParent != nullptr); + + ImGui::SeparatorText("Transform"); + + const char* ParentTransformName = point.transformParent ? point.transformParent->getOwner()->GetName().c_str() : "Drop Transform Here"; + + ImGui::BeginGroup(); + + ImGui::Text("Parent Transform"); + + ImGui::Button(ParentTransformName, ImVec2(200, 0)); + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("GAME_OBJECT")) + { + GameObject* droppedObject = *(GameObject**)payload->Data; + + Component* comp = droppedObject->GetComponent(ComponentType::TRANSFORM); + + if (comp && comp->getType() == ComponentType::TRANSFORM) + { + point.transformParent = comp->getTransform(); + } + } + ImGui::EndDragDropTarget(); + } + + if (point.transformParent) + { + ImGui::SameLine(); + + if (ImGui::SmallButton("X")) + { + point.transformParent = nullptr; + } + } + + ImGui::EndGroup(); + + ImGui::BeginDisabled(disableTransform); + + ImGui::DragFloat3("Position", &point.position.x, 0.1f); + + if (disableTransform && ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) + { + ImGui::SetTooltip("Inherited from parent transform."); + } + + ImGui::EndDisabled(); + + ImGui::SeparatorText("Shape"); + + ImGui::DragFloat( "Width", &point.width, 0.01f, 0.0f); + + } + + ImGui::EndChild(); + + //ImGui::End(); + + + // Color gradient editor + + if (ImGui::GradientButton(&m_color)) { + + ImGui::OpenPopup("GradientEditorPopup"); + } + + ImGui::SameLine(); ImGui::Text("Color Gradient"); + + + if (ImGui::BeginPopup("GradientEditorPopup")) { + + ImGui::GradientEditor(&m_color, m_draggingMark, m_selectedMark); + + if (app->getModuleInput()->isKeyJustPressed(Keyboard::Keys::Delete) && m_selectedMark != nullptr) + { + m_color.removeMark(m_selectedMark); + m_selectedMark = nullptr; + m_draggingMark = nullptr; + } + + ImGui::EndPopup(); + } + + ImGui::Checkbox("Bloom", &m_bloom); + + ImGui::Button("Texture"); + + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ASSET")) + { + UID* data = static_cast(payload->Data); + LoadTexture(data); + } + ImGui::EndDragDropTarget(); + } + + ImGui::SameLine(); + ImGui::Text("Loaded: %s", (m_texture != nullptr) ? "YES" : "NO"); +} + +void LineRendererComponent::update() +{ + + for (auto point = m_points.begin(); point != m_points.end(); ) + { + + if (point->get()->transformParent != nullptr) + { + const Matrix& globalMatrix = point->get()->transformParent->getGlobalMatrix(); + point->get()->position = globalMatrix.Translation(); + } + + ++point; + } + +} + +void LineRendererComponent::CreatePoint() +{ + + std::shared_ptr newPoint = std::make_shared(); + m_points.push_back(newPoint); + + newPoint->position = Vector3::Zero; + newPoint->width = 0.0f; + newPoint->transformParent = nullptr; +} + +float LineRendererComponent::WrapAngle(float angle) +{ + angle = std::fmod(angle, 360.0f); + if (angle < 0.0f) + angle += 360.0f; + return angle; +} + +std::unique_ptr LineRendererComponent::clone(GameObject* newOwner) const +{ + std::unique_ptr cloned = std::make_unique(m_uuid, newOwner); + + cloned->m_points.clear(); + cloned->m_color = m_color; + cloned->m_bloom = m_bloom; + + cloned->m_textureAssetId = m_textureAssetId; + cloned->m_texture = m_texture; + cloned->m_textureAsset = m_textureAsset; + cloned->m_loadRequested = m_loadRequested; + + for (auto point = m_points.begin(); point != m_points.end(); ) + { + cloned->CreatePoint(); + + RenderPoint* clonedPoint = cloned->m_points.back().get(); + + clonedPoint->position = point->get()->position; + clonedPoint->transformParent = point->get()->transformParent; + clonedPoint->width = point->get()->width; + + ++point; + } + + return cloned; +} + +void LineRendererComponent::serialize(IArchive& archive) +{ + Component::serialize(archive); + + //TODO: Serialize Points and its values. + + archive.beginObject("TextureAssetId"); + m_textureAssetId.serialize(archive); + archive.endObject(); + + if (archive.mode() == ArchiveMode::Output) + { + uint32_t pointCount = static_cast(m_points.size()); + archive.beginArray(pointCount, "Points"); + + for (const std::shared_ptr point : m_points) + { + + archive.beginObject(); + + Vector3 position = point.get()->position; + uint32_t positionCount = 3; + archive.beginArray(positionCount, "Position"); + float x = position.x; + float y = position.y; + float z = position.z; + archive.serialize(x, ""); + archive.serialize(y, ""); + archive.serialize(z, ""); + archive.endArray(); + + float width = point.get()->width; + archive.serialize(width, "Width"); + + uint64_t transformParent = 0; + if (point.get()->transformParent != nullptr) + { + transformParent = point.get()->transformParent->getOwner()->GetID(); + } + archive.serialize(transformParent, "TransformParent"); + + archive.endObject(); + } + + archive.endArray(); + + const auto& marks = m_color.getMarks(); + uint32_t markCount = static_cast(marks.size()); + archive.beginArray(markCount, "ColorGradient"); + + for (const ImGradientMark* mark : marks) + { + archive.beginObject(); + bool isAlphaMark = mark->alpha; + float position = mark->position; + archive.serialize(isAlphaMark, "IsAlphaMark"); + archive.serialize(position, "Position"); + + if (mark->alpha) + { + float alpha = mark->color[0]; + archive.serialize(alpha, "Alpha"); + } + else + { + uint32_t colorCount = 3; + archive.beginArray(colorCount, "Color"); + float r = mark->color[0]; + float g = mark->color[1]; + float b = mark->color[2]; + archive.serialize(r, ""); + archive.serialize(g, ""); + archive.serialize(b, ""); + archive.endArray(); + } + + archive.endObject(); + } + + archive.endArray(); + + archive.serialize(m_bloom, "Bloom"); + + } + else + { + uint32_t pointCount = 0; + archive.beginArray(pointCount, "Points"); + m_points.clear(); + for (uint32_t i = 0; i < pointCount; ++i) + { + archive.beginObject(); + + CreatePoint(); + RenderPoint* newPoint = m_points.back().get(); + + uint32_t positionCount = 3; + archive.beginArray(positionCount, "Position"); + float x = 0.f, y = 0.f, z = 0.f; + archive.serialize(x, ""); + archive.serialize(y, ""); + archive.serialize(z, ""); + archive.endArray(); + Vector3 position = Vector3(x, y, z); + newPoint->position = position; + + float width = 0.f; + archive.serialize(width, "Width"); + newPoint->width = width; + + uint64_t transformParent = 0; + archive.serialize(transformParent, "TransformParent"); + newPoint->transformId = transformParent; + + archive.endObject(); + } + + archive.endArray(); + + uint32_t markCount = 0; + archive.beginArray(markCount, "ColorGradient"); + m_color.clearMarks(); + + for (uint32_t i = 0; i < markCount; ++i) + { + archive.beginObject(); + + bool isAlphaMark = false; + float position = 0.f; + archive.serialize(isAlphaMark, "IsAlphaMark"); + archive.serialize(position, "Position"); + + if (isAlphaMark) + { + float alpha = 0.f; + archive.serialize(alpha, "Alpha"); + m_color.addAlphaMark(position, alpha); + } + else + { + uint32_t colorCount = 3; + archive.beginArray(colorCount, "Color"); + float r = 0.f, g = 0.f, b = 0.f; + archive.serialize(r, ""); + archive.serialize(g, ""); + archive.serialize(b, ""); + archive.endArray(); + m_color.addMark(position, ImColor(r, g, b)); + } + + archive.endObject(); + } + + archive.endArray(); + + + bool bloom = 0.f; + archive.serialize(bloom, "Bloom"); + m_bloom = bloom; + + m_texture = nullptr; + m_textureAsset.reset(); + m_loadRequested = false; + + if (m_textureAssetId.isValid()) + { + m_textureAsset = app->getModuleAssets()->load(m_textureAssetId); + if (m_textureAsset) + { + m_loadRequested = true; + + auto texture = app->getModuleResources()->createTexture(*m_textureAsset, true); + + if (texture) + { + m_texture = texture; + } + else + { + m_texture = nullptr; + } + } + } + } +} + +void LineRendererComponent::fixReferences(const SceneReferenceResolver& resolver) +{ + for (int i = 0; i < m_points.size(); i++) + { + if (m_points[i]->transformId != 0) + { + Scene* scene = app->getModuleScene()->getScene(); + m_points[i]->transformParent = HierarchyUtils::findByUID(scene, m_points[i]->transformId)->GetComponent(ComponentType::TRANSFORM)->getTransform(); + } + } + +} + +void LineRendererComponent::debugDraw() +{ + if (!isActive() || !m_owner->GetActive()) //|| !m_textureAsset.isValid() + { + return; + } +} + + +bool LineRendererComponent::consumeLoadRequest() +{ + const bool was = m_loadRequested; + m_loadRequested = false; + return was; +} + +void LineRendererComponent::setTextureAssetId(const AssetId& assetId) +{ + m_textureAssetId = assetId; + m_texture = nullptr; + m_textureAsset.reset(); + m_loadRequested = false; + + if (m_textureAssetId.isValid()) + { + m_textureAsset = app->getModuleAssets()->load(m_textureAssetId); + if (m_textureAsset) + { + m_loadRequested = true; + } + } +} + +void LineRendererComponent::LoadTexture(UID* data) +{ + AssetId* ref = app->getModuleAssets()->findReference(*data); + m_textureAssetId = *ref; + m_textureAsset = app->getModuleAssets()->load(*ref); + if (m_textureAsset) + { + m_loadRequested = true; + } + + if (!m_textureAsset || !m_textureAssetId.isValid()) + { + m_texture = nullptr; + } + else + { + auto texture = app->getModuleResources()->createTexture(*m_textureAsset, true); + if (texture) + { + m_texture = texture; + } + else + { + m_texture = nullptr; + } + } +} diff --git a/Engine_Master_UPC/LineRendererComponent.h b/Engine_Master_UPC/LineRendererComponent.h new file mode 100644 index 00000000..13062a83 --- /dev/null +++ b/Engine_Master_UPC/LineRendererComponent.h @@ -0,0 +1,76 @@ +#pragma once +#include "Component.h" +#include "AssetReference.h" +#include "imgui_color_gradient.h" +#include +#include + +class GameObject; +class Texture; + +class LineRendererComponent : public Component +{ +public: + + struct RenderPoint + { + Vector3 position; + float width; + Transform* transformParent; + uint64_t transformId; + + }; + + LineRendererComponent(UID id, GameObject* owner); + + void drawUi() override; + + void update() override; + + void CreatePoint(); + float WrapAngle(float angle); + + void requestLoad() { m_loadRequested = true; } + + Texture* getTexture() const { return m_texture.get(); } + const AssetId& getTextureAssetId() const { return m_textureAssetId; } + TextureAsset* getTextureAsset() const { return m_textureAsset.get(); } + + bool consumeLoadRequest(); + void setTextureAssetId(const AssetId& assetId); + + std::vector>& getPoints() { return m_points; } + + ImGradient& getColorGradient() { return m_color; } + + bool getBloomValue() { return m_bloom; } + + std::unique_ptr clone(GameObject* newOwner) const override; + + void serialize(IArchive& archive) override; + + void fixReferences(const SceneReferenceResolver& resolver) override; + + void debugDraw() override; + +private: + + std::vector> m_points; + + AssetId m_textureAssetId{}; + std::shared_ptr m_texture = nullptr; + std::shared_ptr m_textureAsset = nullptr; + bool m_loadRequested = false; + + void LoadTexture(UID* data); + + ImGradient m_color; + ImGradientMark* m_draggingMark = nullptr; + ImGradientMark* m_selectedMark = nullptr; + + bool m_bloom = false; + + int m_selectedPoint = -1; + +}; + diff --git a/Engine_Master_UPC/LineRendererPass.cpp b/Engine_Master_UPC/LineRendererPass.cpp new file mode 100644 index 00000000..d8c1380e --- /dev/null +++ b/Engine_Master_UPC/LineRendererPass.cpp @@ -0,0 +1,266 @@ +#include "Globals.h" +#include "LineRendererPass.h" +#include "BasicMaterial.h" +#include "ModuleDescriptors.h" +#include "Application.h" +#include "ModuleScene.h" +#include "RenderContext.h" +#include "LineRendererComponent.h" +#include "RingBuffer.h" +#include "ModuleRender.h" +#include "imgui_color_gradient.h" + +#include +#include "PlatformHelpers.h" + +LineRendererPass::LineRendererPass(ComPtr device) +{ + m_device = device; + + CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; + CD3DX12_ROOT_PARAMETER rootParameters[5] = {}; + CD3DX12_DESCRIPTOR_RANGE srvRange, sampRange, vfxRange; + + srvRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, BasicMaterial::SLOT_COUNT, 0, 0); + sampRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, ModuleDescriptors::SampleType::COUNT, 0); + vfxRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, BasicMaterial::SLOT_COUNT, 0); + + rootParameters[0].InitAsDescriptorTable(1, &srvRange, D3D12_SHADER_VISIBILITY_PIXEL); + rootParameters[1].InitAsDescriptorTable(1, &sampRange, D3D12_SHADER_VISIBILITY_PIXEL); + rootParameters[2].InitAsConstants(sizeof(Matrix) / sizeof(UINT32), 0, 0, D3D12_SHADER_VISIBILITY_VERTEX); // b0 <- view, projection + rootParameters[3].InitAsConstantBufferView(1, 0, D3D12_SHADER_VISIBILITY_PIXEL); + rootParameters[4].InitAsDescriptorTable(1, &vfxRange, D3D12_SHADER_VISIBILITY_PIXEL); //VFX textures + + + rootSignatureDesc.Init(_countof(rootParameters), rootParameters, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); + + ComPtr signature; + ComPtr error; + DXCall(D3D12SerializeRootSignature(&rootSignatureDesc, D3D_ROOT_SIGNATURE_VERSION_1, &signature, &error)); + DXCall(m_device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&m_rootSignature))); + +#if defined(_DEBUG) + UINT compileFlags = D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; +#else + UINT compileFlags = 0; +#endif + + // Load the vertex shader. + ComPtr vertexShaderBlob; + ThrowIfFailed(D3DReadFileToBlob(L"LineRendererVertexShader.cso", &vertexShaderBlob)); + + // Load the pixel shader. + ComPtr pixelShaderBlob; + ThrowIfFailed(D3DReadFileToBlob(L"LineRendererPixelShader.cso", &pixelShaderBlob)); + + // Define the vertex input layout. + D3D12_INPUT_ELEMENT_DESC inputElementDescs[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA,0}, + { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, + { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}, + { "PERCENTAGE", 0, DXGI_FORMAT_R32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } + }; + + // Describe and create the graphics pipeline state object (PSO). + D3D12_GRAPHICS_PIPELINE_STATE_DESC psoDesc = {}; + psoDesc.InputLayout = { inputElementDescs, _countof(inputElementDescs) }; + psoDesc.pRootSignature = m_rootSignature.Get(); + psoDesc.VS = CD3DX12_SHADER_BYTECODE(vertexShaderBlob.Get()); + psoDesc.PS = CD3DX12_SHADER_BYTECODE(pixelShaderBlob.Get()); + psoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT); + psoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE; + psoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT); + psoDesc.BlendState.RenderTarget[0].BlendEnable = TRUE; + psoDesc.BlendState.RenderTarget[0].SrcBlend = D3D12_BLEND_SRC_ALPHA; + psoDesc.BlendState.RenderTarget[0].DestBlend = D3D12_BLEND_INV_SRC_ALPHA; + psoDesc.BlendState.RenderTarget[0].BlendOp = D3D12_BLEND_OP_ADD; + psoDesc.BlendState.RenderTarget[0].SrcBlendAlpha = D3D12_BLEND_ONE; + psoDesc.BlendState.RenderTarget[0].DestBlendAlpha = D3D12_BLEND_INV_SRC_ALPHA; + psoDesc.BlendState.RenderTarget[0].BlendOpAlpha = D3D12_BLEND_OP_ADD; + psoDesc.BlendState.RenderTarget[0].RenderTargetWriteMask = D3D12_COLOR_WRITE_ENABLE_ALL; + psoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT); + psoDesc.DepthStencilState.DepthEnable = TRUE; + psoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL; + psoDesc.DepthStencilState.DepthWriteMask = D3D12_DEPTH_WRITE_MASK_ZERO; + psoDesc.DepthStencilState.StencilEnable = FALSE; + psoDesc.DSVFormat = DXGI_FORMAT_D32_FLOAT; + psoDesc.SampleMask = UINT_MAX; + psoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE; + psoDesc.NumRenderTargets = 1; + psoDesc.RTVFormats[0] = DXGI_FORMAT_R16G16B16A16_FLOAT; + psoDesc.SampleDesc = { 1, 0 }; + + + DXCall(m_device->CreateGraphicsPipelineState(&psoDesc, IID_PPV_ARGS(&m_pipelineState))); +} + +void LineRendererPass::prepare(const RenderContext& ctx) +{ + if (m_ringBuffer == nullptr) m_ringBuffer = ctx.ringBuffer; + + m_viewport = &ctx.viewport; + + m_view = &ctx.view; + m_projection = &ctx.projection; + m_cameraPosition = &ctx.cameraPosition; + + m_lineRendererComponent = app->getModuleScene()->getLineRendererComponents(); +} + +void LineRendererPass::apply(ID3D12GraphicsCommandList4* commandList) +{ + commandList->SetPipelineState(m_pipelineState.Get()); + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + Matrix vp = (*m_view * *m_projection).Transpose(); + commandList->SetGraphicsRoot32BitConstants(2, sizeof(XMMATRIX) / sizeof(UINT32), &vp, 0); + + std::vector indices; + std::vector vertices; + GradientConstantBuffer cb{}; + + for (auto& lineRendererComponent : m_lineRendererComponent) + { + indices.clear(); + vertices.clear(); + for (auto& color : cb.colors) + { + color = {}; + } + + float distance = 0.0f; + + for (auto point = lineRendererComponent->getPoints().begin(); point != lineRendererComponent->getPoints().end(); point++) + { + Vector3 position = point->get()->position; + float halfWidth = point->get()->width * 0.5f; + + Vector3 prevPos = (point == lineRendererComponent->getPoints().begin()) ? point->get()->position : std::prev(point)->get()->position; + Vector3 nextPos = (point == std::prev(lineRendererComponent->getPoints().end())) ? point->get()->position : std::next(point)->get()->position; + + + //tangent + Vector3 tangent = nextPos - prevPos; + tangent.Normalize(); + + Vector3 perpendicularVector = Vector3::Up.Cross(tangent); + + Vector3 right = tangent; + right.Cross(Vector3::Up); + right.Normalize(); + + //normal + Vector3 normal = right; + normal.Cross(tangent); + normal.Normalize(); + + if (point != lineRendererComponent->getPoints().begin()) + { + distance += Vector3::Distance(prevPos, position); + } + + VertexLineRenderer leftVertex{}; + leftVertex.position = position - perpendicularVector * halfWidth; + leftVertex.tangent = tangent; + leftVertex.normal = normal; + leftVertex.texCoord0 = Vector2(0.0f, distance); //Texture tiling can be implemented. Vector2(0.0f, distance / tileLenght) + leftVertex.linePercentage = distance; + + VertexLineRenderer rightVertex{}; + rightVertex.position = position + perpendicularVector * halfWidth; + rightVertex.tangent = tangent; + rightVertex.normal = normal; + rightVertex.texCoord0 = Vector2(1.0f, distance); + rightVertex.linePercentage = distance; + + vertices.push_back(leftVertex); + vertices.push_back(rightVertex); + } + + for (size_t i = 0; i < vertices.size(); i++) + { + if (vertices[i].linePercentage != 0) + { + vertices[i].linePercentage = vertices[i].linePercentage / distance; + } + } + + for (uint32_t i = 0; i < vertices.size() - 2; i += 2) + { + + indices.push_back(i); + indices.push_back(i + 3); + indices.push_back(i + 1); + + indices.push_back(i); + indices.push_back(i + 2); + indices.push_back(i + 3); + } + + uint32_t colorIndex = 0; + bool colorExist; + for (const ImGradientMark* mark : lineRendererComponent->getColorGradient().getMarks()) + { + colorExist = false; + GradientColor color{}; + color.percentage = mark->position; + lineRendererComponent->getColorGradient().getColorAt(mark->position, &color.color.x); + + for (int i = 0; i < 10; ++i) + { + if(color.color == cb.colors[i].color && color.percentage == cb.colors[i].percentage) + { + colorExist = true; + } + } + + if (colorExist) + { + continue; + } + + if (lineRendererComponent->getBloomValue()) + { + color.color.x *= 2; + color.color.y *= 2; + color.color.z *= 2; + } + + cb.colors[colorIndex] = color; + colorIndex++; + } + + D3D12_VERTEX_BUFFER_VIEW vbv; + vbv.BufferLocation = app->getModuleRender()->allocateInRingBuffer(vertices.data(), vertices.size() * sizeof(VertexLineRenderer)); + vbv.SizeInBytes = (UINT)(vertices.size() * sizeof(VertexLineRenderer)); + vbv.StrideInBytes = sizeof(VertexLineRenderer); + + D3D12_INDEX_BUFFER_VIEW ibv; + ibv.BufferLocation = app->getModuleRender()->allocateInRingBuffer(indices.data(), indices.size() * sizeof(uint32_t)); + ibv.SizeInBytes = (UINT)(indices.size() * sizeof(uint32_t)); + ibv.Format = DXGI_FORMAT_R32_UINT; + + Texture* texture = lineRendererComponent->getTexture(); + if (texture != nullptr && texture->getSRV().IsValid()) + { + cb.hasTexture = 1; + commandList->SetGraphicsRootDescriptorTable(4, texture->getSRV().gpu); + } + + D3D12_GPU_VIRTUAL_ADDRESS cbAdress = app->getModuleRender()->allocateInRingBuffer(&cb, sizeof(cb)); + + commandList->SetGraphicsRootConstantBufferView(3, cbAdress); + + commandList->SetGraphicsRootDescriptorTable(1, app->getModuleDescriptors()->getHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER).getGPUHandle(ModuleDescriptors::SampleType::LINEAR_WRAP)); + + commandList->IASetVertexBuffers(0, 1, &vbv); + commandList->IASetIndexBuffer(&ibv); + + commandList->DrawIndexedInstanced((UINT)indices.size(), 1, 0, 0, 0); + } + +} diff --git a/Engine_Master_UPC/LineRendererPass.h b/Engine_Master_UPC/LineRendererPass.h new file mode 100644 index 00000000..85a05156 --- /dev/null +++ b/Engine_Master_UPC/LineRendererPass.h @@ -0,0 +1,64 @@ +#pragma once +#include "IRenderPass.h" +#include "Vertex.h" +#include "IndexBuffer.h" +#include "VertexBuffer.h" + +#include +#include + +class RingBuffer; + +using Microsoft::WRL::ComPtr; + +class LineRendererComponent; + +struct GradientColor +{ + Vector4 color; + + float percentage; + Vector3 padding; +}; + +struct GradientConstantBuffer +{ + UINT hasTexture = 0; + Vector3 padding; + + GradientColor colors[10]; + +}; + +class LineRendererPass : public IRenderPass +{ +public: + + LineRendererPass(ComPtr device); + ~LineRendererPass() override = default; + + virtual void prepare(const RenderContext& ctx) override; + void apply(ID3D12GraphicsCommandList4* commandList) override; + +private: + + ComPtr m_device; + ComPtr m_rootSignature; + ComPtr m_pipelineState; + + RingBuffer* m_ringBuffer; + + std::unique_ptr m_vertexBuffer; + std::unique_ptr m_indexBuffer; + + std::vector m_lineRendererComponent; + std::vector m_vertices; + std::vector m_indices; + + const D3D12_VIEWPORT* m_viewport = nullptr; + const Matrix* m_view = nullptr; + const Matrix* m_projection = nullptr; + const Vector3* m_cameraPosition = nullptr; + +}; + diff --git a/Engine_Master_UPC/LineRendererPixelShader.hlsl b/Engine_Master_UPC/LineRendererPixelShader.hlsl new file mode 100644 index 00000000..2ee96a7c --- /dev/null +++ b/Engine_Master_UPC/LineRendererPixelShader.hlsl @@ -0,0 +1,73 @@ +struct GradientColor +{ + float4 color; + + float percentage; + float3 padding; +}; + +cbuffer GradientConstantBuffer : register(b1) +{ + uint hasTexture; + float3 padding; + + GradientColor colors[10]; + +}; + +struct PSInput +{ + float2 texCoord : TEXCOORD; + float4 position : SV_POSITION; + float3 normal : NORMAL; + float3 tangent : TANGENT; + float percentage : PERCENTAGE; +}; + +Texture2D texture : register(t8); + +SamplerState linearWrapSample : register(s0); +SamplerState pointWrapSample : register(s1); +SamplerState linearClampSample : register(s2); +SamplerState pointClampSample : register(s3); + +float4 main(PSInput input) : SV_TARGET +{ + + GradientColor previousMark; + GradientColor nextMark; + + if (input.percentage == 0) + { + nextMark = colors[1]; + previousMark = colors[0]; + } + else + { + for (int i = 0; i < 10; ++i) + { + if (colors[i].percentage >= input.percentage && colors[i].percentage != 0) + { + nextMark = colors[i]; + previousMark = colors[i - 1]; + break; + } + + } + } + + float distance = nextMark.percentage - previousMark.percentage; + float distancePixel = input.percentage - previousMark.percentage; + + float percentage = distancePixel / distance; + + float4 result = lerp(previousMark.color, nextMark.color, percentage); + + if (hasTexture != 0) + { + float4 texSample = texture.Sample(linearWrapSample, input.texCoord); + + result *= texSample; + } + return result; +} \ No newline at end of file diff --git a/Engine_Master_UPC/LineRendererVertexShader.hlsl b/Engine_Master_UPC/LineRendererVertexShader.hlsl new file mode 100644 index 00000000..3cd35e26 --- /dev/null +++ b/Engine_Master_UPC/LineRendererVertexShader.hlsl @@ -0,0 +1,26 @@ +cbuffer CameraParams : register(b0) +{ + float4x4 vp; +}; + +struct VSOut +{ + float2 texCoord : TEXCOORD; + float4 position : SV_POSITION; + float3 normal : NORMAL; + float3 tangent : TANGENT; + float percentage : PERCENTAGE; +}; + +VSOut main(float3 position : POSITION, float2 texCoord : TEXCOORD, float3 normal : NORMAL, float3 tangent : TANGENT, float percentage : PERCENTAGE) +{ + VSOut output; + output.texCoord = texCoord; + output.position = mul(float4(position, 1.0f), vp); + output.normal = normal; + output.tangent = tangent; + output.percentage = percentage; + + + return output; +} \ No newline at end of file diff --git a/Engine_Master_UPC/ModuleRender.cpp b/Engine_Master_UPC/ModuleRender.cpp index a156c027..009436c3 100644 --- a/Engine_Master_UPC/ModuleRender.cpp +++ b/Engine_Master_UPC/ModuleRender.cpp @@ -45,6 +45,7 @@ #include "SSAOGeometryPass.h" #include "SSAOPass.h" #include "SSAOBlurPass.h" +#include "LineRendererPass.h" #include "Quadtree.h" #include "RenderContext.h" #include "WindowSceneEditor.h" @@ -108,6 +109,7 @@ bool ModuleRender::init() m_renderPasses.push_back(std::make_unique(device, m_volumetricFogComputePass.get())); m_renderPasses.push_back(std::make_unique(device)); m_renderPasses.push_back(std::make_unique(device)); + m_renderPasses.push_back(std::make_unique(device)); m_renderPasses.push_back(std::make_unique(device)); diff --git a/Engine_Master_UPC/ModuleScene.cpp b/Engine_Master_UPC/ModuleScene.cpp index 24ee195a..42b37b18 100644 --- a/Engine_Master_UPC/ModuleScene.cpp +++ b/Engine_Master_UPC/ModuleScene.cpp @@ -20,6 +20,7 @@ #include "ScriptComponent.h" #include "ParticleSystemComponent.h" #include "TrailComponent.h" +#include "LineRendererComponent.h" #include "ScenePicking.h" @@ -106,6 +107,7 @@ void ModuleScene::rebuildComponentCaches() m_scriptComponents.clear(); m_particleSystemComponents.clear(); m_trailComponents.clear(); + m_lineRendererComponents.clear(); for (GameObject* go : m_scene->getAllGameObjects()) { @@ -139,6 +141,11 @@ void ModuleScene::rebuildComponentCaches() { m_trailComponents.push_back(static_cast(component)); } + + else if (component->getType() == ComponentType::LINE_RENDERER) + { + m_lineRendererComponents.push_back(static_cast(component)); + } } } @@ -357,6 +364,15 @@ const std::vector& ModuleScene::getTrailComponents() return m_trailComponents; } +const std::vector& ModuleScene::getLineRendererComponents() +{ + if (m_scene->isComponentCacheDirty()) + { + rebuildComponentCaches(); + } + + return m_lineRendererComponents; +} #pragma endregion @@ -368,12 +384,12 @@ void ModuleScene::saveScene() bool ModuleScene::loadScene(const std::string& sceneName) { + std::string path = "Assets/Scenes/" + sceneName + ".scene"; + clearRuntimeSceneSystems(); clearComponentCaches(); m_scene->unloadSoundBanks(); - std::string path = "Assets/Scenes/" + sceneName + ".scene"; - JsonArchive archive(ArchiveMode::Input); if (!archive.loadFile(path)) { @@ -385,10 +401,13 @@ bool ModuleScene::loadScene(const std::string& sceneName) auto newScene = std::make_unique(ref); newScene->serialize(archive); newScene->setName(sceneName.c_str()); - newScene->FixReferences(); - newScene->initLoadedObjects(); m_scene = std::move(newScene); + + m_scene->FixReferences(); + m_scene->initLoadedObjects(); + + m_scene->markDirty(); m_staticQuadtree = std::make_unique(); diff --git a/Engine_Master_UPC/ModuleScene.h b/Engine_Master_UPC/ModuleScene.h index 9a984cf7..33a64e42 100644 --- a/Engine_Master_UPC/ModuleScene.h +++ b/Engine_Master_UPC/ModuleScene.h @@ -23,6 +23,7 @@ class LightComponent; class IDebugDrawable; class ParticleSystemComponent; class TrailComponent; +class LineRendererComponent; struct ID3D12GraphicsCommandList; @@ -42,6 +43,7 @@ class ModuleScene : public Module std::vector m_scriptComponents; std::vector m_particleSystemComponents; std::vector m_trailComponents; + std::vector m_lineRendererComponents; const std::vector m_staticLayers = { Layer::ENVIRONMENT, Layer::NAVMESH }; const std::vector m_dynamicLayers = { Layer::DEFAULT, Layer::PLAYER, Layer::ENEMY, Layer::PROJECTILE, Layer::BREAKABLE, Layer::PICKUP }; @@ -111,4 +113,5 @@ class ModuleScene : public Module const std::vector& getScriptComponents(); const std::vector& getParticleSystemComponents(); const std::vector& getTrailComponents(); + const std::vector& getLineRendererComponents(); }; \ No newline at end of file diff --git a/Engine_Master_UPC/TrailComponent.cpp b/Engine_Master_UPC/TrailComponent.cpp index 8f81333f..0ef6d15e 100644 --- a/Engine_Master_UPC/TrailComponent.cpp +++ b/Engine_Master_UPC/TrailComponent.cpp @@ -10,6 +10,8 @@ #include "imgui_color_gradient.h" #include "ModuleTime.h" +#include "ModuleAssets.h" +#include "ModuleResources.h" @@ -69,7 +71,24 @@ void TrailComponent::drawUi() ImGui::EndPopup(); } + ImGui::Checkbox("Bloom", &m_bloom); + drawBezierCurveUI(m_colorCurve); + + ImGui::Button("Texture"); + + if (ImGui::BeginDragDropTarget()) + { + if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("ASSET")) + { + UID* data = static_cast(payload->Data); + LoadTexture(data); + } + ImGui::EndDragDropTarget(); + } + + ImGui::SameLine(); + ImGui::Text("Loaded: %s", (m_texture != nullptr) ? "YES" : "NO"); } void TrailComponent::update() @@ -114,6 +133,13 @@ void TrailComponent::update() m_colorOverTime.getColorAt(bezierScale, &trailPoint->get()->color.x); + if(m_bloom) + { + trailPoint->get()->color.z *= 2; + trailPoint->get()->color.x *= 2; + trailPoint->get()->color.y *= 2; + } + ++trailPoint; } @@ -146,6 +172,13 @@ std::unique_ptr TrailComponent::clone(GameObject* newOwner) const cloned->m_spawnDistance = m_spawnDistance; cloned->m_pointLifetime = m_pointLifetime; cloned->m_colorOverTime = m_colorOverTime; + cloned->m_bloom = m_bloom; + + cloned->m_textureAssetId = m_textureAssetId; + cloned->m_texture = m_texture; + cloned->m_textureAsset = m_textureAsset; + cloned->m_loadRequested = m_loadRequested; + std::copy(std::begin(m_colorCurve), std::end(m_colorCurve), std::begin(cloned->m_colorCurve)); return cloned; @@ -159,6 +192,11 @@ void TrailComponent::serialize(IArchive& archive) archive.serialize(m_endWidth, "EndWidth"); archive.serialize(m_spawnDistance, "SpawnDistance"); archive.serialize(m_pointLifetime, "PointLifetime"); + archive.serialize(m_bloom, "Bloom"); + + archive.beginObject("TextureAssetId"); + m_textureAssetId.serialize(archive); + archive.endObject(); if (archive.mode() == ArchiveMode::Output) { @@ -257,6 +295,30 @@ void TrailComponent::serialize(IArchive& archive) m_colorCurve[1] = y; m_colorCurve[2] = z; m_colorCurve[3] = w; + + m_texture = nullptr; + m_textureAsset.reset(); + m_loadRequested = false; + + if (m_textureAssetId.isValid()) + { + m_textureAsset = app->getModuleAssets()->load(m_textureAssetId); + if (m_textureAsset) + { + m_loadRequested = true; + + auto texture = app->getModuleResources()->createTexture(*m_textureAsset, true); + + if (texture) + { + m_texture = texture; + } + else + { + m_texture = nullptr; + } + } + } } } @@ -308,3 +370,56 @@ bool TrailComponent::drawBezierCurveUI(float* curveData) return parameterChanged; } + +bool TrailComponent::consumeLoadRequest() +{ + const bool was = m_loadRequested; + m_loadRequested = false; + return was; +} + +void TrailComponent::setTextureAssetId(const AssetId& assetId) +{ + m_textureAssetId = assetId; + m_texture = nullptr; + m_textureAsset.reset(); + m_loadRequested = false; + + if (m_textureAssetId.isValid()) + { + m_textureAsset = app->getModuleAssets()->load(m_textureAssetId); + if (m_textureAsset) + { + m_loadRequested = true; + } + } +} + +void TrailComponent::LoadTexture(UID* data) +{ + AssetId* ref = app->getModuleAssets()->findReference(*data); + m_textureAssetId = *ref; + m_textureAsset = app->getModuleAssets()->load(*ref); + if (m_textureAsset) + { + m_loadRequested = true; + } + + if (!m_textureAsset || !m_textureAssetId.isValid()) + { + m_texture = nullptr; + } + else + { + auto texture = app->getModuleResources()->createTexture(*m_textureAsset, true); + if (texture) + { + m_texture = texture; + } + else + { + m_texture = nullptr; + } + } +} + diff --git a/Engine_Master_UPC/TrailComponent.h b/Engine_Master_UPC/TrailComponent.h index d0b89ef7..cca47f59 100644 --- a/Engine_Master_UPC/TrailComponent.h +++ b/Engine_Master_UPC/TrailComponent.h @@ -3,6 +3,9 @@ #include "imgui_color_gradient.h" #include #include "AssetReference.h" +#include + +class Texture; class TrailComponent : public Component { @@ -25,7 +28,16 @@ class TrailComponent : public Component void CreatePoint(); - AssetId& getTextureAssetId() { return m_textureAsset; } + + void requestLoad() { m_loadRequested = true; } + + Texture* getTexture() const { return m_texture.get(); } + const AssetId& getTextureAssetId() const { return m_textureAssetId; } + TextureAsset* getTextureAsset() const { return m_textureAsset.get(); } + + bool consumeLoadRequest(); + void setTextureAssetId(const AssetId& assetId); + std::vector>& getTrailPoints() { return m_points; } @@ -50,7 +62,12 @@ class TrailComponent : public Component float m_spawnDistance; float m_pointLifetime; - AssetId m_textureAsset{}; + AssetId m_textureAssetId{}; + std::shared_ptr m_texture = nullptr; + std::shared_ptr m_textureAsset = nullptr; + bool m_loadRequested = false; + + void LoadTexture(UID* data); ImGradient m_colorOverTime; ImGradientMark* m_draggingMark = nullptr; @@ -59,7 +76,9 @@ class TrailComponent : public Component bool drawBezierCurveUI(float* curveData); float m_colorCurve[4] = { 0.000f, 0.000f, 1.000f, 1.000f }; - bool m_generate = false; + bool m_bloom = false; + + bool m_generate = true; }; diff --git a/Engine_Master_UPC/TrailPass.cpp b/Engine_Master_UPC/TrailPass.cpp index cd0bb0d3..13d295c4 100644 --- a/Engine_Master_UPC/TrailPass.cpp +++ b/Engine_Master_UPC/TrailPass.cpp @@ -19,15 +19,18 @@ TrailPass::TrailPass(ComPtr device) m_device = device; CD3DX12_ROOT_SIGNATURE_DESC rootSignatureDesc; - CD3DX12_ROOT_PARAMETER rootParameters[3] = {}; - CD3DX12_DESCRIPTOR_RANGE srvRange, sampRange; + CD3DX12_ROOT_PARAMETER rootParameters[5] = {}; + CD3DX12_DESCRIPTOR_RANGE srvRange, sampRange, vfxRange; srvRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, BasicMaterial::SLOT_COUNT, 0, 0); sampRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, ModuleDescriptors::SampleType::COUNT, 0); + vfxRange.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, BasicMaterial::SLOT_COUNT, 0); rootParameters[0].InitAsDescriptorTable(1, &srvRange, D3D12_SHADER_VISIBILITY_PIXEL); rootParameters[1].InitAsDescriptorTable(1, &sampRange, D3D12_SHADER_VISIBILITY_PIXEL); rootParameters[2].InitAsConstants(sizeof(Matrix) / sizeof(UINT32), 0, 0, D3D12_SHADER_VISIBILITY_VERTEX); // b0 <- view, projection + rootParameters[3].InitAsConstantBufferView(1, 0, D3D12_SHADER_VISIBILITY_PIXEL); + rootParameters[4].InitAsDescriptorTable(1, &vfxRange, D3D12_SHADER_VISIBILITY_PIXEL); //VFX textures rootSignatureDesc.Init(_countof(rootParameters), rootParameters, 0, nullptr, D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT); @@ -110,14 +113,23 @@ void TrailPass::prepare(const RenderContext& ctx) void TrailPass::apply(ID3D12GraphicsCommandList4* commandList) { + commandList->SetPipelineState(m_pipelineState.Get()); + commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + + commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + Matrix vp = (*m_view * *m_projection).Transpose(); + commandList->SetGraphicsRoot32BitConstants(2, sizeof(XMMATRIX) / sizeof(UINT32), &vp, 0); std::vector indices; std::vector vertices; - uint32_t firstVertex = 0; + TextureConstantBuffer cb{}; for (auto& trailComponent : m_trailComponent) { + indices.clear(); + vertices.clear(); GameObject* owner = trailComponent->getOwner(); if (owner == nullptr || !owner->IsActiveInWindowHierarchy()) @@ -135,6 +147,7 @@ void TrailPass::apply(ID3D12GraphicsCommandList4* commandList) continue; } + float distance = 0.0f; for (auto point = trailComponent->getTrailPoints().begin(); point != trailComponent->getTrailPoints().end(); point++) { @@ -152,26 +165,30 @@ void TrailPass::apply(ID3D12GraphicsCommandList4* commandList) Vector3 normal = right; normal.Cross(tangent).Normalize(); + if (point != trailComponent->getTrailPoints().begin()) + { + distance += Vector3::Distance(prevPos, position); + } VertexTrails leftVertex{}; leftVertex.position = position - perpendicularVector * halfWidth; leftVertex.tangent = tangent; leftVertex.normal = normal; - leftVertex.texCoord0 = Vector2::Zero; + leftVertex.texCoord0 = Vector2(0.0f, distance); //Texture tiling can be implemented. Vector2(0.0f, distance / tileLenght) leftVertex.color = point->get()->color; VertexTrails rightVertex{}; rightVertex.position = position + perpendicularVector * halfWidth; rightVertex.tangent = tangent; rightVertex.normal = normal; - rightVertex.texCoord0 = Vector2::Zero; + rightVertex.texCoord0 = Vector2(1.0f, distance); rightVertex.color = point->get()->color; vertices.push_back(leftVertex); vertices.push_back(rightVertex); } - for (uint32_t i = firstVertex; i < vertices.size() - 2; i += 2) + for (uint32_t i = 0; i < vertices.size() - 2; i += 2) { indices.push_back(i); @@ -183,31 +200,32 @@ void TrailPass::apply(ID3D12GraphicsCommandList4* commandList) indices.push_back(i + 3); } - firstVertex = vertices.size(); - - } - - D3D12_VERTEX_BUFFER_VIEW vbv; - vbv.BufferLocation = app->getModuleRender()->allocateInRingBuffer(vertices.data(), vertices.size() * sizeof(VertexTrails)); - vbv.SizeInBytes = (UINT)(vertices.size() * sizeof(VertexTrails)); - vbv.StrideInBytes = sizeof(VertexTrails); - - D3D12_INDEX_BUFFER_VIEW ibv; - ibv.BufferLocation = app->getModuleRender()->allocateInRingBuffer(indices.data(), indices.size() * sizeof(uint32_t)); - ibv.SizeInBytes = (UINT)(indices.size() * sizeof(uint32_t)); - ibv.Format = DXGI_FORMAT_R32_UINT; - - commandList->SetPipelineState(m_pipelineState.Get()); - commandList->SetGraphicsRootSignature(m_rootSignature.Get()); + D3D12_VERTEX_BUFFER_VIEW vbv; + vbv.BufferLocation = app->getModuleRender()->allocateInRingBuffer(vertices.data(), vertices.size() * sizeof(VertexTrails)); + vbv.SizeInBytes = (UINT)(vertices.size() * sizeof(VertexTrails)); + vbv.StrideInBytes = sizeof(VertexTrails); + + D3D12_INDEX_BUFFER_VIEW ibv; + ibv.BufferLocation = app->getModuleRender()->allocateInRingBuffer(indices.data(), indices.size() * sizeof(uint32_t)); + ibv.SizeInBytes = (UINT)(indices.size() * sizeof(uint32_t)); + ibv.Format = DXGI_FORMAT_R32_UINT; + + Texture* texture = trailComponent->getTexture(); + if (texture != nullptr && texture->getSRV().IsValid()) + { + cb.hasTexture = 1; + commandList->SetGraphicsRootDescriptorTable(4, texture->getSRV().gpu); + } - commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + D3D12_GPU_VIRTUAL_ADDRESS cbAdress = app->getModuleRender()->allocateInRingBuffer(&cb, sizeof(cb)); + + commandList->SetGraphicsRootConstantBufferView(3, cbAdress); - commandList->IASetVertexBuffers(0, 1, &vbv); - commandList->IASetIndexBuffer(&ibv); + commandList->SetGraphicsRootDescriptorTable(1, app->getModuleDescriptors()->getHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER).getGPUHandle(ModuleDescriptors::SampleType::LINEAR_WRAP)); - commandList->DrawIndexedInstanced((UINT)indices.size(), 1, 0, 0, 0); + commandList->IASetVertexBuffers(0, 1, &vbv); + commandList->IASetIndexBuffer(&ibv); - Matrix vp = (*m_view) * (*m_projection); - commandList->SetGraphicsRoot32BitConstants(2, sizeof(XMMATRIX) / sizeof(UINT32), &vp, 0); - + commandList->DrawIndexedInstanced((UINT)indices.size(), 1, 0, 0, 0); + } } diff --git a/Engine_Master_UPC/TrailPass.h b/Engine_Master_UPC/TrailPass.h index b9d2078b..bf13f473 100644 --- a/Engine_Master_UPC/TrailPass.h +++ b/Engine_Master_UPC/TrailPass.h @@ -13,6 +13,13 @@ using Microsoft::WRL::ComPtr; class TrailComponent; +struct TextureConstantBuffer +{ + UINT hasTexture = 0; + Vector3 padding; + +}; + class TrailPass : public IRenderPass { public: diff --git a/Engine_Master_UPC/TrailPixelShader.hlsl b/Engine_Master_UPC/TrailPixelShader.hlsl index 1ed14772..a967095b 100644 --- a/Engine_Master_UPC/TrailPixelShader.hlsl +++ b/Engine_Master_UPC/TrailPixelShader.hlsl @@ -7,7 +7,30 @@ struct PSInput float4 color : COLOR; }; +cbuffer GradientConstantBuffer : register(b1) +{ + uint hasTexture; + float3 padding; + +}; + +Texture2D texture : register(t8); + +SamplerState linearWrapSample : register(s0); +SamplerState pointWrapSample : register(s1); +SamplerState linearClampSample : register(s2); +SamplerState pointClampSample : register(s3); + float4 main(PSInput input) : SV_TARGET { - return input.color; + float4 result = input.color; + + if (hasTexture != 0) + { + float4 texSample = texture.Sample(linearWrapSample, input.texCoord); + + result *= texSample; + } + + return result; } \ No newline at end of file diff --git a/Engine_Master_UPC/Vertex.h b/Engine_Master_UPC/Vertex.h index 73c34619..55f6623f 100644 --- a/Engine_Master_UPC/Vertex.h +++ b/Engine_Master_UPC/Vertex.h @@ -19,4 +19,13 @@ struct VertexTrails Vector3 normal = Vector3::UnitZ; Vector3 tangent = Vector3::UnitZ; Vector4 color; +}; + +struct VertexLineRenderer +{ + Vector3 position; + Vector2 texCoord0; + Vector3 normal = Vector3::UnitZ; + Vector3 tangent = Vector3::UnitZ; + float linePercentage; }; \ No newline at end of file