add vertexarray, move Sandbox::Demolayer code to EditorLayer

This commit is contained in:
2025-11-29 11:35:06 +08:00
parent 4c7b79ec8a
commit abdfdd1858
39 changed files with 63 additions and 773 deletions

View File

@ -0,0 +1,5 @@
//
// Created by sfd on 25-11-29.
//
#include "EditorLayer.h"

View File

@ -0,0 +1,16 @@
//
// Created by sfd on 25-11-29.
//
#ifndef EDITORLAYER_H
#define EDITORLAYER_H
class EditorLayer {
};
#endif //EDITORLAYER_H

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 MiB

After

Width:  |  Height:  |  Size: 4.5 MiB

View File

Before

Width:  |  Height:  |  Size: 3.6 MiB

After

Width:  |  Height:  |  Size: 3.6 MiB

View File

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 2.7 MiB

View File

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

View File

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 192 KiB

View File

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 256 KiB

View File

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 256 KiB

View File

Before

Width:  |  Height:  |  Size: 256 KiB

After

Width:  |  Height:  |  Size: 256 KiB

View File

Before

Width:  |  Height:  |  Size: 15 MiB

After

Width:  |  Height:  |  Size: 15 MiB

View File

Before

Width:  |  Height:  |  Size: 6.5 MiB

After

Width:  |  Height:  |  Size: 6.5 MiB

View File

Before

Width:  |  Height:  |  Size: 19 MiB

After

Width:  |  Height:  |  Size: 19 MiB

View File

Before

Width:  |  Height:  |  Size: 11 MiB

After

Width:  |  Height:  |  Size: 11 MiB

View File

Before

Width:  |  Height:  |  Size: 576 KiB

After

Width:  |  Height:  |  Size: 576 KiB

View File

Before

Width:  |  Height:  |  Size: 22 MiB

After

Width:  |  Height:  |  Size: 22 MiB

View File

@ -0,0 +1,5 @@
//
// Created by sfd on 25-11-29.
//
#include "OpenGLVertexArray.h"

View File

@ -0,0 +1,16 @@
//
// Created by sfd on 25-11-29.
//
#ifndef OPENGLVERTEXARRAY_H
#define OPENGLVERTEXARRAY_H
class OpenGLVertexArray {
};
#endif //OPENGLVERTEXARRAY_H

View File

@ -0,0 +1,5 @@
//
// Created by sfd on 25-11-29.
//
#include "VertexArray.h"

View File

@ -0,0 +1,16 @@
//
// Created by sfd on 25-11-29.
//
#ifndef VERTEXARRAY_H
#define VERTEXARRAY_H
class VertexArray {
};
#endif //VERTEXARRAY_H

View File

@ -1,658 +0,0 @@
//
// Created by sfd on 25-11-21.
//
#include "DemoLayer.h"
#include "Prism/Renderer/Renderer.h"
#include "Prism/Renderer/Shader.h"
namespace {
enum class PropertyFlag
{
None = 0, ColorProperty = 1
};
void Property(const std::string& name, bool& value)
{
ImGui::Text(name.c_str());
ImGui::NextColumn();
ImGui::PushItemWidth(-1);
std::string id = "##" + name;
ImGui::Checkbox(id.c_str(), &value);
ImGui::PopItemWidth();
ImGui::NextColumn();
}
void Property(const std::string& name, float& value, float min = -1.0f, float max = 1.0f, PropertyFlag flags = PropertyFlag::None)
{
ImGui::Text(name.c_str());
ImGui::NextColumn();
ImGui::PushItemWidth(-1);
std::string id = "##" + name;
ImGui::SliderFloat(id.c_str(), &value, min, max);
ImGui::PopItemWidth();
ImGui::NextColumn();
}
void Property(const std::string& name, glm::vec3& value, float min = -1.0f, float max = 1.0f, PropertyFlag flags = PropertyFlag::None)
{
ImGui::Text(name.c_str());
ImGui::NextColumn();
ImGui::PushItemWidth(-1);
std::string id = "##" + name;
if ((int)flags & (int)PropertyFlag::ColorProperty)
ImGui::ColorEdit3(id.c_str(), glm::value_ptr(value), ImGuiColorEditFlags_NoInputs);
else
ImGui::SliderFloat3(id.c_str(), glm::value_ptr(value), min, max);
ImGui::PopItemWidth();
ImGui::NextColumn();
}
void Property(const std::string& name, glm::vec3& value, PropertyFlag flags)
{
Property(name, value, -1.0f, 1.0f, flags);
}
void Property(const std::string& name, glm::vec4& value, float min = -1.0f, float max = 1.0f, PropertyFlag flags = PropertyFlag::None)
{
ImGui::Text(name.c_str());
ImGui::NextColumn();
ImGui::PushItemWidth(-1);
std::string id = "##" + name;
if ((int)flags & (int)PropertyFlag::ColorProperty)
ImGui::ColorEdit4(id.c_str(), glm::value_ptr(value), ImGuiColorEditFlags_NoInputs);
else
ImGui::SliderFloat4(id.c_str(), glm::value_ptr(value), min, max);
ImGui::PopItemWidth();
ImGui::NextColumn();
}
void Property(const std::string& name, glm::vec4& value, PropertyFlag flags)
{
Property(name, value, -1.0f, 1.0f, flags);
}
static void ImGuiShowHelpMarker(const char* desc)
{
ImGui::TextDisabled("(?)");
if (ImGui::IsItemHovered())
{
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(desc);
ImGui::PopTextWrapPos();
ImGui::EndTooltip();
}
}
}
DemoLayer::DemoLayer()
: m_ClearColor{ 0.1f, 0.1f, 0.1f, 1.0f }, m_Scene(Scene::Model),
m_Camera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 10000.0f))
{
}
DemoLayer::~DemoLayer()
{
}
void DemoLayer::OnAttach()
{
m_Framebuffer.reset(Prism::FrameBuffer::Create(1280, 720, Prism::FramebufferFormat::RGBA16F));
m_FinalPresentBuffer.reset(Prism::FrameBuffer::Create(1280, 720, Prism::FramebufferFormat::RGBA8));
m_QuadShader = Prism::Shader::Create("assets/shaders/quad.glsl");
m_HDRShader= Prism::Shader::Create("assets/shaders/hdr.glsl");
m_GridShader = Prism::Shader::Create("assets/shaders/Grid.glsl");
m_Mesh = Prism::CreateRef<Prism::Mesh>("assets/models/m1911/m1911.fbx");
m_MeshMaterial = Prism::CreateRef<Prism::MaterialInstance>(m_Mesh->GetMaterial());
m_SphereMesh = Prism::CreateRef<Prism::Mesh>("assets/models/Sphere1m.fbx");
m_PlaneMesh = Prism::CreateRef<Prism::Mesh>("assets/models/Plane1m.fbx");
m_GridShader = Prism::Shader::Create("assets/shaders/Grid.glsl");
m_GridMaterial = Prism::MaterialInstance::Create(Prism::Material::Create(m_GridShader));
m_GridMaterial->Set("u_Scale", m_GridScale);
m_GridMaterial->Set("u_Res", m_GridSize);
// Editor
m_CheckerboardTex.reset(Prism::Texture2D::Create("assets/editor/Checkerboard.tga"));
// Environment
m_EnvironmentCubeMap.reset(Prism::TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Radiance.tga"));
m_EnvironmentIrradiance.reset(Prism::TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Irradiance.tga"));
m_BRDFLUT.reset(Prism::Texture2D::Create("assets/textures/BRDF_LUT.tga"));
float x = -4.0f;
float roughness = 0.0f;
for (int i = 0; i < 8; i++)
{
Prism::Ref<Prism::MaterialInstance> mi = Prism::CreateRef<Prism::MaterialInstance>(m_SphereMesh->GetMaterial());
mi->Set("u_Metalness", 1.0f);
mi->Set("u_Roughness", roughness);
mi->Set("u_ModelMatrix", glm::translate(glm::mat4(1.0f), glm::vec3(x, 0.0f, 0.0f)));
x += 1.1f;
roughness += 0.15f;
m_MetalSphereMaterialInstances.push_back(mi);
}
x = -4.0f;
roughness = 0.0f;
for (int i = 0; i < 8; i++)
{
Prism::Ref<Prism::MaterialInstance> mi = Prism::CreateRef<Prism::MaterialInstance>(m_SphereMesh->GetMaterial());
mi->Set("u_Metalness", 0.0f);
mi->Set("u_Roughness", roughness);
mi->Set("u_ModelMatrix", translate(glm::mat4(1.0f), glm::vec3(x, 1.2f, 0.0f)));
x += 1.1f;
roughness += 0.15f;
m_DielectricSphereMaterialInstances.push_back(mi);
}
// Create Quad
x = -1;
float y = -1;
float width = 2, height = 2;
struct QuadVertex
{
glm::vec3 Position;
glm::vec2 TexCoord;
};
QuadVertex* data = new QuadVertex[4];
data[0].Position = glm::vec3(x, y, 0);
data[0].TexCoord = glm::vec2(0, 0);
data[1].Position = glm::vec3(x + width, y, 0);
data[1].TexCoord = glm::vec2(1, 0);
data[2].Position = glm::vec3(x + width, y + height, 0);
data[2].TexCoord = glm::vec2(1, 1);
data[3].Position = glm::vec3(x, y + height, 0);
data[3].TexCoord = glm::vec2(0, 1);
m_VertexBuffer.reset(Prism::VertexBuffer::Create());
m_VertexBuffer->SetData(data, 4 * sizeof(QuadVertex));
uint32_t* indices = new uint32_t[6] { 0, 1, 2, 2, 3, 0, };
m_IndexBuffer.reset(Prism::IndexBuffer::Create());
m_IndexBuffer->SetData(indices, 6 * sizeof(uint32_t));
m_Light.Direction = { -0.5f, -0.5f, 1.0f };
m_Light.Radiance = { 1.0f, 1.0f, 1.0f };
}
void DemoLayer::OnDetach()
{
}
void DemoLayer::OnUpdate(const Prism::TimeStep deltaTime)
{
{
// THINGS TO LOOK AT:
// - BRDF LUT
// - Cubemap mips and filtering
// - Tonemapping and proper HDR pipeline
using namespace Prism;
using namespace glm;
m_Camera.Update(deltaTime);
auto viewProjection = m_Camera.GetProjectionMatrix() * m_Camera.GetViewMatrix();
m_Framebuffer->Bind();
Renderer::Clear(m_ClearColor[0], m_ClearColor[1], m_ClearColor[2], m_ClearColor[3]);
m_QuadShader->Bind();
m_QuadShader->SetMat4("u_InverseVP", inverse(viewProjection));
m_EnvironmentCubeMap->Bind(0);
m_VertexBuffer->Bind();
m_IndexBuffer->Bind();
Renderer::DrawIndexed(m_IndexBuffer->GetCount(), false);
m_MeshMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color);
m_MeshMaterial->Set("u_Metalness", m_MetalnessInput.Value);
m_MeshMaterial->Set("u_Roughness", m_RoughnessInput.Value);
m_MeshMaterial->Set("u_ViewProjectionMatrix", viewProjection);
m_MeshMaterial->Set("u_ModelMatrix", scale(mat4(1.0f), vec3(m_MeshScale)));
m_MeshMaterial->Set("lights", m_Light);
m_MeshMaterial->Set("u_CameraPosition", m_Camera.GetPosition());
m_MeshMaterial->Set("u_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f);
m_MeshMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f);
m_MeshMaterial->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f);
m_MeshMaterial->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f);
m_MeshMaterial->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f);
m_MeshMaterial->Set("u_EnvMapRotation", m_EnvMapRotation);
m_MeshMaterial->Set("u_EnvRadianceTex", m_EnvironmentCubeMap);
m_MeshMaterial->Set("u_EnvIrradianceTex", m_EnvironmentIrradiance);
m_MeshMaterial->Set("u_BRDFLUTTexture", m_BRDFLUT);
m_SphereMesh->GetMaterial()->Set("u_AlbedoColor", m_AlbedoInput.Color);
m_SphereMesh->GetMaterial()->Set("u_Metalness", m_MetalnessInput.Value);
m_SphereMesh->GetMaterial()->Set("u_Roughness", m_RoughnessInput.Value);
m_SphereMesh->GetMaterial()->Set("u_ViewProjectionMatrix", viewProjection);
m_SphereMesh->GetMaterial()->Set("u_ModelMatrix", scale(mat4(1.0f), vec3(m_MeshScale)));
m_SphereMesh->GetMaterial()->Set("lights", m_Light);
m_SphereMesh->GetMaterial()->Set("u_CameraPosition", m_Camera.GetPosition());
m_SphereMesh->GetMaterial()->Set("u_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f);
m_SphereMesh->GetMaterial()->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f);
m_SphereMesh->GetMaterial()->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f);
m_SphereMesh->GetMaterial()->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f);
m_SphereMesh->GetMaterial()->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f);
m_SphereMesh->GetMaterial()->Set("u_EnvMapRotation", m_EnvMapRotation);
m_SphereMesh->GetMaterial()->Set("u_EnvRadianceTex", m_EnvironmentCubeMap);
m_SphereMesh->GetMaterial()->Set("u_EnvIrradianceTex", m_EnvironmentIrradiance);
m_SphereMesh->GetMaterial()->Set("u_BRDFLUTTexture", m_BRDFLUT);
if (m_AlbedoInput.TextureMap)
m_MeshMaterial->Set("u_AlbedoTexture", m_AlbedoInput.TextureMap);
if (m_NormalInput.TextureMap)
m_MeshMaterial->Set("u_NormalTexture", m_NormalInput.TextureMap);
if (m_MetalnessInput.TextureMap)
m_MeshMaterial->Set("u_MetalnessTexture", m_MetalnessInput.TextureMap);
if (m_RoughnessInput.TextureMap)
m_MeshMaterial->Set("u_RoughnessTexture", m_RoughnessInput.TextureMap);
if (m_Scene == Scene::Spheres)
{
// Metals
for (int i = 0; i < 8; i++)
{
m_SphereMesh->Render(deltaTime, glm::mat4(1.0f), m_MetalSphereMaterialInstances[i]);
/*
m_MetalSphereMaterialInstances[i]->Bind();
m_SphereMesh->Render(deltaTime, m_SimplePBRShader.get());
*/
}
// Dielectrics
for (int i = 0; i < 8; i++)
{
m_SphereMesh->Render(deltaTime, glm::mat4(1.0f), m_DielectricSphereMaterialInstances[i]);
/*
m_DielectricSphereMaterialInstances[i]->Bind();
m_SphereMesh->Render(deltaTime, m_SimplePBRShader.get());
*/
}
}
else if (m_Scene == Scene::Model)
{
if (m_Mesh)
{
m_Mesh->Render(deltaTime, scale(mat4(1.0f), vec3(m_MeshScale)), m_MeshMaterial);
}
}
m_GridMaterial->Set("u_MVP", viewProjection * glm::scale(glm::mat4(1.0f), glm::vec3(16.0f)));
m_PlaneMesh->Render(deltaTime, m_GridMaterial);
m_Framebuffer->Unbind();
m_FinalPresentBuffer->Bind();
m_HDRShader->Bind();
m_HDRShader->SetFloat("u_Exposure", m_Exposure);
m_Framebuffer->BindTexture();
m_VertexBuffer->Bind();
m_IndexBuffer->Bind();
Renderer::DrawIndexed(m_IndexBuffer->GetCount(), false);
m_FinalPresentBuffer->Unbind();
}
}
void DemoLayer::OnImGuiRender()
{
#define ENABLE_DOCKSPACE 1
#if ENABLE_DOCKSPACE
static bool p_open = true;
static bool opt_fullscreen = true;
static bool opt_padding = false;
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
// We are using the ImGuiWindowFlags_NoDocking flag to make the parent window not dockable into,
// because it would be confusing to have two docking targets within each others.
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
if (opt_fullscreen)
{
const ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
}
else
{
dockspace_flags &= ~ImGuiDockNodeFlags_PassthruCentralNode;
}
// When using ImGuiDockNodeFlags_PassthruCentralNode, DockSpace() will render our background
// and handle the pass-thru hole, so we ask Begin() to not render a background.
if (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode)
window_flags |= ImGuiWindowFlags_NoBackground;
// Important: note that we proceed even if Begin() returns false (aka window is collapsed).
// This is because we want to keep our DockSpace() active. If a DockSpace() is inactive,
// all active windows docked into it will lose their parent and become undocked.
// We cannot preserve the docking relationship between an active window and an inactive docking, otherwise
// any change of dockspace/settings would lead to windows being stuck in limbo and never being visible.
if (!opt_padding)
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
ImGui::Begin("DockSpace Demo", &p_open, window_flags);
if (!opt_padding)
ImGui::PopStyleVar();
if (opt_fullscreen)
ImGui::PopStyleVar(2);
// Submit the DockSpace
// REMINDER: THIS IS A DEMO FOR ADVANCED USAGE OF DockSpace()!
// MOST REGULAR APPLICATIONS WILL SIMPLY WANT TO CALL DockSpaceOverViewport(). READ COMMENTS ABOVE.
ImGuiIO& io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
{
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
}
// Show demo options and help
if (ImGui::BeginMenuBar())
{
if (ImGui::BeginMenu("Options"))
{
// Disabling fullscreen would allow the window to be moved to the front of other windows,
// which we can't undo at the moment without finer window depth/z control.
ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen);
ImGui::MenuItem("Padding", NULL, &opt_padding);
ImGui::Separator();
if (ImGui::MenuItem("Flag: NoDockingOverCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingOverCentralNode) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoDockingOverCentralNode; }
if (ImGui::MenuItem("Flag: NoDockingSplit", "", (dockspace_flags & ImGuiDockNodeFlags_NoDockingSplit) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoDockingSplit; }
if (ImGui::MenuItem("Flag: NoUndocking", "", (dockspace_flags & ImGuiDockNodeFlags_NoUndocking) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoUndocking; }
if (ImGui::MenuItem("Flag: NoResize", "", (dockspace_flags & ImGuiDockNodeFlags_NoResize) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_NoResize; }
if (ImGui::MenuItem("Flag: AutoHideTabBar", "", (dockspace_flags & ImGuiDockNodeFlags_AutoHideTabBar) != 0)) { dockspace_flags ^= ImGuiDockNodeFlags_AutoHideTabBar; }
if (ImGui::MenuItem("Flag: PassthruCentralNode", "", (dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0, opt_fullscreen)) { dockspace_flags ^= ImGuiDockNodeFlags_PassthruCentralNode; }
ImGui::Separator();
if (ImGui::MenuItem("Close", NULL, false, p_open != false))
p_open = false;
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Help"))
{
ImGui::TextUnformatted(
"This demo has nothing to do with enabling docking!" "\n"
"This demo only demonstrate the use of ImGui::DockSpace() which allows you to manually\ncreate a docking node _within_ another window." "\n"
"Most application can simply call ImGui::DockSpaceOverViewport() and be done with it.");
ImGui::Separator();
ImGui::TextUnformatted("When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n"
"- Drag from window title bar or their tab to dock/undock." "\n"
"- Drag from window menu button (upper-left button) to undock an entire node (all windows)." "\n"
"- Hold SHIFT to disable docking (if io.ConfigDockingWithShift == false, default)" "\n"
"- Hold SHIFT to enable docking (if io.ConfigDockingWithShift == true)");
ImGui::Separator();
ImGui::TextUnformatted("More details:"); ImGui::Bullet(); ImGui::SameLine(); ImGui::TextLinkOpenURL("Docking Wiki page", "https://github.com/ocornut/imgui/wiki/Docking");
ImGui::BulletText("Read comments in ShowExampleAppDockSpace()");
ImGui::EndMenu();
}
ImGuiShowHelpMarker(
"You can _always_ dock _any_ window into another by holding the SHIFT key while moving a window. Try it now!" "\n"
"This demo app has nothing to do with it!" "\n\n"
"This demo app only demonstrate the use of ImGui::DockSpace() which allows you to manually create a docking node _within_ another window. This is useful so you can decorate your main application window (e.g. with a menu bar)." "\n\n"
"ImGui::DockSpace() comes with one hard constraint: it needs to be submitted _before_ any window which may be docked into it. Therefore, if you use a dock spot as the central point of your application, you'll probably want it to be part of the very first window you are submitting to imgui every frame." "\n\n"
"(NB: because of this constraint, the implicit \"Debug\" window can not be docked into an explicit DockSpace() node, because that window is submitted as part of the NewFrame() call. An easy workaround is that you can create your own implicit \"Debug##2\" window after calling DockSpace() and leave it in the window stack for anyone to use.)"
);
ImGui::EndMenuBar();
}
ImGui::End();
#endif
// Editor Panel ------------------------------------------------------------------------------
ImGui::Begin("Model");
ImGui::RadioButton("Spheres", (int*)&m_Scene, (int)Scene::Spheres);
ImGui::SameLine();
ImGui::RadioButton("Model", (int*)&m_Scene, (int)Scene::Model);
ImGui::Begin("Environment");
ImGui::Columns(2);
ImGui::AlignTextToFramePadding();
Property("Light Direction", m_Light.Direction);
Property("Light Radiance", m_Light.Radiance, PropertyFlag::ColorProperty);
Property("Light Multiplier", m_LightMultiplier, 0.0f, 5.0f);
Property("Exposure", m_Exposure, 0.0f, 5.0f);
Property("Radiance Prefiltering", m_RadiancePrefilter);
Property("Env Map Rotation", m_EnvMapRotation, -360.0f, 360.0f);
ImGui::Columns(1);
ImGui::End();
ImGui::Separator();
{
ImGui::Text("Mesh");
std::string fullpath = m_Mesh ? m_Mesh->GetFilePath() : "None";
size_t found = fullpath.find_last_of("/\\");
std::string path = found != std::string::npos ? fullpath.substr(found + 1) : fullpath;
ImGui::Text(path.c_str()); ImGui::SameLine();
if (ImGui::Button("...##Mesh"))
{
std::string filename = Prism::Application::Get().OpenFile("");
if (filename != "")
m_Mesh.reset(new Prism::Mesh(filename));
}
}
ImGui::Separator();
// Textures ------------------------------------------------------------------------------
{
// Albedo
if (ImGui::CollapsingHeader("Albedo", nullptr, ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10));
ImGui::Image((ImTextureRef)(m_AlbedoInput.TextureMap ? m_AlbedoInput.TextureMap->GetRendererID() : m_CheckerboardTex->GetRendererID()), ImVec2(64, 64));
ImGui::PopStyleVar();
if (ImGui::IsItemHovered())
{
if (m_AlbedoInput.TextureMap)
{
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(m_AlbedoInput.TextureMap->GetPath().c_str());
ImGui::PopTextWrapPos();
ImGui::Image((ImTextureRef)m_AlbedoInput.TextureMap->GetRendererID(), ImVec2(384, 384));
ImGui::EndTooltip();
}
if (ImGui::IsItemClicked())
{
std::string filename = Prism::Application::Get().OpenFile("");
if (filename != "")
m_AlbedoInput.TextureMap.reset(Prism::Texture2D::Create(filename, m_AlbedoInput.SRGB));
}
}
ImGui::SameLine();
ImGui::BeginGroup();
ImGui::Checkbox("Use##AlbedoMap", &m_AlbedoInput.UseTexture);
if (ImGui::Checkbox("sRGB##AlbedoMap", &m_AlbedoInput.SRGB))
{
if (m_AlbedoInput.TextureMap)
m_AlbedoInput.TextureMap.reset(Prism::Texture2D::Create(m_AlbedoInput.TextureMap->GetPath(), m_AlbedoInput.SRGB));
}
ImGui::EndGroup();
ImGui::SameLine();
ImGui::ColorEdit3("Color##Albedo", glm::value_ptr(m_AlbedoInput.Color), ImGuiColorEditFlags_NoInputs);
}
}
{
// Normals
if (ImGui::CollapsingHeader("Normals", nullptr, ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10));
ImGui::Image((ImTextureRef)(m_NormalInput.TextureMap ? m_NormalInput.TextureMap->GetRendererID() : m_CheckerboardTex->GetRendererID()), ImVec2(64, 64));
ImGui::PopStyleVar();
if (ImGui::IsItemHovered())
{
if (m_NormalInput.TextureMap)
{
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(m_NormalInput.TextureMap->GetPath().c_str());
ImGui::PopTextWrapPos();
ImGui::Image((ImTextureRef)m_NormalInput.TextureMap->GetRendererID(), ImVec2(384, 384));
ImGui::EndTooltip();
}
if (ImGui::IsItemClicked())
{
std::string filename = Prism::Application::Get().OpenFile("");
if (filename != "")
m_NormalInput.TextureMap.reset(Prism::Texture2D::Create(filename));
}
}
ImGui::SameLine();
ImGui::Checkbox("Use##NormalMap", &m_NormalInput.UseTexture);
}
}
{
// Metalness
if (ImGui::CollapsingHeader("Metalness", nullptr, ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10));
ImGui::Image((ImTextureRef)(m_MetalnessInput.TextureMap ? m_MetalnessInput.TextureMap->GetRendererID() : m_CheckerboardTex->GetRendererID()), ImVec2(64, 64));
ImGui::PopStyleVar();
if (ImGui::IsItemHovered())
{
if (m_MetalnessInput.TextureMap)
{
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(m_MetalnessInput.TextureMap->GetPath().c_str());
ImGui::PopTextWrapPos();
ImGui::Image((ImTextureRef)m_MetalnessInput.TextureMap->GetRendererID(), ImVec2(384, 384));
ImGui::EndTooltip();
}
if (ImGui::IsItemClicked())
{
std::string filename = Prism::Application::Get().OpenFile("");
if (filename != "")
m_MetalnessInput.TextureMap.reset(Prism::Texture2D::Create(filename));
}
}
ImGui::SameLine();
ImGui::Checkbox("Use##MetalnessMap", &m_MetalnessInput.UseTexture);
ImGui::SameLine();
ImGui::SliderFloat("Value##MetalnessInput", &m_MetalnessInput.Value, 0.0f, 1.0f);
}
}
{
// Roughness
if (ImGui::CollapsingHeader("Roughness", nullptr, ImGuiTreeNodeFlags_DefaultOpen))
{
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(10, 10));
ImGui::Image((ImTextureRef)(m_RoughnessInput.TextureMap ? m_RoughnessInput.TextureMap->GetRendererID() : m_CheckerboardTex->GetRendererID()), ImVec2(64, 64));
ImGui::PopStyleVar();
if (ImGui::IsItemHovered())
{
if (m_RoughnessInput.TextureMap)
{
ImGui::BeginTooltip();
ImGui::PushTextWrapPos(ImGui::GetFontSize() * 35.0f);
ImGui::TextUnformatted(m_RoughnessInput.TextureMap->GetPath().c_str());
ImGui::PopTextWrapPos();
ImGui::Image((ImTextureRef)m_RoughnessInput.TextureMap->GetRendererID(), ImVec2(384, 384));
ImGui::EndTooltip();
}
if (ImGui::IsItemClicked())
{
std::string filename = Prism::Application::Get().OpenFile("");
if (filename != "")
m_RoughnessInput.TextureMap.reset(Prism::Texture2D::Create(filename));
}
}
ImGui::SameLine();
ImGui::Checkbox("Use##RoughnessMap", &m_RoughnessInput.UseTexture);
ImGui::SameLine();
ImGui::SliderFloat("Value##RoughnessInput", &m_RoughnessInput.Value, 0.0f, 1.0f);
}
}
if (ImGui::TreeNode("Shaders"))
{
auto& shaders = Prism::Shader::GetAllShaders();
for (auto& shader : shaders)
{
if (ImGui::TreeNode(shader->GetName().c_str()))
{
std::string buttonName = "Reload##" + shader->GetName();
if (ImGui::Button(buttonName.c_str()))
shader->Reload();
ImGui::TreePop();
}
}
ImGui::TreePop();
}
ImGui::Separator();
ImGui::End();
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::Begin("Viewport");
auto viewportSize = ImGui::GetContentRegionAvail();
m_Framebuffer->Resize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
m_FinalPresentBuffer->Resize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
m_Camera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
ImGui::Image((ImTextureRef)m_FinalPresentBuffer->GetColorAttachmentRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
ImGui::End();
ImGui::PopStyleVar();
ImGui::Begin("Log");
const auto& cameraPos = m_Camera.GetPosition();
ImGui::Text("cameraPos: (%.2f, %.2f, %.2f)", cameraPos.x, cameraPos.y, cameraPos.z);
const auto& Direct = m_Camera.GetForwardDirection();
ImGui::Text("forward Vec: (%.2f, %.2f, %.2f)", Direct.x, Direct.y, Direct.z);
const auto& distance = m_Camera.GetDistance();
ImGui::Text("distance: %.3f", distance);
ImGui::End();
if (m_Mesh)
m_Mesh->OnImGuiRender();
}
void DemoLayer::OnEvent(Prism::Event& e)
{
Layer::OnEvent(e);
}

View File

@ -1,115 +0,0 @@
//
// Created by sfd on 25-11-21.
//
#ifndef DEMOLAYER_H
#define DEMOLAYER_H
#include "Prism.h"
#include "Prism/Renderer/Camera.h"
#include "Prism/Renderer/FrameBuffer.h"
#include "Prism/Renderer/Material.h"
#include "Prism/Renderer/Mesh.h"
class DemoLayer : public Prism::Layer
{
public:
DemoLayer();
virtual ~DemoLayer();
virtual void OnAttach() override;
virtual void OnDetach() override;
virtual void OnUpdate(Prism::TimeStep deltaTime) override;
virtual void OnImGuiRender() override;
virtual void OnEvent(Prism::Event& e) override;
private:
float m_ClearColor[4];
Prism::Ref<Prism::Shader> m_QuadShader;
Prism::Ref<Prism::Shader> m_HDRShader;
Prism::Ref<Prism::Shader> m_GridShader;
Prism::Ref<Prism::Mesh> m_Mesh;
Prism::Ref<Prism::Mesh> m_SphereMesh, m_PlaneMesh;
Prism::Ref<Prism::Texture2D> m_BRDFLUT;
Prism::Ref<Prism::MaterialInstance> m_MeshMaterial;
Prism::Ref<Prism::MaterialInstance> m_GridMaterial;
std::vector<Prism::Ref<Prism::MaterialInstance>> m_MetalSphereMaterialInstances;
std::vector<Prism::Ref<Prism::MaterialInstance>> m_DielectricSphereMaterialInstances;
float m_GridScale = 16.025f, m_GridSize = 0.025f;
float m_MeshScale = 1.0f;
Prism::Ref<Prism::Shader> m_Shader;
Prism::Ref<Prism::Shader> m_PBRShader;
struct AlbedoInput
{
glm::vec3 Color = { 0.972f, 0.96f, 0.915f }; // Silver, from https://docs.unrealengine.com/en-us/Engine/Rendering/Materials/PhysicallyBased
Prism::Ref<Prism::Texture2D> TextureMap;
bool SRGB = true;
bool UseTexture = false;
};
AlbedoInput m_AlbedoInput;
struct NormalInput
{
Prism::Ref<Prism::Texture2D> TextureMap;
bool UseTexture = false;
};
NormalInput m_NormalInput;
struct MetalnessInput
{
float Value = 1.0f;
Prism::Ref<Prism::Texture2D> TextureMap;
bool UseTexture = false;
};
MetalnessInput m_MetalnessInput;
struct RoughnessInput
{
float Value = 0.5f;
Prism::Ref<Prism::Texture2D> TextureMap;
bool UseTexture = false;
};
RoughnessInput m_RoughnessInput;
Prism::Ref<Prism::FrameBuffer> m_Framebuffer, m_FinalPresentBuffer;
Prism::Ref<Prism::VertexBuffer> m_VertexBuffer;
Prism::Ref<Prism::IndexBuffer> m_IndexBuffer;
Prism::Ref<Prism::TextureCube> m_EnvironmentCubeMap, m_EnvironmentIrradiance;
Prism::Camera m_Camera;
struct Light
{
glm::vec3 Direction;
glm::vec3 Radiance;
};
Light m_Light;
float m_LightMultiplier = 0.3f;
// PBR params
float m_Exposure = 1.0f;
bool m_RadiancePrefilter = false;
float m_EnvMapRotation = 0.0f;
enum class Scene : uint32_t
{
Spheres = 0, Model = 1
};
Scene m_Scene;
// Editor resources
Prism::Ref<Prism::Texture2D> m_CheckerboardTex;
};
#endif //DEMOLAYER_H