add aabb cull for mesh, improve NodeEditor view and control

add AO texture
This commit is contained in:
2026-05-17 11:33:56 +08:00
parent f50824bdb1
commit 76ebcc8f66
22 changed files with 530 additions and 154 deletions

View File

@ -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<float>("u_AO");
bool useAOMap = materialInstance->Get<float>("u_AOTexToggle");
Ref<Texture2D> aoMap = materialInstance->TryGetResource<Texture2D>("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<Texture2D>(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<float>("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); if (shouldUpdate) meshComponent.UpdateMaterials(selectedMaterialIndex);
} }
} }

View File

@ -130,6 +130,7 @@ uniform sampler2D u_AlbedoTexture;
uniform sampler2D u_NormalTexture; uniform sampler2D u_NormalTexture;
uniform sampler2D u_MetalnessTexture; uniform sampler2D u_MetalnessTexture;
uniform sampler2D u_RoughnessTexture; uniform sampler2D u_RoughnessTexture;
uniform sampler2D u_AOTexture;
// environment // environment
uniform samplerCube u_EnvRadianceTex; uniform samplerCube u_EnvRadianceTex;
@ -146,12 +147,14 @@ uniform float u_EnvMapRotation;
uniform vec4 u_AlbedoColor; uniform vec4 u_AlbedoColor;
uniform float u_Metalness; uniform float u_Metalness;
uniform float u_Roughness; uniform float u_Roughness;
uniform float u_AO;
// textureToggle // textureToggle
uniform float u_AlbedoTexToggle; uniform float u_AlbedoTexToggle;
uniform float u_NormalTexToggle; uniform float u_NormalTexToggle;
uniform float u_MetalnessTexToggle; uniform float u_MetalnessTexToggle;
uniform float u_RoughnessTexToggle; uniform float u_RoughnessTexToggle;
uniform float u_AOTexToggle;
// shadow // shadow
const int CSM_CASCADE_COUNT = 4; 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 = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
m_Params.Roughness = max(m_Params.Roughness, 0.05); 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 // normal
m_Params.Normal = normalize(vs_Input.Normal); m_Params.Normal = normalize(vs_Input.Normal);
if (u_NormalTexToggle > 0.5) 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); color = vec4(lightContribution + iblContribution, 1.0);

View File

@ -117,6 +117,7 @@ uniform sampler2D u_AlbedoTexture;
uniform sampler2D u_NormalTexture; uniform sampler2D u_NormalTexture;
uniform sampler2D u_MetalnessTexture; uniform sampler2D u_MetalnessTexture;
uniform sampler2D u_RoughnessTexture; uniform sampler2D u_RoughnessTexture;
uniform sampler2D u_AOTexture;
// environment // environment
uniform samplerCube u_EnvRadianceTex; uniform samplerCube u_EnvRadianceTex;
@ -133,12 +134,14 @@ uniform float u_EnvMapRotation;
uniform vec4 u_AlbedoColor; uniform vec4 u_AlbedoColor;
uniform float u_Metalness; uniform float u_Metalness;
uniform float u_Roughness; uniform float u_Roughness;
uniform float u_AO;
// textureToggle // textureToggle
uniform float u_AlbedoTexToggle; uniform float u_AlbedoTexToggle;
uniform float u_NormalTexToggle; uniform float u_NormalTexToggle;
uniform float u_MetalnessTexToggle; uniform float u_MetalnessTexToggle;
uniform float u_RoughnessTexToggle; uniform float u_RoughnessTexToggle;
uniform float u_AOTexToggle;
// shadow // shadow
const int CSM_CASCADE_COUNT = 4; 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 = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
m_Params.Roughness = max(m_Params.Roughness, 0.05); 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 // normal
m_Params.Normal = normalize(vs_Input.Normal); m_Params.Normal = normalize(vs_Input.Normal);
if (u_NormalTexToggle > 0.5) 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); color = vec4(lightContribution + iblContribution, 1.0);

View File

@ -25,29 +25,38 @@ uniform sampler2D u_DepthTexture;
uniform sampler2D u_MaterialInfoTexture; uniform sampler2D u_MaterialInfoTexture;
uniform mat4 u_Projection; 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 vec2 u_ScreenSize;
uniform float u_CameraNear; uniform float u_CameraNear;
uniform float u_CameraFar; uniform float u_CameraFar;
uniform int u_Steps = 64; uniform int u_Steps = 32;
uniform float u_Thickness = 0.5; uniform float u_Thickness = 0.5;
uniform float u_MaxDistance = 30.0; uniform float u_MaxDistance = 30.0;
uniform float u_StepSize = 0.5;
uniform float u_RayOffset = 0.1;
uniform float u_Intensity = 1.0; uniform float u_Intensity = 1.0;
float saturate(float x)
{
return clamp(x, 0.0, 1.0);
}
float LinearizeDepth(float depth) float LinearizeDepth(float depth)
{ {
float z = depth * 2.0 - 1.0; float z = depth * 2.0 - 1.0;
return (2.0 * u_CameraNear * u_CameraFar) / (u_CameraFar + u_CameraNear - z * (u_CameraFar - u_CameraNear)); 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(uv * 2.0 - 1.0, depth * 2.0 - 1.0, 1.0);
vec4 clipPos = vec4(tc * 2.0 - 1.0, z, 1.0); vec4 worldPos = u_InvViewProjection * clipPos;
vec4 viewPos4 = u_InvProjection * clipPos; return worldPos.xyz / worldPos.w;
return viewPos4.xyz / viewPos4.w;
} }
vec3 ReconstructNormalFromDepth(vec2 tc, float depth) vec3 ReconstructNormalFromDepth(vec2 tc, float depth)
@ -64,17 +73,24 @@ vec3 ReconstructNormalFromDepth(vec2 tc, float depth)
float depthB = texture(u_DepthTexture, tcB).r; float depthB = texture(u_DepthTexture, tcB).r;
float depthT = texture(u_DepthTexture, tcT).r; float depthT = texture(u_DepthTexture, tcT).r;
vec3 pL = ReconstructViewPos(tcL, depthL); vec3 pC = ComputeWorldSpacePosition(tc, depth);
vec3 pR = ReconstructViewPos(tcR, depthR); vec3 pR = ComputeWorldSpacePosition(tcR, depthR);
vec3 pB = ReconstructViewPos(tcB, depthB); vec3 pT = ComputeWorldSpacePosition(tcT, depthT);
vec3 pT = ReconstructViewPos(tcT, depthT);
vec3 dx = pR - pL; vec3 dx = pR - pC;
vec3 dy = pT - pB; vec3 dy = pT - pC;
return normalize(cross(dx, dy)); 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() void main()
{ {
float depth = texture(u_DepthTexture, v_TexCoord).r; float depth = texture(u_DepthTexture, v_TexCoord).r;
@ -95,113 +111,68 @@ void main()
return; return;
} }
vec3 viewPos = ReconstructViewPos(v_TexCoord, depth); vec3 positionWS = ComputeWorldSpacePosition(v_TexCoord, depth);
vec3 normal = ReconstructNormalFromDepth(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); if (dot(reflectionWS, normalWS) < 0.0)
float NdotV = max(dot(normal, viewDir), 0.0);
vec3 reflectDir = reflect(-viewDir, normal);
if (dot(reflectDir, normal) < 0.0)
{ {
o_Color = vec4(0.0); o_Color = vec4(0.0);
return; return;
} }
vec3 rayOrigin = viewPos + normal * 0.02; vec3 rayWS = positionWS + normalWS * u_RayOffset;
vec3 rayEnd = rayOrigin + reflectDir * u_MaxDistance;
vec4 p0 = u_Projection * vec4(rayOrigin, 1.0); for (int i = 0; i < u_Steps; i++)
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)
{ {
o_Color = vec4(0.0); rayWS += reflectionWS * u_StepSize;
return;
}
float divisions = min(screenDist, float(u_Steps)); vec3 rayNDC = ComputeNDCWithZ(rayWS);
vec3 dV = (v1 - v0) / divisions; float rayDepth = rayNDC.z;
float dK = (k1 - k0) / divisions;
vec2 dS = sDelta / divisions;
vec3 curV = v0; vec2 raySS = rayNDC.xy * u_ScreenSize;
float curK = k0;
vec2 curS = s0;
vec2 hitUV = vec2(0.0); if (rayNDC.x < 0.0 || rayNDC.x > 1.0 || rayNDC.y < 0.0 || rayNDC.y > 1.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)
break; break;
float sampleDepth = texture(u_DepthTexture, curS).r; float sceneDepth = texture(u_DepthTexture, rayNDC.xy).r;
float surfDepth = LinearizeDepth(sampleDepth); float sceneDepthLinear = LinearizeDepth(sceneDepth);
float rayDepth = -curV.z / curK; 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; vec3 hitNormalWS = ReconstructNormalFromDepth(rayNDC.xy, sceneDepth);
found = true; if (dot(hitNormalWS, reflectionWS) > 0.0)
break; 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);
{
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);
} }

View File

@ -85,7 +85,6 @@ float MultiSampleDepth(sampler2DMS tex, vec2 tc)
void main() void main()
{ {
const float gamma = 2.2; const float gamma = 2.2;
const float pureWhite = 1.0;
// Tonemapping // Tonemapping
vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord); vec4 msColor = MultiSampleTexture(u_Texture, v_TexCoord);
@ -100,7 +99,7 @@ void main()
if (u_EnableSSR) if (u_EnableSSR)
{ {
vec4 ssrSample = texture(u_SSRTexture, v_TexCoord); 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; exposure = u_ManualExposure;
color *= exposure; color *= exposure;
vec3 mappedColor = color;
// Reinhard tonemapping operator. float luminance = dot(mappedColor, vec3(0.2126, 0.7152, 0.0722));
// see: "Photographic Tone Reproduction for Digital Images", eq. 4 if (luminance > 0.00001)
float luminance = dot(color, vec3(0.2126, 0.7152, 0.0722)); {
float mappedLuminance = (luminance * (1.0 + luminance / (pureWhite * pureWhite))) / (1.0 + luminance); float a = 2.51;
float b = 0.03;
// Scale color by ratio of average luminances. float c = 2.43;
vec3 mappedColor = (mappedLuminance / luminance) * color; 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) if (u_FogEnabled > 0.5)
{ {

View File

@ -81,15 +81,20 @@ namespace Prism
Ref<Texture2D> NormalTexture; Ref<Texture2D> NormalTexture;
// Metalness // Metalness
float Metalness = 0.8f; float Metalness = 0.2f;
float MetalnessTexToggle = 0.0f; float MetalnessTexToggle = 0.0f;
Ref<Texture2D> MetalnessTexture; Ref<Texture2D> MetalnessTexture;
// Roughness // Roughness
float Roughness = 0.1f; float Roughness = 1.0f;
float RoughnessTexToggle = 0.0f; float RoughnessTexToggle = 0.0f;
Ref<Texture2D> RoughnessTexture; Ref<Texture2D> RoughnessTexture;
// AO
float AO = 1.0f;
float AOTexToggle = 0.0f;
Ref<Texture2D> AOTexture;
bool IsDirty = true; bool IsDirty = true;
bool PreviewIsDirty = true; bool PreviewIsDirty = true;

View File

@ -123,7 +123,7 @@ namespace Prism
out << YAML::Key << "Roughness"; out << YAML::Key << "Roughness";
out << YAML::BeginMap; 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 << "TexToggle" << YAML::Value << material->RoughnessTexToggle;
out << YAML::Key << "Texture"; out << YAML::Key << "Texture";
@ -142,6 +142,29 @@ namespace Prism
} }
out << YAML::EndMap; 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; break;
} }
} }
@ -279,6 +302,32 @@ namespace Prism
} }
} }
// ==================== AO ====================
if (data["AO"])
{
auto aoNode = data["AO"];
material->AO = aoNode["Value"].as<float>();
material->AOTexToggle = aoNode["TexToggle"].as<float>();
if (aoNode["Texture"])
{
auto texNode = aoNode["Texture"];
UUID texHandle = 0;
std::string texPath;
if (texNode["AssetHandle"])
texHandle = texNode["AssetHandle"].as<uint64_t>();
if (texNode["AssetPath"])
texPath = texNode["AssetPath"].as<std::string>();
if (texHandle != 0 && AssetsManager::IsAssetHandleValid(texHandle))
material->AOTexture = AssetsManager::GetAsset<Texture2D>(texHandle);
else if (!texPath.empty())
material->AOTexture = Texture2D::Create(texPath);
else
material->AOTexture = nullptr;
}
}
return material; return material;
} }
} }

View File

@ -6,6 +6,7 @@
#define PRISM_AABB_H #define PRISM_AABB_H
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <limits>
namespace Prism namespace Prism
{ {
@ -23,6 +24,28 @@ namespace Prism
return Min.x <= Max.x && Min.y <= Max.y && Min.z <= Max.z; 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<float>::max());
glm::vec3 newMax(std::numeric_limits<float>::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);
}
}; };
} }

View File

@ -0,0 +1,64 @@
#ifndef PRISM_FRUSTUM_H
#define PRISM_FRUSTUM_H
#include <glm/glm.hpp>
#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

View File

@ -1,4 +1,4 @@
// //
// Created by Atdunbg on 2026/2/14. // Created by Atdunbg on 2026/2/14.
// //
@ -15,6 +15,7 @@
#include "Prism/Renderer/RHI/RHICommandBuffer.h" #include "Prism/Renderer/RHI/RHICommandBuffer.h"
#include "Prism/Renderer/SceneRenderer.h" #include "Prism/Renderer/SceneRenderer.h"
#include "Prism/Scene/Scene.h" #include "Prism/Scene/Scene.h"
#include "Prism/Utilities/StringUtils.h"
namespace Prism namespace Prism
{ {
@ -150,15 +151,18 @@ namespace Prism
matInst->Set("u_AlbedoColor", materialAsset->AlbedoColor); matInst->Set("u_AlbedoColor", materialAsset->AlbedoColor);
matInst->Set("u_Metalness", materialAsset->Metalness); matInst->Set("u_Metalness", materialAsset->Metalness);
matInst->Set("u_Roughness", materialAsset->Roughness); matInst->Set("u_Roughness", materialAsset->Roughness);
matInst->Set("u_AO", materialAsset->AO);
matInst->Set("u_AlbedoTexToggle", materialAsset->AlbedoTexToggle); matInst->Set("u_AlbedoTexToggle", materialAsset->AlbedoTexToggle);
matInst->Set("u_NormalTexToggle", materialAsset->NormalTexToggle); matInst->Set("u_NormalTexToggle", materialAsset->NormalTexToggle);
matInst->Set("u_MetalnessTexToggle", materialAsset->MetalnessTexToggle); matInst->Set("u_MetalnessTexToggle", materialAsset->MetalnessTexToggle);
matInst->Set("u_RoughnessTexToggle", materialAsset->RoughnessTexToggle); matInst->Set("u_RoughnessTexToggle", materialAsset->RoughnessTexToggle);
matInst->Set("u_AOTexToggle", materialAsset->AOTexToggle);
matInst->Set("u_AlbedoTexture", materialAsset->AlbedoTexture); matInst->Set("u_AlbedoTexture", materialAsset->AlbedoTexture);
matInst->Set("u_NormalTexture", materialAsset->NormalTexture); matInst->Set("u_NormalTexture", materialAsset->NormalTexture);
matInst->Set("u_MetalnessTexture", materialAsset->MetalnessTexture); matInst->Set("u_MetalnessTexture", materialAsset->MetalnessTexture);
matInst->Set("u_RoughnessTexture", materialAsset->RoughnessTexture); matInst->Set("u_RoughnessTexture", materialAsset->RoughnessTexture);
matInst->Set("u_AOTexture", materialAsset->AOTexture);
float aspect = (float)s_PreviewRenderPass->GetSpecification().TargetFramebuffer->GetWidth() / float aspect = (float)s_PreviewRenderPass->GetSpecification().TargetFramebuffer->GetWidth() /
(float)s_PreviewRenderPass->GetSpecification().TargetFramebuffer->GetHeight(); (float)s_PreviewRenderPass->GetSpecification().TargetFramebuffer->GetHeight();
@ -330,7 +334,6 @@ namespace Prism
if (ImGui::SliderFloat("Value##Roughness", &material->Roughness, 0.0f, 1.0f)) if (ImGui::SliderFloat("Value##Roughness", &material->Roughness, 0.0f, 1.0f))
{ {
// 自动保存
MarkDirty(); MarkDirty();
} }
@ -352,6 +355,35 @@ namespace Prism
ImGui::Unindent(); 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<Texture2D>& newTex)
{
material->AOTexture = newTex;
material->AOTexToggle = true;
MarkDirty();
});
ImGui::SameLine();
ImGui::Text("AO Texture");
ImGui::Unindent();
}
} }
} }
@ -411,6 +443,9 @@ namespace Prism
MarkDirty(); MarkDirty();
} }
m_CanvasOrigin = ImGui::GetCursorScreenPos();
m_CanvasSize = ImGui::GetContentRegionAvail();
ed::Begin("MaterialNodeEditor"); ed::Begin("MaterialNodeEditor");
if (m_FirstFrame) if (m_FirstFrame)
@ -518,10 +553,8 @@ namespace Prism
drawInputPin(AO, "AO", [&]() drawInputPin(AO, "AO", [&]()
{ {
ImGui::SetNextItemWidth(80); ImGui::SetNextItemWidth(80);
float ao = 1.0f; // 如果资产没有 AO 字段可以忽略 if (ImGui::SliderFloat("##ao", &m_Asset->AO, 0.0f, 1.0f))
if (ImGui::SliderFloat("##ao", &ao, 0.0f, 1.0f)) MarkDirty();
{
}
}); });
ImGui::EndGroup(); ImGui::EndGroup();
@ -550,10 +583,24 @@ namespace Prism
ImVec2 headerMin = ImGui::GetCursorScreenPos(); ImVec2 headerMin = ImGui::GetCursorScreenPos();
ImGui::BeginGroup(); ImGui::BeginGroup();
float headerMaxY = DrawNodeHeader("Texture2D", nodeWidth);
bool hasTexture = (textureHandle != 0);
std::string nodeTitle = "Texture2D";
if (hasTexture)
{
Ref<Texture2D> tex = AssetsManager::GetAsset<Texture2D>(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 previewSize = 80.0f;
float offsetX = (nodeWidth - previewSize) * 0.5f; float offsetX = (nodeWidth - previewSize) * 0.5f;
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offsetX); 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)); ImGui::Image((ImTextureID)(intptr_t)tex->GetRendererID(), ImVec2(previewSize, previewSize), ImVec2(0,1), ImVec2(1,0));
else else
ImGui::Dummy(ImVec2(previewSize, previewSize)); ImGui::Dummy(ImVec2(previewSize, previewSize));
if (ImGui::IsItemHovered() && tex)
m_PendingTooltip = Utils::GetFilename(tex->GetPath());
} }
else else
{ {
@ -705,19 +755,22 @@ namespace Prism
ed::Suspend(); ed::Suspend();
if (!m_PendingTooltip.empty())
{
ImGui::BeginTooltip();
ImGui::TextUnformatted(m_PendingTooltip.c_str());
ImGui::EndTooltip();
m_PendingTooltip.clear();
}
const ImGuiPayload* payload = ImGui::GetDragDropPayload(); const ImGuiPayload* payload = ImGui::GetDragDropPayload();
if (payload && payload->IsDataType("asset_payload")) if (payload && payload->IsDataType("asset_payload"))
{ {
AssetHandle handle = *(AssetHandle*)payload->Data; AssetHandle handle = *(AssetHandle*)payload->Data;
if (AssetsManager::IsAssetType(handle, AssetType::Texture)) if (AssetsManager::IsAssetType(handle, AssetType::Texture))
{ {
// 获取画布区域 ImGui::SetCursorScreenPos(m_CanvasOrigin);
ImVec2 canvasMin = ImGui::GetCursorScreenPos(); ImGui::InvisibleButton("##canvas_temp_drop", m_CanvasSize,
ImVec2 canvasSize = ImGui::GetContentRegionAvail();
ImGui::SetCursorScreenPos(canvasMin);
ImGui::InvisibleButton("##canvas_temp_drop", canvasSize,
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonLeft |
ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle); ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle);
if (ImGui::BeginDragDropTarget()) if (ImGui::BeginDragDropTarget())
@ -727,7 +780,6 @@ namespace Prism
AssetHandle dropHandle = *(AssetHandle*)dropPayload->Data; AssetHandle dropHandle = *(AssetHandle*)dropPayload->Data;
if (AssetsManager::IsAssetType(dropHandle, AssetType::Texture)) if (AssetsManager::IsAssetType(dropHandle, AssetType::Texture))
{ {
// 将鼠标位置转换为画布坐标,创建节点
ImVec2 mousePos = ImGui::GetMousePos(); ImVec2 mousePos = ImGui::GetMousePos();
ImVec2 canvasPos = ed::ScreenToCanvas(mousePos); ImVec2 canvasPos = ed::ScreenToCanvas(mousePos);
int newId = m_NextNodeId++; int newId = m_NextNodeId++;
@ -845,6 +897,9 @@ namespace Prism
m_Asset->RoughnessTexture = getTexture(GetLinkedTextureHandle(InputPinID(Roughness))); m_Asset->RoughnessTexture = getTexture(GetLinkedTextureHandle(InputPinID(Roughness)));
m_Asset->RoughnessTexToggle = m_Asset->RoughnessTexture ? 1.0f : 0.0f; 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(); MarkDirty();
} }
@ -875,6 +930,7 @@ namespace Prism
addTextureNode(getHandle(m_Asset->NormalTexture), Normal, 150.0f); addTextureNode(getHandle(m_Asset->NormalTexture), Normal, 150.0f);
addTextureNode(getHandle(m_Asset->MetalnessTexture), Metallic, 300.0f); addTextureNode(getHandle(m_Asset->MetalnessTexture), Metallic, 300.0f);
addTextureNode(getHandle(m_Asset->RoughnessTexture), Roughness, 450.0f); addTextureNode(getHandle(m_Asset->RoughnessTexture), Roughness, 450.0f);
addTextureNode(getHandle(m_Asset->AOTexture), AO, 600.0f);
m_FirstFrame = true; m_FirstFrame = true;
} }

View File

@ -75,6 +75,9 @@ namespace Prism
bool m_OpenAlbedoPicker = false; bool m_OpenAlbedoPicker = false;
ImVec2 m_AlbedoPickerPos; ImVec2 m_AlbedoPickerPos;
int m_ContextMenuNodeId = 0; int m_ContextMenuNodeId = 0;
ImVec2 m_CanvasOrigin = ImVec2(0, 0);
ImVec2 m_CanvasSize = ImVec2(0, 0);
std::string m_PendingTooltip;
// 引脚ID辅助函数 // 引脚ID辅助函数
static int InputPinID(int type) { return OUTPUT_NODE_ID * 100 + type; } static int InputPinID(int type) { return OUTPUT_NODE_ID * 100 + type; }

View File

@ -925,6 +925,7 @@ namespace Prism
{ {
meshComponent.UpdateMaterials(-1, true); meshComponent.UpdateMaterials(-1, true);
} }
UI::EndPropertyGrid(); UI::EndPropertyGrid();
UI::EndTreeNode(); UI::EndTreeNode();

View File

@ -357,6 +357,31 @@ namespace Prism
glDepthMask(enable ? GL_TRUE : GL_FALSE); 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, 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 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 uint32_t width, uint32_t height, uint32_t depth) const

View File

@ -77,6 +77,8 @@ namespace Prism
void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const override; void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const override;
void SetLineSmooth(bool enable) const override; void SetLineSmooth(bool enable) const override;
void SetDepthWrite(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; 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; int32_t GetUniformLocation(uint32_t program, const std::string& name) const override;

View File

@ -13,7 +13,7 @@ namespace Prism
AllocateStorage(); AllocateStorage();
m_MaterialFlags |= (uint32_t)MaterialFlag::DepthTest; m_MaterialFlags |= (uint32_t)MaterialFlag::DepthTest;
m_MaterialFlags |= (uint32_t)MaterialFlag::Blend; // m_MaterialFlags |= (uint32_t)MaterialFlag::Blend;
} }
Material::~Material() Material::~Material()
@ -155,7 +155,6 @@ namespace Prism
// 复制纹理列表(共享纹理引用) // 复制纹理列表(共享纹理引用)
newInstance->m_Textures = other->m_Textures; newInstance->m_Textures = other->m_Textures;
// 复制覆盖标记集合
newInstance->m_OverriddenValues = other->m_OverriddenValues; newInstance->m_OverriddenValues = other->m_OverriddenValues;
return newInstance; return newInstance;

View File

@ -212,7 +212,6 @@ namespace Prism
Buffer m_PSUniformStorageBuffer; Buffer m_PSUniformStorageBuffer;
std::vector<Ref<Texture>> m_Textures; std::vector<Ref<Texture>> m_Textures;
// TODO: This is temporary; come up with a proper system to track overrides
std::unordered_set<std::string> m_OverriddenValues; std::unordered_set<std::string> m_OverriddenValues;
}; };

View File

@ -460,6 +460,34 @@ namespace Prism
mi->Set("u_Metalness", metalness); mi->Set("u_Metalness", metalness);
mi->Set("u_MetalnessTexToggle", 0.0f); 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<Texture2D>(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("------------------------"); PM_MESH_LOG("------------------------");
} }

View File

@ -30,6 +30,7 @@ namespace Prism {
enum class BlitFilter { Nearest, Linear }; enum class BlitFilter { Nearest, Linear };
enum class DataType { UnsignedInt }; enum class DataType { UnsignedInt };
enum class BlitMask { Color, Depth, Stencila }; enum class BlitMask { Color, Depth, Stencila };
enum class BlendFactor { Zero, One, SrcAlpha, OneMinusSrcAlpha, DstAlpha, OneMinusDstAlpha };
enum class MemoryBarrierMask { enum class MemoryBarrierMask {
None = 0, None = 0,
@ -98,6 +99,8 @@ namespace Prism {
virtual void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const = 0; virtual void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const = 0;
virtual void SetLineSmooth(bool enable) const = 0; virtual void SetLineSmooth(bool enable) const = 0;
virtual void SetDepthWrite(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, virtual void CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture,
uint32_t srcLevel, uint32_t dstLevel, uint32_t srcLevel, uint32_t dstLevel,

View File

@ -18,6 +18,8 @@ namespace Prism
RendererAPIType RendererAPI::s_CurrentRendererAPI = RendererAPIType::OpenGL; RendererAPIType RendererAPI::s_CurrentRendererAPI = RendererAPIType::OpenGL;
Ref<RHIDevice> Renderer::s_Device; Ref<RHIDevice> Renderer::s_Device;
Ref<RHICommandBuffer> Renderer::s_CommandBuffer; Ref<RHICommandBuffer> Renderer::s_CommandBuffer;
uint32_t Renderer::s_DrawCallCount = 0;
uint32_t Renderer::s_LastFrameDrawCallCount = 0;
struct RendererData struct RendererData
@ -127,6 +129,8 @@ namespace Prism
void Renderer::WaitAndRender() void Renderer::WaitAndRender()
{ {
s_LastFrameDrawCallCount = s_DrawCallCount;
s_DrawCallCount = 0;
s_Data.m_CommandQueue.Execute(); s_Data.m_CommandQueue.Execute();
} }
@ -163,6 +167,7 @@ namespace Prism
void Renderer::SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform) void Renderer::SubmitQuad(Ref<MaterialInstance>& material, const glm::mat4& transform)
{ {
s_DrawCallCount++;
bool depthTest = true; bool depthTest = true;
bool cullFace = true; bool cullFace = true;
@ -185,6 +190,7 @@ namespace Prism
void Renderer::SubmitFullscreenQuad(Ref<MaterialInstance> material) void Renderer::SubmitFullscreenQuad(Ref<MaterialInstance> material)
{ {
s_DrawCallCount++;
bool depthTest = true; bool depthTest = true;
bool cullFace = true; bool cullFace = true;
if (material) if (material)
@ -203,6 +209,7 @@ namespace Prism
void Renderer::SubmitFullscreenQuad(const bool depthTest, const bool cullFace) void Renderer::SubmitFullscreenQuad(const bool depthTest, const bool cullFace)
{ {
s_DrawCallCount++;
s_Data.m_FullscreenQuadVertexBuffer->Bind(); s_Data.m_FullscreenQuadVertexBuffer->Bind();
s_Data.m_FullscreenQuadPipeline->Bind(); s_Data.m_FullscreenQuadPipeline->Bind();
@ -213,10 +220,6 @@ namespace Prism
void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials) void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
{ {
// auto material = overrideMaterial ? overrideMaterial : mesh->GetMaterialInstance();
// auto shader = material->GetShader();
// TODO: Sort this out
mesh->m_VertexBuffer->Bind(); mesh->m_VertexBuffer->Bind();
mesh->m_Pipeline->Bind(); mesh->m_Pipeline->Bind();
mesh->m_IndexBuffer->Bind(); mesh->m_IndexBuffer->Bind();
@ -224,8 +227,9 @@ namespace Prism
const auto& materials = mesh->GetMaterials(); const auto& materials = mesh->GetMaterials();
for (Submesh& submesh : mesh->m_Submeshes) for (Submesh& submesh : mesh->m_Submeshes)
{ {
// Material
auto material = overrideMaterials.empty() ? materials[submesh.MaterialIndex] : overrideMaterials[submesh.MaterialIndex]; auto material = overrideMaterials.empty() ? materials[submesh.MaterialIndex] : overrideMaterials[submesh.MaterialIndex];
s_DrawCallCount++;
auto shader = material->GetShader(); auto shader = material->GetShader();
material->Bind(); material->Bind();
@ -242,12 +246,10 @@ namespace Prism
auto cmd = s_CommandBuffer; auto cmd = s_CommandBuffer;
Submit([cmd, submesh, material]() { Submit([cmd, submesh, material]() {
// 状态设置通过 cmd
cmd->SetDepthTest(material->GetFlag(MaterialFlag::DepthTest)); 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->SetCullMode(material->GetFlag(MaterialFlag::TwoSided) ? CullMode::None : CullMode::Back);
// 绘制
cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0); cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0);
}); });
} }
@ -255,10 +257,6 @@ namespace Prism
void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial) void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const Ref<MaterialInstance>& overrideMaterial)
{ {
// auto material = overrideMaterial ? overrideMaterial : mesh->GetMaterialInstance();
// auto shader = material->GetShader();
// TODO: Sort this out
mesh->m_VertexBuffer->Bind(); mesh->m_VertexBuffer->Bind();
mesh->m_Pipeline->Bind(); mesh->m_Pipeline->Bind();
mesh->m_IndexBuffer->Bind(); mesh->m_IndexBuffer->Bind();
@ -266,8 +264,9 @@ namespace Prism
const auto& materials = mesh->GetMaterials(); const auto& materials = mesh->GetMaterials();
for (Submesh& submesh : mesh->m_Submeshes) for (Submesh& submesh : mesh->m_Submeshes)
{ {
// Material
auto material = overrideMaterial ? overrideMaterial : materials[submesh.MaterialIndex]; auto material = overrideMaterial ? overrideMaterial : materials[submesh.MaterialIndex];
s_DrawCallCount++;
auto shader = material->GetShader(); auto shader = material->GetShader();
material->Bind(); material->Bind();
@ -300,6 +299,7 @@ namespace Prism
for (Submesh& submesh : mesh->m_Submeshes) for (Submesh& submesh : mesh->m_Submeshes)
{ {
s_DrawCallCount++;
if (mesh->m_IsAnimated) if (mesh->m_IsAnimated)
{ {
const auto& boneTransform = mesh->GetBoneTransforms(); const auto& boneTransform = mesh->GetBoneTransforms();

View File

@ -70,11 +70,15 @@ namespace Prism
static void DrawAABB(const Ref<Mesh>& mesh,const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f)); static void DrawAABB(const Ref<Mesh>& mesh,const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f));
static void DispatchCompute(int x, int y, int z); static void DispatchCompute(int x, int y, int z);
static uint32_t GetDrawCallCount() { return s_LastFrameDrawCallCount; }
private: private:
static RenderCommandQueue& GetRenderCommandQueue(); static RenderCommandQueue& GetRenderCommandQueue();
static Ref<RHIDevice> s_Device; static Ref<RHIDevice> s_Device;
static Ref<RHICommandBuffer> s_CommandBuffer; static Ref<RHICommandBuffer> s_CommandBuffer;
static uint32_t s_DrawCallCount;
static uint32_t s_LastFrameDrawCallCount;
}; };
#if 0 #if 0

View File

@ -5,6 +5,7 @@
#include "Renderer3D.h" #include "Renderer3D.h"
#include "Prism/Core/Timer.h" #include "Prism/Core/Timer.h"
#include "Prism/Core/Math/Frustum.h"
#include "Prism/Scene/Scene.h" #include "Prism/Scene/Scene.h"
#include <limits> #include <limits>
@ -116,8 +117,10 @@ namespace Prism
Ref<Mesh> mesh; Ref<Mesh> mesh;
std::vector<Ref<MaterialInstance>> MaterialInstances; std::vector<Ref<MaterialInstance>> MaterialInstances;
glm::mat4 Transform; glm::mat4 Transform;
float DistanceFromCamera = 0.0f;
}; };
std::vector<DrawCommand> DrawList; std::vector<DrawCommand> DrawList;
std::vector<DrawCommand> TransparentDrawList;
std::vector<DrawCommand> SelectedMeshDrawList; std::vector<DrawCommand> SelectedMeshDrawList;
std::vector<DrawCommand> ColliderDrawList; std::vector<DrawCommand> ColliderDrawList;
std::vector<DrawCommand> ShadowPassDrawList; std::vector<DrawCommand> ShadowPassDrawList;
@ -145,7 +148,9 @@ namespace Prism
float Intensity = 1.0f; float Intensity = 1.0f;
float MaxDistance = 30.0f; float MaxDistance = 30.0f;
float Thickness = 0.5f; float Thickness = 0.5f;
int Steps = 64; float StepSize = 0.5f;
float RayOffset = 0.1f;
int Steps = 32;
float BlurRadius = 4.0f; float BlurRadius = 4.0f;
Ref<Shader> SSRShader; Ref<Shader> SSRShader;
@ -158,6 +163,13 @@ namespace Prism
SceneRendererOptions Options; SceneRendererOptions Options;
Frustum CameraFrustum;
uint32_t MeshesSubmitted = 0;
uint32_t MeshesCulled = 0;
uint32_t LastFrameMeshesSubmitted = 0;
uint32_t LastFrameMeshesCulled = 0;
Ref<TextureCube> BlackCubeTexture; Ref<TextureCube> BlackCubeTexture;
Ref<Texture2D> BlackTexture; Ref<Texture2D> BlackTexture;
}; };
@ -351,6 +363,9 @@ namespace Prism
s_Data.SceneData.SceneEnvironment = scene->m_Environment; s_Data.SceneData.SceneEnvironment = scene->m_Environment;
s_Data.SceneData.SceneEnvironmentIntensity = scene->m_EnvironmentIntensity; s_Data.SceneData.SceneEnvironmentIntensity = scene->m_EnvironmentIntensity;
s_Data.SceneData.SceneLightEnvironment = scene->m_LightEnvironment; 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>& renderPass) void Renderer3D::EndScene(Ref<RenderPass>& renderPass)
@ -360,14 +375,51 @@ namespace Prism
void Renderer3D::SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials) void Renderer3D::SubmitMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& 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 }); s_Data.ShadowPassDrawList.push_back({ mesh, overrideMaterials, transform });
} }
void Renderer3D::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials) void Renderer3D::SubmitSelectedMesh(const Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
{ {
s_Data.MeshesSubmitted++;
s_Data.SelectedMeshDrawList.push_back({ mesh, overrideMaterials, transform }); s_Data.SelectedMeshDrawList.push_back({ mesh, overrideMaterials, transform });
s_Data.ShadowPassDrawList.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.DrawList.clear();
s_Data.TransparentDrawList.clear();
s_Data.SelectedMeshDrawList.clear(); s_Data.SelectedMeshDrawList.clear();
s_Data.ColliderDrawList.clear(); s_Data.ColliderDrawList.clear();
s_Data.ShadowPassDrawList.clear(); s_Data.ShadowPassDrawList.clear();
s_Data.SceneData = {}; 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() void Renderer3D::AutoExposurePass()
@ -1321,15 +1378,21 @@ namespace Prism
const auto& sceneCamera = s_Data.SceneData.SceneCamera; const auto& sceneCamera = s_Data.SceneData.SceneCamera;
const auto cameraProjection = sceneCamera.Camera.GetProjectionMatrix(); 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_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->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_CameraNear", sceneCamera.Camera.GetNear());
s_Data.SSRData.SSRShader->SetFloat("u_CameraFar", sceneCamera.Camera.GetFar()); 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->SetInt("u_Steps", s_Data.SSRData.Steps);
s_Data.SSRData.SSRShader->SetFloat("u_MaxDistance", s_Data.SSRData.MaxDistance); 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_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); s_Data.SSRData.SSRShader->SetFloat("u_Intensity", s_Data.SSRData.Intensity);
Renderer::SubmitFullscreenQuad(nullptr); Renderer::SubmitFullscreenQuad(nullptr);
@ -1381,8 +1444,12 @@ namespace Prism
{ {
ImGui::Begin("Scene Renderer"); 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("Composite Pass time", s_Stats.CompositePass);
UI::Property("Shadow Pass time", s_Stats.ShadowPass); UI::Property("Shadow Pass time", s_Stats.ShadowPass);
UI::Property("AutoExposure Pass time", s_Stats.AutoExposurePass); 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("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::Property("Thickness", s_Data.SSRData.Thickness, 0.01f, 0.01f, 5.0f);
UI::PropertySlider("Steps", s_Data.SSRData.Steps, 1, 128); 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::Property("Blur Radius", s_Data.SSRData.BlurRadius, 0.1f, 0.0f, 10.0f);
} }
UI::EndPropertyGrid(); UI::EndPropertyGrid();

View File

@ -143,6 +143,9 @@ namespace Prism
MaterialInstances[i]->Set("u_Roughness", desc->Roughness); MaterialInstances[i]->Set("u_Roughness", desc->Roughness);
MaterialInstances[i]->Set("u_RoughnessTexToggle", desc->RoughnessTexToggle); MaterialInstances[i]->Set("u_RoughnessTexToggle", desc->RoughnessTexToggle);
MaterialInstances[i]->Set("u_RoughnessTexture", desc->RoughnessTexture); 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 }else
{ {
auto& baseMaterial = Mesh->GetMaterials(); auto& baseMaterial = Mesh->GetMaterials();
@ -158,6 +161,9 @@ namespace Prism
MaterialInstances[i]->Set("u_Roughness", baseMaterial[0]->Get<float>("u_Roughness")); MaterialInstances[i]->Set("u_Roughness", baseMaterial[0]->Get<float>("u_Roughness"));
MaterialInstances[i]->Set("u_RoughnessTexToggle", baseMaterial[i]->Get<float>("u_RoughnessTexToggle")); MaterialInstances[i]->Set("u_RoughnessTexToggle", baseMaterial[i]->Get<float>("u_RoughnessTexToggle"));
MaterialInstances[i]->Set("u_RoughnessTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_RoughnessTexture")); MaterialInstances[i]->Set("u_RoughnessTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_RoughnessTexture"));
MaterialInstances[i]->Set("u_AO", baseMaterial[i]->Get<float>("u_AO"));
MaterialInstances[i]->Set("u_AOTexToggle", baseMaterial[i]->Get<float>("u_AOTexToggle"));
MaterialInstances[i]->Set("u_AOTexture", baseMaterial[i]->TryGetResource<Texture2D>("u_AOTexture"));
} }
} }
}else }else
@ -177,6 +183,9 @@ namespace Prism
MaterialInstances[index]->Set("u_Roughness", desc->Roughness); MaterialInstances[index]->Set("u_Roughness", desc->Roughness);
MaterialInstances[index]->Set("u_RoughnessTexToggle", desc->RoughnessTexToggle); MaterialInstances[index]->Set("u_RoughnessTexToggle", desc->RoughnessTexToggle);
MaterialInstances[index]->Set("u_RoughnessTexture", desc->RoughnessTexture); 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 }else
{ {
auto& baseMaterial = Mesh->GetMaterials(); auto& baseMaterial = Mesh->GetMaterials();
@ -192,6 +201,9 @@ namespace Prism
MaterialInstances[index]->Set("u_Roughness", baseMaterial[0]->Get<float>("u_Roughness")); MaterialInstances[index]->Set("u_Roughness", baseMaterial[0]->Get<float>("u_Roughness"));
MaterialInstances[index]->Set("u_RoughnessTexToggle", baseMaterial[index]->Get<float>("u_RoughnessTexToggle")); MaterialInstances[index]->Set("u_RoughnessTexToggle", baseMaterial[index]->Get<float>("u_RoughnessTexToggle"));
MaterialInstances[index]->Set("u_RoughnessTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_RoughnessTexture")); MaterialInstances[index]->Set("u_RoughnessTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_RoughnessTexture"));
MaterialInstances[index]->Set("u_AO", baseMaterial[index]->Get<float>("u_AO"));
MaterialInstances[index]->Set("u_AOTexToggle", baseMaterial[index]->Get<float>("u_AOTexToggle"));
MaterialInstances[index]->Set("u_AOTexture", baseMaterial[index]->TryGetResource<Texture2D>("u_AOTexture"));
} }
} }