its broke, idk. fix latter

This commit is contained in:
OusmBlueNinja 2024-12-25 00:38:12 -06:00
parent 55b521d9bc
commit fdac328a3f
11 changed files with 703 additions and 30 deletions

45
shaders/basic.frag Normal file
View File

@ -0,0 +1,45 @@
#version 330 core
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoords;
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
uniform Light light;
uniform Material material;
uniform vec3 viewPos;
void main()
{
// Ambient
vec3 ambient = light.ambient * texture(material.diffuse, TexCoords).rgb;
// Diffuse
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(light.position - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * texture(material.diffuse, TexCoords).rgb;
// Specular
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * texture(material.specular, TexCoords).rgb;
vec3 result = ambient + diffuse + specular;
FragColor = vec4(result, 1.0);
}

21
shaders/basic.vert Normal file
View File

@ -0,0 +1,21 @@
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;
layout (location = 2) in vec2 aTexCoords;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoords;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main()
{
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal;
TexCoords = aTexCoords;
gl_Position = projection * view * vec4(FragPos, 1.0);
}

5
src/CameraComponent.cpp Normal file
View File

@ -0,0 +1,5 @@
// src/CameraComponent.cpp
#include "CameraComponent.h"
// All methods are defined inline in the header for simplicity.
// You can move them to the cpp file if desired.

108
src/CameraComponent.h Normal file
View File

@ -0,0 +1,108 @@
// src/CameraComponent.h
#pragma once
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
struct CameraComponent {
glm::vec3 Position;
glm::vec3 Front;
glm::vec3 Up;
glm::vec3 Right;
glm::vec3 WorldUp;
// Euler Angles
float Yaw;
float Pitch;
// Camera options
float MovementSpeed;
float MouseSensitivity;
float Zoom;
CameraComponent(
glm::vec3 position = glm::vec3(0.0f, 0.0f, 3.0f),
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f),
float yaw = -90.0f,
float pitch = 0.0f
) : Front(glm::vec3(0.0f, 0.0f, -1.0f)),
MovementSpeed(2.5f),
MouseSensitivity(0.1f),
Zoom(45.0f)
{
Position = position;
WorldUp = up;
Yaw = yaw;
Pitch = pitch;
// Calculate the initial Front, Right, and Up vectors
glm::vec3 front;
front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
front.y = sin(glm::radians(Pitch));
front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
Front = glm::normalize(front);
Right = glm::normalize(glm::cross(Front, WorldUp));
Up = glm::normalize(glm::cross(Right, Front));
}
// Returns the view matrix calculated using Euler Angles and the LookAt Matrix
glm::mat4 GetViewMatrix()
{
return glm::lookAt(Position, Position + Front, Up);
}
// Processes input received from any keyboard-like input system.
void ProcessKeyboard(int direction, float deltaTime)
{
float velocity = MovementSpeed * deltaTime;
if (direction == 0) // Forward
Position += Front * velocity;
if (direction == 1) // Backward
Position -= Front * velocity;
if (direction == 2) // Left
Position -= Right * velocity;
if (direction == 3) // Right
Position += Right * velocity;
if (direction == 4) // Up
Position += Up * velocity;
if (direction == 5) // Down
Position -= Up * velocity;
}
// Processes input received from a mouse input system.
void ProcessMouseMovement(float xoffset, float yoffset, bool constrainPitch = true)
{
xoffset *= MouseSensitivity;
yoffset *= MouseSensitivity;
Yaw += xoffset;
Pitch += yoffset;
// Make sure that when pitch is out of bounds, screen doesn't get flipped
if(constrainPitch)
{
if(Pitch > 89.0f)
Pitch = 89.0f;
if(Pitch < -89.0f)
Pitch = -89.0f;
}
// Update Front, Right and Up Vectors using the updated Euler angles
glm::vec3 front;
front.x = cos(glm::radians(Yaw)) * cos(glm::radians(Pitch));
front.y = sin(glm::radians(Pitch));
front.z = sin(glm::radians(Yaw)) * cos(glm::radians(Pitch));
Front = glm::normalize(front);
Right = glm::normalize(glm::cross(Front, WorldUp));
Up = glm::normalize(glm::cross(Right, Front));
}
// Processes input received from a mouse scroll-wheel event.
void ProcessMouseScroll(float yoffset)
{
Zoom -= yoffset;
if(Zoom < 1.0f)
Zoom = 1.0f;
if(Zoom > 45.0f)
Zoom = 45.0f;
}
};

40
src/CameraSystem.h Normal file
View File

@ -0,0 +1,40 @@
// src/CameraSystem.h
#pragma once
#include "ECS.h"
#include "CameraComponent.h"
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
class CameraSystem {
public:
CameraSystem(GLFWwindow* window, float deltaTime)
: window(window), deltaTime(deltaTime) {}
void ProcessInput(EntityManager& em, ComponentManager& cm) {
// Iterate through entities with CameraComponent
const auto& entities = em.GetActiveEntities();
for(auto entity : entities) {
if(cm.HasComponent<CameraComponent>(entity)) {
auto& camera = cm.GetComponent<CameraComponent>(entity);
// Implement camera movement based on input
if(glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
camera.ProcessKeyboard(0, deltaTime); // Forward
if(glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
camera.ProcessKeyboard(1, deltaTime); // Backward
if(glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
camera.ProcessKeyboard(2, deltaTime); // Left
if(glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
camera.ProcessKeyboard(3, deltaTime); // Right
if(glfwGetKey(window, GLFW_KEY_SPACE) == GLFW_PRESS)
camera.ProcessKeyboard(4, deltaTime); // Up
if(glfwGetKey(window, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS)
camera.ProcessKeyboard(5, deltaTime); // Down
}
}
}
private:
GLFWwindow* window;
float deltaTime;
};

4
src/MeshComponent.cpp Normal file
View File

@ -0,0 +1,4 @@
// src/MeshComponent.cpp
#include "MeshComponent.h"
// You can add functions related to MeshComponent here if needed

22
src/MeshComponent.h Normal file
View File

@ -0,0 +1,22 @@
// src/MeshComponent.h
#pragma once
#include <string>
#include <vector>
#include <GL/glew.h>
#include <glm/glm.hpp>
struct Vertex {
glm::vec3 Position;
glm::vec3 Normal;
glm::vec2 TexCoords;
};
struct MeshComponent {
std::vector<Vertex> vertices;
std::vector<unsigned int> indices;
GLuint VAO, VBO, EBO;
MeshComponent() : VAO(0), VBO(0), EBO(0) {}
};

57
src/Meshes.h Normal file
View File

@ -0,0 +1,57 @@
// src/Meshes.h
#pragma once
#include "MeshComponent.h"
MeshComponent CreateCubeMesh() {
MeshComponent mesh;
// Define cube vertices
Vertex v1 = { glm::vec3(-0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec2(0.0f, 0.0f) };
Vertex v2 = { glm::vec3( 0.5f, -0.5f, -0.5f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec2(1.0f, 0.0f) };
Vertex v3 = { glm::vec3( 0.5f, 0.5f, -0.5f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec2(1.0f, 1.0f) };
Vertex v4 = { glm::vec3(-0.5f, 0.5f, -0.5f), glm::vec3(0.0f, 0.0f, -1.0f), glm::vec2(0.0f, 1.0f) };
// ... define other vertices for the cube
// For brevity, only defining front face. Define all 6 faces similarly.
// Front face
mesh.vertices = {
v1, v2, v3, v4,
// Define other vertices
};
// Define indices
mesh.indices = {
0, 1, 2,
2, 3, 0,
// Define other indices for other faces
};
// Generate buffers
glGenVertexArrays(1, &mesh.VAO);
glGenBuffers(1, &mesh.VBO);
glGenBuffers(1, &mesh.EBO);
glBindVertexArray(mesh.VAO);
glBindBuffer(GL_ARRAY_BUFFER, mesh.VBO);
glBufferData(GL_ARRAY_BUFFER, mesh.vertices.size() * sizeof(Vertex), &mesh.vertices[0], GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mesh.EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, mesh.indices.size() * sizeof(unsigned int), &mesh.indices[0], GL_STATIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
glEnableVertexAttribArray(0);
// Normal attribute
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));
glEnableVertexAttribArray(1);
// Texture coords attribute
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
glEnableVertexAttribArray(2);
glBindVertexArray(0);
return mesh;
}

120
src/ShaderComponent.cpp Normal file
View File

@ -0,0 +1,120 @@
// src/ShaderComponent.cpp
#include "ShaderComponent.h"
#include "Logger.h"
#include <fstream>
#include <sstream>
#include <iostream>
Shader::Shader(const char* vertexPath, const char* fragmentPath)
{
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
std::string fragmentCode;
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// Ensure ifstream objects can throw exceptions:
vShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
try
{
// Open files
vShaderFile.open(vertexPath);
fShaderFile.open(fragmentPath);
std::stringstream vShaderStream, fShaderStream;
// Read file's buffer contents into streams
vShaderStream << vShaderFile.rdbuf();
fShaderStream << fShaderFile.rdbuf();
// Close file handlers
vShaderFile.close();
fShaderFile.close();
// Convert stream into string
vertexCode = vShaderStream.str();
fragmentCode = fShaderStream.str();
}
catch(std::ifstream::failure& e)
{
Logger::GetInstance().Log(LogLevel::ERROR, "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ");
}
const char* vShaderCode = vertexCode.c_str();
const char * fShaderCode = fragmentCode.c_str();
// 2. Compile shaders
GLuint vertex, fragment;
int success;
char infoLog[512];
// Vertex Shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// Print compile errors if any
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
Logger::GetInstance().Log(LogLevel::ERROR, std::string("ERROR::SHADER::VERTEX::COMPILATION_FAILED\n") + infoLog);
};
// Fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
// Print compile errors if any
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
Logger::GetInstance().Log(LogLevel::ERROR, std::string("ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n") + infoLog);
};
// Shader Program
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
// Print linking errors if any
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if(!success) {
glGetProgramInfoLog(ID, 512, NULL, infoLog);
Logger::GetInstance().Log(LogLevel::ERROR, std::string("ERROR::SHADER::PROGRAM::LINKING_FAILED\n") + infoLog);
}
// Delete the shaders as they're linked into our program now and no longer necessary
glDeleteShader(vertex);
glDeleteShader(fragment);
}
void Shader::Use()
{
glUseProgram(ID);
}
void Shader::SetBool(const std::string &name, bool value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
void Shader::SetInt(const std::string &name, int value) const
{
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::SetFloat(const std::string &name, float value) const
{
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::SetMat4(const std::string &name, const glm::mat4 &mat) const
{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}
void Shader::SetVec3(const std::string &name, const glm::vec3 &vec) const
{
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &vec[0]);
}

22
src/ShaderComponent.h Normal file
View File

@ -0,0 +1,22 @@
// src/ShaderComponent.h
#pragma once
#include <string>
#include <GL/glew.h>
#include <glm/glm.hpp>
class Shader {
public:
GLuint ID;
Shader() : ID(0) {}
Shader(const char* vertexPath, const char* fragmentPath);
void Use();
void SetBool(const std::string &name, bool value) const;
void SetInt(const std::string &name, int value) const;
void SetFloat(const std::string &name, float value) const;
void SetMat4(const std::string &name, const glm::mat4 &mat) const;
void SetVec3(const std::string &name, const glm::vec3 &vec) const;
};

View File

@ -5,21 +5,26 @@
#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"
#include "../IconsFontAwesome6.h"
#include "../IconsFontAwesome6.h" // Ensure correct path
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h" // Include stb_image.h
#include "ECS.h" // Include the ECS header
#include "Logger.h" // Include the Logger header
#include "TextureManager.h" // Include the TextureManager header
#include "UI.h" // Include the UI header
#include "Meshes.h" // Include the Meshes header
#include "ShaderComponent.h" // Include the ShaderComponent header
#include "CameraSystem.h" // Include the CameraSystem header
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
// =====================
// Callback for GLFW errors
@ -30,6 +35,28 @@ static void glfw_error_callback(int error, const char* description)
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
}
// =====================
// Global Variables for Camera Control
// =====================
bool firstMouse = true;
float lastX = 1280.0f / 2.0f;
float lastY = 720.0f / 2.0f;
bool mouseCaptured = true;
// =====================
// Forward Declarations
// =====================
void mouse_callback(GLFWwindow* window, double xpos, double ypos);
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset);
// =====================
// Camera Entity ID
// =====================
Entity cameraEntity = UINT32_MAX;
// =====================
// Main Function
// =====================
@ -37,29 +64,42 @@ static void glfw_error_callback(int error, const char* description)
int main(int, char**)
{
// Setup Logger
//LOGPOINT("Loading Engine");
Logger::GetInstance().Log(LogLevel::INFO, "Loading engine...");
Logger::GetInstance().Log(LogLevel::INFO, "Loading Engine...");
// Setup GLFW error callback
glfwSetErrorCallback(glfw_error_callback);
// Initialize GLFW
if (!glfwInit())
return 1;
{
Logger::GetInstance().Log(LogLevel::ERROR, "Failed to initialize GLFW.");
return -1;
}
// GL 3.0 + GLSL 130
// GL 3.3 + GLSL 330
const char* glsl_version = "#version 330";
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
#ifdef __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
#endif
// Create window with graphics context
GLFWwindow* window = glfwCreateWindow(1280, 720, "Tesseract Engine", NULL, NULL);
GLFWwindow* window = glfwCreateWindow(1280, 720, "Tesseract Engine - 3D", NULL, NULL);
if (window == NULL)
return 1;
{
Logger::GetInstance().Log(LogLevel::ERROR, "Failed to create GLFW window.");
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
glfwSwapInterval(1); // Enable vsync
// Set viewport
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
@ -73,7 +113,7 @@ int main(int, char**)
fontConfig.MergeMode = true;
fontConfig.PixelSnapH = true;
// Path to your fonts
// Paths to your fonts
const char* font_path = "./assets/fonts/Roboto-Medium.ttf"; // Replace with your default font
const char* fa_font_path = "./assets/fonts/fa-solid-900.ttf"; // Replace with your Font Awesome font
@ -81,8 +121,8 @@ int main(int, char**)
ImFont* default_font = io.Fonts->AddFontFromFileTTF(font_path, 16.0f);
if (!default_font)
{
fprintf(stderr, "Failed to load default font!\n");
return 1;
Logger::GetInstance().Log(LogLevel::ERROR, "Failed to load default font!");
return -1;
}
// Define the Font Awesome icon range
@ -91,11 +131,10 @@ int main(int, char**)
// Merge Font Awesome icons
fontConfig.GlyphMinAdvanceX = 13.0f; // Adjust if necessary
ImFont* fa_font = io.Fonts->AddFontFromFileTTF(fa_font_path, 16.0f, &fontConfig, icons_ranges);
if (!fa_font)
{
fprintf(stderr, "Failed to load Font Awesome font!\n");
return 1;
Logger::GetInstance().Log(LogLevel::ERROR, "Failed to load Font Awesome font!");
return -1;
}
// Build the font atlas
@ -124,17 +163,67 @@ int main(int, char**)
ComponentManager componentManager;
entityManager.Init();
componentManager.RegisterComponent<TransformComponent>();
componentManager.RegisterComponent<SpriteComponent>();
componentManager.RegisterComponent<MeshComponent>();
componentManager.RegisterComponent<Shader>();
componentManager.RegisterComponent<CameraComponent>();
// Create a default entity with TransformComponent (without SpriteComponent)
// Create a default entity with TransformComponent, MeshComponent, Shader, and CameraComponent
Entity defaultEntity = entityManager.CreateEntity();
componentManager.AddComponent<TransformComponent>(defaultEntity, TransformComponent());
componentManager.AddComponent<MeshComponent>(defaultEntity, CreateCubeMesh());
Shader shader("shaders/basic.vert", "shaders/basic.frag");
componentManager.AddComponent<Shader>(defaultEntity, shader);
componentManager.AddComponent<CameraComponent>(defaultEntity, CameraComponent());
Logger::GetInstance().Log(LogLevel::INFO, "Engine initialized successfully.");
// Instantiate TextureManager
TextureManager textureManager;
// Load Textures if necessary
// GLuint diffuseMap = textureManager.LoadTexture("path_to_diffuse_map.png");
// GLuint specularMap = textureManager.LoadTexture("path_to_specular_map.png");
// Setup Framebuffer Object (FBO) for rendering
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
// Create a color attachment texture
GLuint texColorBuffer;
glGenTextures(1, &texColorBuffer);
glBindTexture(GL_TEXTURE_2D, texColorBuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, display_w, display_h, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColorBuffer, 0);
// Create a renderbuffer object for depth and stencil attachment
GLuint rbo;
glGenRenderbuffers(1, &rbo);
glBindRenderbuffer(GL_RENDERBUFFER, rbo);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, display_w, display_h);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
// Check if framebuffer is complete
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
Logger::GetInstance().Log(LogLevel::ERROR, "ERROR::FRAMEBUFFER:: Framebuffer is not complete!");
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Setup Camera System
float deltaTime = 0.0f; // Time between current frame and last frame
float lastFrame = 0.0f; // Time of last frame
CameraSystem cameraSystem(window, deltaTime);
// Setup Mouse Callbacks
glfwSetCursorPosCallback(window, mouse_callback);
glfwSetScrollCallback(window, scroll_callback);
// Capture the mouse cursor
glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
// Variables for Console
bool show_console = true;
@ -144,6 +233,11 @@ int main(int, char**)
// Main loop
while (!glfwWindowShouldClose(window))
{
// Per-frame time logic
float currentFrame = static_cast<float>(glfwGetTime());
deltaTime = currentFrame - lastFrame;
lastFrame = currentFrame;
// Poll and handle events (inputs, window resize, etc.)
glfwPollEvents();
@ -152,19 +246,101 @@ int main(int, char**)
ImGui_ImplGlfw_NewFrame();
ImGui::NewFrame();
// Bind to framebuffer and draw scene as we normally would to color texture
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glEnable(GL_DEPTH_TEST); // Enable depth testing for 3D
// Clear buffers
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use shader
Shader& activeShader = componentManager.GetComponent<Shader>(defaultEntity);
activeShader.Use();
// Retrieve camera view and projection matrices
glm::mat4 view;
glm::mat4 projection;
glm::vec3 cameraPos;
for(auto entity : entityManager.GetActiveEntities()) {
if(componentManager.HasComponent<CameraComponent>(entity)) {
auto& camera = componentManager.GetComponent<CameraComponent>(entity);
view = camera.GetViewMatrix();
cameraPos = camera.Position;
}
}
projection = glm::perspective(glm::radians(45.0f),
(float)display_w / (float)display_h,
0.1f, 100.0f);
// Set uniforms
activeShader.SetMat4("view", view);
activeShader.SetMat4("projection", projection);
activeShader.SetVec3("viewPos", cameraPos);
// Set light properties
activeShader.SetVec3("light.position", glm::vec3(1.2f, 1.0f, 2.0f));
activeShader.SetVec3("light.ambient", glm::vec3(0.2f, 0.2f, 0.2f));
activeShader.SetVec3("light.diffuse", glm::vec3(0.5f, 0.5f, 0.5f));
activeShader.SetVec3("light.specular", glm::vec3(1.0f, 1.0f, 1.0f));
// Set material properties
activeShader.SetInt("material.diffuse", 0);
activeShader.SetInt("material.specular", 1);
activeShader.SetFloat("material.shininess", 32.0f);
// Bind textures if any
// For example:
// glActiveTexture(GL_TEXTURE0);
// glBindTexture(GL_TEXTURE_2D, diffuseMap);
// glActiveTexture(GL_TEXTURE1);
// glBindTexture(GL_TEXTURE_2D, specularMap);
// Render all meshes
for(auto entity : entityManager.GetActiveEntities()) {
if(componentManager.HasComponent<MeshComponent>(entity) && componentManager.HasComponent<TransformComponent>(entity)) {
auto& mesh = componentManager.GetComponent<MeshComponent>(entity);
auto& transform = componentManager.GetComponent<TransformComponent>(entity);
// Create model matrix
glm::mat4 model = glm::mat4(1.0f);
model = glm::translate(model, transform.position);
model = glm::rotate(model, glm::radians(transform.rotation.x), glm::vec3(1.0f, 0.0f, 0.0f));
model = glm::rotate(model, glm::radians(transform.rotation.y), glm::vec3(0.0f, 1.0f, 0.0f));
model = glm::rotate(model, glm::radians(transform.rotation.z), glm::vec3(0.0f, 0.0f, 1.0f));
model = glm::scale(model, transform.scale);
activeShader.SetMat4("model", model);
// Bind VAO and draw
glBindVertexArray(mesh.VAO);
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}
}
// Unbind framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// Disable depth testing for UI rendering
glDisable(GL_DEPTH_TEST);
// Start ImGui frame
ImGui::NewFrame();
// Create DockSpace
ImGuiWindowFlags dockspace_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
const ImGuiViewport* viewport = ImGui::GetMainViewport();
const ImGuiViewport* viewport_main = ImGui::GetMainViewport();
// Adjust the docking space position by 20 pixels to avoid overlapping with the main menu bar
ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + 20));
ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, viewport->Size.y - 20));
ImGui::SetNextWindowViewport(viewport->ID);
ImGui::SetNextWindowPos(ImVec2(viewport_main->Pos.x, viewport_main->Pos.y));
ImGui::SetNextWindowSize(ImVec2(viewport_main->Size.x, viewport_main->Size.y));
ImGui::SetNextWindowViewport(viewport_main->ID);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::Begin("DockSpace", nullptr, dockspace_flags);
ImGui::Begin("DockSpaceWindow", nullptr, dockspace_flags);
ImGui::PopStyleVar(2);
// DockSpace
@ -178,16 +354,18 @@ int main(int, char**)
// Show GUI windows
ShowMainMenuBar();
ShowViewport(textureManager, entityManager, componentManager); // Pass references
ShowConsole(&show_console);
// Show ECS UI panels
ShowEntityTree(entityManager, componentManager, selectedEntity);
ShowInspector(entityManager, componentManager, selectedEntity);
ShowInspector(componentManager, selectedEntity);
// Render the framebuffer texture in the Viewport panel
ImGui::Begin("Viewport");
ImGui::Text("3D Viewport");
ImGui::Image((void*)(intptr_t)texColorBuffer, ImVec2(1280, 720), ImVec2(0,1), ImVec2(1,0));
ImGui::End();
// Rendering
ImGui::Render();
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
glViewport(0, 0, display_w, display_h);
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Dark background
@ -206,8 +384,16 @@ int main(int, char**)
*/
glfwSwapBuffers(window);
// Process camera input
cameraSystem.ProcessInput(entityManager, componentManager);
}
// Cleanup framebuffer objects
glDeleteFramebuffers(1, &framebuffer);
glDeleteTextures(1, &texColorBuffer);
glDeleteRenderbuffers(1, &rbo);
// Cleanup
textureManager.Cleanup();
ImGui_ImplOpenGL3_Shutdown();
@ -219,3 +405,46 @@ int main(int, char**)
return 0;
}
// =====================
// Mouse Movement Callback
// =====================
void mouse_callback(GLFWwindow* window, double xpos, double ypos)
{
if (cameraEntity == UINT32_MAX)
return;
auto& camera = EntityManager::GetInstance().GetComponent<CameraComponent>(cameraEntity); // Assuming GetInstance exists
if (!cameraEntity) return;
if (firstMouse)
{
lastX = static_cast<float>(xpos);
lastY = static_cast<float>(ypos);
firstMouse = false;
}
float xoffset = static_cast<float>(xpos) - lastX;
float yoffset = lastY - static_cast<float>(ypos); // Reversed since y-coordinates go from bottom to top
lastX = static_cast<float>(xpos);
lastY = static_cast<float>(ypos);
camera.ProcessMouseMovement(xoffset, yoffset);
}
// =====================
// Scroll Callback
// =====================
void scroll_callback(GLFWwindow* window, double xoffset, double yoffset)
{
if (cameraEntity == UINT32_MAX)
return;
auto& camera = EntityManager::GetInstance().GetComponent<CameraComponent>(cameraEntity); // Assuming GetInstance exists
if (!cameraEntity) return;
camera.ProcessMouseScroll(static_cast<float>(yoffset));
}