diff --git a/$tmpPly.polys b/$tmpPly.polys index 3b259bc..68f7606 100644 --- a/$tmpPly.polys +++ b/$tmpPly.polys @@ -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] - Camera: - Zoom: 10 - FOV: 45 - Orthographic: false - NearPlane: 0.100000001 - FarPlane: 1000 \ No newline at end of file + - 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] \ No newline at end of file diff --git a/assets/Example.polys b/assets/Example.polys new file mode 100644 index 0000000..74b1f4b --- /dev/null +++ b/assets/Example.polys @@ -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] \ No newline at end of file diff --git a/assets/light.polys b/assets/light.polys new file mode 100644 index 0000000..16ab721 --- /dev/null +++ b/assets/light.polys @@ -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] \ No newline at end of file diff --git a/build/CameraComponent.o b/build/CameraComponent.o index b7aa542..3370028 100644 Binary files a/build/CameraComponent.o and b/build/CameraComponent.o differ diff --git a/build/CollisionShape3DComponent.o b/build/CollisionShape3DComponent.o index c14fcfb..0171475 100644 Binary files a/build/CollisionShape3DComponent.o and b/build/CollisionShape3DComponent.o differ diff --git a/build/EditorCamera.o b/build/EditorCamera.o index 2ff4439..7306ba5 100644 Binary files a/build/EditorCamera.o and b/build/EditorCamera.o differ diff --git a/build/Entity.o b/build/Entity.o index e034607..f24dc15 100644 Binary files a/build/Entity.o and b/build/Entity.o differ diff --git a/build/GraphEditor.o b/build/GraphEditor.o index 7c039f2..6967743 100644 Binary files a/build/GraphEditor.o and b/build/GraphEditor.o differ diff --git a/build/ImCurveEdit.o b/build/ImCurveEdit.o index dd20c7c..ebc75b7 100644 Binary files a/build/ImCurveEdit.o and b/build/ImCurveEdit.o differ diff --git a/build/ImGradient.o b/build/ImGradient.o index bb81515..e59451b 100644 Binary files a/build/ImGradient.o and b/build/ImGradient.o differ diff --git a/build/ImGuiStyle.o b/build/ImGuiStyle.o index ad2f6a3..50a81f9 100644 Binary files a/build/ImGuiStyle.o and b/build/ImGuiStyle.o differ diff --git a/build/ImGuizmo.o b/build/ImGuizmo.o index b611d5a..ecc944f 100644 Binary files a/build/ImGuizmo.o and b/build/ImGuizmo.o differ diff --git a/build/ImSequencer.o b/build/ImSequencer.o index f040646..a70fe67 100644 Binary files a/build/ImSequencer.o and b/build/ImSequencer.o differ diff --git a/build/LightComponent.o b/build/LightComponent.o index b0c01a3..851f438 100644 Binary files a/build/LightComponent.o and b/build/LightComponent.o differ diff --git a/build/LogSystem.o b/build/LogSystem.o index 1a4b0a0..d5a1aeb 100644 Binary files a/build/LogSystem.o and b/build/LogSystem.o differ diff --git a/build/RenderComponent.o b/build/RenderComponent.o index 72e3a1e..c72d6ff 100644 Binary files a/build/RenderComponent.o and b/build/RenderComponent.o differ diff --git a/build/RigidBody3DComponent.o b/build/RigidBody3DComponent.o index a069181..b7737cb 100644 Binary files a/build/RigidBody3DComponent.o and b/build/RigidBody3DComponent.o differ diff --git a/build/Shader.o b/build/Shader.o index 5b3d6e3..8db28ff 100644 Binary files a/build/Shader.o and b/build/Shader.o differ diff --git a/build/TransformComponent.o b/build/TransformComponent.o index bee6130..1c0c3b7 100644 Binary files a/build/TransformComponent.o and b/build/TransformComponent.o differ diff --git a/build/game_engine.exe b/build/game_engine.exe index 192df87..062f8d2 100644 Binary files a/build/game_engine.exe and b/build/game_engine.exe differ diff --git a/build/imgui.o b/build/imgui.o index d351d30..24be791 100644 Binary files a/build/imgui.o and b/build/imgui.o differ diff --git a/build/imgui_demo.o b/build/imgui_demo.o index 1e7875a..f65d4a7 100644 Binary files a/build/imgui_demo.o and b/build/imgui_demo.o differ diff --git a/build/imgui_draw.o b/build/imgui_draw.o index e5f677f..fcc7cec 100644 Binary files a/build/imgui_draw.o and b/build/imgui_draw.o differ diff --git a/build/imgui_impl_glfw.o b/build/imgui_impl_glfw.o index 87e2741..a76185a 100644 Binary files a/build/imgui_impl_glfw.o and b/build/imgui_impl_glfw.o differ diff --git a/build/imgui_impl_opengl3.o b/build/imgui_impl_opengl3.o index dafc5ba..a6aa89f 100644 Binary files a/build/imgui_impl_opengl3.o and b/build/imgui_impl_opengl3.o differ diff --git a/build/imgui_tables.o b/build/imgui_tables.o index 3571fae..c88d199 100644 Binary files a/build/imgui_tables.o and b/build/imgui_tables.o differ diff --git a/build/imgui_widgets.o b/build/imgui_widgets.o index 34b76b6..563b3d6 100644 Binary files a/build/imgui_widgets.o and b/build/imgui_widgets.o differ diff --git a/build/main.o b/build/main.o index d4ad90f..53b3ebc 100644 Binary files a/build/main.o and b/build/main.o differ diff --git a/build/modelImported.o b/build/modelImported.o index c599447..f27bbe5 100644 Binary files a/build/modelImported.o and b/build/modelImported.o differ diff --git a/imgui.ini b/imgui.ini index 9a14dc6..5d09055 100644 --- a/imgui.ini +++ b/imgui.ini @@ -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 -[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 +[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=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 diff --git a/scene.polys b/scene.polys index d297cf4..e69de29 100644 --- a/scene.polys +++ b/scene.polys @@ -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] \ No newline at end of file diff --git a/shaders/cube_shader.fs b/shaders/cube_shader.fs new file mode 100644 index 0000000..f0e5820 --- /dev/null +++ b/shaders/cube_shader.fs @@ -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); +} diff --git a/shaders/cube_shader.vs b/shaders/cube_shader.vs new file mode 100644 index 0000000..1f5f658 --- /dev/null +++ b/shaders/cube_shader.vs @@ -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); +} diff --git a/shaders/depth_shader.fs b/shaders/depth_shader.fs new file mode 100644 index 0000000..f5895be --- /dev/null +++ b/shaders/depth_shader.fs @@ -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 +} diff --git a/shaders/depth_shader.vs b/shaders/depth_shader.vs new file mode 100644 index 0000000..196c250 --- /dev/null +++ b/shaders/depth_shader.vs @@ -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; +} diff --git a/src/LogSystem.cpp b/src/LogSystem.cpp index f8390f3..805aa92 100644 --- a/src/LogSystem.cpp +++ b/src/LogSystem.cpp @@ -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 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 { diff --git a/src/LogSystem.h b/src/LogSystem.h index 2a1dce4..54a66f4 100644 --- a/src/LogSystem.h +++ b/src/LogSystem.h @@ -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); diff --git a/src/RenderComponent.h b/src/RenderComponent.h index 407677f..1e2cdb5 100644 --- a/src/RenderComponent.h +++ b/src/RenderComponent.h @@ -7,6 +7,7 @@ #include #include +#include #include class RenderComponent : public Component @@ -14,6 +15,10 @@ class RenderComponent : public Component public: std::string meshName; glm::vec3 color; + + // Texture IDs + GLuint diffuseMap; + GLuint specularMap; RenderComponent(); virtual const std::string& GetName() const override; diff --git a/src/Shader.cpp b/src/Shader.cpp index 4206b90..ea1dfcc 100644 --- a/src/Shader.cpp +++ b/src/Shader.cpp @@ -1,14 +1,13 @@ +// Shader.cpp #include "Shader.h" #include #include #include +#include // C++17 feature for file existence -#include -#include -#include +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,107 +15,122 @@ Shader::Shader(const GLchar* vertexPath, const GLchar* fragmentPath) 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 + // 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 { // 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(); + fShaderStream << fShaderFile.rdbuf(); + // Close file handlers vShaderFile.close(); fShaderFile.close(); + // Convert stream into string vertexCode = vShaderStream.str(); - fragmentCode = fShaderStream.str(); + fragmentCode = fShaderStream.str(); } 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) + 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) + 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); - if (!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); + +void Shader::Use() +{ + 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]); } diff --git a/src/Shader.h b/src/Shader.h index 5ebf864..499302e 100644 --- a/src/Shader.h +++ b/src/Shader.h @@ -1,30 +1,26 @@ -#ifndef SHADER_H -#define SHADER_H +// Shader.h +#pragma once -#include #include - +#include #include - 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 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 diff --git a/src/main.cpp b/src/main.cpp index a0958c3..e950390 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -68,7 +68,13 @@ const int MAX_SPOT_LIGHTS = 64; #include #include // 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 selectedEntity = nullptr; - std::shared_ptr selectedAsset = nullptr; std::filesystem::path assetsDir = "./assets/"; @@ -126,76 +131,68 @@ void RenderCube(glm::mat4 model, glm::mat4 view, glm::mat4 projection, glm::vec3 void ShowEntityComponentTree(std::vector> &entities, std::shared_ptr &selectedEntity); void ShowInspector(std::shared_ptr &selectedEntity); -void ShowGameView(std::vector> &entities); +void ShowGameView(std::vector> &entities, std::shared_ptr &selectedEntity); -void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_ptr &selectedAsset, std::vector>& entities); +void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_ptr &selectedAsset, std::vector> &entities); void ShowCameraComponent(std::shared_ptr entity); void ManipulateEditorCamera(EditorCamera &editorCamera, float aspectRatio); // Function declarations -GLFWwindow* InitializeGLFW(int width, int height, const std::string& title); +GLFWwindow *InitializeGLFW(int width, int height, const std::string &title); bool InitializeOpenGL(); bool InitializeShaders(); bool LoadModels(); bool SetupCube(); bool SetupFramebuffer(int width, int height); -bool InitializeImGui(GLFWwindow* window, const char* glsl_version); -void Cleanup(GLFWwindow* window); -void MainLoop(GLFWwindow* window, std::vector>& entities, std::shared_ptr& selectedEntity, std::shared_ptr& selectedAsset, const std::filesystem::path& assetsDir, Settings& settings); +bool InitializeImGui(GLFWwindow *window, const char *glsl_version); +void Cleanup(GLFWwindow *window); +void MainLoop(GLFWwindow *window, std::vector> &entities, std::shared_ptr &selectedEntity, std::shared_ptr &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) -//{ -// // Cleanup ImGui -// ImGui_ImplOpenGL3_Shutdown(); -// ImGui_ImplGlfw_Shutdown(); -// ImGui::DestroyContext(); -// -// // Cleanup OpenGL resources -// if (cubeShader) { delete cubeShader; cubeShader = nullptr; } -// if (gizmoShader) { delete gizmoShader; gizmoShader = nullptr; } -// if (previewShader) { delete previewShader; previewShader = nullptr; } -// if (FrustumShader) { delete FrustumShader; FrustumShader = nullptr; } -// -// if (cubeVAO) { glDeleteVertexArrays(1, &cubeVAO); cubeVAO = 0; } -// if (cubeVBO) { glDeleteBuffers(1, &cubeVBO); cubeVBO = 0; } -// -// if (framebuffer) { glDeleteFramebuffers(1, &framebuffer); framebuffer = 0; } -// if (renderedTexture) { glDeleteTextures(1, &renderedTexture); renderedTexture = 0; } -// if (depthRenderbuffer) { glDeleteRenderbuffers(1, &depthRenderbuffer); depthRenderbuffer = 0; } -// -// // Delete textures -// if (fileIconTexture) { glDeleteTextures(1, &fileIconTexture); fileIconTexture = 0; } -// if (sceneIconTexture) { glDeleteTextures(1, &sceneIconTexture); sceneIconTexture = 0; } -// if (objectIconTexture) { glDeleteTextures(1, &objectIconTexture); objectIconTexture = 0; } -// -// // Destroy window and terminate GLFW -// glfwDestroyWindow(window); -// glfwTerminate(); -//} - + // void Cleanup(GLFWwindow* window) + //{ + // // Cleanup ImGui + // ImGui_ImplOpenGL3_Shutdown(); + // ImGui_ImplGlfw_Shutdown(); + // ImGui::DestroyContext(); + // + // // Cleanup OpenGL resources + // if (cubeShader) { delete cubeShader; cubeShader = nullptr; } + // if (gizmoShader) { delete gizmoShader; gizmoShader = nullptr; } + // if (previewShader) { delete previewShader; previewShader = nullptr; } + // if (FrustumShader) { delete FrustumShader; FrustumShader = nullptr; } + // + // if (cubeVAO) { glDeleteVertexArrays(1, &cubeVAO); cubeVAO = 0; } + // if (cubeVBO) { glDeleteBuffers(1, &cubeVBO); cubeVBO = 0; } + // + // if (framebuffer) { glDeleteFramebuffers(1, &framebuffer); framebuffer = 0; } + // if (renderedTexture) { glDeleteTextures(1, &renderedTexture); renderedTexture = 0; } + // if (depthRenderbuffer) { glDeleteRenderbuffers(1, &depthRenderbuffer); depthRenderbuffer = 0; } + // + // // Delete textures + // if (fileIconTexture) { glDeleteTextures(1, &fileIconTexture); fileIconTexture = 0; } + // if (sceneIconTexture) { glDeleteTextures(1, &sceneIconTexture); sceneIconTexture = 0; } + // if (objectIconTexture) { glDeleteTextures(1, &objectIconTexture); objectIconTexture = 0; } + // + // // Destroy window and terminate GLFW + // glfwDestroyWindow(window); + // glfwTerminate(); + // } } - - - - - - // Function to retrieve the active game camera (first CameraComponent found) -std::shared_ptr GetActiveGameCamera(const std::vector>& entities) +std::shared_ptr GetActiveGameCamera(const std::vector> &entities) { auto it = std::find_if(entities.begin(), entities.end(), - [](const std::shared_ptr& entity) { - return entity->GetComponent() != nullptr; - }); + [](const std::shared_ptr &entity) + { + return entity->GetComponent() != nullptr; + }); if (it != entities.end()) { @@ -203,21 +200,19 @@ std::shared_ptr GetActiveGameCamera(const std::vector FindEntityWithCamera(const std::vector>& entities, const std::shared_ptr& camera) +std::shared_ptr FindEntityWithCamera(const std::vector> &entities, const std::shared_ptr &camera) { auto it = std::find_if(entities.begin(), entities.end(), - [&camera](const std::shared_ptr& entity) { - auto entityCamera = entity->GetComponent(); - return entityCamera && entityCamera == camera; - }); + [&camera](const std::shared_ptr &entity) + { + auto entityCamera = entity->GetComponent(); + return entityCamera && entityCamera == camera; + }); if (it != entities.end()) { @@ -282,10 +277,10 @@ std::wstring SaveFileDialog(HWND owner = NULL, const std::wstring &defaultFilena } // Function to load a texture and return it as ImTextureID -ImTextureID LoadTexture(const std::string& filename) +ImTextureID LoadTexture(const std::string &filename) { int width, height, channels; - unsigned char* data = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha); + unsigned char *data = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha); if (!data) { std::cerr << "[Poly] Failed to load texture: " << filename << std::endl; @@ -298,14 +293,14 @@ ImTextureID LoadTexture(const std::string& filename) // Upload texture data glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - + // Generate mipmaps glGenerateMipmap(GL_TEXTURE_2D); // Set texture parameters for wrapping and filtering - 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_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + 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_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Unbind texture and free image data @@ -317,7 +312,7 @@ ImTextureID LoadTexture(const std::string& filename) } // Function to render a light gizmo (small cube) at a specified position -void RenderLightGizmo(const glm::vec3& position, const glm::mat4& view, const glm::mat4& projection) +void RenderLightGizmo(const glm::vec3 &position, const glm::mat4 &view, const glm::mat4 &projection) { if (!gizmoShader) { @@ -328,14 +323,14 @@ void RenderLightGizmo(const glm::vec3& position, const glm::mat4& view, const gl gizmoShader->Use(); // Construct model matrix: translate and scale - glm::mat4 model = glm::translate(glm::mat4(1.0f), position) * + glm::mat4 model = glm::translate(glm::mat4(1.0f), position) * 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) { @@ -344,8 +339,8 @@ void RenderLightGizmo(const glm::vec3& position, const glm::mat4& view, const gl } glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model)); - glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); - glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); + glUniformMatrix4fv(viewLoc, 1, GL_FALSE, glm::value_ptr(view)); + glUniformMatrix4fv(projLoc, 1, GL_FALSE, glm::value_ptr(projection)); // Set gizmo color to yellow glUniform3f(colorLoc, 1.0f, 1.0f, 0.0f); @@ -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() { @@ -582,7 +573,7 @@ int main() std::cout << "[Poly] GLFW " << GLFW_VERSION_MAJOR << "." << GLFW_VERSION_MINOR << std::endl; // Initialize GLFW and create window - GLFWwindow* window = InitializeGLFW(1280, 720, "Poly Engine"); + GLFWwindow *window = InitializeGLFW(1280, 720, "Poly Engine"); if (!window) { std::cerr << "[Poly] Failed to initialize GLFW window." << std::endl; @@ -636,8 +627,7 @@ int main() Cleanup(window); return -1; } - - + // Have to initialize after imgui glfwSetCursorPosCallback(window, MouseCallback); glfwSetScrollCallback(window, ScrollCallback); @@ -650,19 +640,22 @@ 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> entities; std::shared_ptr selectedEntity = nullptr; std::shared_ptr selectedAsset = nullptr; std::filesystem::path assetsDir = "./assets"; // Define your assets directory path - Settings settings; // Assumed to be a struct holding engine settings - settings.vsyncEnabled = true; // Example initialization + Settings settings; // Assumed to be a struct holding engine settings + settings.vsyncEnabled = true; // Example initialization 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); @@ -672,7 +665,7 @@ int main() // Function definitions -GLFWwindow* InitializeGLFW(int width, int height, const std::string& title) +GLFWwindow *InitializeGLFW(int width, int height, const std::string &title) { if (!glfwInit()) { @@ -686,7 +679,7 @@ GLFWwindow* InitializeGLFW(int width, int height, const std::string& title) glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // Create GLFW window - GLFWwindow* window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); + GLFWwindow *window = glfwCreateWindow(width, height, title.c_str(), NULL, NULL); if (!window) { std::cerr << "[Poly] GLFW window creation failed." << std::endl; @@ -699,8 +692,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,12 +717,14 @@ 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) + catch (const std::exception &e) { std::cerr << "[Poly] Shader compilation/linking failed: " << e.what() << std::endl; return false; @@ -768,52 +761,51 @@ bool SetupCube() // Positions // Normals // Back face -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, - -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + 0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, + -0.5f, 0.5f, -0.5f, 0.0f, 0.0f, -1.0f, -0.5f, -0.5f, -0.5f, 0.0f, 0.0f, -1.0f, // Front face - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, - -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + 0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, 0.5f, 0.5f, 0.0f, 0.0f, 1.0f, + -0.5f, -0.5f, 0.5f, 0.0f, 0.0f, 1.0f, // Left face - -0.5f, 0.5f, 0.5f,-1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, -0.5f,-1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f,-1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, -0.5f,-1.0f, 0.0f, 0.0f, - -0.5f, -0.5f, 0.5f,-1.0f, 0.0f, 0.0f, - -0.5f, 0.5f, 0.5f,-1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, -0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, -0.5f, 0.5f, -1.0f, 0.0f, 0.0f, + -0.5f, 0.5f, 0.5f, -1.0f, 0.0f, 0.0f, // Right face - 0.5f, 0.5f, 0.5f,1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, -0.5f,1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f,1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, -0.5f,1.0f, 0.0f, 0.0f, - 0.5f, -0.5f, 0.5f,1.0f, 0.0f, 0.0f, - 0.5f, 0.5f, 0.5f,1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, -0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, -0.5f, 0.5f, 1.0f, 0.0f, 0.0f, + 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 0.0f, // Bottom face - -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, - -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, + -0.5f, -0.5f, 0.5f, 0.0f, -1.0f, 0.0f, + -0.5f, -0.5f, -0.5f, 0.0f, -1.0f, 0.0f, // Top face - -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, - -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, + -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); @@ -825,10 +817,10 @@ bool SetupCube() glBindVertexArray(cubeVAO); // Position attribute glEnableVertexAttribArray(0); - glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)0); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)0); // Normal attribute glEnableVertexAttribArray(1); - glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat))); + glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 6 * sizeof(GLfloat), (GLvoid *)(3 * sizeof(GLfloat))); glBindBuffer(GL_ARRAY_BUFFER, 0); glBindVertexArray(0); @@ -870,12 +862,89 @@ bool SetupFramebuffer(int width, int height) return true; } -bool InitializeImGui(GLFWwindow* window, const char* glsl_version) +// 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(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 @@ -900,18 +969,16 @@ bool InitializeImGui(GLFWwindow* window, const char* glsl_version) std::cerr << "[Poly] Failed to load fonts." << std::endl; return false; } - - // Configure ImGui style - ImGuiStyle& style = ImGui::GetStyle(); + ImGuiStyle &style = ImGui::GetStyle(); style.WindowBorderSize = 0.0f; style.WindowRounding = 0.0f; return true; } -void MainLoop(GLFWwindow* window, std::vector>& entities, std::shared_ptr& selectedEntity, std::shared_ptr& selectedAsset, const std::filesystem::path& assetsDir, Settings& settings) +void MainLoop(GLFWwindow *window, std::vector> &entities, std::shared_ptr &selectedEntity, std::shared_ptr &selectedAsset, const std::filesystem::path &assetsDir, Settings &settings) { // Initialize timing variables double previousTime = glfwGetTime(); @@ -963,7 +1030,7 @@ void MainLoop(GLFWwindow* window, std::vector>& 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,15 +1040,15 @@ void MainLoop(GLFWwindow* window, std::vector>& entities { std::filesystem::path destinationPath(selectedFile); SaveScene(entities, destinationPath.string()); - AddLogMessage("Scene saved to " + destinationPath.string()); + LogMessage("Scene saved to " + destinationPath.string()); } } if (ImGui::MenuItem("Load Scene")) { LoadScene(entities, "./scene.polys"); // Assumed to be defined elsewhere - selectedEntity = nullptr; // Reset selected entity - AddLogMessage("Scene loaded from ./scene.polys"); + selectedEntity = nullptr; // Reset selected entity + LogMessage("Scene loaded from ./scene.polys"); } ImGui::EndMenu(); @@ -996,14 +1063,14 @@ void MainLoop(GLFWwindow* window, std::vector>& 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>& entities ImGui::EndMainMenuBar(); } + RenderDropTarget(); + // Get the framebuffer size int display_w, display_h; glfwGetFramebufferSize(window, &display_w, &display_h); @@ -1020,9 +1089,9 @@ void MainLoop(GLFWwindow* window, std::vector>& 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 + DrawLogTerminal("Info"); // Assumed to be defined elsewhere // Rendering ImGui::Render(); @@ -1044,19 +1113,18 @@ void MainLoop(GLFWwindow* window, std::vector>& 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> &entities, std } ImGui::SameLine(); - - } ImGui::Separator(); @@ -1111,7 +1177,7 @@ void ShowEntityComponentTree(std::vector> &entities, std // Unique identifier for each entity node std::string nodeLabel = entity->name; - bool nodeOpen = ImGui::TreeNodeEx((void*)(intptr_t)i, flags, nodeLabel.c_str()); + bool nodeOpen = ImGui::TreeNodeEx((void *)(intptr_t)i, flags, nodeLabel.c_str()); // Handle selection if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) @@ -1161,7 +1227,6 @@ void ShowEntityComponentTree(std::vector> &entities, std ImGui::End(); // End of Scene window } - // Function to display error messages within the UI void DisplayError(const std::string &message) { @@ -1178,7 +1243,7 @@ void DisplayError(const std::string &message) } // Function to display the Asset Panel as a Grid without recursion and folders -void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_ptr &selectedAsset, std::vector>& entities) +void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_ptr &selectedAsset, std::vector> &entities) { ImGui::Begin("Asset Panel"); @@ -1188,13 +1253,13 @@ void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_pt // ----------------------------- // Search Bar Section // ----------------------------- - + static char searchBuffer[256] = ""; if (ImGui::InputTextWithHint("##Search", "Search assets...", searchBuffer, IM_ARRAYSIZE(searchBuffer))) { // Implement search filtering if needed } - + ImGui::Separator(); // ----------------------------- @@ -1277,8 +1342,9 @@ 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 + ImGui::TableHeadersRow(); // Optional: Add headers if needed for (const auto &entry : std::filesystem::directory_iterator(currentPath, std::filesystem::directory_options::skip_permission_denied)) { @@ -1329,7 +1395,7 @@ void ShowAssetPanel(const std::filesystem::path &assetsDirectory, std::shared_pt // Image Button for the asset if (ImGui::ImageButton(("##" + entry.path().string()).c_str(), icon, ImVec2(thumbnailSize, thumbnailSize))) { - + // Handle asset selection selectedAsset = std::make_shared(); selectedAsset->path = entry.path(); @@ -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 &selectedEntity) { ImGui::Begin("Inspector"); @@ -1421,7 +1498,8 @@ void ShowInspector(std::shared_ptr &selectedEntity) if (ImGui::BeginPopup("AddComponentPopup")) { // List of available components with their corresponding add actions - struct ComponentInfo { + struct ComponentInfo + { std::string name; std::function addFunc; }; @@ -1429,31 +1507,26 @@ void ShowInspector(std::shared_ptr &selectedEntity) std::vector availableComponents; // Populate available components based on absence in the selected entity - auto addAvailableComponent = [&](const std::string &compName, std::function addFunc) { + auto addAvailableComponent = [&](const std::string &compName, std::function addFunc) + { if (!selectedEntity->GetComponentByName(compName)) { - availableComponents.push_back({ compName, addFunc }); + availableComponents.push_back({compName, addFunc}); } }; - addAvailableComponent("Transform Component", [&]() { - selectedEntity->AddComponent(std::make_shared()); - }); - addAvailableComponent("Render Component", [&]() { - selectedEntity->AddComponent(std::make_shared()); - }); - addAvailableComponent("Light Component", [&]() { - selectedEntity->AddComponent(std::make_shared()); - }); - addAvailableComponent("RigidBody3D Component", [&]() { - selectedEntity->AddComponent(std::make_shared()); - }); - addAvailableComponent("CollisionShape3D Component", [&]() { - selectedEntity->AddComponent(std::make_shared()); - }); - addAvailableComponent("Camera Component", [&]() { - selectedEntity->AddComponent(std::make_shared()); - }); + addAvailableComponent("Transform Component", [&]() + { selectedEntity->AddComponent(std::make_shared()); }); + addAvailableComponent("Render Component", [&]() + { selectedEntity->AddComponent(std::make_shared()); }); + addAvailableComponent("Light Component", [&]() + { selectedEntity->AddComponent(std::make_shared()); }); + addAvailableComponent("RigidBody3D Component", [&]() + { selectedEntity->AddComponent(std::make_shared()); }); + addAvailableComponent("CollisionShape3D Component", [&]() + { selectedEntity->AddComponent(std::make_shared()); }); + addAvailableComponent("Camera Component", [&]() + { selectedEntity->AddComponent(std::make_shared()); }); // Render menu items for available components for (const auto &comp : availableComponents) @@ -1475,7 +1548,8 @@ void ShowInspector(std::shared_ptr &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 &selectedEntity) if (ImGui::CollapsingHeader(component->GetName().c_str(), ImGuiTreeNodeFlags_DefaultOpen)) { // Lambda to simplify setting component properties - auto handleTransformComponent = [&](std::shared_ptr transform) { + auto handleTransformComponent = [&](std::shared_ptr 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 render) { + auto handleRenderComponent = [&](std::shared_ptr render) + { char meshBuffer[128]; strncpy(meshBuffer, render->meshName.c_str(), sizeof(meshBuffer)); meshBuffer[sizeof(meshBuffer) - 1] = 0; @@ -1508,9 +1584,10 @@ void ShowInspector(std::shared_ptr &selectedEntity) ImGui::ColorEdit3("Color", glm::value_ptr(render->color)); }; - auto handleLightComponent = [&](std::shared_ptr light) { + auto handleLightComponent = [&](std::shared_ptr light) + { // Light Type Combo Box - const char *lightTypes[] = { "Point", "Directional", "Spot" }; + const char *lightTypes[] = {"Point", "Directional", "Spot"}; int typeIndex = static_cast(light->type); if (ImGui::Combo("Type", &typeIndex, lightTypes, IM_ARRAYSIZE(lightTypes))) { @@ -1543,13 +1620,14 @@ void ShowInspector(std::shared_ptr &selectedEntity) } }; - auto handleRigidBody3DComponent = [&](std::shared_ptr rigidBody) { + auto handleRigidBody3DComponent = [&](std::shared_ptr 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); // RigidBody Type Combo Box - const char *rbTypes[] = { "Static", "Dynamic", "Kinematic" }; + const char *rbTypes[] = {"Static", "Dynamic", "Kinematic"}; int typeIndex = static_cast(rigidBody->type); if (ImGui::Combo("Type", &typeIndex, rbTypes, IM_ARRAYSIZE(rbTypes))) { @@ -1557,9 +1635,10 @@ void ShowInspector(std::shared_ptr &selectedEntity) } }; - auto handleCollisionShape3DComponent = [&](std::shared_ptr collisionShape) { + auto handleCollisionShape3DComponent = [&](std::shared_ptr collisionShape) + { // Shape Type Combo Box - const char *shapeTypes[] = { "Box", "Sphere", "Capsule" }; + const char *shapeTypes[] = {"Box", "Sphere", "Capsule"}; int shapeIndex = static_cast(collisionShape->shapeType); if (ImGui::Combo("Shape Type", &shapeIndex, shapeTypes, IM_ARRAYSIZE(shapeTypes))) { @@ -1569,23 +1648,24 @@ void ShowInspector(std::shared_ptr &selectedEntity) // Display properties based on shape type switch (collisionShape->shapeType) { - case CollisionShapeType::Box: - ImGui::DragFloat3("Size", glm::value_ptr(collisionShape->size), 0.1f, 0.1f, 100.0f); - break; - case CollisionShapeType::Sphere: - ImGui::DragFloat("Radius", &collisionShape->radius, 0.1f, 0.1f, 100.0f); - break; - case CollisionShapeType::Capsule: - ImGui::DragFloat3("Direction", glm::value_ptr(collisionShape->direction), 0.1f); - ImGui::DragFloat("Height", &collisionShape->height, 0.1f, 0.1f, 100.0f); - break; - // Add UI elements for additional shapes here - default: - break; + case CollisionShapeType::Box: + ImGui::DragFloat3("Size", glm::value_ptr(collisionShape->size), 0.1f, 0.1f, 100.0f); + break; + case CollisionShapeType::Sphere: + ImGui::DragFloat("Radius", &collisionShape->radius, 0.1f, 0.1f, 100.0f); + break; + case CollisionShapeType::Capsule: + ImGui::DragFloat3("Direction", glm::value_ptr(collisionShape->direction), 0.1f); + ImGui::DragFloat("Height", &collisionShape->height, 0.1f, 0.1f, 100.0f); + break; + // Add UI elements for additional shapes here + default: + break; } }; - auto handleCameraComponent = [&](std::shared_ptr camera) { + auto handleCameraComponent = [&](std::shared_ptr 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 &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 &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) @@ -1799,113 +1874,121 @@ glm::mat4 GetRotationMatrix(const TransformComponent *transform) return rotation; } -//void ShowCameraPreview(std::vector> &entities) +// void ShowCameraPreview(std::vector> &entities) //{ -// ImGui::Begin("Camera Preview"); +// ImGui::Begin("Camera Preview"); // -// // Get the window size for rendering -// ImVec2 windowSize = ImGui::GetContentRegionAvail(); -// int texWidth = static_cast(windowSize.x); -// int texHeight = static_cast(windowSize.y); +// // Get the window size for rendering +// ImVec2 windowSize = ImGui::GetContentRegionAvail(); +// int texWidth = static_cast(windowSize.x); +// int texHeight = static_cast(windowSize.y); // -// // Initialize framebuffer if not done -// static Framebuffer fb = {0, 0, 0}; -// static bool framebufferInitialized = false; +// // Initialize framebuffer if not done +// static Framebuffer fb = {0, 0, 0}; +// static bool framebufferInitialized = false; // -// if (!framebufferInitialized || texWidth != 0 || texHeight != 0) -// { -// if (framebufferInitialized) -// { -// // Delete previous framebuffer resources -// glDeleteFramebuffers(1, &fb.FBO); -// glDeleteTextures(1, &fb.texture); -// glDeleteRenderbuffers(1, &fb.RBO); -// } -// fb = InitFramebuffer(texWidth, texHeight); -// framebufferInitialized = true; -// } +// if (!framebufferInitialized || texWidth != 0 || texHeight != 0) +// { +// if (framebufferInitialized) +// { +// // Delete previous framebuffer resources +// glDeleteFramebuffers(1, &fb.FBO); +// glDeleteTextures(1, &fb.texture); +// glDeleteRenderbuffers(1, &fb.RBO); +// } +// fb = InitFramebuffer(texWidth, texHeight); +// framebufferInitialized = true; +// } // -// // Bind the framebuffer -// glBindFramebuffer(GL_FRAMEBUFFER, fb.FBO); +// // Bind the framebuffer +// glBindFramebuffer(GL_FRAMEBUFFER, fb.FBO); // -// // Set viewport to match the framebuffer size -// glViewport(0, 0, texWidth, texHeight); +// // Set viewport to match the framebuffer size +// glViewport(0, 0, texWidth, texHeight); // -// // Clear the framebuffer -// glEnable(GL_DEPTH_TEST); -// glClearColor(0.2f, 0.2f, 0.2f, 1.0f); // Slightly lighter background for visibility -// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); +// // Clear the framebuffer +// glEnable(GL_DEPTH_TEST); +// glClearColor(0.2f, 0.2f, 0.2f, 1.0f); // Slightly lighter background for visibility +// glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // -// // Find the camera entity -// std::shared_ptr activeGameCamera = GetActiveGameCamera(entities); -// std::shared_ptr cameraEntity = FindEntityWithCamera(entities, activeGameCamera); -// if (cameraEntity) -// { -// auto camera = cameraEntity->GetComponent(); -// auto transform = cameraEntity->GetComponent(); +// // Find the camera entity +// std::shared_ptr activeGameCamera = GetActiveGameCamera(entities); +// std::shared_ptr cameraEntity = FindEntityWithCamera(entities, activeGameCamera); +// if (cameraEntity) +// { +// auto camera = cameraEntity->GetComponent(); +// auto transform = cameraEntity->GetComponent(); // -// if (camera && transform) -// { -// // Compute view and projection matrices -// glm::mat4 viewMatrix = camera->GetViewMatrix(transform->position, transform->rotation); -// glm::mat4 projectionMatrix = camera->GetProjectionMatrix(static_cast(texWidth) / static_cast(texHeight)); +// if (camera && transform) +// { +// // Compute view and projection matrices +// glm::mat4 viewMatrix = camera->GetViewMatrix(transform->position, transform->rotation); +// glm::mat4 projectionMatrix = camera->GetProjectionMatrix(static_cast(texWidth) / static_cast(texHeight)); // -// // Use the minimal shader -// previewShader->Use(); +// // Use the minimal shader +// 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)); +// // Set uniforms +// 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) -// { -// if (entity == cameraEntity) -// continue; // Skip the camera entity +// // Render all entities except the camera itself +// for (const auto &entity : entities) +// { +// if (entity == cameraEntity) +// continue; // Skip the camera entity // -// auto render = entity->GetComponent(); -// auto entityTransform = entity->GetComponent(); +// auto render = entity->GetComponent(); +// auto entityTransform = entity->GetComponent(); // -// if (render && entityTransform) -// { -// // Compute model matrix -// glm::mat4 model = glm::mat4(1.0f); -// model = glm::translate(model, entityTransform->position); -// model = glm::rotate(model, glm::radians(entityTransform->rotation.x), glm::vec3(1, 0, 0)); -// model = glm::rotate(model, glm::radians(entityTransform->rotation.y), glm::vec3(0, 1, 0)); -// model = glm::rotate(model, glm::radians(entityTransform->rotation.z), glm::vec3(0, 0, 1)); -// model = glm::scale(model, entityTransform->scale); +// if (render && entityTransform) +// { +// // Compute model matrix +// glm::mat4 model = glm::mat4(1.0f); +// model = glm::translate(model, entityTransform->position); +// model = glm::rotate(model, glm::radians(entityTransform->rotation.x), glm::vec3(1, 0, 0)); +// model = glm::rotate(model, glm::radians(entityTransform->rotation.y), glm::vec3(0, 1, 0)); +// model = glm::rotate(model, glm::radians(entityTransform->rotation.z), glm::vec3(0, 0, 1)); +// 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)); +// // Set model and object 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); -// glDrawArrays(GL_TRIANGLES, 0, 36); // Assuming a cube with 36 vertices -// glBindVertexArray(0); -// } -// } -// } -// } -// else -// { -// // No camera found, display a message -// ImGui::Text("No camera entity found."); -// } +// // Bind VAO and draw +// glBindVertexArray(cubeVAO); +// glDrawArrays(GL_TRIANGLES, 0, 36); // Assuming a cube with 36 vertices +// glBindVertexArray(0); +// } +// } +// } +// } +// else +// { +// // No camera found, display a message +// ImGui::Text("No camera entity found."); +// } // -// // Unbind framebuffer -// glBindFramebuffer(GL_FRAMEBUFFER, 0); -// glDisable(GL_DEPTH_TEST); +// // Unbind framebuffer +// glBindFramebuffer(GL_FRAMEBUFFER, 0); +// glDisable(GL_DEPTH_TEST); // -// // Display the rendered texture in ImGui -// ImGui::Image((intptr_t)fb.texture, windowSize, ImVec2(0, 1), ImVec2(1, 0)); +// // Display the rendered texture in ImGui +// ImGui::Image((intptr_t)fb.texture, windowSize, ImVec2(0, 1), ImVec2(1, 0)); // -// ImGui::End(); // End of Camera Preview window -//} +// ImGui::End(); // End of Camera Preview window +// } -void ShowGameView(std::vector> &entities) + + + + + +void ShowGameView( + std::vector> &entities, + std::shared_ptr &selectedEntity) { + // Begin ImGui window ImGui::Begin("Game View"); UpdateGameWindowFocus(); @@ -1920,8 +2003,9 @@ void ShowGameView(std::vector> &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(texWidth) / static_cast(texHeight), 0.1f, 100.0f); + glm::mat4 fallbackProjection = glm::perspective(glm::radians(45.0f), + static_cast(texWidth) / static_cast(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> &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> &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(); + auto render = entity->GetComponent(); + + 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,14 +2193,28 @@ void ShowGameView(std::vector> &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> lights; + std::vector> lights; for (const auto &entity : entities) { auto light = entity->GetComponent(); @@ -2049,58 +2233,63 @@ void ShowGameView(std::vector> &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))); + cubeShader->SetVec3(base + "direction", worldDir); + cubeShader->SetVec3(base + "color", light->color * light->intensity); + dirLightCount++; + } + 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); - 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); - 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); - spotLightCount++; - } - break; + case LightType::Spot: + if (spotLightCount < MAX_SPOT_LIGHTS) + { + std::string base = "spotLights[" + std::to_string(spotLightCount) + "]."; + cubeShader->SetVec3(base + "position", transform->position); + glm::vec3 worldDir = glm::normalize(glm::vec3(getRotationMatrix(transform) * glm::vec4(light->direction, 0.0f))); + 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; - default: - break; + default: + break; } } // 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(); @@ -2115,9 +2304,19 @@ void ShowGameView(std::vector> &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> &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(); - 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(); if (transform) { gizmoShader->Use(); - DrawImGuizmo(*transform, viewMatrix, projectionMatrix); + DrawImGuizmo(selectedEntity, *transform, viewMatrix, projectionMatrix); } } + ImGui::End(); // End of Game View window } - diff --git a/src/modelImported.cpp b/src/modelImported.cpp index 88f101f..ec47cc4 100644 --- a/src/modelImported.cpp +++ b/src/modelImported.cpp @@ -103,14 +103,14 @@ void Model::render(std::shared_ptr 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