Added right click menu on scene view. and fixed rendering
This commit is contained in:
parent
02594dc015
commit
7945ff246b
@ -1,3 +1,6 @@
|
|||||||
[LINK] g++ src\build\src\Engine.o src\build\src\main.o src\build\src\Renderer.o src\build\src\Components\SpriteComponent.o src\build\src\Entitys\Object.o src\build\src\utils\FileDialog.o src\build\vendor\imgui\imgui.o src\build\vendor\imgui\imgui_demo.o src\build\vendor\imgui\imgui_draw.o src\build\vendor\imgui\imgui_impl_glfw.o src\build\vendor\imgui\imgui_impl_opengl3.o src\build\vendor\imgui\imgui_tables.o src\build\vendor\imgui\imgui_widgets.o -o src\build\app.exe -LC:/msys64/mingw64/lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
|
[COMPILE] g++ -std=c++20 -Wall -Isrc/include -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -MMD -MP -c src\src\main.cpp -o src\build\src\main.o
|
||||||
|
[LINK] g++ src\build\src\Engine.o src\build\src\main.o src\build\src\Renderer.o src\build\src\Components\SpriteComponent.o src\build\src\Entitys\Object.o src\build\src\utils\FileDialog.o src\build\src\utils\Shader.o src\build\vendor\imgui\imgui.o src\build\vendor\imgui\imgui_demo.o src\build\vendor\imgui\imgui_draw.o src\build\vendor\imgui\imgui_impl_glfw.o src\build\vendor\imgui\imgui_impl_opengl3.o src\build\vendor\imgui\imgui_tables.o src\build\vendor\imgui\imgui_widgets.o -o src\build\app.exe -LC:/msys64/mingw64/lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
|
||||||
|
|
||||||
[TIME] Build duration: 0.43s
|
[TIME] Build duration: 1.23s
|
||||||
|
[ERROR] Runtime crash
|
||||||
|
Command 'src\build\app.exe' returned non-zero exit status 3221226356.
|
||||||
|
12
imgui.ini
12
imgui.ini
@ -14,8 +14,8 @@ Size=1920,1158
|
|||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Inspector]
|
[Window][Inspector]
|
||||||
Pos=1597,19
|
Pos=1513,19
|
||||||
Size=323,1158
|
Size=407,1158
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000004,0
|
DockId=0x00000004,0
|
||||||
|
|
||||||
@ -27,14 +27,14 @@ DockId=0x00000001,0
|
|||||||
|
|
||||||
[Window][Viewport]
|
[Window][Viewport]
|
||||||
Pos=265,19
|
Pos=265,19
|
||||||
Size=1330,1158
|
Size=1246,1158
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000002,0
|
DockId=0x00000002,0
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X
|
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X
|
||||||
DockNode ID=0x00000003 Parent=0x11111111 SizeRef=1595,1158 Split=X
|
DockNode ID=0x00000003 Parent=0x11111111 SizeRef=1511,1158 Split=X
|
||||||
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=263,701 HiddenTabBar=1 Selected=0x12EF0F59
|
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=263,701 HiddenTabBar=1 Selected=0x12EF0F59
|
||||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1330,701 CentralNode=1 Selected=0xC450F867
|
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1246,701 CentralNode=1 Selected=0xC450F867
|
||||||
DockNode ID=0x00000004 Parent=0x11111111 SizeRef=323,1158 HiddenTabBar=1 Selected=0x36DC96AB
|
DockNode ID=0x00000004 Parent=0x11111111 SizeRef=407,1158 HiddenTabBar=1 Selected=0x36DC96AB
|
||||||
|
|
||||||
|
9
src/assets/shaders/sprite.frag
Normal file
9
src/assets/shaders/sprite.frag
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#version 330 core
|
||||||
|
in vec2 vUV;
|
||||||
|
out vec4 FragColor;
|
||||||
|
|
||||||
|
uniform sampler2D uTex;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
FragColor = texture(uTex, vUV);
|
||||||
|
}
|
16
src/assets/shaders/sprite.vert
Normal file
16
src/assets/shaders/sprite.vert
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout(location = 0) in vec2 aPos;
|
||||||
|
layout(location = 1) in vec2 aUV;
|
||||||
|
|
||||||
|
uniform vec2 uPos;
|
||||||
|
uniform vec2 uSize;
|
||||||
|
uniform vec2 uScreen;
|
||||||
|
|
||||||
|
out vec2 vUV;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 scaled = aPos * uSize + uPos;
|
||||||
|
vec2 ndc = scaled / uScreen * 2.0 - 1.0;
|
||||||
|
gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0);
|
||||||
|
vUV = vec2(aUV.x, 1.0 - aUV.y);
|
||||||
|
}
|
@ -15,6 +15,8 @@ unsigned int SpriteComponent::LoadTexture(const std::string& path) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size = glm::vec2(w,h);
|
||||||
|
|
||||||
unsigned int id;
|
unsigned int id;
|
||||||
glGenTextures(1, &id);
|
glGenTextures(1, &id);
|
||||||
glBindTexture(GL_TEXTURE_2D, id);
|
glBindTexture(GL_TEXTURE_2D, id);
|
||||||
@ -22,7 +24,6 @@ unsigned int SpriteComponent::LoadTexture(const std::string& path) {
|
|||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
|
||||||
glGenerateMipmap(GL_TEXTURE_2D);
|
glGenerateMipmap(GL_TEXTURE_2D);
|
||||||
|
|
||||||
// Default params
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||||
|
@ -18,12 +18,17 @@ public:
|
|||||||
std::string GetTexturePath() const;
|
std::string GetTexturePath() const;
|
||||||
std::string GetNormalMapPath() const;
|
std::string GetNormalMapPath() const;
|
||||||
|
|
||||||
|
virtual glm::vec2 GetSize() const { return size; }
|
||||||
|
|
||||||
virtual std::string GetName() const override { return "SpriteComponent"; }
|
virtual std::string GetName() const override { return "SpriteComponent"; }
|
||||||
|
|
||||||
virtual void Save(YAML::Emitter& out) const override;
|
virtual void Save(YAML::Emitter& out) const override;
|
||||||
virtual void Load(const YAML::Node& node) override;
|
virtual void Load(const YAML::Node& node) override;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
glm::vec2 size = { 64, 64 };
|
||||||
std::string texturePath;
|
std::string texturePath;
|
||||||
std::string normalMapPath;
|
std::string normalMapPath;
|
||||||
unsigned int textureID = 0;
|
unsigned int textureID = 0;
|
||||||
|
@ -28,15 +28,18 @@ static std::shared_ptr<Object> selected = nullptr;
|
|||||||
static bool playing = false;
|
static bool playing = false;
|
||||||
GLFWwindow *window = nullptr;
|
GLFWwindow *window = nullptr;
|
||||||
|
|
||||||
Engine::Engine() {
|
Engine::Engine()
|
||||||
|
{
|
||||||
Init();
|
Init();
|
||||||
}
|
}
|
||||||
|
|
||||||
Engine::~Engine() {
|
Engine::~Engine()
|
||||||
|
{
|
||||||
Shutdown();
|
Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::Init() {
|
void Engine::Init()
|
||||||
|
{
|
||||||
glfwInit();
|
glfwInit();
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||||
@ -49,7 +52,8 @@ void Engine::Init() {
|
|||||||
|
|
||||||
IMGUI_CHECKVERSION();
|
IMGUI_CHECKVERSION();
|
||||||
ImGui::CreateContext();
|
ImGui::CreateContext();
|
||||||
ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
ImGuiIO &io = ImGui::GetIO();
|
||||||
|
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||||
ImGui::StyleColorsDark();
|
ImGui::StyleColorsDark();
|
||||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||||
ImGui_ImplOpenGL3_Init("#version 330");
|
ImGui_ImplOpenGL3_Init("#version 330");
|
||||||
@ -61,8 +65,10 @@ void Engine::Init() {
|
|||||||
selected = obj;
|
selected = obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::Run() {
|
void Engine::Run()
|
||||||
while (!glfwWindowShouldClose(window)) {
|
{
|
||||||
|
while (!glfwWindowShouldClose(window))
|
||||||
|
{
|
||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
|
|
||||||
ImGui_ImplOpenGL3_NewFrame();
|
ImGui_ImplOpenGL3_NewFrame();
|
||||||
@ -70,17 +76,22 @@ void Engine::Run() {
|
|||||||
ImGui::NewFrame();
|
ImGui::NewFrame();
|
||||||
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()->ID);
|
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()->ID);
|
||||||
|
|
||||||
if (ImGui::BeginMainMenuBar()) {
|
if (ImGui::BeginMainMenuBar())
|
||||||
if (ImGui::Button(playing ? "Stop" : "Play")) {
|
{
|
||||||
|
if (ImGui::Button(playing ? "Stop" : "Play"))
|
||||||
|
{
|
||||||
playing = !playing;
|
playing = !playing;
|
||||||
}
|
}
|
||||||
if (ImGui::BeginMenu("File")) {
|
if (ImGui::BeginMenu("File"))
|
||||||
if (ImGui::MenuItem("Save Scene")) {
|
{
|
||||||
|
if (ImGui::MenuItem("Save Scene"))
|
||||||
|
{
|
||||||
std::string file = OpenFileDialog(FileDialogType::Scenes); // reuse your dialog
|
std::string file = OpenFileDialog(FileDialogType::Scenes); // reuse your dialog
|
||||||
if (!file.empty())
|
if (!file.empty())
|
||||||
SaveScene(file);
|
SaveScene(file);
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Load Scene")) {
|
if (ImGui::MenuItem("Load Scene"))
|
||||||
|
{
|
||||||
std::string file = OpenFileDialog(FileDialogType::Scenes);
|
std::string file = OpenFileDialog(FileDialogType::Scenes);
|
||||||
if (!file.empty())
|
if (!file.empty())
|
||||||
LoadScene(file);
|
LoadScene(file);
|
||||||
@ -92,12 +103,45 @@ void Engine::Run() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Begin("Scene Tree");
|
ImGui::Begin("Scene Tree");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (ImGui::BeginPopupContextWindow("SceneTreeContext", ImGuiPopupFlags_MouseButtonRight))
|
||||||
|
{
|
||||||
|
if (ImGui::MenuItem("Create New Object"))
|
||||||
|
{
|
||||||
|
auto obj = std::make_shared<Object>("NewObject");
|
||||||
|
obj->AddComponent<SpriteComponent>();
|
||||||
|
objects.push_back(obj);
|
||||||
|
selected = obj;
|
||||||
|
ImGui::OpenPopup("RenameObject");
|
||||||
|
}
|
||||||
|
ImGui::Separator();
|
||||||
|
if (ImGui::MenuItem("Create New Sprite Object"))
|
||||||
|
{
|
||||||
|
auto obj = std::make_shared<Object>("NewSprite");
|
||||||
|
obj->AddComponent<SpriteComponent>();
|
||||||
|
objects.push_back(obj);
|
||||||
|
selected = obj;
|
||||||
|
ImGui::OpenPopup("RenameObject");
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
for (auto &obj : objects)
|
for (auto &obj : objects)
|
||||||
|
if (!obj->GetParent()) // Only draw root nodes
|
||||||
DrawObjectNode(obj);
|
DrawObjectNode(obj);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
ImGui::Begin("Inspector");
|
ImGui::Begin("Inspector");
|
||||||
if (selected) {
|
if (selected)
|
||||||
|
{
|
||||||
char buffer[128];
|
char buffer[128];
|
||||||
strcpy(buffer, selected->GetName().c_str());
|
strcpy(buffer, selected->GetName().c_str());
|
||||||
if (ImGui::InputText("Name", buffer, sizeof(buffer)))
|
if (ImGui::InputText("Name", buffer, sizeof(buffer)))
|
||||||
@ -108,13 +152,15 @@ void Engine::Run() {
|
|||||||
selected->SetLocalPosition(pos);
|
selected->SetLocalPosition(pos);
|
||||||
|
|
||||||
// Add component
|
// Add component
|
||||||
if (ImGui::Button("Add SpriteComponent")) {
|
if (ImGui::Button("Add SpriteComponent"))
|
||||||
|
{
|
||||||
if (!selected->GetComponent<SpriteComponent>())
|
if (!selected->GetComponent<SpriteComponent>())
|
||||||
selected->AddComponent<SpriteComponent>();
|
selected->AddComponent<SpriteComponent>();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show SpriteComponent UI
|
// Show SpriteComponent UI
|
||||||
if (auto sprite = selected->GetComponent<SpriteComponent>()) {
|
if (auto sprite = selected->GetComponent<SpriteComponent>())
|
||||||
|
{
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
ImGui::Text("Sprite Component");
|
ImGui::Text("Sprite Component");
|
||||||
|
|
||||||
@ -122,38 +168,47 @@ void Engine::Run() {
|
|||||||
std::string norm = sprite->GetNormalMapPath();
|
std::string norm = sprite->GetNormalMapPath();
|
||||||
|
|
||||||
ImGui::Text("Texture: %s", tex.c_str());
|
ImGui::Text("Texture: %s", tex.c_str());
|
||||||
if (ImGui::Button("Load Texture")) {
|
if (ImGui::Button("Load Texture"))
|
||||||
|
{
|
||||||
auto path = OpenFileDialog(FileDialogType::Images);
|
auto path = OpenFileDialog(FileDialogType::Images);
|
||||||
if (!path.empty())
|
if (!path.empty())
|
||||||
sprite->SetTexture(path);
|
sprite->SetTexture(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::Text("Normal Map: %s", norm.c_str());
|
ImGui::Text("Normal Map: %s", norm.c_str());
|
||||||
if (ImGui::Button("Load Normal Map")) {
|
if (ImGui::Button("Load Normal Map"))
|
||||||
|
{
|
||||||
auto path = OpenFileDialog(FileDialogType::Images);
|
auto path = OpenFileDialog(FileDialogType::Images);
|
||||||
if (!path.empty())
|
if (!path.empty())
|
||||||
sprite->SetNormalMap(path);
|
sprite->SetNormalMap(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::Button("Remove SpriteComponent")) {
|
if (ImGui::Button("Remove SpriteComponent"))
|
||||||
|
{
|
||||||
selected->RemoveComponent<SpriteComponent>();
|
selected->RemoveComponent<SpriteComponent>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ImGui::Text("No object selected.");
|
ImGui::Text("No object selected.");
|
||||||
}
|
}
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Viewport
|
// Viewport
|
||||||
ImGui::Begin("Viewport", nullptr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
ImGui::Begin("Viewport", nullptr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
||||||
ImVec2 size = ImGui::GetContentRegionAvail();
|
ImVec2 size = ImGui::GetContentRegionAvail();
|
||||||
Renderer::Resize((int)size.x, (int)size.y);
|
Renderer::Resize((int)size.x, (int)size.y);
|
||||||
Renderer::Begin();
|
Renderer::Begin();
|
||||||
|
|
||||||
for (auto& obj : objects) {
|
for (auto &obj : objects)
|
||||||
if (auto sprite = obj->GetComponent<SpriteComponent>()) {
|
{
|
||||||
|
if (auto sprite = obj->GetComponent<SpriteComponent>())
|
||||||
|
{
|
||||||
Renderer::DrawSprite(sprite.get(), obj->GetWorldPosition());
|
Renderer::DrawSprite(sprite.get(), obj->GetWorldPosition());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -163,6 +218,32 @@ void Engine::Run() {
|
|||||||
ImGui::Image((ImTextureID)(uintptr_t)texID, size, ImVec2(0, 1), ImVec2(1, 0));
|
ImGui::Image((ImTextureID)(uintptr_t)texID, size, ImVec2(0, 1), ImVec2(1, 0));
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
|
|
||||||
|
if (ImGui::BeginPopup("RenameObject")) {
|
||||||
|
static char nameBuffer[128];
|
||||||
|
static bool once = true;
|
||||||
|
|
||||||
|
if (once && selected) {
|
||||||
|
strcpy(nameBuffer, selected->GetName().c_str());
|
||||||
|
once = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::InputText("##rename", nameBuffer, sizeof(nameBuffer));
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_Enter) || ImGui::Button("OK")) {
|
||||||
|
if (selected)
|
||||||
|
selected->SetName(nameBuffer);
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
once = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Cancel")) {
|
||||||
|
ImGui::CloseCurrentPopup();
|
||||||
|
once = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
// ImGui render
|
// ImGui render
|
||||||
ImGui::Render();
|
ImGui::Render();
|
||||||
int w, h;
|
int w, h;
|
||||||
@ -174,8 +255,10 @@ void Engine::Run() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::DrawObjectNode(const std::shared_ptr<Object>& obj) {
|
void Engine::DrawObjectNode(const std::shared_ptr<Object> &obj)
|
||||||
|
{
|
||||||
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow |
|
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow |
|
||||||
|
ImGuiTreeNodeFlags_SpanAvailWidth |
|
||||||
(obj == selected ? ImGuiTreeNodeFlags_Selected : 0);
|
(obj == selected ? ImGuiTreeNodeFlags_Selected : 0);
|
||||||
|
|
||||||
bool open = ImGui::TreeNodeEx((void *)(intptr_t)obj->id, flags, "%s", obj->GetName().c_str());
|
bool open = ImGui::TreeNodeEx((void *)(intptr_t)obj->id, flags, "%s", obj->GetName().c_str());
|
||||||
@ -183,14 +266,54 @@ void Engine::DrawObjectNode(const std::shared_ptr<Object>& obj) {
|
|||||||
if (ImGui::IsItemClicked())
|
if (ImGui::IsItemClicked())
|
||||||
selected = obj;
|
selected = obj;
|
||||||
|
|
||||||
if (ImGui::BeginDragDropSource()) {
|
// === Context Menu on Object ===
|
||||||
|
if (ImGui::BeginPopupContextItem())
|
||||||
|
{
|
||||||
|
if (ImGui::MenuItem("Rename"))
|
||||||
|
{
|
||||||
|
selected = obj;
|
||||||
|
ImGui::OpenPopup("RenameObject");
|
||||||
|
}
|
||||||
|
if (ImGui::MenuItem("Delete"))
|
||||||
|
{
|
||||||
|
// Remove from parent or root
|
||||||
|
if (obj->GetParent())
|
||||||
|
{
|
||||||
|
obj->GetParent()->RemoveChild(obj.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
objects.erase(std::remove_if(objects.begin(), objects.end(),
|
||||||
|
[&](const std::shared_ptr<Object> &o)
|
||||||
|
{ return o == obj; }),
|
||||||
|
objects.end());
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
return; // Don't draw deleted node
|
||||||
|
}
|
||||||
|
if (ImGui::MenuItem("Create Child"))
|
||||||
|
{
|
||||||
|
auto child = std::make_shared<Object>("NewObject");
|
||||||
|
obj->AddChild(child);
|
||||||
|
selected = child;
|
||||||
|
child->SetName("NewObject");
|
||||||
|
ImGui::OpenPopup("RenameObject");
|
||||||
|
}
|
||||||
|
ImGui::EndPopup();
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Drag and Drop ===
|
||||||
|
if (ImGui::BeginDragDropSource())
|
||||||
|
{
|
||||||
ImGui::SetDragDropPayload("OBJECT", &obj, sizeof(obj));
|
ImGui::SetDragDropPayload("OBJECT", &obj, sizeof(obj));
|
||||||
ImGui::Text("Move: %s", obj->GetName().c_str());
|
ImGui::Text("Move: %s", obj->GetName().c_str());
|
||||||
ImGui::EndDragDropSource();
|
ImGui::EndDragDropSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ImGui::BeginDragDropTarget()) {
|
if (ImGui::BeginDragDropTarget())
|
||||||
if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("OBJECT")) {
|
{
|
||||||
|
if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("OBJECT"))
|
||||||
|
{
|
||||||
auto dragged = *(std::shared_ptr<Object> *)payload->Data;
|
auto dragged = *(std::shared_ptr<Object> *)payload->Data;
|
||||||
if (dragged != obj)
|
if (dragged != obj)
|
||||||
obj->AddChild(dragged);
|
obj->AddChild(dragged);
|
||||||
@ -198,14 +321,17 @@ void Engine::DrawObjectNode(const std::shared_ptr<Object>& obj) {
|
|||||||
ImGui::EndDragDropTarget();
|
ImGui::EndDragDropTarget();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (open) {
|
// === Children ===
|
||||||
|
if (open)
|
||||||
|
{
|
||||||
for (auto &child : obj->GetChildren())
|
for (auto &child : obj->GetChildren())
|
||||||
DrawObjectNode(child);
|
DrawObjectNode(child);
|
||||||
ImGui::TreePop();
|
ImGui::TreePop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::SaveScene(const std::string& path) {
|
void Engine::SaveScene(const std::string &path)
|
||||||
|
{
|
||||||
YAML::Emitter out;
|
YAML::Emitter out;
|
||||||
YAML::Emitter sceneData;
|
YAML::Emitter sceneData;
|
||||||
|
|
||||||
@ -235,8 +361,10 @@ void Engine::SaveScene(const std::string& path) {
|
|||||||
file << out.c_str();
|
file << out.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VerifySceneHash(const YAML::Node& root) {
|
bool VerifySceneHash(const YAML::Node &root)
|
||||||
if (!root["scene_hash"] || !root["objects"]) return false;
|
{
|
||||||
|
if (!root["scene_hash"] || !root["objects"])
|
||||||
|
return false;
|
||||||
|
|
||||||
YAML::Emitter sceneOnly;
|
YAML::Emitter sceneOnly;
|
||||||
sceneOnly << root["objects"];
|
sceneOnly << root["objects"];
|
||||||
@ -252,28 +380,32 @@ bool VerifySceneHash(const YAML::Node& root) {
|
|||||||
return hashHex.str() == root["scene_hash"].as<std::string>();
|
return hashHex.str() == root["scene_hash"].as<std::string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Engine::LoadScene(const std::string& path) {
|
void Engine::LoadScene(const std::string &path)
|
||||||
|
{
|
||||||
YAML::Node root = YAML::LoadFile(path);
|
YAML::Node root = YAML::LoadFile(path);
|
||||||
|
|
||||||
if (!root["engine_version"] || !root["format_version"] || !root["scene_name"]) {
|
if (!root["engine_version"] || !root["format_version"] || !root["scene_name"])
|
||||||
|
{
|
||||||
std::cerr << "[LoadScene] Missing required metadata!\n";
|
std::cerr << "[LoadScene] Missing required metadata!\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["engine_version"].as<std::string>() != "0.1.0") {
|
if (root["engine_version"].as<std::string>() != "0.1.0")
|
||||||
|
{
|
||||||
std::cerr << "[LoadScene] Version mismatch! Expected 0.1.0, got " << root["engine_version"].as<std::string>() << "\n";
|
std::cerr << "[LoadScene] Version mismatch! Expected 0.1.0, got " << root["engine_version"].as<std::string>() << "\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!VerifySceneHash(root)) {
|
if (!VerifySceneHash(root))
|
||||||
|
{
|
||||||
std::cerr << "[LoadScene] Scene hash does not match! File may be corrupted or tampered.\n";
|
std::cerr << "[LoadScene] Scene hash does not match! File may be corrupted or tampered.\n";
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
objects.clear();
|
objects.clear();
|
||||||
const auto &objectArray = root["objects"];
|
const auto &objectArray = root["objects"];
|
||||||
for (const auto& node : objectArray) {
|
for (const auto &node : objectArray)
|
||||||
auto obj = std::make_shared<Object>("(loaded)");
|
{
|
||||||
|
auto obj = std::make_shared<Object>("[DefaultObject]");
|
||||||
obj->Load(node);
|
obj->Load(node);
|
||||||
objects.push_back(obj);
|
objects.push_back(obj);
|
||||||
}
|
}
|
||||||
@ -281,9 +413,8 @@ void Engine::LoadScene(const std::string& path) {
|
|||||||
std::cout << "[LoadScene] Loaded scene: " << root["scene_name"].as<std::string>() << "\n";
|
std::cout << "[LoadScene] Loaded scene: " << root["scene_name"].as<std::string>() << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Engine::Shutdown()
|
||||||
|
{
|
||||||
void Engine::Shutdown() {
|
|
||||||
ImGui_ImplOpenGL3_Shutdown();
|
ImGui_ImplOpenGL3_Shutdown();
|
||||||
ImGui_ImplGlfw_Shutdown();
|
ImGui_ImplGlfw_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
|
@ -1,42 +1,73 @@
|
|||||||
#include "Renderer.h"
|
#include "Renderer.h"
|
||||||
#include "Components/SpriteComponent.h"
|
#include "Components/SpriteComponent.h"
|
||||||
|
#include "utils/Shader.h"
|
||||||
|
|
||||||
|
#include <GL/glew.h>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
static Shader spriteShader;
|
||||||
|
|
||||||
GLuint Renderer::fbo = 0;
|
GLuint Renderer::fbo = 0;
|
||||||
GLuint Renderer::textureColorBuffer = 0;
|
GLuint Renderer::textureColorBuffer = 0;
|
||||||
GLuint Renderer::rbo = 0;
|
GLuint Renderer::rbo = 0;
|
||||||
|
GLuint Renderer::quadVAO = 0;
|
||||||
|
GLuint Renderer::quadVBO = 0;
|
||||||
int Renderer::width = 1280;
|
int Renderer::width = 1280;
|
||||||
int Renderer::height = 720;
|
int Renderer::height = 720;
|
||||||
|
|
||||||
|
void Renderer::InitQuad() {
|
||||||
|
float vertices[] = {
|
||||||
|
// pos // uv
|
||||||
|
0.f, 0.f, 0.f, 0.f,
|
||||||
|
1.f, 0.f, 1.f, 0.f,
|
||||||
|
1.f, 1.f, 1.f, 1.f,
|
||||||
|
0.f, 1.f, 0.f, 1.f
|
||||||
|
};
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &quadVAO);
|
||||||
|
glBindVertexArray(quadVAO);
|
||||||
|
|
||||||
|
glGenBuffers(1, &quadVBO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, quadVBO);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0); // position
|
||||||
|
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)0);
|
||||||
|
glEnableVertexAttribArray(1); // UV
|
||||||
|
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), (void*)(2 * sizeof(float)));
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
void Renderer::Init() {
|
void Renderer::Init() {
|
||||||
glGenFramebuffers(1, &fbo);
|
glGenFramebuffers(1, &fbo);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||||
|
|
||||||
glGenTextures(1, &textureColorBuffer);
|
glGenTextures(1, &textureColorBuffer);
|
||||||
glBindTexture(GL_TEXTURE_2D, textureColorBuffer);
|
glBindTexture(GL_TEXTURE_2D, textureColorBuffer);
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||||
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureColorBuffer, 0);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
|
||||||
GL_TEXTURE_2D, textureColorBuffer, 0);
|
|
||||||
|
|
||||||
glGenRenderbuffers(1, &rbo);
|
glGenRenderbuffers(1, &rbo);
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
|
||||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
|
||||||
GL_RENDERBUFFER, rbo);
|
|
||||||
|
|
||||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||||
std::cerr << "Framebuffer is not complete!" << std::endl;
|
std::cerr << "Framebuffer is not complete!" << std::endl;
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
|
|
||||||
|
InitQuad();
|
||||||
|
|
||||||
|
spriteShader.LoadFromFile("src/assets/shaders/sprite.vert", "src/assets/shaders/sprite.frag");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::Resize(int w, int h) {
|
void Renderer::Resize(int w, int h) {
|
||||||
if (w == width && h == height) return;
|
if (w == width && h == height) return;
|
||||||
|
|
||||||
width = w;
|
width = w;
|
||||||
height = h;
|
height = h;
|
||||||
|
|
||||||
@ -61,6 +92,23 @@ void Renderer::End() {
|
|||||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Renderer::DrawSprite(SpriteComponent* sprite, const glm::vec2& pos) {
|
||||||
|
if (!sprite || sprite->GetTextureID() == 0) return;
|
||||||
|
|
||||||
|
spriteShader.Use();
|
||||||
|
spriteShader.SetVec2("uPos", pos);
|
||||||
|
spriteShader.SetVec2("uSize", sprite->GetSize());
|
||||||
|
spriteShader.SetVec2("uScreen", glm::vec2(width, height));
|
||||||
|
spriteShader.SetInt("uTex", 0);
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, sprite->GetTextureID());
|
||||||
|
|
||||||
|
glBindVertexArray(quadVAO);
|
||||||
|
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||||
|
glBindVertexArray(0);
|
||||||
|
}
|
||||||
|
|
||||||
GLuint Renderer::GetRenderTexture() {
|
GLuint Renderer::GetRenderTexture() {
|
||||||
return textureColorBuffer;
|
return textureColorBuffer;
|
||||||
}
|
}
|
||||||
@ -68,19 +116,3 @@ GLuint Renderer::GetRenderTexture() {
|
|||||||
glm::ivec2 Renderer::GetSize() {
|
glm::ivec2 Renderer::GetSize() {
|
||||||
return { width, height };
|
return { width, height };
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::DrawSprite(SpriteComponent* sprite, const glm::vec2& pos) {
|
|
||||||
GLuint tex = sprite->GetTextureID();
|
|
||||||
if (!tex) return;
|
|
||||||
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex);
|
|
||||||
glBegin(GL_QUADS);
|
|
||||||
float size = 100.0f;
|
|
||||||
|
|
||||||
glTexCoord2f(0, 0); glVertex2f(pos.x, pos.y);
|
|
||||||
glTexCoord2f(1, 0); glVertex2f(pos.x + size, pos.y);
|
|
||||||
glTexCoord2f(1, 1); glVertex2f(pos.x + size, pos.y + size);
|
|
||||||
glTexCoord2f(0, 1); glVertex2f(pos.x, pos.y + size);
|
|
||||||
|
|
||||||
glEnd();
|
|
||||||
}
|
|
||||||
|
@ -7,7 +7,7 @@ class SpriteComponent;
|
|||||||
class Renderer {
|
class Renderer {
|
||||||
public:
|
public:
|
||||||
static void Init();
|
static void Init();
|
||||||
static void Resize(int width, int height);
|
static void Resize(int w, int h);
|
||||||
static void Begin();
|
static void Begin();
|
||||||
static void End();
|
static void End();
|
||||||
static void DrawSprite(SpriteComponent* sprite, const glm::vec2& pos);
|
static void DrawSprite(SpriteComponent* sprite, const glm::vec2& pos);
|
||||||
@ -17,4 +17,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
static GLuint fbo, textureColorBuffer, rbo;
|
static GLuint fbo, textureColorBuffer, rbo;
|
||||||
static int width, height;
|
static int width, height;
|
||||||
|
|
||||||
|
static GLuint shader, quadVAO, quadVBO;
|
||||||
|
static void InitQuad();
|
||||||
|
static GLuint LoadShader(const char* vertexSrc, const char* fragmentSrc);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
#include "Engine.h"
|
#include "Engine.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
try {
|
||||||
Engine engine;
|
Engine engine;
|
||||||
engine.Run();
|
engine.Run();
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
std::cerr << "[Fatal Error] " << e.what() << std::endl;
|
||||||
|
return 1;
|
||||||
|
} catch (...) {
|
||||||
|
std::cerr << "[Fatal Error] Unknown exception occurred!" << std::endl;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
116
src/src/utils/Shader.cpp
Normal file
116
src/src/utils/Shader.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#include "Shader.h"
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
Shader::Shader() {}
|
||||||
|
Shader::~Shader() { Clear(); }
|
||||||
|
|
||||||
|
void Shader::Clear() {
|
||||||
|
if (id != 0) {
|
||||||
|
glDeleteProgram(id);
|
||||||
|
id = 0;
|
||||||
|
}
|
||||||
|
uniformCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Shader::ReadFile(const std::string& path) {
|
||||||
|
std::ifstream stream(path);
|
||||||
|
std::stringstream buffer;
|
||||||
|
buffer << stream.rdbuf();
|
||||||
|
return buffer.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint Shader::Compile(GLenum type, const std::string& source) {
|
||||||
|
GLuint shader = glCreateShader(type);
|
||||||
|
const char* src = source.c_str();
|
||||||
|
glShaderSource(shader, 1, &src, nullptr);
|
||||||
|
glCompileShader(shader);
|
||||||
|
|
||||||
|
GLint success;
|
||||||
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
||||||
|
if (!success) {
|
||||||
|
char info[512];
|
||||||
|
glGetShaderInfoLog(shader, 512, nullptr, info);
|
||||||
|
std::cerr << "[Shader Compile Error]:\n" << info << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shader::LoadFromFile(const std::string& vertexPath, const std::string& fragmentPath) {
|
||||||
|
return LoadFromSource(ReadFile(vertexPath), ReadFile(fragmentPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Shader::LoadFromSource(const std::string& vertexSrc, const std::string& fragmentSrc) {
|
||||||
|
Clear();
|
||||||
|
|
||||||
|
GLuint vertex = Compile(GL_VERTEX_SHADER, vertexSrc);
|
||||||
|
GLuint fragment = Compile(GL_FRAGMENT_SHADER, fragmentSrc);
|
||||||
|
|
||||||
|
id = glCreateProgram();
|
||||||
|
glAttachShader(id, vertex);
|
||||||
|
glAttachShader(id, fragment);
|
||||||
|
glLinkProgram(id);
|
||||||
|
|
||||||
|
glDeleteShader(vertex);
|
||||||
|
glDeleteShader(fragment);
|
||||||
|
|
||||||
|
GLint success;
|
||||||
|
glGetProgramiv(id, GL_LINK_STATUS, &success);
|
||||||
|
if (!success) {
|
||||||
|
char info[512];
|
||||||
|
glGetProgramInfoLog(id, 512, nullptr, info);
|
||||||
|
std::cerr << "[Shader Link Error]:\n" << info << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::Use() const {
|
||||||
|
glUseProgram(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
GLuint Shader::GetID() const {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
GLint Shader::GetUniformLocation(const std::string& name) {
|
||||||
|
if (uniformCache.contains(name)) return uniformCache[name];
|
||||||
|
GLint loc = glGetUniformLocation(id, name.c_str());
|
||||||
|
if (loc == -1)
|
||||||
|
std::cerr << "[Shader] Warning: Uniform not found: " << name << "\n";
|
||||||
|
uniformCache[name] = loc;
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Uniform Setters ===
|
||||||
|
|
||||||
|
void Shader::SetBool(const std::string& name, bool value) {
|
||||||
|
glUniform1i(GetUniformLocation(name), (int)value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::SetInt(const std::string& name, int value) {
|
||||||
|
glUniform1i(GetUniformLocation(name), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::SetFloat(const std::string& name, float value) {
|
||||||
|
glUniform1f(GetUniformLocation(name), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::SetVec2(const std::string& name, const glm::vec2& value) {
|
||||||
|
glUniform2fv(GetUniformLocation(name), 1, &value[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::SetVec3(const std::string& name, const glm::vec3& value) {
|
||||||
|
glUniform3fv(GetUniformLocation(name), 1, &value[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::SetVec4(const std::string& name, const glm::vec4& value) {
|
||||||
|
glUniform4fv(GetUniformLocation(name), 1, &value[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Shader::SetMat4(const std::string& name, const glm::mat4& mat) {
|
||||||
|
glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, &mat[0][0]);
|
||||||
|
}
|
36
src/src/utils/Shader.h
Normal file
36
src/src/utils/Shader.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <gl/glew.h>
|
||||||
|
|
||||||
|
class Shader {
|
||||||
|
public:
|
||||||
|
Shader();
|
||||||
|
~Shader();
|
||||||
|
|
||||||
|
bool LoadFromFile(const std::string& vertexPath, const std::string& fragmentPath);
|
||||||
|
bool LoadFromSource(const std::string& vertexSrc, const std::string& fragmentSrc);
|
||||||
|
|
||||||
|
void Use() const;
|
||||||
|
GLuint GetID() const;
|
||||||
|
|
||||||
|
// Setters
|
||||||
|
void SetBool(const std::string& name, bool value);
|
||||||
|
void SetInt(const std::string& name, int value);
|
||||||
|
void SetFloat(const std::string& name, float value);
|
||||||
|
void SetVec2(const std::string& name, const glm::vec2& value);
|
||||||
|
void SetVec3(const std::string& name, const glm::vec3& value);
|
||||||
|
void SetVec4(const std::string& name, const glm::vec4& value);
|
||||||
|
void SetMat4(const std::string& name, const glm::mat4& mat);
|
||||||
|
|
||||||
|
private:
|
||||||
|
GLuint id = 0;
|
||||||
|
std::unordered_map<std::string, GLint> uniformCache;
|
||||||
|
|
||||||
|
std::string ReadFile(const std::string& path);
|
||||||
|
GLuint Compile(GLenum type, const std::string& source);
|
||||||
|
GLint GetUniformLocation(const std::string& name);
|
||||||
|
void Clear();
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user