add vertexarray, move Sandbox::Demolayer code to EditorLayer
This commit is contained in:
@ -1,7 +1,13 @@
|
||||
project(PrismEditor)
|
||||
|
||||
file(GLOB ASSETS assets)
|
||||
file(COPY ${ASSETS} DESTINATION ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
file(GLOB_RECURSE SRC_SOURCE ./**.cpp)
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SRC_SOURCE})
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE Prism-shared)
|
||||
|
||||
# Enable ImGui Docking space
|
||||
target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_DOCKSPACE)
|
||||
|
||||
@ -3,26 +3,27 @@
|
||||
//
|
||||
|
||||
|
||||
#include "Prism/Core/Application.h"
|
||||
#include "EditorLayer.h"
|
||||
#include "Prism.h"
|
||||
#include "Prism/Core/EntryPoint.h"
|
||||
#include "Prism/Core/ImGui/ImGuiLayer.h"
|
||||
|
||||
|
||||
class Editor : public Prism::Application
|
||||
{
|
||||
public:
|
||||
Editor()
|
||||
Editor(const Prism::ApplicationProps& props)
|
||||
: Application(props)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void OnInit() override
|
||||
{
|
||||
PushLayer(new Prism::ImGuiLayer("ImGui Layer"));
|
||||
PushLayer(new Prism::EditorLayer());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Prism::Application* Prism::CreateApplication()
|
||||
{
|
||||
return new Editor();
|
||||
return new Editor({"hello wrold", 1920, 1080});
|
||||
}
|
||||
|
||||
@ -3,3 +3,705 @@
|
||||
//
|
||||
|
||||
#include "EditorLayer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
EditorLayer::EditorLayer()
|
||||
: 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))
|
||||
{
|
||||
}
|
||||
|
||||
EditorLayer::~EditorLayer()
|
||||
{
|
||||
}
|
||||
|
||||
void EditorLayer::OnAttach()
|
||||
{
|
||||
m_Framebuffer.reset(FrameBuffer::Create(1280, 720, FramebufferFormat::RGBA16F));
|
||||
m_FinalPresentBuffer.reset(FrameBuffer::Create(1280, 720, FramebufferFormat::RGBA8));
|
||||
|
||||
m_QuadShader = Shader::Create("assets/shaders/quad.glsl");
|
||||
m_HDRShader = Shader::Create("assets/shaders/hdr.glsl");
|
||||
m_GridShader = Shader::Create("assets/shaders/Grid.glsl");
|
||||
|
||||
m_Mesh = CreateRef<Mesh>("assets/models/m1911/m1911.fbx");
|
||||
m_MeshMaterial = CreateRef<MaterialInstance>(m_Mesh->GetMaterial());
|
||||
|
||||
m_SphereMesh = CreateRef<Mesh>("assets/models/Sphere1m.fbx");
|
||||
m_PlaneMesh = CreateRef<Mesh>("assets/models/Plane1m.fbx");
|
||||
|
||||
m_GridShader = Shader::Create("assets/shaders/Grid.glsl");
|
||||
m_GridMaterial = MaterialInstance::Create(Material::Create(m_GridShader));
|
||||
m_GridMaterial->Set("u_Scale", m_GridScale);
|
||||
m_GridMaterial->Set("u_Res", m_GridSize);
|
||||
|
||||
// Editor
|
||||
m_CheckerboardTex.reset(Texture2D::Create("assets/editor/Checkerboard.tga"));
|
||||
|
||||
// Environment
|
||||
m_EnvironmentCubeMap.reset(
|
||||
TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Radiance.tga"));
|
||||
m_EnvironmentIrradiance.reset(
|
||||
TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Irradiance.tga"));
|
||||
m_BRDFLUT.reset(Texture2D::Create("assets/textures/BRDF_LUT.tga"));
|
||||
|
||||
|
||||
float x = -4.0f;
|
||||
float roughness = 0.0f;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
Ref<MaterialInstance> mi = CreateRef<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++)
|
||||
{
|
||||
Ref<MaterialInstance> mi = CreateRef<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;
|
||||
};
|
||||
|
||||
static float QuadVertex[] = {
|
||||
-1.0f, -1.0f, 0.0f, 0.0f, 0.0f,
|
||||
1.0f, -1.0f, 0.0f, 1.0f, 0.0f,
|
||||
1.0f, 1.0f, 0.0f, 1.0f, 1.0f,
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
static uint32_t QuadIndices[] = {
|
||||
0, 1, 2, 2, 3, 0
|
||||
};
|
||||
|
||||
m_FullscreenQuadVertexArray = VertexArray::Create();
|
||||
auto quadVB = VertexBuffer::Create(QuadVertex, sizeof(float) * sizeof(QuadVertex));
|
||||
quadVB->SetLayout({
|
||||
{ ShaderDataType::Float3, "a_Position" },
|
||||
{ ShaderDataType::Float2, "a_TexCoord" }
|
||||
});
|
||||
|
||||
auto quadIB = IndexBuffer::Create(QuadIndices, sizeof(QuadIndices) * sizeof(uint32_t));
|
||||
m_FullscreenQuadVertexArray->AddVertexBuffer(quadVB);
|
||||
m_FullscreenQuadVertexArray->SetIndexBuffer(quadIB);
|
||||
|
||||
|
||||
m_Light.Direction = {-0.5f, -0.5f, 1.0f};
|
||||
m_Light.Radiance = {1.0f, 1.0f, 1.0f};
|
||||
}
|
||||
|
||||
void EditorLayer::OnDetach()
|
||||
{
|
||||
}
|
||||
|
||||
void EditorLayer::OnUpdate(const 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();
|
||||
*/
|
||||
m_FullscreenQuadVertexArray->Bind();
|
||||
Renderer::DrawIndexed(m_FullscreenQuadVertexArray->GetIndexBuffer()->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();
|
||||
*/
|
||||
m_FullscreenQuadVertexArray->Bind();
|
||||
Renderer::DrawIndexed(m_FullscreenQuadVertexArray->GetIndexBuffer()->GetCount(), false);
|
||||
m_FinalPresentBuffer->Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
void EditorLayer::OnImGuiRender()
|
||||
{
|
||||
|
||||
#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 = Application::Get().OpenFile("");
|
||||
if (filename != "")
|
||||
m_Mesh.reset(new 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 = Application::Get().OpenFile("");
|
||||
if (filename != "")
|
||||
m_AlbedoInput.TextureMap.reset(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(
|
||||
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 = Application::Get().OpenFile("");
|
||||
if (filename != "")
|
||||
m_NormalInput.TextureMap.reset(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 = Application::Get().OpenFile("");
|
||||
if (filename != "")
|
||||
m_MetalnessInput.TextureMap.reset(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 = Application::Get().OpenFile("");
|
||||
if (filename != "")
|
||||
m_RoughnessInput.TextureMap.reset(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 = 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 EditorLayer::OnEvent(Event& e)
|
||||
{
|
||||
Layer::OnEvent(e);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,12 +5,114 @@
|
||||
#ifndef EDITORLAYER_H
|
||||
#define EDITORLAYER_H
|
||||
|
||||
#include "Prism.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class EditorLayer : public Layer
|
||||
{
|
||||
public:
|
||||
EditorLayer();
|
||||
virtual ~EditorLayer();
|
||||
|
||||
virtual void OnAttach() override;
|
||||
virtual void OnDetach() override;
|
||||
virtual void OnUpdate(TimeStep deltaTime) override;
|
||||
virtual void OnImGuiRender() override;
|
||||
virtual void OnEvent(Event& e) override;
|
||||
|
||||
private:
|
||||
float m_ClearColor[4];
|
||||
|
||||
Ref<FrameBuffer> m_Framebuffer, m_FinalPresentBuffer;
|
||||
|
||||
/*
|
||||
Ref<VertexBuffer> m_VertexBuffer;
|
||||
Ref<IndexBuffer> m_IndexBuffer;
|
||||
*/
|
||||
Ref<VertexArray> m_FullscreenQuadVertexArray;
|
||||
Ref<TextureCube> m_EnvironmentCubeMap, m_EnvironmentIrradiance;
|
||||
|
||||
Camera m_Camera;
|
||||
|
||||
Ref<Shader> m_QuadShader;
|
||||
Ref<Shader> m_HDRShader;
|
||||
Ref<Shader> m_GridShader;
|
||||
Ref<Mesh> m_Mesh;
|
||||
Ref<Mesh> m_SphereMesh, m_PlaneMesh;
|
||||
Ref<Texture2D> m_BRDFLUT;
|
||||
|
||||
Ref<MaterialInstance> m_MeshMaterial;
|
||||
Ref<MaterialInstance> m_GridMaterial;
|
||||
|
||||
std::vector<Ref<MaterialInstance>> m_MetalSphereMaterialInstances;
|
||||
std::vector<Ref<MaterialInstance>> m_DielectricSphereMaterialInstances;
|
||||
|
||||
float m_GridScale = 16.025f, m_GridSize = 0.025f;
|
||||
float m_MeshScale = 1.0f;
|
||||
|
||||
Ref<Shader> m_Shader;
|
||||
Ref<Shader> m_PBRShader;
|
||||
|
||||
|
||||
class EditorLayer {
|
||||
struct AlbedoInput
|
||||
{
|
||||
glm::vec3 Color = { 0.972f, 0.96f, 0.915f }; // Silver, from https://docs.unrealengine.com/en-us/Engine/Rendering/Materials/PhysicallyBased
|
||||
Ref<Texture2D> TextureMap;
|
||||
bool SRGB = true;
|
||||
bool UseTexture = false;
|
||||
};
|
||||
AlbedoInput m_AlbedoInput;
|
||||
|
||||
struct NormalInput
|
||||
{
|
||||
Ref<Texture2D> TextureMap;
|
||||
bool UseTexture = false;
|
||||
};
|
||||
NormalInput m_NormalInput;
|
||||
|
||||
struct MetalnessInput
|
||||
{
|
||||
float Value = 1.0f;
|
||||
Ref<Texture2D> TextureMap;
|
||||
bool UseTexture = false;
|
||||
};
|
||||
MetalnessInput m_MetalnessInput;
|
||||
|
||||
struct RoughnessInput
|
||||
{
|
||||
float Value = 0.5f;
|
||||
Ref<Texture2D> TextureMap;
|
||||
bool UseTexture = false;
|
||||
};
|
||||
RoughnessInput m_RoughnessInput;
|
||||
|
||||
|
||||
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
|
||||
Ref<Texture2D> m_CheckerboardTex;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif //EDITORLAYER_H
|
||||
|
||||
@ -7,13 +7,23 @@
|
||||
|
||||
|
||||
#include "Prism/Core/Application.h"
|
||||
#include "Prism/Core/Events/ApplicationEvent.h"
|
||||
#include "Prism/Core/TimeStep.h"
|
||||
#include "Prism/Core/Events/Event.h"
|
||||
#include "Prism/Core/Events/ApplicationEvent.h"
|
||||
#include "Prism/Core/Events/KeyEvent.h"
|
||||
#include "Prism/Core/Events/MouseEvent.h"
|
||||
|
||||
// ImGui
|
||||
#include "imgui.h"
|
||||
|
||||
#include "Prism/Renderer/Buffer.h"
|
||||
#include "Prism/Renderer/Renderer.h"
|
||||
#include "Prism/Renderer/Shader.h"
|
||||
#include "Prism/Renderer/Texture.h"
|
||||
#include "Prism/Renderer/FrameBuffer.h"
|
||||
#include "Prism/Renderer/Shader.h"
|
||||
#include "Prism/Renderer/Mesh.h"
|
||||
#include "Prism/Renderer/Camera.h"
|
||||
#include "Prism/Renderer/Material.h"
|
||||
|
||||
#endif //PRISM_H
|
||||
|
||||
@ -23,13 +23,13 @@ namespace Prism
|
||||
#endif
|
||||
|
||||
|
||||
// Application* Application::s_Instance = nullptr;
|
||||
Application* Application::s_Instance = nullptr;
|
||||
|
||||
Application::Application()
|
||||
Application::Application(const ApplicationProps& props)
|
||||
{
|
||||
s_Instance = this;
|
||||
|
||||
m_Window = std::unique_ptr<Window>(Window::Create());
|
||||
m_Window = std::unique_ptr<Window>(Window::Create(WindowProps{props.Name, props.Width, props.Height}));
|
||||
m_Window->SetEventCallback(BIND_EVENT_FN(OnEvent));
|
||||
|
||||
m_ImGuiLayer = new ImGuiLayer("ImGui Layer");
|
||||
@ -162,6 +162,11 @@ namespace Prism
|
||||
|
||||
}
|
||||
|
||||
Application& Application::Get()
|
||||
{
|
||||
return *s_Instance;
|
||||
}
|
||||
|
||||
void Application::PushLayer(Layer* layer)
|
||||
{
|
||||
m_LayerStack.PushLayer(layer);
|
||||
|
||||
@ -13,10 +13,16 @@
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
struct ApplicationProps
|
||||
{
|
||||
std::string Name;
|
||||
uint32_t Width, Height;
|
||||
};
|
||||
|
||||
class PRISM_API Application
|
||||
{
|
||||
public:
|
||||
Application();
|
||||
Application(const ApplicationProps& props = { "Prism Engine", 1920, 1080});
|
||||
virtual ~Application();
|
||||
|
||||
void Run();
|
||||
@ -33,7 +39,7 @@ namespace Prism
|
||||
|
||||
inline Window& GetWindow() { return *m_Window; }
|
||||
|
||||
inline static Application& Get() { return *s_Instance; }
|
||||
static Application& Get();
|
||||
|
||||
void PushLayer(Layer* layer);
|
||||
void PushOverlay(Layer* layer);
|
||||
@ -54,7 +60,7 @@ namespace Prism
|
||||
LayerStack m_LayerStack;
|
||||
ImGuiLayer* m_ImGuiLayer;
|
||||
|
||||
static inline Application* s_Instance = nullptr;
|
||||
static Application* s_Instance;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -36,6 +36,14 @@ namespace Prism
|
||||
Size = size;
|
||||
}
|
||||
|
||||
static Buffer Copy(void* data, uint32_t size)
|
||||
{
|
||||
Buffer buffer;
|
||||
buffer.Allocate(size);
|
||||
memcpy(buffer.Data, data, size);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void ZeroInitialize() const
|
||||
{
|
||||
if (Data)
|
||||
|
||||
@ -43,7 +43,7 @@ namespace Prism
|
||||
virtual void SetVSync(bool enable) = 0;
|
||||
virtual bool const IsVSync() const = 0;
|
||||
|
||||
static Window* Create(const WindowProps& props = WindowProps());
|
||||
static Window* Create(const WindowProps& props);
|
||||
|
||||
virtual void* GetNativeWindow() const = 0;
|
||||
};
|
||||
|
||||
@ -9,17 +9,41 @@
|
||||
namespace Prism
|
||||
{
|
||||
|
||||
static GLenum OpenGLUsage(VertexBufferUsage usage)
|
||||
{
|
||||
switch (usage)
|
||||
{
|
||||
case VertexBufferUsage::Static: return GL_STATIC_DRAW;
|
||||
case VertexBufferUsage::Dynamic: return GL_DYNAMIC_DRAW;
|
||||
}
|
||||
PM_CORE_ASSERT(false, "Unknown vertex buffer usage");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ******************************************
|
||||
// Vertex
|
||||
// ******************************************
|
||||
OpenGLVertexBuffer::OpenGLVertexBuffer(unsigned int size)
|
||||
: m_RendererID(0), m_Size(size)
|
||||
OpenGLVertexBuffer::OpenGLVertexBuffer(void* data, const uint32_t size, const VertexBufferUsage usage)
|
||||
: m_Size(size), m_Usage(usage)
|
||||
{
|
||||
m_LocalData = Buffer::Copy(data, size);
|
||||
|
||||
PM_RENDER_S({
|
||||
glGenBuffers(1, &self->m_RendererID);
|
||||
glCreateBuffers(1, &self->m_RendererID);
|
||||
glNamedBufferData(self->m_RendererID, self->m_Size, self->m_LocalData.Data, OpenGLUsage(self->m_Usage));
|
||||
});
|
||||
}
|
||||
|
||||
OpenGLVertexBuffer::OpenGLVertexBuffer(const uint32_t size, const VertexBufferUsage usage)
|
||||
: m_Size(size), m_Usage(usage)
|
||||
{
|
||||
PM_RENDER_S({
|
||||
glCreateBuffers(1, &self->m_RendererID);
|
||||
glNamedBufferData(self->m_RendererID, self->m_Size, nullptr, OpenGLUsage(self->m_Usage));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
OpenGLVertexBuffer::~OpenGLVertexBuffer()
|
||||
{
|
||||
PM_RENDER_S({
|
||||
@ -27,12 +51,12 @@ namespace Prism
|
||||
});
|
||||
}
|
||||
|
||||
void OpenGLVertexBuffer::SetData(void* buffer, unsigned int size, unsigned int offset)
|
||||
void OpenGLVertexBuffer::SetData(void* buffer, uint32_t size, uint32_t offset)
|
||||
{
|
||||
m_LocalData = Buffer::Copy(buffer, size);
|
||||
m_Size = size;
|
||||
PM_RENDER_S3(buffer, size, offset, {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, self->m_RendererID);
|
||||
glBufferData(GL_ARRAY_BUFFER, size, buffer, GL_STATIC_DRAW);
|
||||
PM_RENDER_S1(offset, {
|
||||
glNamedBufferSubData(self->m_RendererID, offset, self->m_Size, self->m_LocalData.Data);
|
||||
});
|
||||
}
|
||||
|
||||
@ -52,11 +76,14 @@ namespace Prism
|
||||
// ******************************************
|
||||
// IndexBuffer
|
||||
// ******************************************
|
||||
OpenGLIndexBuffer::OpenGLIndexBuffer(unsigned int size)
|
||||
: m_RendererID(0), m_Size(size)
|
||||
OpenGLIndexBuffer::OpenGLIndexBuffer(void* data, const uint32_t size)
|
||||
: m_Size(size)
|
||||
{
|
||||
m_LocalData = Buffer::Copy(data, size);
|
||||
|
||||
PM_RENDER_S({
|
||||
glGenBuffers(1, &self->m_RendererID);
|
||||
glCreateBuffers(1, &self->m_RendererID);
|
||||
glNamedBufferData(self->m_RendererID, self->m_Size, self->m_LocalData.Data, GL_STATIC_DRAW);
|
||||
});
|
||||
}
|
||||
|
||||
@ -67,12 +94,12 @@ namespace Prism
|
||||
});
|
||||
}
|
||||
|
||||
void OpenGLIndexBuffer::SetData(void* buffer, unsigned int size, unsigned int offset)
|
||||
void OpenGLIndexBuffer::SetData(void* data, uint32_t size, uint32_t offset)
|
||||
{
|
||||
m_LocalData = Buffer::Copy(data, size);
|
||||
m_Size = size;
|
||||
PM_RENDER_S3(buffer, size, offset, {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, self->m_RendererID);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, buffer, GL_STATIC_DRAW);
|
||||
PM_RENDER_S1(offset, {
|
||||
glNamedBufferSubData(self->m_RendererID, offset, self->m_Size, self->m_LocalData.Data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#define OPENGLBUFFER_H
|
||||
|
||||
#include "glad/glad.h"
|
||||
#include "Prism/Core/Buffer.h"
|
||||
#include "Prism/Renderer/Buffer.h"
|
||||
|
||||
namespace Prism
|
||||
@ -17,17 +18,26 @@ namespace Prism
|
||||
class OpenGLVertexBuffer : public VertexBuffer
|
||||
{
|
||||
public:
|
||||
OpenGLVertexBuffer(unsigned int size);
|
||||
OpenGLVertexBuffer(void* data, uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Static);
|
||||
OpenGLVertexBuffer(uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Dynamic);
|
||||
virtual ~OpenGLVertexBuffer();
|
||||
|
||||
virtual void SetData(void* buffer, unsigned int size, unsigned int offset = 0);
|
||||
virtual void SetData(void* buffer, uint32_t size, uint32_t offset = 0);
|
||||
virtual void Bind() const;
|
||||
|
||||
virtual unsigned int GetSize() const { return m_Size; }
|
||||
virtual const BufferLayout& GetLayout() const override { return m_Layout; }
|
||||
virtual void SetLayout(const BufferLayout& layout) override { m_Layout = layout; }
|
||||
|
||||
virtual uint32_t GetSize() const { return m_Size; }
|
||||
virtual RendererID GetRendererID() const { return m_RendererID; }
|
||||
private:
|
||||
RendererID m_RendererID;
|
||||
unsigned int m_Size;
|
||||
RendererID m_RendererID = 0;
|
||||
uint32_t m_Size;
|
||||
|
||||
VertexBufferUsage m_Usage;
|
||||
BufferLayout m_Layout;
|
||||
|
||||
Buffer m_LocalData;
|
||||
};
|
||||
|
||||
// ******************************************
|
||||
@ -37,19 +47,20 @@ namespace Prism
|
||||
class OpenGLIndexBuffer : public IndexBuffer
|
||||
{
|
||||
public:
|
||||
OpenGLIndexBuffer(unsigned int size);
|
||||
OpenGLIndexBuffer(void* data, uint32_t size);
|
||||
virtual ~OpenGLIndexBuffer();
|
||||
|
||||
virtual void SetData(void* buffer, unsigned int size, unsigned int offset = 0);
|
||||
virtual void SetData(void* data, uint32_t size, uint32_t offset = 0);
|
||||
virtual void Bind() const;
|
||||
|
||||
virtual uint32_t GetCount() const { return m_Size / sizeof(uint32_t); }
|
||||
|
||||
virtual unsigned int GetSize() const { return m_Size; }
|
||||
virtual uint32_t GetSize() const { return m_Size; }
|
||||
virtual RendererID GetRendererID() const { return m_RendererID; }
|
||||
private:
|
||||
RendererID m_RendererID;
|
||||
unsigned int m_Size;
|
||||
RendererID m_RendererID = 0;
|
||||
uint32_t m_Size;
|
||||
Buffer m_LocalData;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ namespace Prism
|
||||
{
|
||||
PM_CORE_TRACE("{0}", message);
|
||||
}
|
||||
|
||||
PM_CORE_ASSERT(0);
|
||||
}
|
||||
|
||||
void RendererAPI::Init()
|
||||
|
||||
@ -22,9 +22,20 @@ namespace Prism
|
||||
|
||||
}
|
||||
|
||||
Ref<OpenGLShader> OpenGLShader::CreateFromString(const std::string& source)
|
||||
{
|
||||
Ref<OpenGLShader> shader = std::make_shared<OpenGLShader>();
|
||||
shader->Load(source);
|
||||
return shader;
|
||||
}
|
||||
|
||||
void OpenGLShader::Reload()
|
||||
{
|
||||
const std::string source = ReadShaderFromFile(m_AssetPath);
|
||||
Load(source);
|
||||
}
|
||||
void OpenGLShader::Load(const std::string& source)
|
||||
{
|
||||
m_ShaderSource = PreProcess(source);
|
||||
Parse();
|
||||
|
||||
@ -142,6 +153,7 @@ namespace Prism
|
||||
return m_Name;
|
||||
}
|
||||
|
||||
|
||||
std::string OpenGLShader::ReadShaderFromFile(const std::string& filepath) const
|
||||
{
|
||||
std::string result;
|
||||
|
||||
@ -15,7 +15,9 @@ namespace Prism
|
||||
class OpenGLShader : public Shader
|
||||
{
|
||||
public:
|
||||
OpenGLShader() = default;
|
||||
OpenGLShader(const std::string& filepath);
|
||||
static Ref<OpenGLShader> CreateFromString(const std::string& source);
|
||||
|
||||
virtual void Reload();
|
||||
virtual void Bind() override;
|
||||
@ -35,6 +37,8 @@ namespace Prism
|
||||
|
||||
|
||||
private:
|
||||
void Load(const std::string& source);
|
||||
|
||||
std::string ReadShaderFromFile(const std::string& filepath) const;
|
||||
std::unordered_map<GLenum, std::string> PreProcess(const std::string& source);
|
||||
void Parse();
|
||||
|
||||
@ -3,3 +3,101 @@
|
||||
//
|
||||
|
||||
#include "OpenGLVertexArray.h"
|
||||
#include "glad/glad.h"
|
||||
#include "Prism/Renderer/Renderer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
static GLenum ShaderDataTypeToOpenGLBaseType(ShaderDataType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case Prism::ShaderDataType::Float: return GL_FLOAT;
|
||||
case Prism::ShaderDataType::Float2: return GL_FLOAT;
|
||||
case Prism::ShaderDataType::Float3: return GL_FLOAT;
|
||||
case Prism::ShaderDataType::Float4: return GL_FLOAT;
|
||||
case Prism::ShaderDataType::Mat3: return GL_FLOAT;
|
||||
case Prism::ShaderDataType::Mat4: return GL_FLOAT;
|
||||
case Prism::ShaderDataType::Int: return GL_INT;
|
||||
case Prism::ShaderDataType::Int2: return GL_INT;
|
||||
case Prism::ShaderDataType::Int3: return GL_INT;
|
||||
case Prism::ShaderDataType::Int4: return GL_INT;
|
||||
case Prism::ShaderDataType::Bool: return GL_BOOL;
|
||||
}
|
||||
|
||||
PM_CORE_ASSERT(false, "Unknown ShaderDataType!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
OpenGLVertexArray::OpenGLVertexArray()
|
||||
{
|
||||
PM_RENDER_S({
|
||||
glCreateVertexArrays(1, &self->m_RendererID);
|
||||
});
|
||||
}
|
||||
|
||||
OpenGLVertexArray::~OpenGLVertexArray()
|
||||
{
|
||||
PM_RENDER_S({
|
||||
glDeleteVertexArrays(1, &self->m_RendererID);
|
||||
});
|
||||
}
|
||||
|
||||
void OpenGLVertexArray::Bind() const
|
||||
{
|
||||
PM_RENDER_S({
|
||||
glBindVertexArray(self->m_RendererID);
|
||||
});
|
||||
}
|
||||
|
||||
void OpenGLVertexArray::Unbind() const
|
||||
{
|
||||
PM_RENDER_S({
|
||||
glBindVertexArray(0);
|
||||
});
|
||||
}
|
||||
|
||||
void OpenGLVertexArray::AddVertexBuffer(const Ref<VertexBuffer>& vertexBuffer)
|
||||
{
|
||||
PM_CORE_ASSERT(vertexBuffer->GetLayout().GetElements().size(), "Vertex Buffer has no layout!");
|
||||
|
||||
Bind();
|
||||
vertexBuffer->Bind();
|
||||
|
||||
PM_RENDER_S1(vertexBuffer, {
|
||||
const auto& layout = vertexBuffer->GetLayout();
|
||||
for (const auto& element : layout)
|
||||
{
|
||||
auto glBaseType = ShaderDataTypeToOpenGLBaseType(element.Type);
|
||||
glEnableVertexAttribArray(self->m_VertexBufferIndex);
|
||||
if (glBaseType == GL_INT)
|
||||
{
|
||||
glVertexAttribIPointer(self->m_VertexBufferIndex,
|
||||
element.GetComponentCount(),
|
||||
glBaseType,
|
||||
layout.GetStride(),
|
||||
(const void*)(intptr_t)element.Offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
glVertexAttribPointer(self->m_VertexBufferIndex,
|
||||
element.GetComponentCount(),
|
||||
glBaseType,
|
||||
element.Normalized ? GL_TRUE : GL_FALSE,
|
||||
layout.GetStride(),
|
||||
(const void*)(intptr_t)element.Offset);
|
||||
}
|
||||
self->m_VertexBufferIndex++;
|
||||
}
|
||||
});
|
||||
m_VertexBuffers.push_back(vertexBuffer);
|
||||
}
|
||||
|
||||
void OpenGLVertexArray::SetIndexBuffer(const Ref<IndexBuffer>& indexBuffer)
|
||||
{
|
||||
Bind();
|
||||
indexBuffer->Bind();
|
||||
|
||||
m_IndexBuffer = indexBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,12 +5,31 @@
|
||||
#ifndef OPENGLVERTEXARRAY_H
|
||||
#define OPENGLVERTEXARRAY_H
|
||||
|
||||
#include "Prism/Renderer/VertexArray.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class OpenGLVertexArray : public VertexArray
|
||||
{
|
||||
public:
|
||||
OpenGLVertexArray();
|
||||
virtual ~OpenGLVertexArray();
|
||||
|
||||
class OpenGLVertexArray {
|
||||
virtual void Bind() const override;
|
||||
virtual void Unbind() const override;
|
||||
|
||||
};
|
||||
virtual void AddVertexBuffer(const Ref<VertexBuffer>& vertexBuffer) override;
|
||||
virtual void SetIndexBuffer(const Ref<IndexBuffer>& indexBuffer) override;
|
||||
|
||||
virtual const std::vector<Ref<VertexBuffer>>& GetVertexBuffers() const { return m_VertexBuffers; }
|
||||
virtual const Ref<IndexBuffer>& GetIndexBuffer() const { return m_IndexBuffer; }
|
||||
private:
|
||||
RendererID m_RendererID = 0;
|
||||
uint32_t m_VertexBufferIndex = 0;
|
||||
std::vector<std::shared_ptr<VertexBuffer>> m_VertexBuffers;
|
||||
std::shared_ptr<IndexBuffer> m_IndexBuffer;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //OPENGLVERTEXARRAY_H
|
||||
|
||||
@ -62,7 +62,7 @@ namespace Prism
|
||||
{
|
||||
int x, y;
|
||||
glfwGetWindowPos(m_Window, &x, &y);
|
||||
return { x, y };
|
||||
return { (float)x, (float)y };
|
||||
}
|
||||
|
||||
void WindowsWindow::Init(const WindowProps& props)
|
||||
|
||||
@ -8,24 +8,39 @@
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
VertexBuffer* VertexBuffer::Create(unsigned int size)
|
||||
Ref<VertexBuffer> VertexBuffer::Create(void* data, uint32_t size, VertexBufferUsage usage)
|
||||
{
|
||||
switch (RendererAPI::Current())
|
||||
{
|
||||
case RendererAPIType::None: return nullptr;
|
||||
case RendererAPIType::OpenGL: return new OpenGLVertexBuffer(size);
|
||||
case RendererAPIType::OpenGL: return CreateRef<OpenGLVertexBuffer>(data, size, usage);
|
||||
}
|
||||
PM_CORE_ASSERT(false, "Unknown RendererAPI");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
IndexBuffer* IndexBuffer::Create(const unsigned int size)
|
||||
Ref<VertexBuffer> VertexBuffer::Create(uint32_t size, VertexBufferUsage usage)
|
||||
{
|
||||
switch (RendererAPI::Current())
|
||||
{
|
||||
case RendererAPIType::None: return nullptr;
|
||||
case RendererAPIType::OpenGL: return new OpenGLIndexBuffer(size);
|
||||
case RendererAPIType::OpenGL: return CreateRef<OpenGLVertexBuffer>(size, usage);
|
||||
}
|
||||
PM_CORE_ASSERT(false, "Unknown RendererAPI");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ref<IndexBuffer> IndexBuffer::Create(void* data, uint32_t size)
|
||||
{
|
||||
switch (RendererAPI::Current())
|
||||
{
|
||||
case RendererAPIType::None: return nullptr;
|
||||
case RendererAPIType::OpenGL: return CreateRef<OpenGLIndexBuffer>(data, size);
|
||||
}
|
||||
PM_CORE_ASSERT(false, "Unknown RendererAPI");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,18 +9,130 @@
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
enum class ShaderDataType
|
||||
{
|
||||
None = 0, Float, Float2, Float3, Float4, Mat3, Mat4, Int, Int2, Int3, Int4, Bool
|
||||
};
|
||||
|
||||
static uint32_t ShaderDataTypeSize(ShaderDataType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case ShaderDataType::Float: return 4;
|
||||
case ShaderDataType::Float2: return 4 * 2;
|
||||
case ShaderDataType::Float3: return 4 * 3;
|
||||
case ShaderDataType::Float4: return 4 * 4;
|
||||
case ShaderDataType::Mat3: return 4 * 3 * 3;
|
||||
case ShaderDataType::Mat4: return 4 * 4 * 4;
|
||||
case ShaderDataType::Int: return 4;
|
||||
case ShaderDataType::Int2: return 4 * 2;
|
||||
case ShaderDataType::Int3: return 4 * 3;
|
||||
case ShaderDataType::Int4: return 4 * 4;
|
||||
case ShaderDataType::Bool: return 1;
|
||||
}
|
||||
|
||||
PM_CORE_ASSERT(false, "Unknown ShaderDataType!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct BufferElement
|
||||
{
|
||||
std::string Name;
|
||||
ShaderDataType Type;
|
||||
uint32_t Size;
|
||||
uint32_t Offset;
|
||||
bool Normalized;
|
||||
|
||||
BufferElement() = default;
|
||||
|
||||
BufferElement(ShaderDataType type, const std::string& name, bool normalized = false)
|
||||
: Name(name), Type(type), Size(ShaderDataTypeSize(type)), Offset(0), Normalized(normalized)
|
||||
{
|
||||
}
|
||||
|
||||
uint32_t GetComponentCount() const
|
||||
{
|
||||
switch (Type)
|
||||
{
|
||||
case ShaderDataType::Float: return 1;
|
||||
case ShaderDataType::Float2: return 2;
|
||||
case ShaderDataType::Float3: return 3;
|
||||
case ShaderDataType::Float4: return 4;
|
||||
case ShaderDataType::Mat3: return 3 * 3;
|
||||
case ShaderDataType::Mat4: return 4 * 4;
|
||||
case ShaderDataType::Int: return 1;
|
||||
case ShaderDataType::Int2: return 2;
|
||||
case ShaderDataType::Int3: return 3;
|
||||
case ShaderDataType::Int4: return 4;
|
||||
case ShaderDataType::Bool: return 1;
|
||||
}
|
||||
|
||||
PM_CORE_ASSERT(false, "Unknown ShaderDataType!");
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class BufferLayout
|
||||
{
|
||||
public:
|
||||
BufferLayout() {}
|
||||
|
||||
BufferLayout(const std::initializer_list<BufferElement>& elements)
|
||||
: m_Elements(elements)
|
||||
{
|
||||
CalculateOffsetsAndStride();
|
||||
}
|
||||
|
||||
inline uint32_t GetStride() const { return m_Stride; }
|
||||
inline const std::vector<BufferElement>& GetElements() const { return m_Elements; }
|
||||
|
||||
std::vector<BufferElement>::iterator begin() { return m_Elements.begin(); }
|
||||
std::vector<BufferElement>::iterator end() { return m_Elements.end(); }
|
||||
std::vector<BufferElement>::const_iterator begin() const { return m_Elements.begin(); }
|
||||
std::vector<BufferElement>::const_iterator end() const { return m_Elements.end(); }
|
||||
private:
|
||||
void CalculateOffsetsAndStride()
|
||||
{
|
||||
uint32_t offset = 0;
|
||||
m_Stride = 0;
|
||||
for (auto& element : m_Elements)
|
||||
{
|
||||
element.Offset = offset;
|
||||
offset += element.Size;
|
||||
m_Stride += element.Size;
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<BufferElement> m_Elements;
|
||||
uint32_t m_Stride = 0;
|
||||
};
|
||||
|
||||
|
||||
enum class VertexBufferUsage
|
||||
{
|
||||
None = 0, Static = 1, Dynamic = 2
|
||||
};
|
||||
|
||||
|
||||
class PRISM_API VertexBuffer
|
||||
{
|
||||
public:
|
||||
virtual ~VertexBuffer() {}
|
||||
|
||||
static Ref<VertexBuffer> Create(void* data, uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Static);
|
||||
static Ref<VertexBuffer> Create(uint32_t size, VertexBufferUsage usage = VertexBufferUsage::Dynamic);
|
||||
|
||||
virtual void SetData(void* buffer, uint32_t size, uint32_t offset = 0) = 0;
|
||||
virtual void Bind() const = 0;
|
||||
|
||||
virtual const BufferLayout& GetLayout() const = 0;
|
||||
virtual void SetLayout(const BufferLayout& layout) = 0;
|
||||
|
||||
virtual unsigned int GetSize() const = 0;
|
||||
virtual RendererID GetRendererID() const = 0;
|
||||
|
||||
static VertexBuffer* Create(unsigned int size = 0);
|
||||
};
|
||||
|
||||
|
||||
@ -29,14 +141,15 @@ namespace Prism
|
||||
public:
|
||||
virtual ~IndexBuffer() {}
|
||||
|
||||
virtual void SetData(void* buffer, unsigned int size, unsigned int offset = 0) = 0;
|
||||
static Ref<IndexBuffer> Create(void* data, uint32_t size = 0);
|
||||
|
||||
virtual void SetData(void* buffer, uint32_t size, uint32_t offset = 0) = 0;
|
||||
virtual void Bind() const = 0;
|
||||
|
||||
virtual uint32_t GetCount() const = 0;
|
||||
virtual unsigned int GetSize() const = 0;
|
||||
virtual RendererID GetRendererID() const = 0;
|
||||
|
||||
static IndexBuffer* Create(unsigned int size = 0);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -223,6 +223,35 @@ namespace Prism
|
||||
}
|
||||
}
|
||||
|
||||
m_VertexArray = VertexArray::Create();
|
||||
if (m_IsAnimated)
|
||||
{
|
||||
auto vb = VertexBuffer::Create(m_AnimatedVertices.data(), (uint32_t)m_AnimatedVertices.size() * sizeof(AnimatedVertex));
|
||||
vb->SetLayout({
|
||||
{ ShaderDataType::Float3, "a_Position" },
|
||||
{ ShaderDataType::Float3, "a_Normal" },
|
||||
{ ShaderDataType::Float3, "a_Tangent" },
|
||||
{ ShaderDataType::Float3, "a_Binormal" },
|
||||
{ ShaderDataType::Float2, "a_TexCoord" },
|
||||
{ ShaderDataType::Int4, "a_BoneIDs" },
|
||||
{ ShaderDataType::Float4, "a_BoneWeights" },
|
||||
});
|
||||
m_VertexArray->AddVertexBuffer(vb);
|
||||
}else
|
||||
{
|
||||
auto vb = VertexBuffer::Create(m_StaticVertices.data(), (uint32_t)m_StaticVertices.size() * sizeof(Vertex));
|
||||
vb->SetLayout({
|
||||
{ ShaderDataType::Float3, "a_Position" },
|
||||
{ ShaderDataType::Float3, "a_Normal" },
|
||||
{ ShaderDataType::Float3, "a_Tangent" },
|
||||
{ ShaderDataType::Float3, "a_Binormal" },
|
||||
{ ShaderDataType::Float2, "a_TexCoord" },
|
||||
});
|
||||
m_VertexArray->AddVertexBuffer(vb);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
m_VertexBuffer.reset(VertexBuffer::Create());
|
||||
if (m_IsAnimated)
|
||||
m_VertexBuffer->SetData(m_AnimatedVertices.data(), m_AnimatedVertices.size() * sizeof(AnimatedVertex));
|
||||
@ -231,7 +260,10 @@ namespace Prism
|
||||
|
||||
m_IndexBuffer.reset(IndexBuffer::Create());
|
||||
m_IndexBuffer->SetData(m_Indices.data(), m_Indices.size() * sizeof(Index));
|
||||
*/
|
||||
|
||||
auto ib = IndexBuffer::Create(m_Indices.data(), (uint32_t)m_Indices.size() * sizeof(Index));
|
||||
m_VertexArray->SetIndexBuffer(ib);
|
||||
m_Scene = scene;
|
||||
}
|
||||
|
||||
@ -264,13 +296,33 @@ namespace Prism
|
||||
materialInstance->Bind();
|
||||
|
||||
// TODO: Sort this out
|
||||
/*
|
||||
m_VertexBuffer->Bind();
|
||||
m_IndexBuffer->Bind();
|
||||
*/
|
||||
m_VertexArray->Bind();
|
||||
|
||||
bool materialOverride = !!materialInstance;
|
||||
|
||||
// TODO: replace with render API calls
|
||||
PM_RENDER_S2(transform, materialOverride,{
|
||||
for (Submesh& submesh : self->m_Submeshes)
|
||||
{
|
||||
if (self->m_IsAnimated)
|
||||
{
|
||||
for (size_t i = 0; i < self->m_BoneTransforms.size(); i++)
|
||||
{
|
||||
std::string uniformName = std::string("u_BoneTransforms[") + std::to_string(i) + std::string("]");
|
||||
self->m_MeshShader->SetMat4FromRenderThread(uniformName, self->m_BoneTransforms[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!materialOverride)
|
||||
self->m_MeshShader->SetMat4FromRenderThread("u_ModelMatrix", transform * submesh.Transform);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
||||
}
|
||||
|
||||
/*
|
||||
for (const Submesh& submesh : self->m_Submeshes)
|
||||
{
|
||||
if (self->m_IsAnimated)
|
||||
@ -295,6 +347,7 @@ namespace Prism
|
||||
|
||||
glEnableVertexAttribArray(6);
|
||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(AnimatedVertex), (const void*)offsetof(AnimatedVertex, Weights));
|
||||
#1#
|
||||
|
||||
if (self->m_Scene->mAnimations)
|
||||
{
|
||||
@ -326,6 +379,7 @@ namespace Prism
|
||||
self->m_MeshShader->SetMat4FromRenderThread("u_ModelMatrix", transform * submesh.Transform);
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
||||
}
|
||||
*/
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "Buffer.h"
|
||||
#include "Material.h"
|
||||
#include "Shader.h"
|
||||
#include "VertexArray.h"
|
||||
#include "Prism/Core/TimeStep.h"
|
||||
|
||||
struct aiNode;
|
||||
@ -125,8 +126,12 @@ namespace Prism
|
||||
uint32_t m_BoneCount = 0;
|
||||
std::vector<BoneInfo> m_BoneInfo;
|
||||
|
||||
Ref<VertexArray> m_VertexArray;
|
||||
|
||||
/*
|
||||
std::unique_ptr<VertexBuffer> m_VertexBuffer;
|
||||
std::unique_ptr<IndexBuffer> m_IndexBuffer;
|
||||
*/
|
||||
|
||||
|
||||
std::vector<Vertex> m_StaticVertices;
|
||||
|
||||
@ -27,7 +27,7 @@ namespace Prism
|
||||
{
|
||||
}
|
||||
|
||||
void Renderer::DrawIndexed(unsigned int count, bool depthTest)
|
||||
void Renderer::DrawIndexed(uint32_t count, bool depthTest)
|
||||
{
|
||||
PM_RENDER_2(count, depthTest, {
|
||||
RendererAPI::DrawIndexed(count, depthTest);
|
||||
|
||||
@ -19,7 +19,7 @@ namespace Prism
|
||||
static void Clear();
|
||||
static void Clear(float r, float g, float b, float a = 1.0f);
|
||||
static void SetClearColor(float r, float g, float b, float a);
|
||||
static void DrawIndexed(unsigned int count, bool depthTest = true);
|
||||
static void DrawIndexed(uint32_t count, bool depthTest = true);
|
||||
|
||||
// test
|
||||
static void ClearMagenta();
|
||||
|
||||
@ -26,6 +26,21 @@ namespace Prism
|
||||
return result;
|
||||
}
|
||||
|
||||
Ref<Shader> Shader::CreateFromSring(const std::string& source)
|
||||
{
|
||||
Ref<Shader> result = nullptr;
|
||||
|
||||
switch (RendererAPI::Current())
|
||||
{
|
||||
case RendererAPIType::None: return nullptr;
|
||||
case RendererAPIType::OpenGL: result = OpenGLShader::CreateFromSring(source);
|
||||
}
|
||||
|
||||
s_AllShaders.push_back(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<Ref<Shader>>& Shader::GetAllShaders()
|
||||
{
|
||||
return s_AllShaders;
|
||||
|
||||
@ -99,6 +99,8 @@ namespace Prism
|
||||
public:
|
||||
using ShaderReloadedCallback = std::function<void()>;
|
||||
|
||||
static Ref<Shader> Create(const std::string& filepath);
|
||||
static Ref<Shader> CreateFromSring(const std::string& source);
|
||||
|
||||
virtual void Reload() = 0;
|
||||
virtual void Bind() = 0;
|
||||
@ -122,7 +124,6 @@ namespace Prism
|
||||
|
||||
virtual void AddShaderReloadedCallback(const ShaderReloadedCallback& callback) = 0;
|
||||
|
||||
static Ref<Shader> Create(const std::string& filepath);
|
||||
static std::vector<Ref<Shader>>& GetAllShaders();
|
||||
|
||||
private:
|
||||
|
||||
@ -3,3 +3,21 @@
|
||||
//
|
||||
|
||||
#include "VertexArray.h"
|
||||
|
||||
#include "Prism/Platform/OpenGL/OpenGLVertexArray.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
Ref<VertexArray> VertexArray::Create()
|
||||
{
|
||||
switch (RendererAPI::Current())
|
||||
{
|
||||
case RendererAPIType::None: PM_CORE_ASSERT(false, "RendererAPI::None is currently not supported!");
|
||||
return nullptr;
|
||||
case RendererAPIType::OpenGL: return std::make_shared<OpenGLVertexArray>();
|
||||
}
|
||||
|
||||
PM_CORE_ASSERT(false, "Unknown RendererAPI");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,13 +4,29 @@
|
||||
|
||||
#ifndef VERTEXARRAY_H
|
||||
#define VERTEXARRAY_H
|
||||
#include "Buffer.h"
|
||||
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class PRISM_API VertexArray
|
||||
{
|
||||
public:
|
||||
virtual ~VertexArray() {}
|
||||
|
||||
class VertexArray {
|
||||
static Ref<VertexArray> Create();
|
||||
|
||||
};
|
||||
virtual void Bind() const = 0;
|
||||
virtual void Unbind() const = 0;
|
||||
|
||||
virtual void AddVertexBuffer(const Ref<VertexBuffer>& vertexBuffer) = 0;
|
||||
virtual void SetIndexBuffer(const Ref<IndexBuffer>& indexBuffer) = 0;
|
||||
|
||||
virtual const std::vector<Ref<VertexBuffer>>& GetVertexBuffers() const = 0;
|
||||
virtual const Ref<IndexBuffer>& GetIndexBuffer() const = 0;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //VERTEXARRAY_H
|
||||
|
||||
@ -2,8 +2,6 @@ project(Sandbox)
|
||||
|
||||
file(GLOB_RECURSE SRC_SOURCE ./**.cpp)
|
||||
|
||||
file(GLOB ASSETS assets)
|
||||
file(COPY ${ASSETS} DESTINATION ${CMAKE_BINARY_DIR}/bin)
|
||||
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SRC_SOURCE})
|
||||
|
||||
@ -4,12 +4,8 @@
|
||||
|
||||
#include "TestLayer.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
#include "Prism/Renderer/Renderer.h"
|
||||
#include "Prism/Renderer/Shader.h"
|
||||
#include "Prism.h"
|
||||
|
||||
|
||||
static void EnableDockSpace(const bool enable)
|
||||
@ -162,15 +158,20 @@ void TestLayer::OnAttach()
|
||||
-1.0f, 1.0f, 0.0f, 0.0f, 1.0f
|
||||
};
|
||||
|
||||
static unsigned int QuadIndices[] = {
|
||||
static uint32_t QuadIndices[] = {
|
||||
0, 1, 2, 2, 3, 0
|
||||
};
|
||||
|
||||
m_VertexBuffer = std::unique_ptr<Prism::VertexBuffer>(Prism::VertexBuffer::Create());
|
||||
m_VertexBuffer->SetData(QuadVertex, sizeof(QuadVertex));
|
||||
m_VertexArray = Prism::VertexArray::Create();
|
||||
auto quadVB = Prism::VertexBuffer::Create(QuadVertex, sizeof(QuadVertex) * sizeof(float));
|
||||
quadVB->SetLayout({
|
||||
{ Prism::ShaderDataType::Float3, "a_Position" },
|
||||
{ Prism::ShaderDataType::Float2, "a_TexCoord" }
|
||||
});
|
||||
m_VertexArray->AddVertexBuffer(quadVB);
|
||||
|
||||
m_IndexBuffer = std::unique_ptr<Prism::IndexBuffer>(Prism::IndexBuffer::Create());
|
||||
m_IndexBuffer->SetData(QuadIndices, sizeof(QuadIndices));
|
||||
auto ib = Prism::IndexBuffer::Create(QuadIndices, 6 * sizeof(uint32_t));
|
||||
m_VertexArray->SetIndexBuffer(ib);
|
||||
|
||||
m_SkyBoxTextureCube.reset(Prism::TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Radiance.tga"));
|
||||
|
||||
@ -178,7 +179,8 @@ void TestLayer::OnAttach()
|
||||
m_Shader = Prism::Shader::Create("assets/shaders/demo.glsl");
|
||||
m_HDRShader = Prism::Shader::Create("assets/shaders/hdr.glsl");
|
||||
|
||||
m_Mesh = std::make_unique<Prism::Mesh>("assets/meshes/cerberus.fbx");
|
||||
// m_Mesh = std::make_unique<Prism::Mesh>("assets/meshes/cerberus.fbx");
|
||||
// m_MeshMaterial = Prism::CreateRef<Prism::MaterialInstance>(m_Mesh->GetMaterial());
|
||||
}
|
||||
|
||||
void TestLayer::OnDetach()
|
||||
@ -194,38 +196,22 @@ void TestLayer::OnUpdate(Prism::TimeStep deltaTime)
|
||||
m_FrameBuffer->Bind();
|
||||
Prism::Renderer::Clear(m_clearColor[0], m_clearColor[1], m_clearColor[2], m_clearColor[3]);
|
||||
|
||||
Prism::UniformBufferDeclaration<sizeof(glm::mat4), 1> skyboxShaderUB;
|
||||
skyboxShaderUB.Push("u_InverseVP", inverse(viewProjection));
|
||||
m_SkyboxShader->UploadUniformBuffer(skyboxShaderUB);
|
||||
// SkyBox
|
||||
m_SkyboxShader->Bind();
|
||||
m_SkyboxShader->SetMat4("u_InverseVP", inverse(viewProjection));
|
||||
m_SkyBoxTextureCube->Bind(0);
|
||||
m_VertexBuffer->Bind();
|
||||
m_IndexBuffer->Bind();
|
||||
Prism::Renderer::DrawIndexed(m_IndexBuffer->GetCount(), false);
|
||||
m_VertexArray->Bind();
|
||||
Prism::Renderer::DrawIndexed(m_VertexArray->GetIndexBuffer()->GetCount(), false);
|
||||
|
||||
Prism::UniformBufferDeclaration<sizeof(glm::vec4) + sizeof(glm::mat4), 2> uniformbuffer;
|
||||
uniformbuffer.Push("u_Color", m_TriangleColor);
|
||||
uniformbuffer.Push("u_MVP", viewProjection);
|
||||
m_Shader->UploadUniformBuffer(uniformbuffer);
|
||||
|
||||
m_Shader->Bind();
|
||||
|
||||
// m_Mesh->Render(deltaTime, m_Shader);
|
||||
// m_VertexBuffer->Bind();
|
||||
// m_IndexBuffer->Bind();
|
||||
|
||||
// m_Mesh->Render();
|
||||
// Prism::Renderer::DrawIndexed(3, false);
|
||||
m_FrameBuffer->Unbind();
|
||||
|
||||
|
||||
// HDR
|
||||
m_FinalPresentBuffer->Bind();
|
||||
m_HDRShader->Bind();
|
||||
m_HDRShader->SetFloat("u_Exposure", m_Exposure);
|
||||
m_FrameBuffer->BindTexture();
|
||||
m_VertexBuffer->Bind();
|
||||
m_IndexBuffer->Bind();
|
||||
Prism::Renderer::DrawIndexed(m_IndexBuffer->GetCount(), false);
|
||||
Prism::Renderer::DrawIndexed(m_VertexArray->GetIndexBuffer()->GetCount(), false);
|
||||
m_FinalPresentBuffer->Unbind();
|
||||
}
|
||||
|
||||
|
||||
@ -29,16 +29,15 @@ private:
|
||||
glm::vec4 m_TriangleColor = glm::vec4(1.0f);
|
||||
|
||||
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_SkyBoxTextureCube;
|
||||
|
||||
Prism::Ref<Prism::VertexArray> m_VertexArray;
|
||||
Prism::Ref<Prism::Shader> m_SkyboxShader;
|
||||
Prism::Ref<Prism::Shader> m_Shader;
|
||||
Prism::Ref<Prism::Shader> m_HDRShader;
|
||||
Prism::Ref<Prism::Mesh> m_Mesh;
|
||||
Prism::Ref<Prism::MaterialInstance> m_MeshMaterial;
|
||||
|
||||
Prism::Camera m_Camera;
|
||||
|
||||
|
||||
@ -6,7 +6,6 @@
|
||||
#include "Prism.h"
|
||||
#include "Prism/Core/EntryPoint.h"
|
||||
|
||||
#include "Layer/DemoLayer.h"
|
||||
#include "Layer/TestLayer.h"
|
||||
|
||||
class Sandbox : public Prism::Application
|
||||
@ -18,8 +17,8 @@ public:
|
||||
|
||||
virtual void OnInit() override
|
||||
{
|
||||
// PushLayer(new TestLayer());
|
||||
PushLayer(new DemoLayer());
|
||||
PushLayer(new TestLayer());
|
||||
// PushLayer(new DemoLayer());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user