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);
}
}

View File

@ -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);

View File

@ -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);

View File

@ -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);
}

View File

@ -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)
{

View File

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

View File

@ -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<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;
}
}

View File

@ -6,6 +6,7 @@
#define PRISM_AABB_H
#include <glm/glm.hpp>
#include <limits>
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<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.
//
@ -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<Texture2D>& 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<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 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;
}

View File

@ -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; }

View File

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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -212,7 +212,6 @@ namespace Prism
Buffer m_PSUniformStorageBuffer;
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;
};

View File

@ -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<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("------------------------");
}

View File

@ -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,

View File

@ -18,6 +18,8 @@ namespace Prism
RendererAPIType RendererAPI::s_CurrentRendererAPI = RendererAPIType::OpenGL;
Ref<RHIDevice> Renderer::s_Device;
Ref<RHICommandBuffer> 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<MaterialInstance>& material, const glm::mat4& transform)
{
s_DrawCallCount++;
bool depthTest = true;
bool cullFace = true;
@ -185,6 +190,7 @@ namespace Prism
void Renderer::SubmitFullscreenQuad(Ref<MaterialInstance> 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>& 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_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>& 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_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();

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 DispatchCompute(int x, int y, int z);
static uint32_t GetDrawCallCount() { return s_LastFrameDrawCallCount; }
private:
static RenderCommandQueue& GetRenderCommandQueue();
static Ref<RHIDevice> s_Device;
static Ref<RHICommandBuffer> s_CommandBuffer;
static uint32_t s_DrawCallCount;
static uint32_t s_LastFrameDrawCallCount;
};
#if 0

View File

@ -5,6 +5,7 @@
#include "Renderer3D.h"
#include "Prism/Core/Timer.h"
#include "Prism/Core/Math/Frustum.h"
#include "Prism/Scene/Scene.h"
#include <limits>
@ -116,8 +117,10 @@ namespace Prism
Ref<Mesh> mesh;
std::vector<Ref<MaterialInstance>> MaterialInstances;
glm::mat4 Transform;
float DistanceFromCamera = 0.0f;
};
std::vector<DrawCommand> DrawList;
std::vector<DrawCommand> TransparentDrawList;
std::vector<DrawCommand> SelectedMeshDrawList;
std::vector<DrawCommand> ColliderDrawList;
std::vector<DrawCommand> 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<Shader> 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<TextureCube> BlackCubeTexture;
Ref<Texture2D> 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>& renderPass)
@ -360,14 +375,51 @@ namespace Prism
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 });
}
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.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();

View File

@ -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<float>("u_Roughness"));
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_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
@ -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<float>("u_Roughness"));
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_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"));
}
}