Shadows Test 1

This commit is contained in:
OusmBlueNinja 2024-11-27 11:51:31 -06:00
parent 864b0d60b9
commit 85fe3dbbe1
42 changed files with 1123 additions and 607 deletions

View File

@ -2,84 +2,61 @@ Entities:
- ID: 0
Name: Light
Components:
Transform:
Position: [-8.23400021, -0.379575908, 0.520573974]
Rotation: [1.5, 2.70000005, 342.5]
Scale: [1, 1, 1]
Light:
Type: 0
Intensity: 1
Color: [0, 1, 0]
Color: [1, 1, 1]
Constant: 1
Linear: 0.0900000036
Quadratic: 0.0320000015
cutOff: 0
outerCutOff: 39.7900009
Direction: [-0.200000003, -1, -0.300000012]
Transform:
Position: [-1.6726234, -0.228918433, 0.638042808]
Rotation: [1.5, 2.70000005, 342.5]
Scale: [1, 1, 1]
- ID: 1
Name: Cube
Components:
Render:
MeshName: model
Color: [1, 1, 1]
Transform:
Position: [0, 0, 0]
Rotation: [0, -166.600006, 0]
Scale: [0.100000001, 0.100000001, 0.100000001]
Position: [-1.21370173, -0.400000006, -8.60000038]
Rotation: [1.34287302e-05, -41.9440002, 1.62548586e-05]
Scale: [1, 1, 1]
Render:
MeshName: shelf
Color: [1, 1, 1]
- ID: 2
Name: Environment
Name: Light
Components:
Transform:
Position: [0, 0, 0]
Rotation: [0, 0, 0]
Scale: [18.7000008, 7.4000001, 10]
Render:
MeshName: WhiteCube
Color: [1, 1, 1]
- ID: 3
Name: LightBlue
Components:
Transform:
Position: [0, 1.8090117, 3.07234383]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
Light:
Type: 0
Intensity: 2
Color: [0, 0, 1]
Constant: 1
Linear: 0
Quadratic: 0.200000003
cutOff: 12.5
outerCutOff: 17.5
Direction: [-0.200000003, -1, -0.300000012]
- ID: 4
Name: LightRed
Components:
Transform:
Position: [-2.94120026, 1.60229158, -1.5770874]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
Light:
Type: 0
Intensity: 1
Color: [1, 0, 0]
Color: [1, 1, 1]
Constant: 1
Linear: 0.0900000036
Quadratic: 0.0320000015
cutOff: 12.5
outerCutOff: 17.5
Direction: [-0.200000003, -1, -0.300000012]
- ID: 5
Name: Camera
Components:
Transform:
Position: [-4.12095118, 0.57130301, -1.16569459]
Rotation: [0, 106.199997, 0]
Position: [0, -2.21429968, 4.51696587]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
- ID: 3
Name: Light
Components:
Light:
Type: 0
Intensity: 1
Color: [1, 1, 1]
Constant: 1
Linear: 0.0900000036
Quadratic: 0.0320000015
cutOff: 12.5
outerCutOff: 17.5
Direction: [-0.200000003, -1, -0.300000012]
Transform:
Position: [-4.97912979, 7.21913528, 4.91323614]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
Camera:
Zoom: 10
FOV: 45
Orthographic: false
NearPlane: 0.100000001
FarPlane: 1000

85
assets/Example.polys Normal file
View File

@ -0,0 +1,85 @@
Entities:
- ID: 0
Name: Light
Components:
Transform:
Position: [-1.6726234, -0.228918433, 0.638042808]
Rotation: [1.5, 2.70000005, 342.5]
Scale: [1, 1, 1]
Light:
Type: 0
Intensity: 1
Color: [0, 1, 0]
Constant: 1
Linear: 0.0900000036
Quadratic: 0.0320000015
cutOff: 0
outerCutOff: 39.7900009
Direction: [-0.200000003, -1, -0.300000012]
- ID: 1
Name: Cube
Components:
Transform:
Position: [-1.21370173, 1.20000005, 0]
Rotation: [55.3640938, 313.355988, 2.4872179e-05]
Scale: [1, 1, 1]
Render:
MeshName: WhiteCube
Color: [1, 1, 1]
- ID: 2
Name: Environment
Components:
Render:
MeshName: WhiteCube
Color: [1, 1, 1]
Transform:
Position: [0, 0, 0]
Rotation: [0, 0, 0]
Scale: [18.7000008, 7.4000001, 10]
- ID: 3
Name: LightBlue
Components:
Light:
Type: 0
Intensity: 2
Color: [0, 0, 1]
Constant: 1
Linear: 0
Quadratic: 0.200000003
cutOff: 12.5
outerCutOff: 17.5
Direction: [-0.200000003, -1, -0.300000012]
Transform:
Position: [0, 1.8090117, 3.07234383]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
- ID: 4
Name: LightRed
Components:
Light:
Type: 0
Intensity: 1
Color: [1, 0, 0]
Constant: 1
Linear: 0.0900000036
Quadratic: 0.0320000015
cutOff: 12.5
outerCutOff: 17.5
Direction: [-0.200000003, -1, -0.300000012]
Transform:
Position: [-2.94120026, 1.60229158, -1.5770874]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
- ID: 5
Name: Camera
Components:
Camera:
Zoom: 10
FOV: 45
Orthographic: false
NearPlane: 0.100000001
FarPlane: 1000
Transform:
Position: [-7.4000001, 0.899999976, -1.60000002]
Rotation: [0, 106.199997, 0]
Scale: [1, 1, 1]

18
assets/light.polys Normal file
View File

@ -0,0 +1,18 @@
Entities:
- ID: 0
Name: Entity 0
Components:
Light:
Type: 0
Intensity: 1
Color: [1, 1, 1]
Constant: 1
Linear: 0.0900000036
Quadratic: 0.0320000015
cutOff: 12.5
outerCutOff: 17.5
Direction: [-0.200000003, -1, -0.300000012]
Transform:
Position: [0, 0, 0]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -15,40 +15,40 @@ Collapsed=0
DockId=0x00000005,0
[Window][Game View]
Pos=312,28
Size=1213,680
Pos=311,28
Size=1214,704
Collapsed=0
DockId=0x00000009,0
[Window][Asset Panel]
Pos=8,519
Size=302,670
Pos=311,734
Size=625,455
Collapsed=0
DockId=0x00000008,0
DockId=0x00000007,0
[Window][Inspector]
Pos=1527,28
Size=385,779
Size=385,700
Collapsed=0
DockId=0x0000000B,0
[Window][Scene]
Pos=8,28
Size=302,489
Size=301,1161
Collapsed=0
DockId=0x00000007,0
DockId=0x00000001,0
[Window][Info]
Pos=312,710
Size=1213,479
Pos=938,734
Size=587,455
Collapsed=0
DockId=0x0000000A,0
DockId=0x00000008,0
[Window][Settings]
Pos=1527,809
Size=385,380
Pos=1527,730
Size=385,149
Collapsed=0
DockId=0x0000000C,0
DockId=0x0000000D,0
[Window][Camera Preview]
Pos=312,28
@ -56,18 +56,32 @@ Size=1213,779
Collapsed=0
DockId=0x00000009,1
[Window][Drop Target]
Pos=938,734
Size=587,455
Collapsed=0
DockId=0x00000008,1
[Window][Shadow Map]
Pos=1527,881
Size=385,308
Collapsed=0
DockId=0x0000000E,0
[Docking][Data]
DockSpace ID=0xC746EC7D Window=0x9DF47A72 Pos=8,28 Size=1904,1161 Split=X Selected=0x642CEEBB
DockNode ID=0x00000003 Parent=0xC746EC7D SizeRef=1517,1161 Split=X
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=302,1161 Split=Y Selected=0xE192E354
DockNode ID=0x00000007 Parent=0x00000001 SizeRef=302,489 Selected=0xE192E354
DockNode ID=0x00000008 Parent=0x00000001 SizeRef=302,670 Selected=0x9D571615
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1213,1161 Split=X
DockNode ID=0x00000005 Parent=0x00000002 SizeRef=197,1161 Selected=0x4E0EE8E4
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=1035,1161 Split=Y Selected=0x642CEEBB
DockNode ID=0x00000009 Parent=0x00000006 SizeRef=1266,680 CentralNode=1 Selected=0x642CEEBB
DockNode ID=0x0000000A Parent=0x00000006 SizeRef=1266,479 Selected=0xE534E588
DockNode ID=0x00000004 Parent=0xC746EC7D SizeRef=385,1161 Split=Y Selected=0xE7039252
DockNode ID=0x0000000B Parent=0x00000004 SizeRef=385,779 Selected=0xE7039252
DockNode ID=0x0000000C Parent=0x00000004 SizeRef=385,380 Selected=0x54723243
DockNode ID=0x00000001 Parent=0xC746EC7D SizeRef=301,1161 Selected=0xE192E354
DockNode ID=0x00000002 Parent=0xC746EC7D SizeRef=1601,1161 Split=X
DockNode ID=0x00000003 Parent=0x00000002 SizeRef=1517,1161 Split=X
DockNode ID=0x00000005 Parent=0x00000003 SizeRef=197,1161 Selected=0x4E0EE8E4
DockNode ID=0x00000006 Parent=0x00000003 SizeRef=1035,1161 Split=Y Selected=0x642CEEBB
DockNode ID=0x00000009 Parent=0x00000006 SizeRef=1266,704 CentralNode=1 Selected=0x642CEEBB
DockNode ID=0x0000000A Parent=0x00000006 SizeRef=1266,455 Split=X Selected=0x9D571615
DockNode ID=0x00000007 Parent=0x0000000A SizeRef=625,479 Selected=0x9D571615
DockNode ID=0x00000008 Parent=0x0000000A SizeRef=587,479 Selected=0xE534E588
DockNode ID=0x00000004 Parent=0x00000002 SizeRef=385,1161 Split=Y Selected=0xE7039252
DockNode ID=0x0000000B Parent=0x00000004 SizeRef=385,700 Selected=0xE7039252
DockNode ID=0x0000000C Parent=0x00000004 SizeRef=385,459 Split=Y Selected=0x54723243
DockNode ID=0x0000000D Parent=0x0000000C SizeRef=385,149 Selected=0x54723243
DockNode ID=0x0000000E Parent=0x0000000C SizeRef=385,308 Selected=0x77A73815

View File

@ -1,62 +0,0 @@
Entities:
- ID: 0
Name: Light
Components:
Light:
Type: 0
Intensity: 1
Color: [1, 0, 0]
Constant: 1
Linear: 0.0900000036
Quadratic: 0.0320000015
cutOff: 0
outerCutOff: 39.7900009
Direction: [-0.200000003, -1, -0.300000012]
Transform:
Position: [-8.23400021, -0.379575908, 0.520573974]
Rotation: [1.5, 2.70000005, 342.5]
Scale: [1, 1, 1]
- ID: 1
Name: Cube
Components:
Render:
MeshName: shelf
Color: [1, 1, 1]
Transform:
Position: [-1.21370173, 1.20000005, 0]
Rotation: [1.34287302e-05, -41.9440002, 1.62548586e-05]
Scale: [1, 1, 1]
- ID: 2
Name: Light
Components:
Transform:
Position: [0, -2.21429968, 4.51696587]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
Light:
Type: 0
Intensity: 1
Color: [0.186046124, 0, 1]
Constant: 1
Linear: 0.0900000036
Quadratic: 0.0320000015
cutOff: 12.5
outerCutOff: 17.5
Direction: [-0.200000003, -1, -0.300000012]
- ID: 3
Name: Light
Components:
Transform:
Position: [-4.97912979, 7.21913528, 4.91323614]
Rotation: [0, 0, 0]
Scale: [1, 1, 1]
Light:
Type: 0
Intensity: 1
Color: [0, 1, 0]
Constant: 1
Linear: 0.0900000036
Quadratic: 0.0320000015
cutOff: 12.5
outerCutOff: 17.5
Direction: [-0.200000003, -1, -0.300000012]

198
shaders/cube_shader.fs Normal file
View File

@ -0,0 +1,198 @@
// cube_fragment_shader.fs
#version 330 core
// Outputs
out vec4 FragColor;
// Inputs from Vertex Shader
in VS_OUT {
vec3 FragPos; // Fragment position in world space
vec3 Normal; // Fragment normal in world space
vec2 TexCoords; // Texture coordinates
vec4 FragPosLightSpace; // Fragment position in light space
} fs_in;
// Structures for different light types
struct DirLight {
vec3 direction; // Direction of the light
vec3 color; // Color/intensity of the light
};
struct PointLight {
vec3 position; // Position of the light
vec3 color; // Color/intensity of the light
float constant; // Attenuation constant
float linear; // Attenuation linear factor
float quadratic; // Attenuation quadratic factor
};
struct SpotLight {
vec3 position; // Position of the light
vec3 direction; // Direction the spotlight is pointing
vec3 color; // Color/intensity of the light
float cutOff; // Inner cutoff angle (in degrees)
float outerCutOff; // Outer cutoff angle (in degrees)
float constant; // Attenuation constant
float linear; // Attenuation linear factor
float quadratic; // Attenuation quadratic factor
};
// Maximum number of each light type
#define MAX_POINT_LIGHTS 10
#define MAX_DIR_LIGHTS 10
#define MAX_SPOT_LIGHTS 10
// Uniforms for lights
uniform DirLight dirLights[MAX_DIR_LIGHTS];
uniform int numDirLights;
uniform PointLight pointLights[MAX_POINT_LIGHTS];
uniform int numPointLights;
uniform SpotLight spotLights[MAX_SPOT_LIGHTS];
uniform int numSpotLights;
// Camera position
uniform vec3 viewPos;
// Shadow map
uniform sampler2D shadowMap;
// Texture samplers
uniform sampler2D diffuseMap;
uniform sampler2D specularMap;
// Function to calculate shadow with PCF
float ShadowCalculation(vec4 fragPosLightSpace)
{
// Perform perspective divide
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
// Transform to [0,1] range
projCoords = projCoords * 0.5 + 0.5;
// Get closest depth value from light's perspective (using [0,1] range fragPos as coords)
float closestDepth = texture(shadowMap, projCoords.xy).r;
// Get depth of current fragment from light's perspective
float currentDepth = projCoords.z;
// Bias to prevent shadow acne
float bias = 0.005;
// PCF parameters
float shadow = 0.0;
vec2 texelSize = 1.0 / textureSize(shadowMap, 0);
int samples = 2; // Number of samples per axis (total samples = (2*samples +1)^2)
for(int x = -samples; x <= samples; ++x)
{
for(int y = -samples; y <= samples; ++y)
{
float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x, y) * texelSize).r;
shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
}
}
shadow /= float((2 * samples + 1) * (2 * samples + 1));
// Keep the shadow at 0.0 when outside the far_plane region of light's orthographic projection
if(projCoords.z > 1.0)
shadow = 0.0;
return shadow;
}
void main()
{
// Sample textures
vec3 diffuseColor = texture(diffuseMap, fs_in.TexCoords).rgb;
vec3 specularColor = texture(specularMap, fs_in.TexCoords).rgb;
// Properties
vec3 color = diffuseColor; // Use texture color
vec3 normal = normalize(fs_in.Normal);
vec3 viewDir = normalize(viewPos - fs_in.FragPos);
// Initialize ambient component
vec3 ambient = 0.1 * color; // Adjust ambient strength as needed
vec3 lighting = ambient;
// Iterate over directional lights
for(int i = 0; i < numDirLights; ++i)
{
// Directional light properties
vec3 lightDir = normalize(-dirLights[i].direction);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
vec3 diffuse = diff * dirLights[i].color * color;
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0); // Shininess factor
vec3 specular = spec * specularColor * dirLights[i].color;
// Calculate shadow
float shadow = ShadowCalculation(fs_in.FragPosLightSpace);
// Accumulate lighting with shadow influence
lighting += (1.0 - shadow) * (diffuse + specular);
}
// Iterate over point lights
for(int i = 0; i < numPointLights; ++i)
{
// Point light properties
vec3 lightDir = normalize(pointLights[i].position - fs_in.FragPos);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
vec3 diffuse = diff * pointLights[i].color * color;
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);
vec3 specular = spec * specularColor * pointLights[i].color;
// Attenuation
float distance = length(pointLights[i].position - fs_in.FragPos);
float attenuation = 1.0 / (pointLights[i].constant + pointLights[i].linear * distance +
pointLights[i].quadratic * (distance * distance));
// Accumulate lighting with attenuation
lighting += attenuation * (diffuse + specular);
}
// Iterate over spotlights
for(int i = 0; i < numSpotLights; ++i)
{
// Spotlight properties
vec3 lightDir = normalize(spotLights[i].position - fs_in.FragPos);
float theta = dot(lightDir, normalize(-spotLights[i].direction));
float epsilon = spotLights[i].cutOff - spotLights[i].outerCutOff;
float intensity = clamp((theta - spotLights[i].outerCutOff) / epsilon, 0.0, 1.0);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
vec3 diffuse = diff * spotLights[i].color * color;
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);
vec3 specular = spec * specularColor * spotLights[i].color;
// Attenuation
float distance = length(spotLights[i].position - fs_in.FragPos);
float attenuation = 1.0 / (spotLights[i].constant + spotLights[i].linear * distance +
spotLights[i].quadratic * (distance * distance));
// Accumulate lighting with attenuation and spotlight intensity
lighting += attenuation * intensity * (diffuse + specular);
}
// Final fragment color
FragColor = vec4(lighting, 1.0);
}

39
shaders/cube_shader.vs Normal file
View File

@ -0,0 +1,39 @@
// cube_vertex_shader.vs
#version 330 core
// Vertex Attributes
layout(location = 0) in vec3 aPos; // Vertex position
layout(location = 1) in vec3 aNormal; // Vertex normal
layout(location = 2) in vec2 aTexCoords; // Texture coordinates
// Uniform Matrices
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 lightSpaceMatrix;
// Output to Fragment Shader
out VS_OUT {
vec3 FragPos; // Fragment position in world space
vec3 Normal; // Fragment normal in world space
vec2 TexCoords; // Texture coordinates
vec4 FragPosLightSpace; // Fragment position in light space
} fs_in;
void main()
{
// Calculate fragment position in world space
fs_in.FragPos = vec3(model * vec4(aPos, 1.0));
// Calculate and normalize the normal vector in world space
fs_in.Normal = mat3(transpose(inverse(model))) * aNormal;
// Pass through texture coordinates
fs_in.TexCoords = aTexCoords;
// Calculate fragment position in light space for shadow mapping
fs_in.FragPosLightSpace = lightSpaceMatrix * vec4(fs_in.FragPos, 1.0);
// Final vertex position in clip space
gl_Position = projection * view * vec4(fs_in.FragPos, 1.0);
}

12
shaders/depth_shader.fs Normal file
View File

@ -0,0 +1,12 @@
// depth_fragment_shader.fs
#version 330 core
// Inputs from Vertex Shader
in vec4 FragPosLightSpace;
// Output
void main()
{
// The depth value is automatically written to the depth buffer
// No need to output any color
}

24
shaders/depth_shader.vs Normal file
View File

@ -0,0 +1,24 @@
// depth_vertex_shader.vs
#version 330 core
// Vertex Attributes
layout(location = 0) in vec3 aPos;
// Uniform Matrices
uniform mat4 model;
uniform mat4 lightSpaceMatrix;
// Output to Fragment Shader
out vec4 FragPosLightSpace;
void main()
{
// Calculate fragment position in world space
vec3 FragPos = vec3(model * vec4(aPos, 1.0));
// Calculate fragment position in light space
FragPosLightSpace = lightSpaceMatrix * vec4(FragPos, 1.0);
// Final vertex position in clip space
gl_Position = FragPosLightSpace;
}

View File

@ -32,7 +32,7 @@ std::string GetCurrentTimestamp() {
}
// Function to add a new log message with timestamp
void AddLogMessage(const std::string& message) {
void LogMessage(const std::string& message) {
std::lock_guard<std::mutex> lock(g_LogMutex);
// Create the log entry with timestamp
@ -61,7 +61,7 @@ void DrawLogTerminal(const char* title, bool* p_open) {
ImGui::Separator();
// Child region for scrolling
ImGui::BeginChild("ScrollingRegion", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
ImGui::BeginChild("ScrollingRegion", ImVec2(-1, -1), false, ImGuiWindowFlags_HorizontalScrollbar);
// Lock the mutex to safely access the log buffer
{

View File

@ -14,7 +14,7 @@ extern std::mutex g_LogMutex;
constexpr size_t MAX_LOG_MESSAGES = 1000;
// Function to add a new log message
void AddLogMessage(const std::string& message);
void LogMessage(const std::string& message);
// Function to draw the log terminal
void DrawLogTerminal(const char* title = "Terminal", bool* p_open = nullptr);

View File

@ -7,6 +7,7 @@
#include <fstream>
#include <glm/glm.hpp>
#include <GL/glew.h>
#include <yaml-cpp/yaml.h>
class RenderComponent : public Component
@ -15,6 +16,10 @@ public:
std::string meshName;
glm::vec3 color;
// Texture IDs
GLuint diffuseMap;
GLuint specularMap;
RenderComponent();
virtual const std::string& GetName() const override;
static const std::string& GetStaticName();

View File

@ -1,14 +1,13 @@
// Shader.cpp
#include "Shader.h"
#include <fstream>
#include <sstream>
#include <iostream>
#include <filesystem> // C++17 feature for file existence
#include <glm/gtc/type_ptr.hpp>
#include <GL/glew.h>
#include <glm/glm.hpp>
namespace fs = std::filesystem;
// Shader constructor
Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
Shader::Shader(const char* vertexPath, const char* fragmentPath)
{
// 1. Retrieve the vertex/fragment source code from filePath
std::string vertexCode;
@ -16,7 +15,17 @@ Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
std::ifstream vShaderFile;
std::ifstream fShaderFile;
// Ensure ifstream objects can throw exceptions
// Check if shader files exist
if (!fs::exists(vertexPath)) {
std::cerr << "ERROR::SHADER::VERTEX_SHADER_FILE_NOT_FOUND: " << vertexPath << "\n";
return;
}
if (!fs::exists(fragmentPath)) {
std::cerr << "ERROR::SHADER::FRAGMENT_SHADER_FILE_NOT_FOUND: " << fragmentPath << "\n";
return;
}
// Ensure ifstream objects can throw exceptions:
vShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
fShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
try
@ -25,12 +34,15 @@ Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
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();
@ -38,85 +50,87 @@ Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
catch (std::ifstream::failure& e)
{
std::cerr << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ\n";
std::cerr << "Failed to read shader files: " << vertexPath << " and " << fragmentPath << "\n";
return;
}
const GLchar* vShaderCode = vertexCode.c_str();
const GLchar* fShaderCode = fragmentCode.c_str();
const char* vShaderCode = vertexCode.c_str();
const char * fShaderCode = fragmentCode.c_str();
// 2. Compile shaders
GLuint vertex, fragment;
GLint success;
GLchar infoLog[512];
GLchar infoLog[1024];
// Vertex Shader
vertex = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vertex, 1, &vShaderCode, NULL);
glCompileShader(vertex);
// Check compile errors
// Print compile errors if any
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
std::cerr << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << '\n';
glGetShaderInfoLog(vertex, 1024, NULL, infoLog);
std::cerr << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << "\n";
}
// Fragment Shader
fragment = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(fragment, 1, &fShaderCode, NULL);
glCompileShader(fragment);
// Check compile errors
// Print compile errors if any
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
if(!success)
{
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
std::cerr << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << '\n';
glGetShaderInfoLog(fragment, 1024, NULL, infoLog);
std::cerr << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << "\n";
}
// Shader Program
Program = glCreateProgram();
glAttachShader(Program, vertex);
glAttachShader(Program, fragment);
glLinkProgram(Program);
// Check linking errors
glGetProgramiv(Program, GL_LINK_STATUS, &success);
ID = glCreateProgram();
glAttachShader(ID, vertex);
glAttachShader(ID, fragment);
glLinkProgram(ID);
// Print linking errors if any
glGetProgramiv(ID, GL_LINK_STATUS, &success);
if(!success)
{
glGetProgramInfoLog(Program, 512, NULL, infoLog);
std::cerr << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << '\n';
glGetProgramInfoLog(ID, 1024, NULL, infoLog);
std::cerr << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << "\n";
}
// Delete the shaders
// Delete the shaders as they're linked into our program now and no longer necessary
glDeleteShader(vertex);
glDeleteShader(fragment);
}
// Activate the shader
void Shader::Use()
{
glUseProgram(Program);
}
// Set integer uniform
void Shader::setInt(const std::string& name, int value) const
{
glUniform1i(glGetUniformLocation(Program, name.c_str()), value);
glUseProgram(ID);
}
void Shader::SetBool(const std::string &name, bool value) const
{
glUniform1i(glGetUniformLocation(Program, name.c_str()), (int)value);
glUniform1i(glGetUniformLocation(ID, name.c_str()), (int)value);
}
void Shader::SetInt(const std::string &name, int value) const
{
glUniform1i(glGetUniformLocation(Program, name.c_str()), value);
glUniform1i(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::SetFloat(const std::string &name, float value) const
{
glUniform1f(glGetUniformLocation(Program, name.c_str()), value);
glUniform1f(glGetUniformLocation(ID, name.c_str()), value);
}
void Shader::SetVec3(const std::string &name, const glm::vec3 &value) const
{
glUniform3fv(glGetUniformLocation(Program, name.c_str()), 1, glm::value_ptr(value));
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
}
void Shader::SetMat4(const std::string &name, const glm::mat4 &mat) const
{
glUniformMatrix4fv(glGetUniformLocation(ID, name.c_str()), 1, GL_FALSE, &mat[0][0]);
}

View File

@ -1,30 +1,26 @@
#ifndef SHADER_H
#define SHADER_H
// Shader.h
#pragma once
#include <GL/glew.h>
#include <string>
#include <GL/glew.h>
#include <glm/glm.hpp>
class Shader {
public:
GLuint Program; // The program ID
GLuint ID;
// Constructor reads and builds the shader
Shader(const GLchar* vertexPath, const GLchar* fragmentPath);
Shader(const char* vertexPath, const char* fragmentPath);
// Use/activate the shader
// Use the shader
void Use();
// Utility uniform functions
void setInt(const std::string& name, int value) const;
// Utility uniform functions
// Utility functions to set uniforms
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 SetVec3(const std::string &name, const glm::vec3 &value) const;
void SetMat4(const std::string &name, const glm::mat4 &mat) const;
};
#endif // SHADER_H

View File

@ -68,7 +68,13 @@ const int MAX_SPOT_LIGHTS = 64;
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/euler_angles.hpp> // For yawPitchRoll in light calculations
#define DEBUG 1
#ifdef DEBUG
#define LOGPOINT(msg) std::cout << "[POLYDBG] [" << __func__ << ":" << __LINE__ << "] " << (msg) << std::endl;
#else
#define LOGPOINT(msg)
#endif
#define MAX_LIGHTS 256
@ -99,13 +105,12 @@ Shader *gizmoShader = nullptr;
Shader *FrustumShader = nullptr;
Shader *previewShader = nullptr;
Shader *depthShader = nullptr;
GLuint framebuffer = 0;
GLuint renderedTexture = 0;
GLuint depthRenderbuffer = 0;
std::shared_ptr<Entity> selectedEntity = nullptr;
std::shared_ptr<Asset> selectedAsset = nullptr;
std::filesystem::path assetsDir = "./assets/";
@ -126,7 +131,7 @@ void RenderCube(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3
void ShowEntityComponentTree(std::vector<std::shared_ptr<Entity>> &entities, std::shared_ptr<Entity> &selectedEntity);
void ShowInspector(std::shared_ptr<Entity> &selectedEntity);
void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities);
void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities, std::shared_ptr<Entity> &selectedEntity);
void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_ptr<Asset> &selectedAsset, std::vector<std::shared_ptr<Entity>> &entities);
@ -145,10 +150,8 @@ bool InitializeImGui(GLFWwindow* window, const char* glsl_version);
void Cleanup(GLFWwindow *window);
void MainLoop(GLFWwindow *window, std::vector<std::shared_ptr<Entity>> &entities, std::shared_ptr<Entity> &selectedEntity, std::shared_ptr<Asset> &selectedAsset, const std::filesystem::path &assetsDir, Settings &settings);
void Cleanup(GLFWwindow* window) {
void Cleanup(GLFWwindow *window)
{
LOGPOINT("Remember to add this");
// void Cleanup(GLFWwindow* window)
@ -180,20 +183,14 @@ void Cleanup(GLFWwindow* window) {
// glfwDestroyWindow(window);
// glfwTerminate();
// }
}
// Function to retrieve the active game camera (first CameraComponent found)
std::shared_ptr<CameraComponent> GetActiveGameCamera(const std::vector<std::shared_ptr<Entity>> &entities)
{
auto it = std::find_if(entities.begin(), entities.end(),
[](const std::shared_ptr<Entity>& entity) {
[](const std::shared_ptr<Entity> &entity)
{
return entity->GetComponent<CameraComponent>() != nullptr;
});
@ -203,18 +200,16 @@ std::shared_ptr<CameraComponent> GetActiveGameCamera(const std::vector<std::shar
}
// Log a warning if no camera is found
std::cerr << "[Poly] Warning: No active game camera found in the scene." << std::endl;
// std::cerr << "[Poly] Warning: No active game camera found in the scene." << std::endl;
return nullptr;
}
// Helper function to find the entity owning a specific CameraComponent
std::shared_ptr<Entity> FindEntityWithCamera(const std::vector<std::shared_ptr<Entity>> &entities, const std::shared_ptr<CameraComponent> &camera)
{
auto it = std::find_if(entities.begin(), entities.end(),
[&camera](const std::shared_ptr<Entity>& entity) {
[&camera](const std::shared_ptr<Entity> &entity)
{
auto entityCamera = entity->GetComponent<CameraComponent>();
return entityCamera && entityCamera == camera;
});
@ -332,10 +327,10 @@ void RenderLightGizmo(const glm::vec3& position, const glm::mat4& view, const gl
glm::scale(glm::mat4(1.0f), glm::vec3(0.05f));
// Set shader uniforms
GLint modelLoc = glGetUniformLocation(gizmoShader->Program, "model");
GLint viewLoc = glGetUniformLocation(gizmoShader->Program, "view");
GLint projLoc = glGetUniformLocation(gizmoShader->Program, "projection");
GLint colorLoc = glGetUniformLocation(gizmoShader->Program, "gizmoColor");
GLint modelLoc = glGetUniformLocation(gizmoShader->ID, "model");
GLint viewLoc = glGetUniformLocation(gizmoShader->ID, "view");
GLint projLoc = glGetUniformLocation(gizmoShader->ID, "projection");
GLint colorLoc = glGetUniformLocation(gizmoShader->ID, "gizmoColor");
if (modelLoc == -1 || viewLoc == -1 || projLoc == -1 || colorLoc == -1)
{
@ -404,12 +399,12 @@ void RenderCameraGizmo(glm::vec3 position, glm::vec3 direction, glm::mat4 view,
model = glm::scale(model, glm::vec3(0.1f, 0.1f, 0.1f)); // Adjust scale as needed
// Set uniforms
glUniformMatrix4fv(glGetUniformLocation(gizmoShader->Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(glGetUniformLocation(gizmoShader->Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(gizmoShader->Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(gizmoShader->ID, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(glGetUniformLocation(gizmoShader->ID, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(gizmoShader->ID, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
// Set gizmo color (e.g., white)
glUniform3f(glGetUniformLocation(gizmoShader->Program, "gizmoColor"), 1.0f, 1.0f, 1.0f);
glUniform3f(glGetUniformLocation(gizmoShader->ID, "gizmoColor"), 1.0f, 1.0f, 1.0f);
// Draw cone
glDrawArrays(GL_TRIANGLE_FAN, 0, segments + 2); // +2: one for the tip, one to close the circle
@ -569,10 +564,6 @@ void setupCube(GLfloat *vertices, size_t vertexArraySize, GLuint &cubeVAO, GLuin
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
// Entry point
int main()
{
@ -637,7 +628,6 @@ int main()
return -1;
}
// Have to initialize after imgui
glfwSetCursorPosCallback(window, MouseCallback);
glfwSetScrollCallback(window, ScrollCallback);
@ -650,7 +640,7 @@ int main()
// Log Engine Start
std::cout << "[Poly] Starting" << std::endl;
AddLogMessage("PolyEngine3D Version " + std::to_string(POLY_VERSION_MAJOR) + "." + std::to_string(POLY_VERSION_MINOR));
LogMessage("PolyEngine3D Version " + std::to_string(POLY_VERSION_MAJOR) + "." + std::to_string(POLY_VERSION_MINOR));
// Initialize entities and assets
std::vector<std::shared_ptr<Entity>> entities;
@ -662,7 +652,10 @@ int main()
settings.maxLights = MAX_LIGHTS;
// Enter the main loop
LOGPOINT("Entering Main Loop");
MainLoop(window, entities, selectedEntity, selectedAsset, assetsDir, settings);
LOGPOINT("Exiting Main Loop");
// Cleanup and exit
Cleanup(window);
@ -700,8 +693,6 @@ GLFWwindow* InitializeGLFW(int width, int height, const std::string& title)
// Enable VSync based on settings
glfwSwapInterval(0); // Enable vsync by default
return window;
}
@ -726,10 +717,12 @@ bool InitializeShaders()
{
try
{
cubeShader = new Shader("./shaders/vertex_shader.glsl", "./shaders/fragment_shader.glsl");
std::cout << "[Poly] Initializing shaders" << std::endl;
cubeShader = new Shader("./shaders/cube_shader.vs", "./shaders/cube_shader.fs");
gizmoShader = new Shader("./shaders/gizmo_vertex_shader.glsl", "./shaders/gizmo_fragment_shader.glsl");
previewShader = new Shader("shaders/preview_vertex.glsl", "shaders/preview_fragment.glsl");
FrustumShader = new Shader("./shaders/cam_vertex.glsl", "./shaders/cam_frag.glsl");
depthShader = new Shader("./shaders/depth_shader.vs", "./shaders/depth_shader.fs");
}
catch (const std::exception &e)
{
@ -812,8 +805,7 @@ bool SetupCube()
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, -0.5f,0.0f, 1.0f, 0.0f
};
-0.5f, 0.5f, -0.5f, 0.0f, 1.0f, 0.0f};
// Generate and bind VAO and VBO
glGenVertexArrays(1, &cubeVAO);
@ -870,12 +862,89 @@ bool SetupFramebuffer(int width, int height)
return true;
}
// Function to render the drop target with visual feedback
void RenderDropTarget()
{
// Begin the "Drop Target" window
ImGui::Begin("Drop Target");
// Define the size of the drop target area
// Use -1 to make it take the full available width, and set a fixed height (e.g., 100)
ImVec2 drop_target_size = ImVec2(-1.0f, 100.0f);
// Begin the drop target area as a child window
ImGui::BeginChild("##DropTargetChild", drop_target_size, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
// Variable to track if a drag is over the drop target
bool is_drag_over = false;
// Get the draw list for custom drawing
ImDrawList *draw_list = ImGui::GetWindowDrawList();
// Get the screen position of the child window
ImVec2 child_pos = ImGui::GetCursorScreenPos();
// Get the size of the child window
ImVec2 child_size = drop_target_size;
// Create an Invisible Button that covers the entire child window
// This allows the drop target to capture drag events without interfering with the UI layout
ImGui::InvisibleButton("##drop_target_button", child_size);
// Check if a drag-and-drop payload is hovering over the drop target
if (ImGui::BeginDragDropTarget())
{
if (const ImGuiPayload *payload = ImGui::AcceptDragDropPayload("DND_ASSET_PATH"))
{
if (payload->Data != nullptr)
{
// Assuming the payload is a null-terminated string
const char *droppedPath = static_cast<const char *>(payload->Data);
LogMessage("Dropped asset path: " + std::string(droppedPath));
// You can add additional handling here, such as loading the asset or updating the UI
}
}
// Indicate that a drag is over the drop target
is_drag_over = true;
ImGui::EndDragDropTarget();
}
// If a drag is over, draw a semi-transparent overlay to indicate the drop target is active
if (is_drag_over)
{
// Define the color for the overlay (e.g., semi-transparent yellow)
ImU32 overlay_color = IM_COL32(255, 255, 0, 100); // RGBA
// Draw a filled rectangle over the entire child window
draw_list->AddRectFilled(child_pos, ImVec2(child_pos.x + child_size.x, child_pos.y + child_size.y), overlay_color);
}
// Center the instructional text within the drop target area
const char *drop_text = "Drop Assets Here";
ImVec2 text_size = ImGui::CalcTextSize(drop_text);
ImVec2 text_pos = ImVec2(
(child_size.x - text_size.x) * 0.5f,
(child_size.y - text_size.y) * 0.5f);
ImGui::SetCursorPos(ImVec2(text_pos.x, text_pos.y));
ImGui::Text(drop_text);
// End the child window
ImGui::EndChild();
// End the "Drop Target" window
ImGui::End();
}
bool InitializeImGui(GLFWwindow *window, const char *glsl_version)
{
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGuiIO &io = ImGui::GetIO();
(void)io;
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable docking
// Setup Dear ImGui style
@ -901,8 +970,6 @@ bool InitializeImGui(GLFWwindow* window, const char* glsl_version)
return false;
}
// Configure ImGui style
ImGuiStyle &style = ImGui::GetStyle();
style.WindowBorderSize = 0.0f;
@ -963,7 +1030,7 @@ void MainLoop(GLFWwindow* window, std::vector<std::shared_ptr<Entity>>& entities
if (ImGui::MenuItem("Save Scene"))
{
SaveScene(entities, "./scene.polys"); // Assumed to be defined elsewhere
AddLogMessage("Scene saved to ./scene.polys");
LogMessage("Scene saved to ./scene.polys");
}
if (ImGui::MenuItem("Save Scene As"))
@ -973,7 +1040,7 @@ void MainLoop(GLFWwindow* window, std::vector<std::shared_ptr<Entity>>& entities
{
std::filesystem::path destinationPath(selectedFile);
SaveScene(entities, destinationPath.string());
AddLogMessage("Scene saved to " + destinationPath.string());
LogMessage("Scene saved to " + destinationPath.string());
}
}
@ -981,7 +1048,7 @@ void MainLoop(GLFWwindow* window, std::vector<std::shared_ptr<Entity>>& entities
{
LoadScene(entities, "./scene.polys"); // Assumed to be defined elsewhere
selectedEntity = nullptr; // Reset selected entity
AddLogMessage("Scene loaded from ./scene.polys");
LogMessage("Scene loaded from ./scene.polys");
}
ImGui::EndMenu();
@ -996,14 +1063,14 @@ void MainLoop(GLFWwindow* window, std::vector<std::shared_ptr<Entity>>& entities
SaveScene(entities, "./$tmpPly.polys");
selectedEntity = nullptr;
GameRunning = true;
AddLogMessage("Game started.");
LogMessage("Game started.");
}
else
{
LoadScene(entities, "./$tmpPly.polys");
selectedEntity = nullptr;
GameRunning = false;
AddLogMessage("Game stopped.");
LogMessage("Game stopped.");
}
}
ImGui::EndMenu();
@ -1012,6 +1079,8 @@ void MainLoop(GLFWwindow* window, std::vector<std::shared_ptr<Entity>>& entities
ImGui::EndMainMenuBar();
}
RenderDropTarget();
// Get the framebuffer size
int display_w, display_h;
glfwGetFramebufferSize(window, &display_w, &display_h);
@ -1020,7 +1089,7 @@ void MainLoop(GLFWwindow* window, std::vector<std::shared_ptr<Entity>>& entities
DrawSettingsWindow(settings, fps, window); // Assumed to be defined elsewhere
ShowEntityComponentTree(entities, selectedEntity);
ShowInspector(selectedEntity);
ShowGameView(entities); // Assumed to be defined elsewhere
ShowGameView(entities, selectedEntity); // Assumed to be defined elsewhere
ShowAssetPanel(assetsDir, selectedAsset, entities); // Refactored earlier
DrawLogTerminal("Info"); // Assumed to be defined elsewhere
@ -1044,19 +1113,18 @@ void MainLoop(GLFWwindow* window, std::vector<std::shared_ptr<Entity>>& entities
}
}
void RenderCube(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 viewPos, glm::vec3 lightPos, glm::vec3 objectColor)
{
cubeShader->Use();
// Set uniforms
glUniformMatrix4fv(glGetUniformLocation(cubeShader->Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(glGetUniformLocation(cubeShader->Program, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(cubeShader->Program, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniformMatrix4fv(glGetUniformLocation(cubeShader->ID, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniformMatrix4fv(glGetUniformLocation(cubeShader->ID, "view"), 1, GL_FALSE, glm::value_ptr(view));
glUniformMatrix4fv(glGetUniformLocation(cubeShader->ID, "projection"), 1, GL_FALSE, glm::value_ptr(projection));
glUniform3fv(glGetUniformLocation(cubeShader->Program, "lightPos"), 1, glm::value_ptr(lightPos));
glUniform3fv(glGetUniformLocation(cubeShader->Program, "viewPos"), 1, glm::value_ptr(viewPos));
glUniform3fv(glGetUniformLocation(cubeShader->Program, "objectColor"), 1, glm::value_ptr(objectColor));
glUniform1i(glGetUniformLocation(cubeShader->Program, "useTexture"), false);
glUniform3fv(glGetUniformLocation(cubeShader->ID, "lightPos"), 1, glm::value_ptr(lightPos));
glUniform3fv(glGetUniformLocation(cubeShader->ID, "viewPos"), 1, glm::value_ptr(viewPos));
glUniform3fv(glGetUniformLocation(cubeShader->ID, "objectColor"), 1, glm::value_ptr(objectColor));
glUniform1i(glGetUniformLocation(cubeShader->ID, "useTexture"), false);
// Draw cube
glBindVertexArray(cubeVAO);
@ -1086,8 +1154,6 @@ void ShowEntityComponentTree(std::vector<std::shared_ptr<Entity>> &entities, std
}
ImGui::SameLine();
}
ImGui::Separator();
@ -1161,7 +1227,6 @@ void ShowEntityComponentTree(std::vector<std::shared_ptr<Entity>> &entities, std
ImGui::End(); // End of Scene window
}
// Function to display error messages within the UI
void DisplayError(const std::string &message)
{
@ -1277,6 +1342,7 @@ void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_pt
// Set up the table with calculated columns
if (ImGui::BeginTable("AssetGridTable", columns, ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_SizingFixedFit))
{
ImGui::TableSetupScrollFreeze(0, 1); // Keep header row frozen
ImGui::TableHeadersRow(); // Optional: Add headers if needed
@ -1339,6 +1405,8 @@ void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_pt
{
try
{
LogMessage("Loading " + entry.path().string());
// Save the current scene to a temporary file
SaveScene(entities, "./scene.polys");
@ -1347,19 +1415,29 @@ void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_pt
// Update the selected asset with the new path
selectedAsset->path = entry.path();
}
catch (const std::exception &e)
{
// Display an error message if loading fails
DisplayError("Error loading scene: " + std::string(e.what()));
LOGPOINT("Error Loading Scene");
}
}
// Handle other file types here if necessary
}
// **Drag Source Implementation**
if (ImGui::BeginDragDropSource(ImGuiDragDropFlags_None))
{
// Set the payload to carry the file path
std::string filePath = entry.path().string();
ImGui::SetDragDropPayload("DND_ASSET_PATH", filePath.c_str(), filePath.size() + 1);
// Optional: Display preview while dragging
ImGui::Text("%s", label.c_str());
ImGui::EndDragDropSource();
}
// Optional: Add tooltip for better UX
if (ImGui::IsItemHovered())
{
@ -1386,7 +1464,6 @@ void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_pt
ImGui::End(); // End of Asset Panel window
}
void ShowInspector(std::shared_ptr<Entity> &selectedEntity)
{
ImGui::Begin("Inspector");
@ -1421,7 +1498,8 @@ void ShowInspector(std::shared_ptr<Entity> &selectedEntity)
if (ImGui::BeginPopup("AddComponentPopup"))
{
// List of available components with their corresponding add actions
struct ComponentInfo {
struct ComponentInfo
{
std::string name;
std::function<void()> addFunc;
};
@ -1429,31 +1507,26 @@ void ShowInspector(std::shared_ptr<Entity> &selectedEntity)
std::vector<ComponentInfo> availableComponents;
// Populate available components based on absence in the selected entity
auto addAvailableComponent = [&](const std::string &compName, std::function<void()> addFunc) {
auto addAvailableComponent = [&](const std::string &compName, std::function<void()> addFunc)
{
if (!selectedEntity->GetComponentByName(compName))
{
availableComponents.push_back({compName, addFunc});
}
};
addAvailableComponent("Transform Component", [&]() {
selectedEntity->AddComponent(std::make_shared<TransformComponent>());
});
addAvailableComponent("Render Component", [&]() {
selectedEntity->AddComponent(std::make_shared<RenderComponent>());
});
addAvailableComponent("Light Component", [&]() {
selectedEntity->AddComponent(std::make_shared<LightComponent>());
});
addAvailableComponent("RigidBody3D Component", [&]() {
selectedEntity->AddComponent(std::make_shared<RigidBody3DComponent>());
});
addAvailableComponent("CollisionShape3D Component", [&]() {
selectedEntity->AddComponent(std::make_shared<CollisionShape3DComponent>());
});
addAvailableComponent("Camera Component", [&]() {
selectedEntity->AddComponent(std::make_shared<CameraComponent>());
});
addAvailableComponent("Transform Component", [&]()
{ selectedEntity->AddComponent(std::make_shared<TransformComponent>()); });
addAvailableComponent("Render Component", [&]()
{ selectedEntity->AddComponent(std::make_shared<RenderComponent>()); });
addAvailableComponent("Light Component", [&]()
{ selectedEntity->AddComponent(std::make_shared<LightComponent>()); });
addAvailableComponent("RigidBody3D Component", [&]()
{ selectedEntity->AddComponent(std::make_shared<RigidBody3DComponent>()); });
addAvailableComponent("CollisionShape3D Component", [&]()
{ selectedEntity->AddComponent(std::make_shared<CollisionShape3DComponent>()); });
addAvailableComponent("Camera Component", [&]()
{ selectedEntity->AddComponent(std::make_shared<CameraComponent>()); });
// Render menu items for available components
for (const auto &comp : availableComponents)
@ -1475,7 +1548,8 @@ void ShowInspector(std::shared_ptr<Entity> &selectedEntity)
// -----------------------------
{
// Lambda to handle removal of components
auto removeComponent = [&](auto it) -> decltype(it) {
auto removeComponent = [&](auto it) -> decltype(it)
{
return selectedEntity->components.erase(it);
};
@ -1489,13 +1563,15 @@ void ShowInspector(std::shared_ptr<Entity> &selectedEntity)
if (ImGui::CollapsingHeader(component->GetName().c_str(), ImGuiTreeNodeFlags_DefaultOpen))
{
// Lambda to simplify setting component properties
auto handleTransformComponent = [&](std::shared_ptr<TransformComponent> transform) {
auto handleTransformComponent = [&](std::shared_ptr<TransformComponent> transform)
{
ImGui::DragFloat3("Position", glm::value_ptr(transform->position), 0.1f);
ImGui::DragFloat3("Rotation", glm::value_ptr(transform->rotation), 0.1f);
ImGui::DragFloat3("Scale", glm::value_ptr(transform->scale), 0.1f);
};
auto handleRenderComponent = [&](std::shared_ptr<RenderComponent> render) {
auto handleRenderComponent = [&](std::shared_ptr<RenderComponent> render)
{
char meshBuffer[128];
strncpy(meshBuffer, render->meshName.c_str(), sizeof(meshBuffer));
meshBuffer[sizeof(meshBuffer) - 1] = 0;
@ -1508,7 +1584,8 @@ void ShowInspector(std::shared_ptr<Entity> &selectedEntity)
ImGui::ColorEdit3("Color", glm::value_ptr(render->color));
};
auto handleLightComponent = [&](std::shared_ptr<LightComponent> light) {
auto handleLightComponent = [&](std::shared_ptr<LightComponent> light)
{
// Light Type Combo Box
const char *lightTypes[] = {"Point", "Directional", "Spot"};
int typeIndex = static_cast<int>(light->type);
@ -1543,7 +1620,8 @@ void ShowInspector(std::shared_ptr<Entity> &selectedEntity)
}
};
auto handleRigidBody3DComponent = [&](std::shared_ptr<RigidBody3DComponent> rigidBody) {
auto handleRigidBody3DComponent = [&](std::shared_ptr<RigidBody3DComponent> rigidBody)
{
ImGui::DragFloat3("Velocity", glm::value_ptr(rigidBody->velocity), 0.1f);
ImGui::DragFloat3("Acceleration", glm::value_ptr(rigidBody->acceleration), 0.1f);
ImGui::DragFloat("Mass", &rigidBody->mass, 0.1f, 0.1f, 100.0f);
@ -1557,7 +1635,8 @@ void ShowInspector(std::shared_ptr<Entity> &selectedEntity)
}
};
auto handleCollisionShape3DComponent = [&](std::shared_ptr<CollisionShape3DComponent> collisionShape) {
auto handleCollisionShape3DComponent = [&](std::shared_ptr<CollisionShape3DComponent> collisionShape)
{
// Shape Type Combo Box
const char *shapeTypes[] = {"Box", "Sphere", "Capsule"};
int shapeIndex = static_cast<int>(collisionShape->shapeType);
@ -1585,7 +1664,8 @@ void ShowInspector(std::shared_ptr<Entity> &selectedEntity)
}
};
auto handleCameraComponent = [&](std::shared_ptr<CameraComponent> camera) {
auto handleCameraComponent = [&](std::shared_ptr<CameraComponent> camera)
{
// Field of View (FOV) slider
ImGui::DragFloat("Field of View", &camera->fov, 1.0f, 1.0f, 120.0f, "%.1f degrees");
@ -1657,7 +1737,6 @@ void ShowInspector(std::shared_ptr<Entity> &selectedEntity)
ImGui::End(); // End of Inspector window
}
// Function to manipulate the Editor Camera using ImGuizmo
void ManipulateEditorCamera(EditorCamera &editorCamera, float aspectRatio)
{
@ -1703,12 +1782,8 @@ void ManipulateEditorCamera(EditorCamera &editorCamera, float aspectRatio)
}
}
void DrawImGuizmo(TransformComponent &transform, glm::mat4 &view, glm::mat4 &projection)
void DrawImGuizmo(std::shared_ptr<Entity> &selectedEntity, TransformComponent &transform, glm::mat4 &view, glm::mat4 &projection)
{
if (GameRunning)
{
return;
}
// Ensure ImGuizmo context is initialized
ImGuizmo::BeginFrame();
@ -1777,7 +1852,7 @@ void DrawImGuizmo(TransformComponent &transform, glm::mat4 &view, glm::mat4 &pro
}
// Function to create a rotation matrix from Euler angles (in degrees)
glm::mat4 GetRotationMatrix(const TransformComponent *transform)
glm::mat4 getRotationMatrix(const TransformComponent *transform)
{
// Convert Euler angles from degrees to radians
float yaw = glm::radians(transform->rotation.y); // Yaw (rotation around Y-axis)
@ -1854,8 +1929,8 @@ glm::mat4 GetRotationMatrix(const TransformComponent *transform)
// previewShader->Use();
//
// // Set uniforms
// glUniformMatrix4fv(glGetUniformLocation(previewShader->Program, "view"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
// glUniformMatrix4fv(glGetUniformLocation(previewShader->Program, "projection"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));
// glUniformMatrix4fv(glGetUniformLocation(previewShader->ID, "view"), 1, GL_FALSE, glm::value_ptr(viewMatrix));
// glUniformMatrix4fv(glGetUniformLocation(previewShader->ID, "projection"), 1, GL_FALSE, glm::value_ptr(projectionMatrix));
//
// // Render all entities except the camera itself
// for (const auto &entity : entities)
@ -1877,8 +1952,8 @@ glm::mat4 GetRotationMatrix(const TransformComponent *transform)
// model = glm::scale(model, entityTransform->scale);
//
// // Set model and object color
// glUniformMatrix4fv(glGetUniformLocation(previewShader->Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
// glUniform3fv(glGetUniformLocation(previewShader->Program, "objectColor"), 1, glm::value_ptr(render->color));
// glUniformMatrix4fv(glGetUniformLocation(previewShader->ID, "model"), 1, GL_FALSE, glm::value_ptr(model));
// glUniform3fv(glGetUniformLocation(previewShader->ID, "objectColor"), 1, glm::value_ptr(render->color));
//
// // Bind VAO and draw
// glBindVertexArray(cubeVAO);
@ -1904,8 +1979,16 @@ glm::mat4 GetRotationMatrix(const TransformComponent *transform)
// ImGui::End(); // End of Camera Preview window
// }
void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities)
void ShowGameView(
std::vector<std::shared_ptr<Entity>> &entities,
std::shared_ptr<Entity> &selectedEntity)
{
// Begin ImGui window
ImGui::Begin("Game View");
UpdateGameWindowFocus();
@ -1921,7 +2004,8 @@ void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities)
// Fallback camera parameters
glm::mat4 fallbackView = glm::translate(glm::mat4(1.0f), glm::vec3(0, 0, -5));
glm::mat4 fallbackProjection = glm::perspective(glm::radians(45.0f),
static_cast<float>(texWidth) / static_cast<float>(texHeight), 0.1f, 100.0f);
static_cast<float>(texWidth) / static_cast<float>(texHeight),
0.1f, 100.0f);
glm::vec3 fallbackPosition = glm::vec3(0, 0, 5);
// Handle framebuffer and texture resizing
@ -1930,16 +2014,18 @@ void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities)
prevWidth = texWidth;
prevHeight = texHeight;
// Resize the texture
// Resize the color texture
glBindTexture(GL_TEXTURE_2D, renderedTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texWidth, texHeight, 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);
// Resize the depth renderbuffer
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, texWidth, texHeight);
}
// Bind the framebuffer and set viewport
// Bind the main framebuffer and set viewport
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glViewport(0, 0, texWidth, texHeight);
@ -1948,27 +2034,111 @@ void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities)
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Dark background
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Cache uniform locations
// --- SHADOW PASS ---
// Initialize shadow mapping resources once
const unsigned int SHADOW_WIDTH = 2048, SHADOW_HEIGHT = 2048; // High-resolution shadow map
static GLuint depthMapFBO = 0;
static GLuint depthMap = 0;
static bool shadowMapInitialized = false;
if (!shadowMapInitialized)
{
// Generate framebuffer for shadow mapping
glGenFramebuffers(1, &depthMapFBO);
// Create depth texture
glGenTextures(1, &depthMap);
glBindTexture(GL_TEXTURE_2D, depthMap);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT,
SHADOW_WIDTH, SHADOW_HEIGHT, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); // PCF requires linear filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); // Prevent shadow artifacts
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
float borderColor[] = {1.0, 1.0, 1.0, 1.0};
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
// Attach depth texture as FBO's depth buffer
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthMap, 0);
glDrawBuffer(GL_NONE); // No color buffer is drawn to.
glReadBuffer(GL_NONE);
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
std::cerr << "ERROR::FRAMEBUFFER:: Shadow Framebuffer is not complete!\n";
glBindFramebuffer(GL_FRAMEBUFFER, 0);
shadowMapInitialized = true;
}
// Define light properties for shadow mapping
glm::vec3 lightDir = glm::normalize(glm::vec3(-2.0f, -4.0f, -1.0f));
glm::mat4 lightProjection = glm::ortho(-20.0f, 20.0f, -20.0f, 20.0f, 1.0f, 50.0f); // Orthographic projection for directional light
glm::mat4 lightView = glm::lookAt(-lightDir * 25.0f, // Position the light farther to cover larger area
glm::vec3(0.0f), // Look at origin
glm::vec3(0.0f, 1.0f, 0.0f)); // Up vector
glm::mat4 lightSpaceMatrix = lightProjection * lightView;
// --- Render Shadow Map ---
depthShader->Use();
depthShader->SetMat4("lightSpaceMatrix", lightSpaceMatrix);
// Bind the shadow framebuffer and set viewport
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO);
glClear(GL_DEPTH_BUFFER_BIT);
// Render scene from light's perspective
for (const auto &entity : entities)
{
auto transform = entity->GetComponent<TransformComponent>();
auto render = entity->GetComponent<RenderComponent>();
if (transform && render)
{
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, 0, 0));
model = glm::rotate(model, glm::radians(transform->rotation.y), glm::vec3(0, 1, 0));
model = glm::rotate(model, glm::radians(transform->rotation.z), glm::vec3(0, 0, 1));
model = glm::scale(model, transform->scale);
depthShader->SetMat4("model", model);
if (render->meshName == "model")
{
ImportedModel.render(transform, render, depthShader);
}
else if (render->meshName == "shelf")
{
ImportedModel_shelf.render(transform, render, depthShader);
}
else
{
glBindVertexArray(cubeVAO);
glDrawArrays(GL_TRIANGLES, 0, 36);
glBindVertexArray(0);
}
}
}
ImGui::Begin("Shadow Map");
ImGui::Image((intptr_t)depthMap, ImVec2(256, 256), ImVec2(0, 1), ImVec2(1, 0));
ImGui::End();
// Unbind shadow framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// --- MAIN PASS ---
// Restore main framebuffer and set viewport
glViewport(0, 0, texWidth, texHeight);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Enable depth testing for main pass
glEnable(GL_DEPTH_TEST);
// Use the main shader program
cubeShader->Use();
GLuint viewLoc = glGetUniformLocation(cubeShader->Program, "view");
GLuint projLoc = glGetUniformLocation(cubeShader->Program, "projection");
GLuint viewPosLoc = glGetUniformLocation(cubeShader->Program, "viewPos");
GLuint useTextureLoc = glGetUniformLocation(cubeShader->Program, "useTexture");
GLuint modelLoc = glGetUniformLocation(cubeShader->Program, "model");
GLuint objectColorLoc = glGetUniformLocation(cubeShader->Program, "objectColor");
// Helper lambdas
auto setUniform = [&](const std::string& name, const glm::vec3& value) {
glUniform3fv(glGetUniformLocation(cubeShader->Program, name.c_str()), 1, glm::value_ptr(value));
};
auto setUniformFloat = [&](const std::string& name, float value) {
glUniform1f(glGetUniformLocation(cubeShader->Program, name.c_str()), value);
};
auto getRotationMatrix = [&](TransformComponent* transform) -> glm::mat4 {
return glm::mat4_cast(glm::quat(glm::radians(transform->rotation)));
};
// Determine and set up the active camera
glm::mat4 viewMatrix;
@ -2023,12 +2193,26 @@ void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities)
}
}
// Set camera uniforms
glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(viewMatrix));
glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projectionMatrix));
glUniform3fv(viewPosLoc, 1, glm::value_ptr(cameraPosition));
glUniform1i(useTextureLoc, false);
// Set camera-related uniforms
cubeShader->SetMat4("view", viewMatrix);
cubeShader->SetMat4("projection", projectionMatrix);
cubeShader->SetVec3("viewPos", cameraPosition);
cubeShader->SetMat4("lightSpaceMatrix", lightSpaceMatrix);
// Bind shadow map to texture unit 1
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthMap);
cubeShader->SetInt("shadowMap", 1);
// Set texture samplers (diffuse and specular) once
cubeShader->SetInt("diffuseMap", 2);
cubeShader->SetInt("specularMap", 3);
// Bind shadow map texture
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, depthMap); // Shadow map already bound
// Pass lighting information to shader
// Collect lights from entities
std::vector<std::pair<LightComponent *, TransformComponent *>> lights;
for (const auto &entity : entities)
@ -2049,43 +2233,43 @@ void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities)
{
switch (light->type)
{
case LightType::Point:
if (pointLightCount < MAX_POINT_LIGHTS)
{
std::string base = "pointLights[" + std::to_string(pointLightCount) + "].";
setUniform(base + "position", transform->position);
setUniform(base + "color", light->color * light->intensity);
setUniformFloat(base + "constant", light->constant);
setUniformFloat(base + "linear", light->linear);
setUniformFloat(base + "quadratic", light->quadratic);
pointLightCount++;
}
break;
case LightType::Directional:
if (dirLightCount < MAX_DIR_LIGHTS)
{
std::string base = "dirLights[" + std::to_string(dirLightCount) + "].";
glm::vec3 worldDir = glm::normalize(glm::vec3(getRotationMatrix(transform) * glm::vec4(light->direction, 0.0f)));
setUniform(base + "direction", worldDir);
setUniform(base + "color", light->color * light->intensity);
cubeShader->SetVec3(base + "direction", worldDir);
cubeShader->SetVec3(base + "color", light->color * light->intensity);
dirLightCount++;
}
break;
case LightType::Point:
if (pointLightCount < MAX_POINT_LIGHTS)
{
std::string base = "pointLights[" + std::to_string(pointLightCount) + "].";
cubeShader->SetVec3(base + "position", transform->position);
cubeShader->SetVec3(base + "color", light->color * light->intensity);
cubeShader->SetFloat(base + "constant", light->constant);
cubeShader->SetFloat(base + "linear", light->linear);
cubeShader->SetFloat(base + "quadratic", light->quadratic);
pointLightCount++;
}
break;
case LightType::Spot:
if (spotLightCount < MAX_SPOT_LIGHTS)
{
std::string base = "spotLights[" + std::to_string(spotLightCount) + "].";
setUniform(base + "position", transform->position);
cubeShader->SetVec3(base + "position", transform->position);
glm::vec3 worldDir = glm::normalize(glm::vec3(getRotationMatrix(transform) * glm::vec4(light->direction, 0.0f)));
setUniform(base + "direction", worldDir);
setUniform(base + "color", light->color * light->intensity);
setUniformFloat(base + "cutOff", glm::cos(glm::radians(light->cutOff)));
setUniformFloat(base + "outerCutOff", glm::cos(glm::radians(light->outerCutOff)));
setUniformFloat(base + "constant", light->constant);
setUniformFloat(base + "linear", light->linear);
setUniformFloat(base + "quadratic", light->quadratic);
cubeShader->SetVec3(base + "direction", worldDir);
cubeShader->SetVec3(base + "color", light->color * light->intensity);
cubeShader->SetFloat(base + "cutOff", glm::cos(glm::radians(light->cutOff)));
cubeShader->SetFloat(base + "outerCutOff", glm::cos(glm::radians(light->outerCutOff)));
cubeShader->SetFloat(base + "constant", light->constant);
cubeShader->SetFloat(base + "linear", light->linear);
cubeShader->SetFloat(base + "quadratic", light->quadratic);
spotLightCount++;
}
break;
@ -2096,11 +2280,16 @@ void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities)
}
// Pass light counts to the shader
glUniform1i(glGetUniformLocation(cubeShader->Program, "numPointLights"), pointLightCount);
glUniform1i(glGetUniformLocation(cubeShader->Program, "numDirLights"), dirLightCount);
glUniform1i(glGetUniformLocation(cubeShader->Program, "numSpotLights"), spotLightCount);
cubeShader->SetInt("numDirLights", dirLightCount);
cubeShader->SetInt("numPointLights", pointLightCount);
cubeShader->SetInt("numSpotLights", spotLightCount);
// Render entities
// Bind diffuse and specular maps to texture units 2 and 3
// Assuming all entities share the same diffuse and specular maps for simplicity
// If entities have unique textures, bind before rendering each entity
// Here, we assume unique textures and bind per entity
// Render entities with lighting and shadows
for (const auto &entity : entities)
{
auto transform = entity->GetComponent<TransformComponent>();
@ -2115,9 +2304,19 @@ void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities)
model = glm::rotate(model, glm::radians(transform->rotation.z), glm::vec3(0, 0, 1));
model = glm::scale(model, transform->scale);
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
glUniform3fv(objectColorLoc, 1, glm::value_ptr(render->color));
cubeShader->SetMat4("model", model);
cubeShader->SetVec3("objectColor", render->color);
// Bind textures for this entity
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, render->diffuseMap); // Bind diffuse map
// Note: diffuseMap is already set to texture unit 2 in the shader
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, render->specularMap); // Bind specular map
// Note: specularMap is already set to texture unit 3 in the shader
// Render the appropriate mesh
if (render->meshName == "model")
{
ImportedModel.render(transform, render, cubeShader);
@ -2135,45 +2334,42 @@ void ShowGameView(std::vector<std::shared_ptr<Entity>> &entities)
}
}
// Render gizmos if not in Game mode
// --- OPTIONAL: Render Gizmos and Additional Debug Information ---
if (!GameRunning)
{
totalLights = 0;
// Render light gizmos
int totalLights = 0;
for (const auto &[light, transform] : lights)
{
totalLights++;
RenderLightGizmo(transform->position, viewMatrix, projectionMatrix);
}
if (selectedEntity)
{
auto transform = selectedEntity->GetComponent<TransformComponent>();
if (transform)
{
gizmoShader->Use();
DrawImGuizmo(*transform, viewMatrix, projectionMatrix);
}
}
}
// Unbind framebuffer and disable depth testing
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDisable(GL_DEPTH_TEST);
// Display the rendered texture in ImGui
ImGui::Image((intptr_t)renderedTexture, windowSize, ImVec2(0, 1), ImVec2(1, 0));
// Handle Gizmo Manipulation
// Render selected entity gizmo
if (selectedEntity)
{
auto transform = selectedEntity->GetComponent<TransformComponent>();
if (transform)
{
gizmoShader->Use();
DrawImGuizmo(*transform, viewMatrix, projectionMatrix);
DrawImGuizmo(selectedEntity, *transform, viewMatrix, projectionMatrix);
}
}
ImGui::End(); // End of Game View window
}

View File

@ -103,14 +103,14 @@ void Model::render(std::shared_ptr<TransformComponent> transform, std::shared_pt
// Set shader uniforms
shaderProgram->Use();
glUniformMatrix4fv(glGetUniformLocation(shaderProgram->Program, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniform3fv(glGetUniformLocation(shaderProgram->Program, "objectColor"), 1, glm::value_ptr(render->color));
glUniform1i(glGetUniformLocation(shaderProgram->Program, "useTexture"), textureID != 0);
glUniformMatrix4fv(glGetUniformLocation(shaderProgram->ID, "model"), 1, GL_FALSE, glm::value_ptr(model));
glUniform3fv(glGetUniformLocation(shaderProgram->ID, "objectColor"), 1, glm::value_ptr(render->color));
glUniform1i(glGetUniformLocation(shaderProgram->ID, "useTexture"), textureID != 0);
if (textureID) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textureID);
shaderProgram->setInt("texture1", 0); // Bind texture unit 0
shaderProgram->SetInt("texture1", 0); // Bind texture unit 0
}
// Bind VAO and render