From 76ebcc8f669f5eab99154f471e157be60c15eb8d Mon Sep 17 00:00:00 2001 From: Atdunbg Date: Sun, 17 May 2026 11:33:56 +0800 Subject: [PATCH] add aabb cull for mesh, improve NodeEditor view and control add AO texture --- Editor/Editor/EditorLayer.cpp | 50 +++++ Editor/assets/shaders/PBRShader_Anim.glsl | 7 +- Editor/assets/shaders/PBRShader_Static.glsl | 7 +- Editor/assets/shaders/SSR.glsl | 177 ++++++++---------- Editor/assets/shaders/SceneComposite.glsl | 21 ++- Prism/src/Prism/Asset/Asset.h | 9 +- Prism/src/Prism/Asset/AssetSerializer.cpp | 51 ++++- Prism/src/Prism/Core/Math/AABB.h | 23 +++ Prism/src/Prism/Core/Math/Frustum.h | 64 +++++++ .../PBRMaterialAssetEditor.cpp | 88 +++++++-- .../PBRMaterialAssetEditor.h | 3 + Prism/src/Prism/Editor/SceneHierachyPanel.cpp | 1 + .../Platform/OpenGL/OpenGLCommandBuffer.cpp | 25 +++ .../Platform/OpenGL/OpenGLCommandBuffer.h | 2 + Prism/src/Prism/Renderer/Material.cpp | 3 +- Prism/src/Prism/Renderer/Material.h | 1 - Prism/src/Prism/Renderer/Mesh.cpp | 28 +++ .../src/Prism/Renderer/RHI/RHICommandBuffer.h | 3 + Prism/src/Prism/Renderer/Renderer.cpp | 26 +-- Prism/src/Prism/Renderer/Renderer.h | 4 + Prism/src/Prism/Renderer/Renderer3D.cpp | 79 +++++++- .../ECSFramework/Components/Components.h | 12 ++ 22 files changed, 530 insertions(+), 154 deletions(-) create mode 100644 Prism/src/Prism/Core/Math/Frustum.h diff --git a/Editor/Editor/EditorLayer.cpp b/Editor/Editor/EditorLayer.cpp index 6aee7e9..d548a4d 100644 --- a/Editor/Editor/EditorLayer.cpp +++ b/Editor/Editor/EditorLayer.cpp @@ -578,6 +578,56 @@ namespace Prism } } } + { + // AO + if (ImGui::CollapsingHeader("AO", nullptr, ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10)); + float& aoValue = materialInstance->Get("u_AO"); + bool useAOMap = materialInstance->Get("u_AOTexToggle"); + Ref aoMap = materialInstance->TryGetResource("u_AOTexture"); + + ImGui::Image(aoMap ? (ImTextureRef)aoMap->GetRendererID() : (ImTextureRef)m_CheckerboardTex->GetRendererID(), ImVec2(64, 64)); + if (ImGui::BeginDragDropTarget()) + { + if (const auto data = ImGui::AcceptDragDropPayload("asset_payload")) + { + AssetHandle assetHandle = *(AssetHandle*)data->Data; + if (AssetsManager::IsAssetType(assetHandle, AssetType::Texture)) + { + aoMap = AssetsManager::GetAsset(assetHandle); + shouldUpdate = true; + } + } + ImGui::EndDragDropTarget(); + } + + ImGui::PopStyleVar(); + if (ImGui::IsItemHovered()) + { + if (aoMap) + { + ImGui::BeginTooltip(); + ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f); + ImGui::TextUnformatted(aoMap->GetPath().c_str()); + ImGui::PopTextWrapPos(); + ImGui::Image((ImTextureRef)aoMap->GetRendererID(), ImVec2(384, 384)); + ImGui::EndTooltip(); + } + } + ImGui::SameLine(); + if (ImGui::Checkbox("Use##AOMap", &useAOMap)) + { + materialInstance->Set("u_AOTexToggle", useAOMap ? 1.0f : 0.0f); + shouldUpdate = true; + } + ImGui::SameLine(); + if (ImGui::SliderFloat("Value##AOInput", &aoValue, 0.0f, 1.0f)) + { + shouldUpdate = true; + } + } + } if (shouldUpdate) meshComponent.UpdateMaterials(selectedMaterialIndex); } } diff --git a/Editor/assets/shaders/PBRShader_Anim.glsl b/Editor/assets/shaders/PBRShader_Anim.glsl index cf6c6d7..a6ee93d 100644 --- a/Editor/assets/shaders/PBRShader_Anim.glsl +++ b/Editor/assets/shaders/PBRShader_Anim.glsl @@ -130,6 +130,7 @@ uniform sampler2D u_AlbedoTexture; uniform sampler2D u_NormalTexture; uniform sampler2D u_MetalnessTexture; uniform sampler2D u_RoughnessTexture; +uniform sampler2D u_AOTexture; // environment uniform samplerCube u_EnvRadianceTex; @@ -146,12 +147,14 @@ uniform float u_EnvMapRotation; uniform vec4 u_AlbedoColor; uniform float u_Metalness; uniform float u_Roughness; +uniform float u_AO; // textureToggle uniform float u_AlbedoTexToggle; uniform float u_NormalTexToggle; uniform float u_MetalnessTexToggle; uniform float u_RoughnessTexToggle; +uniform float u_AOTexToggle; // shadow const int CSM_CASCADE_COUNT = 4; @@ -485,6 +488,8 @@ void main() m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness; m_Params.Roughness = max(m_Params.Roughness, 0.05); + float ao = u_AOTexToggle > 0.5 ? texture(u_AOTexture, vs_Input.TexCoord).r : u_AO; + // normal m_Params.Normal = normalize(vs_Input.Normal); if (u_NormalTexToggle > 0.5) @@ -524,7 +529,7 @@ void main() } } - vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution; + vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution * ao; color = vec4(lightContribution + iblContribution, 1.0); diff --git a/Editor/assets/shaders/PBRShader_Static.glsl b/Editor/assets/shaders/PBRShader_Static.glsl index 0fd449e..66c69b7 100644 --- a/Editor/assets/shaders/PBRShader_Static.glsl +++ b/Editor/assets/shaders/PBRShader_Static.glsl @@ -117,6 +117,7 @@ uniform sampler2D u_AlbedoTexture; uniform sampler2D u_NormalTexture; uniform sampler2D u_MetalnessTexture; uniform sampler2D u_RoughnessTexture; +uniform sampler2D u_AOTexture; // environment uniform samplerCube u_EnvRadianceTex; @@ -133,12 +134,14 @@ uniform float u_EnvMapRotation; uniform vec4 u_AlbedoColor; uniform float u_Metalness; uniform float u_Roughness; +uniform float u_AO; // textureToggle uniform float u_AlbedoTexToggle; uniform float u_NormalTexToggle; uniform float u_MetalnessTexToggle; uniform float u_RoughnessTexToggle; +uniform float u_AOTexToggle; // shadow const int CSM_CASCADE_COUNT = 4; @@ -470,6 +473,8 @@ void main() m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness; m_Params.Roughness = max(m_Params.Roughness, 0.05); + float ao = u_AOTexToggle > 0.5 ? texture(u_AOTexture, vs_Input.TexCoord).r : u_AO; + // normal m_Params.Normal = normalize(vs_Input.Normal); if (u_NormalTexToggle > 0.5) @@ -511,7 +516,7 @@ void main() } } - vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution; + vec3 iblContribution = IBL(F0, Lr) * u_IBLContribution * ao; color = vec4(lightContribution + iblContribution, 1.0); diff --git a/Editor/assets/shaders/SSR.glsl b/Editor/assets/shaders/SSR.glsl index e23a03a..8b1d0eb 100644 --- a/Editor/assets/shaders/SSR.glsl +++ b/Editor/assets/shaders/SSR.glsl @@ -25,29 +25,38 @@ uniform sampler2D u_DepthTexture; uniform sampler2D u_MaterialInfoTexture; uniform mat4 u_Projection; -uniform mat4 u_InvProjection; +uniform mat4 u_View; +uniform mat4 u_InvViewProjection; + +uniform vec3 u_CameraPosition; uniform vec2 u_ScreenSize; uniform float u_CameraNear; uniform float u_CameraFar; -uniform int u_Steps = 64; +uniform int u_Steps = 32; uniform float u_Thickness = 0.5; uniform float u_MaxDistance = 30.0; +uniform float u_StepSize = 0.5; +uniform float u_RayOffset = 0.1; uniform float u_Intensity = 1.0; +float saturate(float x) +{ + return clamp(x, 0.0, 1.0); +} + float LinearizeDepth(float depth) { float z = depth * 2.0 - 1.0; return (2.0 * u_CameraNear * u_CameraFar) / (u_CameraFar + u_CameraNear - z * (u_CameraFar - u_CameraNear)); } -vec3 ReconstructViewPos(vec2 tc, float depth) +vec3 ComputeWorldSpacePosition(vec2 uv, float depth) { - float z = depth * 2.0 - 1.0; - vec4 clipPos = vec4(tc * 2.0 - 1.0, z, 1.0); - vec4 viewPos4 = u_InvProjection * clipPos; - return viewPos4.xyz / viewPos4.w; + vec4 clipPos = vec4(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0); + vec4 worldPos = u_InvViewProjection * clipPos; + return worldPos.xyz / worldPos.w; } vec3 ReconstructNormalFromDepth(vec2 tc, float depth) @@ -64,17 +73,24 @@ vec3 ReconstructNormalFromDepth(vec2 tc, float depth) float depthB = texture(u_DepthTexture, tcB).r; float depthT = texture(u_DepthTexture, tcT).r; - vec3 pL = ReconstructViewPos(tcL, depthL); - vec3 pR = ReconstructViewPos(tcR, depthR); - vec3 pB = ReconstructViewPos(tcB, depthB); - vec3 pT = ReconstructViewPos(tcT, depthT); + vec3 pC = ComputeWorldSpacePosition(tc, depth); + vec3 pR = ComputeWorldSpacePosition(tcR, depthR); + vec3 pT = ComputeWorldSpacePosition(tcT, depthT); - vec3 dx = pR - pL; - vec3 dy = pT - pB; + vec3 dx = pR - pC; + vec3 dy = pT - pC; return normalize(cross(dx, dy)); } +vec3 ComputeNDCWithZ(vec3 worldPos) +{ + vec4 clipPos = u_Projection * u_View * vec4(worldPos, 1.0); + vec3 ndc = clipPos.xyz / clipPos.w; + ndc.xy = ndc.xy * 0.5 + 0.5; + return ndc; +} + void main() { float depth = texture(u_DepthTexture, v_TexCoord).r; @@ -95,113 +111,68 @@ void main() return; } - vec3 viewPos = ReconstructViewPos(v_TexCoord, depth); - vec3 normal = ReconstructNormalFromDepth(v_TexCoord, depth); + vec3 positionWS = ComputeWorldSpacePosition(v_TexCoord, depth); + vec3 viewWS = normalize(u_CameraPosition - positionWS); + vec3 normalWS = ReconstructNormalFromDepth(v_TexCoord, depth); + vec3 reflectionWS = normalize(reflect(-viewWS, normalWS)); - vec3 viewDir = normalize(-viewPos); - float NdotV = max(dot(normal, viewDir), 0.0); - - vec3 reflectDir = reflect(-viewDir, normal); - - if (dot(reflectDir, normal) < 0.0) + if (dot(reflectionWS, normalWS) < 0.0) { o_Color = vec4(0.0); return; } - vec3 rayOrigin = viewPos + normal * 0.02; - vec3 rayEnd = rayOrigin + reflectDir * u_MaxDistance; + vec3 rayWS = positionWS + normalWS * u_RayOffset; - vec4 p0 = u_Projection * vec4(rayOrigin, 1.0); - vec4 p1 = u_Projection * vec4(rayEnd, 1.0); - - float k0 = 1.0 / p0.w; - float k1 = 1.0 / p1.w; - - p0.xyz *= k0; - p1.xyz *= k1; - - vec3 v0 = rayOrigin * k0; - vec3 v1 = rayEnd * k1; - - vec2 s0 = p0.xy * 0.5 + 0.5; - vec2 s1 = p1.xy * 0.5 + 0.5; - - vec2 sDelta = s1 - s0; - float screenDist = length(sDelta * u_ScreenSize); - - if (screenDist < 1.0) + for (int i = 0; i < u_Steps; i++) { - o_Color = vec4(0.0); - return; - } + rayWS += reflectionWS * u_StepSize; - float divisions = min(screenDist, float(u_Steps)); - vec3 dV = (v1 - v0) / divisions; - float dK = (k1 - k0) / divisions; - vec2 dS = sDelta / divisions; + vec3 rayNDC = ComputeNDCWithZ(rayWS); + float rayDepth = rayNDC.z; - vec3 curV = v0; - float curK = k0; - vec2 curS = s0; + vec2 raySS = rayNDC.xy * u_ScreenSize; - vec2 hitUV = vec2(0.0); - bool found = false; - - for (int i = 0; i < int(divisions); i++) - { - curV += dV; - curK += dK; - curS += dS; - - if (curS.x < 0.0 || curS.x > 1.0 || curS.y < 0.0 || curS.y > 1.0) + if (rayNDC.x < 0.0 || rayNDC.x > 1.0 || rayNDC.y < 0.0 || rayNDC.y > 1.0) break; - float sampleDepth = texture(u_DepthTexture, curS).r; - float surfDepth = LinearizeDepth(sampleDepth); - float rayDepth = -curV.z / curK; + float sceneDepth = texture(u_DepthTexture, rayNDC.xy).r; + float sceneDepthLinear = LinearizeDepth(sceneDepth); + float rayDepthLinear = LinearizeDepth(rayDepth * 0.5 + 0.5); - float depthDiff = rayDepth - surfDepth; + float delta = rayDepthLinear - sceneDepthLinear; - if (depthDiff > 0.0 && depthDiff < u_Thickness) + if (delta >= 0.0 && delta <= u_Thickness) { - hitUV = curS; - found = true; - break; + vec3 hitNormalWS = ReconstructNormalFromDepth(rayNDC.xy, sceneDepth); + if (dot(hitNormalWS, reflectionWS) > 0.0) + break; + + float ssrStrength = saturate(1.0 - roughness * roughness); + + float dist = distance(positionWS, rayWS); + float fadeFactor = 1.0 - smoothstep(u_MaxDistance * 0.3, u_MaxDistance, dist); + + float edgeFade = 1.0; + edgeFade *= smoothstep(0.0, 0.1, rayNDC.x); + edgeFade *= smoothstep(0.0, 0.1, rayNDC.y); + edgeFade *= smoothstep(0.0, 0.1, 1.0 - rayNDC.x); + edgeFade *= smoothstep(0.0, 0.1, 1.0 - rayNDC.y); + + float NdotV = max(dot(normalWS, viewWS), 0.0); + vec3 F0 = mix(vec3(0.04), vec3(1.0), metalness); + vec3 Fresnel = F0 + (1.0 - F0) * pow(1.0 - NdotV, 5.0); + + ssrStrength *= fadeFactor * edgeFade * u_Intensity; + + vec4 color = texture(u_ColorTexture, rayNDC.xy); + color.rgb *= ssrStrength * Fresnel; + color.a = ssrStrength * dot(Fresnel, vec3(0.333)); + + o_Color = color; + return; } } - if (!found) - { - o_Color = vec4(0.0); - return; - } - - vec3 hitNormal = ReconstructNormalFromDepth(hitUV, texture(u_DepthTexture, hitUV).r); - if (dot(hitNormal, -reflectDir) < 0.0) - { - o_Color = vec4(0.0); - return; - } - - vec3 reflectColor = texture(u_ColorTexture, hitUV).rgb; - - float dist = distance(viewPos, ReconstructViewPos(hitUV, texture(u_DepthTexture, hitUV).r)); - float fadeFactor = 1.0 - smoothstep(u_MaxDistance * 0.5, u_MaxDistance, dist); - - float edgeFade = 1.0; - edgeFade *= smoothstep(0.0, 0.15, hitUV.x); - edgeFade *= smoothstep(0.0, 0.15, hitUV.y); - edgeFade *= smoothstep(0.0, 0.15, 1.0 - hitUV.x); - edgeFade *= smoothstep(0.0, 0.15, 1.0 - hitUV.y); - - vec3 F0 = mix(vec3(0.04), reflectColor, metalness); - vec3 Fresnel = F0 + (1.0 - F0) * pow(1.0 - NdotV, 5.0); - - float roughnessFade = 1.0 - roughness * roughness; - - vec3 ssrContrib = reflectColor * Fresnel * fadeFactor * edgeFade * roughnessFade * u_Intensity; - float ssrAlpha = length(Fresnel) * fadeFactor * edgeFade * roughnessFade; - - o_Color = vec4(ssrContrib, ssrAlpha); + o_Color = vec4(0.0); } diff --git a/Editor/assets/shaders/SceneComposite.glsl b/Editor/assets/shaders/SceneComposite.glsl index 0e90c2f..e9aaa92 100644 --- a/Editor/assets/shaders/SceneComposite.glsl +++ b/Editor/assets/shaders/SceneComposite.glsl @@ -85,7 +85,6 @@ float MultiSampleDepth(sampler2DMS tex, vec2 tc) void main() { const float gamma = 2.2; - const float pureWhite = 1.0; // Tonemapping vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord); @@ -100,7 +99,7 @@ void main() if (u_EnableSSR) { vec4 ssrSample = texture(u_SSRTexture, v_TexCoord); - color += ssrSample.rgb * ssrSample.a; + color = mix(color, ssrSample.rgb, ssrSample.a); } @@ -111,14 +110,18 @@ void main() exposure = u_ManualExposure; color *= exposure; + vec3 mappedColor = color; - // Reinhard tonemapping operator. - // see: "Photographic Tone Reproduction for Digital Images", eq. 4 - float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722)); - float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance); - - // Scale color by ratio of average luminances. - vec3 mappedColor = (mappedLuminance / luminance) * color; + float luminance = dot(mappedColor, vec3(0.2126, 0.7152, 0.0722)); + if (luminance > 0.00001) + { + float a = 2.51; + float b = 0.03; + float c = 2.43; + float d = 0.59; + float e = 0.14; + mappedColor = clamp((mappedColor * (a * mappedColor + b)) / (mappedColor * (c * mappedColor + d) + e), 0.0, 1.0); + } if (u_FogEnabled > 0.5) { diff --git a/Prism/src/Prism/Asset/Asset.h b/Prism/src/Prism/Asset/Asset.h index 1b87807..98e100e 100644 --- a/Prism/src/Prism/Asset/Asset.h +++ b/Prism/src/Prism/Asset/Asset.h @@ -81,15 +81,20 @@ namespace Prism Ref NormalTexture; // Metalness - float Metalness = 0.8f; + float Metalness = 0.2f; float MetalnessTexToggle = 0.0f; Ref MetalnessTexture; // Roughness - float Roughness = 0.1f; + float Roughness = 1.0f; float RoughnessTexToggle = 0.0f; Ref RoughnessTexture; + // AO + float AO = 1.0f; + float AOTexToggle = 0.0f; + Ref AOTexture; + bool IsDirty = true; bool PreviewIsDirty = true; diff --git a/Prism/src/Prism/Asset/AssetSerializer.cpp b/Prism/src/Prism/Asset/AssetSerializer.cpp index 3c437ad..9436692 100644 --- a/Prism/src/Prism/Asset/AssetSerializer.cpp +++ b/Prism/src/Prism/Asset/AssetSerializer.cpp @@ -123,7 +123,7 @@ namespace Prism out << YAML::Key << "Roughness"; out << YAML::BeginMap; { - out << YAML::Key << "Value" << YAML::Value << material->Roughness; // 粗糙度数值 + out << YAML::Key << "Value" << YAML::Value << material->Roughness; out << YAML::Key << "TexToggle" << YAML::Value << material->RoughnessTexToggle; out << YAML::Key << "Texture"; @@ -142,6 +142,29 @@ namespace Prism } out << YAML::EndMap; + // AO + out << YAML::Key << "AO"; + out << YAML::BeginMap; + { + out << YAML::Key << "Value" << YAML::Value << material->AO; + out << YAML::Key << "TexToggle" << YAML::Value << material->AOTexToggle; + + out << YAML::Key << "Texture"; + out << YAML::BeginMap; + if (material->AOTexture) + { + out << YAML::Key << "AssetHandle" << YAML::Value << material->AOTexture->Handle; + out << YAML::Key << "AssetPath" << YAML::Value << material->AOTexture->FilePath; + } + else + { + out << YAML::Key << "AssetHandle" << YAML::Value << 0; + out << YAML::Key << "AssetPath" << YAML::Value << ""; + } + out << YAML::EndMap; + } + out << YAML::EndMap; + break; } } @@ -279,6 +302,32 @@ namespace Prism } } + // ==================== AO ==================== + if (data["AO"]) + { + auto aoNode = data["AO"]; + material->AO = aoNode["Value"].as(); + material->AOTexToggle = aoNode["TexToggle"].as(); + + if (aoNode["Texture"]) + { + auto texNode = aoNode["Texture"]; + UUID texHandle = 0; + std::string texPath; + if (texNode["AssetHandle"]) + texHandle = texNode["AssetHandle"].as(); + if (texNode["AssetPath"]) + texPath = texNode["AssetPath"].as(); + + if (texHandle != 0 && AssetsManager::IsAssetHandleValid(texHandle)) + material->AOTexture = AssetsManager::GetAsset(texHandle); + else if (!texPath.empty()) + material->AOTexture = Texture2D::Create(texPath); + else + material->AOTexture = nullptr; + } + } + return material; } } diff --git a/Prism/src/Prism/Core/Math/AABB.h b/Prism/src/Prism/Core/Math/AABB.h index 8197ca6..89cb61b 100644 --- a/Prism/src/Prism/Core/Math/AABB.h +++ b/Prism/src/Prism/Core/Math/AABB.h @@ -6,6 +6,7 @@ #define PRISM_AABB_H #include +#include namespace Prism { @@ -23,6 +24,28 @@ namespace Prism return Min.x <= Max.x && Min.y <= Max.y && Min.z <= Max.z; } + AABB Transform(const glm::mat4& m) const + { + glm::vec3 corners[8] = { + {Min.x, Min.y, Min.z}, {Min.x, Min.y, Max.z}, + {Min.x, Max.y, Min.z}, {Min.x, Max.y, Max.z}, + {Max.x, Min.y, Min.z}, {Max.x, Min.y, Max.z}, + {Max.x, Max.y, Min.z}, {Max.x, Max.y, Max.z} + }; + + glm::vec3 newMin(std::numeric_limits::max()); + glm::vec3 newMax(std::numeric_limits::lowest()); + + for (int i = 0; i < 8; i++) + { + glm::vec3 c = glm::vec3(m * glm::vec4(corners[i], 1.0f)); + newMin = glm::min(newMin, c); + newMax = glm::max(newMax, c); + } + + return AABB(newMin, newMax); + } + }; } diff --git a/Prism/src/Prism/Core/Math/Frustum.h b/Prism/src/Prism/Core/Math/Frustum.h new file mode 100644 index 0000000..85f8dcb --- /dev/null +++ b/Prism/src/Prism/Core/Math/Frustum.h @@ -0,0 +1,64 @@ +#ifndef PRISM_FRUSTUM_H +#define PRISM_FRUSTUM_H + +#include +#include "Prism/Core/Math/AABB.h" + +namespace Prism +{ + struct Frustum + { + glm::vec4 Planes[6]; + + enum PlaneIndex + { + Left = 0, Right, Bottom, Top, Near, Far + }; + + static Frustum FromViewProjection(const glm::mat4& vp) + { + Frustum f; + glm::mat4 t = glm::transpose(vp); + glm::vec4 row0 = t[0]; + glm::vec4 row1 = t[1]; + glm::vec4 row2 = t[2]; + glm::vec4 row3 = t[3]; + + f.Planes[Left] = row3 + row0; + f.Planes[Right] = row3 - row0; + f.Planes[Bottom] = row3 + row1; + f.Planes[Top] = row3 - row1; + f.Planes[Near] = row3 + row2; + f.Planes[Far] = row3 - row2; + + for (int i = 0; i < 6; i++) + { + float len = glm::length(glm::vec3(f.Planes[i])); + if (len > 0.0001f) + f.Planes[i] /= len; + } + + return f; + } + + bool IsInside(const AABB& aabb) const + { + for (int i = 0; i < 6; i++) + { + const glm::vec4& p = Planes[i]; + glm::vec3 normal(p.x, p.y, p.z); + + glm::vec3 positive = aabb.Min; + if (p.x >= 0) positive.x = aabb.Max.x; + if (p.y >= 0) positive.y = aabb.Max.y; + if (p.z >= 0) positive.z = aabb.Max.z; + + if (glm::dot(normal, positive) + p.w < 0.0f) + return false; + } + return true; + } + }; +} + +#endif diff --git a/Prism/src/Prism/Editor/DefaultAssetEditors/PBRMaterialAssetEditor.cpp b/Prism/src/Prism/Editor/DefaultAssetEditors/PBRMaterialAssetEditor.cpp index 2104047..ac8a53a 100644 --- a/Prism/src/Prism/Editor/DefaultAssetEditors/PBRMaterialAssetEditor.cpp +++ b/Prism/src/Prism/Editor/DefaultAssetEditors/PBRMaterialAssetEditor.cpp @@ -1,4 +1,4 @@ -// +// // Created by Atdunbg on 2026/2/14. // @@ -15,6 +15,7 @@ #include "Prism/Renderer/RHI/RHICommandBuffer.h" #include "Prism/Renderer/SceneRenderer.h" #include "Prism/Scene/Scene.h" +#include "Prism/Utilities/StringUtils.h" namespace Prism { @@ -150,15 +151,18 @@ namespace Prism matInst->Set("u_AlbedoColor", materialAsset->AlbedoColor); matInst->Set("u_Metalness", materialAsset->Metalness); matInst->Set("u_Roughness", materialAsset->Roughness); + matInst->Set("u_AO", materialAsset->AO); matInst->Set("u_AlbedoTexToggle", materialAsset->AlbedoTexToggle); matInst->Set("u_NormalTexToggle", materialAsset->NormalTexToggle); matInst->Set("u_MetalnessTexToggle", materialAsset->MetalnessTexToggle); matInst->Set("u_RoughnessTexToggle", materialAsset->RoughnessTexToggle); + matInst->Set("u_AOTexToggle", materialAsset->AOTexToggle); matInst->Set("u_AlbedoTexture", materialAsset->AlbedoTexture); matInst->Set("u_NormalTexture", materialAsset->NormalTexture); matInst->Set("u_MetalnessTexture", materialAsset->MetalnessTexture); matInst->Set("u_RoughnessTexture", materialAsset->RoughnessTexture); + matInst->Set("u_AOTexture", materialAsset->AOTexture); float aspect = (float)s_PreviewRenderPass->GetSpecification().TargetFramebuffer->GetWidth() / (float)s_PreviewRenderPass->GetSpecification().TargetFramebuffer->GetHeight(); @@ -330,7 +334,6 @@ namespace Prism if (ImGui::SliderFloat("Value##Roughness", &material->Roughness, 0.0f, 1.0f)) { - // 自动保存 MarkDirty(); } @@ -352,6 +355,35 @@ namespace Prism ImGui::Unindent(); } + + // AO + if (ImGui::CollapsingHeader("AO", ImGuiTreeNodeFlags_DefaultOpen)) + { + ImGui::Indent(); + + if (ImGui::SliderFloat("Value##AO", &material->AO, 0.0f, 1.0f)) + { + MarkDirty(); + } + + bool useAOMap = (material->AOTexToggle > 0.5f); + if (ImGui::Checkbox("Use Texture##AO", &useAOMap)) + { + material->AOTexToggle = useAOMap ? 1.0f : 0.0f; + MarkDirty(); + } + + DrawTextureSlot(material->AOTexture, [&](const Ref& newTex) + { + material->AOTexture = newTex; + material->AOTexToggle = true; + MarkDirty(); + }); + ImGui::SameLine(); + ImGui::Text("AO Texture"); + + ImGui::Unindent(); + } } } @@ -411,6 +443,9 @@ namespace Prism MarkDirty(); } + m_CanvasOrigin = ImGui::GetCursorScreenPos(); + m_CanvasSize = ImGui::GetContentRegionAvail(); + ed::Begin("MaterialNodeEditor"); if (m_FirstFrame) @@ -518,10 +553,8 @@ namespace Prism drawInputPin(AO, "AO", [&]() { ImGui::SetNextItemWidth(80); - float ao = 1.0f; // 如果资产没有 AO 字段可以忽略 - if (ImGui::SliderFloat("##ao", &ao, 0.0f, 1.0f)) - { - } + if (ImGui::SliderFloat("##ao", &m_Asset->AO, 0.0f, 1.0f)) + MarkDirty(); }); ImGui::EndGroup(); @@ -550,10 +583,24 @@ namespace Prism ImVec2 headerMin = ImGui::GetCursorScreenPos(); ImGui::BeginGroup(); - float headerMaxY = DrawNodeHeader("Texture2D", nodeWidth); + + bool hasTexture = (textureHandle != 0); + std::string nodeTitle = "Texture2D"; + if (hasTexture) + { + Ref tex = AssetsManager::GetAsset(textureHandle); + if (tex) + { + std::string name = Utils::GetFilename(tex->GetPath()); + if (name.length() > 14) + name = name.substr(0, 11) + "..."; + if (!name.empty()) + nodeTitle = name; + } + } + float headerMaxY = DrawNodeHeader(nodeTitle.c_str(), nodeWidth); // 纹理预览 - bool hasTexture = (textureHandle != 0); float previewSize = 80.0f; float offsetX = (nodeWidth - previewSize) * 0.5f; ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX); @@ -565,6 +612,9 @@ namespace Prism ImGui::Image((ImTextureID)(intptr_t)tex->GetRendererID(), ImVec2(previewSize, previewSize), ImVec2(0,1), ImVec2(1,0)); else ImGui::Dummy(ImVec2(previewSize, previewSize)); + + if (ImGui::IsItemHovered() && tex) + m_PendingTooltip = Utils::GetFilename(tex->GetPath()); } else { @@ -705,19 +755,22 @@ namespace Prism ed::Suspend(); + if (!m_PendingTooltip.empty()) + { + ImGui::BeginTooltip(); + ImGui::TextUnformatted(m_PendingTooltip.c_str()); + ImGui::EndTooltip(); + m_PendingTooltip.clear(); + } + const ImGuiPayload* payload = ImGui::GetDragDropPayload(); if (payload && payload->IsDataType("asset_payload")) { AssetHandle handle = *(AssetHandle*)payload->Data; if (AssetsManager::IsAssetType(handle, AssetType::Texture)) { - // 获取画布区域 - ImVec2 canvasMin = ImGui::GetCursorScreenPos(); - ImVec2 canvasSize = ImGui::GetContentRegionAvail(); - - - ImGui::SetCursorScreenPos(canvasMin); - ImGui::InvisibleButton("##canvas_temp_drop", canvasSize, + ImGui::SetCursorScreenPos(m_CanvasOrigin); + ImGui::InvisibleButton("##canvas_temp_drop", m_CanvasSize, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle); if (ImGui::BeginDragDropTarget()) @@ -727,7 +780,6 @@ namespace Prism AssetHandle dropHandle = *(AssetHandle*)dropPayload->Data; if (AssetsManager::IsAssetType(dropHandle, AssetType::Texture)) { - // 将鼠标位置转换为画布坐标,创建节点 ImVec2 mousePos = ImGui::GetMousePos(); ImVec2 canvasPos = ed::ScreenToCanvas(mousePos); int newId = m_NextNodeId++; @@ -845,6 +897,9 @@ namespace Prism m_Asset->RoughnessTexture = getTexture(GetLinkedTextureHandle(InputPinID(Roughness))); m_Asset->RoughnessTexToggle = m_Asset->RoughnessTexture ? 1.0f : 0.0f; + m_Asset->AOTexture = getTexture(GetLinkedTextureHandle(InputPinID(AO))); + m_Asset->AOTexToggle = m_Asset->AOTexture ? 1.0f : 0.0f; + MarkDirty(); } @@ -875,6 +930,7 @@ namespace Prism addTextureNode(getHandle(m_Asset->NormalTexture), Normal, 150.0f); addTextureNode(getHandle(m_Asset->MetalnessTexture), Metallic, 300.0f); addTextureNode(getHandle(m_Asset->RoughnessTexture), Roughness, 450.0f); + addTextureNode(getHandle(m_Asset->AOTexture), AO, 600.0f); m_FirstFrame = true; } diff --git a/Prism/src/Prism/Editor/DefaultAssetEditors/PBRMaterialAssetEditor.h b/Prism/src/Prism/Editor/DefaultAssetEditors/PBRMaterialAssetEditor.h index 6b4ccdb..f90c299 100644 --- a/Prism/src/Prism/Editor/DefaultAssetEditors/PBRMaterialAssetEditor.h +++ b/Prism/src/Prism/Editor/DefaultAssetEditors/PBRMaterialAssetEditor.h @@ -75,6 +75,9 @@ namespace Prism bool m_OpenAlbedoPicker = false; ImVec2 m_AlbedoPickerPos; int m_ContextMenuNodeId = 0; + ImVec2 m_CanvasOrigin = ImVec2(0, 0); + ImVec2 m_CanvasSize = ImVec2(0, 0); + std::string m_PendingTooltip; // 引脚ID辅助函数 static int InputPinID(int type) { return OUTPUT_NODE_ID * 100 + type; } diff --git a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp index aee12b3..22cfbb2 100644 --- a/Prism/src/Prism/Editor/SceneHierachyPanel.cpp +++ b/Prism/src/Prism/Editor/SceneHierachyPanel.cpp @@ -925,6 +925,7 @@ namespace Prism { meshComponent.UpdateMaterials(-1, true); } + UI::EndPropertyGrid(); UI::EndTreeNode(); diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp b/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp index 004e530..8914ebb 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp @@ -357,6 +357,31 @@ namespace Prism glDepthMask(enable ? GL_TRUE : GL_FALSE); } + static GLenum MapBlendFactor(BlendFactor factor) + { + switch (factor) + { + case BlendFactor::Zero: return GL_ZERO; + case BlendFactor::One: return GL_ONE; + case BlendFactor::SrcAlpha: return GL_SRC_ALPHA; + case BlendFactor::OneMinusSrcAlpha: return GL_ONE_MINUS_SRC_ALPHA; + case BlendFactor::DstAlpha: return GL_DST_ALPHA; + case BlendFactor::OneMinusDstAlpha: return GL_ONE_MINUS_DST_ALPHA; + } + return GL_ONE; + } + + void OpenGLCommandBuffer::SetBlend(const bool enable) const + { + if (enable) glEnable(GL_BLEND); + else glDisable(GL_BLEND); + } + + void OpenGLCommandBuffer::SetBlendFunc(BlendFactor src, BlendFactor dst) const + { + glBlendFunc(MapBlendFactor(src), MapBlendFactor(dst)); + } + void OpenGLCommandBuffer::CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture, uint32_t srcLevel, uint32_t dstLevel, uint32_t srcX, uint32_t srcY, uint32_t srcZ, uint32_t dstX, uint32_t dstY, uint32_t dstZ, uint32_t width, uint32_t height, uint32_t depth) const diff --git a/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h b/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h index 717766d..060f492 100644 --- a/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h +++ b/Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h @@ -77,6 +77,8 @@ namespace Prism void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const override; void SetLineSmooth(bool enable) const override; void SetDepthWrite(bool enable) const override; + void SetBlend(bool enable) const override; + void SetBlendFunc(BlendFactor src, BlendFactor dst) const override; void CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture, uint32_t srcLevel, uint32_t dstLevel, uint32_t srcX, uint32_t srcY, uint32_t srcZ, uint32_t dstX, uint32_t dstY, uint32_t dstZ, uint32_t width, uint32_t height, uint32_t depth) const override; int32_t GetUniformLocation(uint32_t program, const std::string& name) const override; diff --git a/Prism/src/Prism/Renderer/Material.cpp b/Prism/src/Prism/Renderer/Material.cpp index fbab3f1..40eb18d 100644 --- a/Prism/src/Prism/Renderer/Material.cpp +++ b/Prism/src/Prism/Renderer/Material.cpp @@ -13,7 +13,7 @@ namespace Prism AllocateStorage(); m_MaterialFlags |= (uint32_t)MaterialFlag::DepthTest; - m_MaterialFlags |= (uint32_t)MaterialFlag::Blend; + // m_MaterialFlags |= (uint32_t)MaterialFlag::Blend; } Material::~Material() @@ -155,7 +155,6 @@ namespace Prism // 复制纹理列表(共享纹理引用) newInstance->m_Textures = other->m_Textures; - // 复制覆盖标记集合 newInstance->m_OverriddenValues = other->m_OverriddenValues; return newInstance; diff --git a/Prism/src/Prism/Renderer/Material.h b/Prism/src/Prism/Renderer/Material.h index d3f970f..d36dcdf 100644 --- a/Prism/src/Prism/Renderer/Material.h +++ b/Prism/src/Prism/Renderer/Material.h @@ -212,7 +212,6 @@ namespace Prism Buffer m_PSUniformStorageBuffer; std::vector> m_Textures; - // TODO: This is temporary; come up with a proper system to track overrides std::unordered_set m_OverriddenValues; }; diff --git a/Prism/src/Prism/Renderer/Mesh.cpp b/Prism/src/Prism/Renderer/Mesh.cpp index 739db82..ea839d1 100644 --- a/Prism/src/Prism/Renderer/Mesh.cpp +++ b/Prism/src/Prism/Renderer/Mesh.cpp @@ -460,6 +460,34 @@ namespace Prism mi->Set("u_Metalness", metalness); mi->Set("u_MetalnessTexToggle", 0.0f); } + + // AO map + mi->Set("u_AO", 1.0f); + mi->Set("u_AOTexToggle", 0.0f); + + if (aiMaterial->GetTexture(aiTextureType_AMBIENT_OCCLUSION, 0, &aiTexPath) == AI_SUCCESS) + { + std::filesystem::path path = filename; + auto parentPath = path.parent_path(); + parentPath /= std::string(aiTexPath.data); + std::string texturePath = parentPath.string(); + + PM_MESH_LOG(" AO map path = {0}", texturePath); + auto texture = AssetsManager::TryGetAsset(texturePath); + if (texture && texture->Loaded()) + { + mi->Set("u_AOTexture", texture); + mi->Set("u_AOTexToggle", 1.0f); + } + else + { + PM_CORE_ERROR(" Could not load AO texture: {0}", texturePath); + } + } + else + { + PM_MESH_LOG(" No AO map"); + } } PM_MESH_LOG("------------------------"); } diff --git a/Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h b/Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h index 867bdc9..28d9883 100644 --- a/Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h +++ b/Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h @@ -30,6 +30,7 @@ namespace Prism { enum class BlitFilter { Nearest, Linear }; enum class DataType { UnsignedInt }; enum class BlitMask { Color, Depth, Stencila }; + enum class BlendFactor { Zero, One, SrcAlpha, OneMinusSrcAlpha, DstAlpha, OneMinusDstAlpha }; enum class MemoryBarrierMask { None = 0, @@ -98,6 +99,8 @@ namespace Prism { virtual void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const = 0; virtual void SetLineSmooth(bool enable) const = 0; virtual void SetDepthWrite(bool enable) const = 0; + virtual void SetBlend(bool enable) const = 0; + virtual void SetBlendFunc(BlendFactor src, BlendFactor dst) const = 0; virtual void CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture, uint32_t srcLevel, uint32_t dstLevel, diff --git a/Prism/src/Prism/Renderer/Renderer.cpp b/Prism/src/Prism/Renderer/Renderer.cpp index 334c23a..811cfda 100644 --- a/Prism/src/Prism/Renderer/Renderer.cpp +++ b/Prism/src/Prism/Renderer/Renderer.cpp @@ -18,6 +18,8 @@ namespace Prism RendererAPIType RendererAPI::s_CurrentRendererAPI = RendererAPIType::OpenGL; Ref Renderer::s_Device; Ref Renderer::s_CommandBuffer; + uint32_t Renderer::s_DrawCallCount = 0; + uint32_t Renderer::s_LastFrameDrawCallCount = 0; struct RendererData @@ -127,6 +129,8 @@ namespace Prism void Renderer::WaitAndRender() { + s_LastFrameDrawCallCount = s_DrawCallCount; + s_DrawCallCount = 0; s_Data.m_CommandQueue.Execute(); } @@ -163,6 +167,7 @@ namespace Prism void Renderer::SubmitQuad(Ref& material, const glm::mat4& transform) { + s_DrawCallCount++; bool depthTest = true; bool cullFace = true; @@ -185,6 +190,7 @@ namespace Prism void Renderer::SubmitFullscreenQuad(Ref material) { + s_DrawCallCount++; bool depthTest = true; bool cullFace = true; if (material) @@ -203,6 +209,7 @@ namespace Prism void Renderer::SubmitFullscreenQuad(const bool depthTest, const bool cullFace) { + s_DrawCallCount++; s_Data.m_FullscreenQuadVertexBuffer->Bind(); s_Data.m_FullscreenQuadPipeline->Bind(); @@ -213,10 +220,6 @@ namespace Prism void Renderer::SubmitMesh(Ref& mesh, const glm::mat4& transform, const std::vector>& overrideMaterials) { - // auto material = overrideMaterial ? overrideMaterial : mesh->GetMaterialInstance(); - // auto shader = material->GetShader(); - - // TODO: Sort this out mesh->m_VertexBuffer->Bind(); mesh->m_Pipeline->Bind(); mesh->m_IndexBuffer->Bind(); @@ -224,8 +227,9 @@ namespace Prism const auto& materials = mesh->GetMaterials(); for (Submesh& submesh : mesh->m_Submeshes) { - // Material auto material = overrideMaterials.empty() ? materials[submesh.MaterialIndex] : overrideMaterials[submesh.MaterialIndex]; + + s_DrawCallCount++; auto shader = material->GetShader(); material->Bind(); @@ -242,12 +246,10 @@ namespace Prism auto cmd = s_CommandBuffer; Submit([cmd, submesh, material]() { - // 状态设置通过 cmd cmd->SetDepthTest(material->GetFlag(MaterialFlag::DepthTest)); - cmd->SetDepthFunc(CompareOp::LessEqual); // 对应 GL_LEQUAL + cmd->SetDepthFunc(CompareOp::LessEqual); cmd->SetCullMode(material->GetFlag(MaterialFlag::TwoSided) ? CullMode::None : CullMode::Back); - // 绘制 cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0); }); } @@ -255,10 +257,6 @@ namespace Prism void Renderer::SubmitMesh(Ref& mesh, const glm::mat4& transform, const Ref& overrideMaterial) { - // auto material = overrideMaterial ? overrideMaterial : mesh->GetMaterialInstance(); - // auto shader = material->GetShader(); - - // TODO: Sort this out mesh->m_VertexBuffer->Bind(); mesh->m_Pipeline->Bind(); mesh->m_IndexBuffer->Bind(); @@ -266,8 +264,9 @@ namespace Prism const auto& materials = mesh->GetMaterials(); for (Submesh& submesh : mesh->m_Submeshes) { - // Material auto material = overrideMaterial ? overrideMaterial : materials[submesh.MaterialIndex]; + + s_DrawCallCount++; auto shader = material->GetShader(); material->Bind(); @@ -300,6 +299,7 @@ namespace Prism for (Submesh& submesh : mesh->m_Submeshes) { + s_DrawCallCount++; if (mesh->m_IsAnimated) { const auto& boneTransform = mesh->GetBoneTransforms(); diff --git a/Prism/src/Prism/Renderer/Renderer.h b/Prism/src/Prism/Renderer/Renderer.h index a7b6d5b..5c200d3 100644 --- a/Prism/src/Prism/Renderer/Renderer.h +++ b/Prism/src/Prism/Renderer/Renderer.h @@ -70,11 +70,15 @@ namespace Prism static void DrawAABB(const Ref& mesh,const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f)); static void DispatchCompute(int x, int y, int z); + static uint32_t GetDrawCallCount() { return s_LastFrameDrawCallCount; } + private: static RenderCommandQueue& GetRenderCommandQueue(); static Ref s_Device; static Ref s_CommandBuffer; + static uint32_t s_DrawCallCount; + static uint32_t s_LastFrameDrawCallCount; }; #if 0 diff --git a/Prism/src/Prism/Renderer/Renderer3D.cpp b/Prism/src/Prism/Renderer/Renderer3D.cpp index 8a4c506..a14c228 100644 --- a/Prism/src/Prism/Renderer/Renderer3D.cpp +++ b/Prism/src/Prism/Renderer/Renderer3D.cpp @@ -5,6 +5,7 @@ #include "Renderer3D.h" #include "Prism/Core/Timer.h" +#include "Prism/Core/Math/Frustum.h" #include "Prism/Scene/Scene.h" #include @@ -116,8 +117,10 @@ namespace Prism Ref mesh; std::vector> MaterialInstances; glm::mat4 Transform; + float DistanceFromCamera = 0.0f; }; std::vector DrawList; + std::vector TransparentDrawList; std::vector SelectedMeshDrawList; std::vector ColliderDrawList; std::vector ShadowPassDrawList; @@ -145,7 +148,9 @@ namespace Prism float Intensity = 1.0f; float MaxDistance = 30.0f; float Thickness = 0.5f; - int Steps = 64; + float StepSize = 0.5f; + float RayOffset = 0.1f; + int Steps = 32; float BlurRadius = 4.0f; Ref SSRShader; @@ -158,6 +163,13 @@ namespace Prism SceneRendererOptions Options; + Frustum CameraFrustum; + + uint32_t MeshesSubmitted = 0; + uint32_t MeshesCulled = 0; + uint32_t LastFrameMeshesSubmitted = 0; + uint32_t LastFrameMeshesCulled = 0; + Ref BlackCubeTexture; Ref BlackTexture; }; @@ -351,6 +363,9 @@ namespace Prism s_Data.SceneData.SceneEnvironment = scene->m_Environment; s_Data.SceneData.SceneEnvironmentIntensity = scene->m_EnvironmentIntensity; s_Data.SceneData.SceneLightEnvironment = scene->m_LightEnvironment; + + glm::mat4 vp = camera.Camera.GetProjectionMatrix() * camera.ViewMatrix; + s_Data.CameraFrustum = Frustum::FromViewProjection(vp); } void Renderer3D::EndScene(Ref& renderPass) @@ -360,14 +375,51 @@ namespace Prism void Renderer3D::SubmitMesh(const Ref& mesh, const glm::mat4& transform, const std::vector>& overrideMaterials) { - // TODO: Culling, sorting, etc. + s_Data.MeshesSubmitted++; + + AABB worldAABB = mesh->GetBoundingBox().Transform(transform); + if (!s_Data.CameraFrustum.IsInside(worldAABB)) + { + s_Data.MeshesCulled++; + return; + } + + bool isTransparent = false; + if (!overrideMaterials.empty()) + { + for (auto& mi : overrideMaterials) + { + if (mi && mi->GetFlag(MaterialFlag::Blend)) + { + isTransparent = true; + break; + } + } + } + else + { + auto& materials = mesh->GetMaterials(); + for (auto& mi : materials) + { + if (mi && mi->GetFlag(MaterialFlag::Blend)) + { + isTransparent = true; + break; + } + } + } + + if (isTransparent) + s_Data.TransparentDrawList.push_back({ mesh, overrideMaterials, transform }); + else + s_Data.DrawList.push_back({ mesh, overrideMaterials, transform }); - s_Data.DrawList.push_back({ mesh, overrideMaterials, transform }); s_Data.ShadowPassDrawList.push_back({ mesh, overrideMaterials, transform }); } void Renderer3D::SubmitSelectedMesh(const Ref& mesh, const glm::mat4& transform, const std::vector>& overrideMaterials) { + s_Data.MeshesSubmitted++; s_Data.SelectedMeshDrawList.push_back({ mesh, overrideMaterials, transform }); s_Data.ShadowPassDrawList.push_back({ mesh, overrideMaterials, transform }); } @@ -572,10 +624,15 @@ namespace Prism } s_Data.DrawList.clear(); + s_Data.TransparentDrawList.clear(); s_Data.SelectedMeshDrawList.clear(); s_Data.ColliderDrawList.clear(); s_Data.ShadowPassDrawList.clear(); s_Data.SceneData = {}; + s_Data.LastFrameMeshesSubmitted = s_Data.MeshesSubmitted; + s_Data.LastFrameMeshesCulled = s_Data.MeshesCulled; + s_Data.MeshesSubmitted = 0; + s_Data.MeshesCulled = 0; } void Renderer3D::AutoExposurePass() @@ -1321,15 +1378,21 @@ namespace Prism const auto& sceneCamera = s_Data.SceneData.SceneCamera; const auto cameraProjection = sceneCamera.Camera.GetProjectionMatrix(); + const auto viewMatrix = sceneCamera.ViewMatrix; + const glm::vec3 cameraPosition = glm::inverse(viewMatrix)[3]; s_Data.SSRData.SSRShader->SetMat4("u_Projection", cameraProjection); - s_Data.SSRData.SSRShader->SetMat4("u_InvProjection", glm::inverse(cameraProjection)); + s_Data.SSRData.SSRShader->SetMat4("u_View", viewMatrix); + s_Data.SSRData.SSRShader->SetMat4("u_InvViewProjection", glm::inverse(cameraProjection * viewMatrix)); + s_Data.SSRData.SSRShader->SetFloat3("u_CameraPosition", cameraPosition); s_Data.SSRData.SSRShader->SetFloat2("u_ScreenSize", glm::vec2((float)width, (float)height)); s_Data.SSRData.SSRShader->SetFloat("u_CameraNear", sceneCamera.Camera.GetNear()); s_Data.SSRData.SSRShader->SetFloat("u_CameraFar", sceneCamera.Camera.GetFar()); s_Data.SSRData.SSRShader->SetInt("u_Steps", s_Data.SSRData.Steps); s_Data.SSRData.SSRShader->SetFloat("u_MaxDistance", s_Data.SSRData.MaxDistance); s_Data.SSRData.SSRShader->SetFloat("u_Thickness", s_Data.SSRData.Thickness); + s_Data.SSRData.SSRShader->SetFloat("u_StepSize", s_Data.SSRData.StepSize); + s_Data.SSRData.SSRShader->SetFloat("u_RayOffset", s_Data.SSRData.RayOffset); s_Data.SSRData.SSRShader->SetFloat("u_Intensity", s_Data.SSRData.Intensity); Renderer::SubmitFullscreenQuad(nullptr); @@ -1381,8 +1444,12 @@ namespace Prism { ImGui::Begin("Scene Renderer"); + ImGui::Text("Draw Calls: %u", Renderer::GetDrawCallCount()); + ImGui::Text("Meshes Submitted: %u", s_Data.LastFrameMeshesSubmitted); + ImGui::Text("Meshes Culled: %u", s_Data.LastFrameMeshesCulled); + ImGui::Separator(); - UI::Property("Geometry Pass time", s_Stats.GeometryPass); + UI::Property("Geometry Pass time", s_Stats.GeometryPass); UI::Property("Composite Pass time", s_Stats.CompositePass); UI::Property("Shadow Pass time", s_Stats.ShadowPass); UI::Property("AutoExposure Pass time", s_Stats.AutoExposurePass); @@ -1574,6 +1641,8 @@ namespace Prism UI::Property("Max Distance", s_Data.SSRData.MaxDistance, 0.1f, 1.0f, 200.0f); UI::Property("Thickness", s_Data.SSRData.Thickness, 0.01f, 0.01f, 5.0f); UI::PropertySlider("Steps", s_Data.SSRData.Steps, 1, 128); + UI::Property("Step Size", s_Data.SSRData.StepSize, 0.01f, 0.01f, 5.0f); + UI::Property("Ray Offset", s_Data.SSRData.RayOffset, 0.01f, 0.0f, 1.0f); UI::Property("Blur Radius", s_Data.SSRData.BlurRadius, 0.1f, 0.0f, 10.0f); } UI::EndPropertyGrid(); diff --git a/Prism/src/Prism/Scene/ECSFramework/Components/Components.h b/Prism/src/Prism/Scene/ECSFramework/Components/Components.h index 007a1aa..615ab8e 100644 --- a/Prism/src/Prism/Scene/ECSFramework/Components/Components.h +++ b/Prism/src/Prism/Scene/ECSFramework/Components/Components.h @@ -143,6 +143,9 @@ namespace Prism MaterialInstances[i]->Set("u_Roughness", desc->Roughness); MaterialInstances[i]->Set("u_RoughnessTexToggle", desc->RoughnessTexToggle); MaterialInstances[i]->Set("u_RoughnessTexture", desc->RoughnessTexture); + MaterialInstances[i]->Set("u_AO", desc->AO); + MaterialInstances[i]->Set("u_AOTexToggle", desc->AOTexToggle); + MaterialInstances[i]->Set("u_AOTexture", desc->AOTexture); }else { auto& baseMaterial = Mesh->GetMaterials(); @@ -158,6 +161,9 @@ namespace Prism MaterialInstances[i]->Set("u_Roughness", baseMaterial[0]->Get("u_Roughness")); MaterialInstances[i]->Set("u_RoughnessTexToggle", baseMaterial[i]->Get("u_RoughnessTexToggle")); MaterialInstances[i]->Set("u_RoughnessTexture", baseMaterial[i]->TryGetResource("u_RoughnessTexture")); + MaterialInstances[i]->Set("u_AO", baseMaterial[i]->Get("u_AO")); + MaterialInstances[i]->Set("u_AOTexToggle", baseMaterial[i]->Get("u_AOTexToggle")); + MaterialInstances[i]->Set("u_AOTexture", baseMaterial[i]->TryGetResource("u_AOTexture")); } } }else @@ -177,6 +183,9 @@ namespace Prism MaterialInstances[index]->Set("u_Roughness", desc->Roughness); MaterialInstances[index]->Set("u_RoughnessTexToggle", desc->RoughnessTexToggle); MaterialInstances[index]->Set("u_RoughnessTexture", desc->RoughnessTexture); + MaterialInstances[index]->Set("u_AO", desc->AO); + MaterialInstances[index]->Set("u_AOTexToggle", desc->AOTexToggle); + MaterialInstances[index]->Set("u_AOTexture", desc->AOTexture); }else { auto& baseMaterial = Mesh->GetMaterials(); @@ -192,6 +201,9 @@ namespace Prism MaterialInstances[index]->Set("u_Roughness", baseMaterial[0]->Get("u_Roughness")); MaterialInstances[index]->Set("u_RoughnessTexToggle", baseMaterial[index]->Get("u_RoughnessTexToggle")); MaterialInstances[index]->Set("u_RoughnessTexture", baseMaterial[index]->TryGetResource("u_RoughnessTexture")); + MaterialInstances[index]->Set("u_AO", baseMaterial[index]->Get("u_AO")); + MaterialInstances[index]->Set("u_AOTexToggle", baseMaterial[index]->Get("u_AOTexToggle")); + MaterialInstances[index]->Set("u_AOTexture", baseMaterial[index]->TryGetResource("u_AOTexture")); } }