Added Sub meshing Asseet Loader : Broak Play Pause Button
When you resume the Asset cache returns an invalid Mesh The Asset Cache needs to be updated
This commit is contained in:
parent
41a09cc8f3
commit
a558ea092b
@ -3,14 +3,17 @@ local Math = require("./assets/scripts/math") -- Require the enhanced math modul
|
||||
local Engine = require("./assets/scripts/engine")
|
||||
|
||||
|
||||
local GameObjectName = "Bacround"
|
||||
|
||||
|
||||
-- Variables to track elapsed time and rotation
|
||||
local elapsedTime = 0
|
||||
local rotationSpeed = 45 -- Degrees per second for spinning
|
||||
local rotationSpeed = 25 -- Degrees per second for spinning
|
||||
local new_rotation = 0
|
||||
|
||||
-- Variables for bobbing effect
|
||||
local initial_position = {x = 0, y = 0, z = 0} -- To store the gun's initial position
|
||||
local bobAmplitude = 0.5 -- Amplitude of the bobbing (units)
|
||||
local bobAmplitude = 5 -- Amplitude of the bobbing (units)
|
||||
local bobFrequency = 0.5 -- Frequency of the bobbing (oscillations per second)
|
||||
|
||||
-- Reference to the Gun GameObject and its Transform component
|
||||
@ -26,7 +29,7 @@ function OnInit()
|
||||
|
||||
|
||||
if not gun then
|
||||
gun = Engine.GetGameObjectByTag("Gun")
|
||||
gun = Engine.GetGameObjectByTag(GameObjectName)
|
||||
if gun then
|
||||
transform = gun:GetComponent("Transform")
|
||||
if transform then
|
||||
@ -68,7 +71,7 @@ end
|
||||
function OnUpdate(deltaTime)
|
||||
-- Ensure that the Gun and its Transform component are valid
|
||||
if not gun then
|
||||
gun = Engine.GetGameObjectByTag("Gun")
|
||||
gun = Engine.GetGameObjectByTag(GameObjectName)
|
||||
if gun then
|
||||
transform = gun:GetComponent("Transform")
|
||||
if transform then
|
||||
|
@ -1,29 +1,49 @@
|
||||
#version 330 core
|
||||
|
||||
// Struct to hold an array of diffuse textures
|
||||
struct TextureArray {
|
||||
sampler2D texture_diffuse[32]; // Array of diffuse texture samplers
|
||||
sampler2D texture_diffuse[32]; // Array of diffuse textures
|
||||
// You can add more texture types here (e.g., specular, normal) if needed
|
||||
};
|
||||
|
||||
// Uniforms
|
||||
uniform TextureArray uTextures; // Array of diffuse textures
|
||||
uniform TextureArray uTextures; // Array of textures
|
||||
uniform int uNumDiffuseTextures; // Number of active diffuse textures
|
||||
|
||||
// Input variables from the vertex shader
|
||||
in vec2 TexCoords; // Texture coordinates
|
||||
flat in int TextureIndex; // Texture index for this fragment
|
||||
in vec2 TexCoord; // From vertex shader
|
||||
in vec3 Normal; // From vertex shader
|
||||
in vec3 FragPos; // From vertex shader
|
||||
|
||||
// Output fragment color
|
||||
out vec4 FragColor;
|
||||
out vec4 FragColor; // Final fragment color
|
||||
|
||||
// Example lighting parameters
|
||||
uniform vec3 lightPos; // Position of the light source
|
||||
uniform vec3 viewPos; // Position of the camera/viewer
|
||||
|
||||
void main()
|
||||
{
|
||||
// Clamp the texture index to prevent out-of-bounds access
|
||||
int texIndex = clamp(TextureIndex, 0, uNumDiffuseTextures - 1);
|
||||
|
||||
// Sample the texture using the provided index and texture coordinates
|
||||
vec4 sampledColor = texture(uTextures.texture_diffuse[texIndex], TexCoords);
|
||||
|
||||
// Set the final fragment color
|
||||
FragColor = sampledColor;
|
||||
// Normalize the normal vector
|
||||
vec3 norm = normalize(Normal);
|
||||
|
||||
// Calculate the direction from the fragment to the light
|
||||
vec3 lightDir = normalize(lightPos - FragPos);
|
||||
|
||||
// Compute the diffuse intensity
|
||||
float diff = max(dot(norm, lightDir), 0.0);
|
||||
|
||||
// Initialize diffuse color
|
||||
vec4 diffuseColor = vec4(0.0);
|
||||
|
||||
// Sample and accumulate diffuse textures
|
||||
for(int i = 0; i < uNumDiffuseTextures; ++i)
|
||||
{
|
||||
diffuseColor += texture(uTextures.texture_diffuse[i], TexCoord);
|
||||
}
|
||||
|
||||
// Apply the diffuse intensity
|
||||
diffuseColor *= diff;
|
||||
|
||||
// Simple ambient lighting
|
||||
vec3 ambient = 0.1 * diffuseColor.rgb;
|
||||
|
||||
// Final color combining ambient and diffuse components
|
||||
FragColor = vec4(ambient + diffuseColor.rgb, diffuseColor.a);
|
||||
}
|
||||
|
@ -1,33 +1,27 @@
|
||||
#version 330 core
|
||||
|
||||
// Input vertex attributes (from the VAO)
|
||||
layout(location = 0) in vec3 aPos; // Vertex position
|
||||
layout(location = 1) in vec3 aNormal; // Vertex normal
|
||||
layout(location = 2) in vec2 aTexCoords; // Vertex texture coordinates
|
||||
layout(location = 3) in int aTexIndex; // Texture index (integer)
|
||||
layout(location = 0) in vec3 aPos; // Vertex position
|
||||
layout(location = 1) in vec2 aTexCoord; // Texture coordinate
|
||||
layout(location = 2) in vec3 aNormal; // Vertex normal
|
||||
|
||||
// Uniforms
|
||||
uniform mat4 uMVP; // Model-View-Projection matrix
|
||||
uniform mat4 uModel; // Model matrix
|
||||
|
||||
// Output variables to the fragment shader
|
||||
out vec2 TexCoords; // Passed texture coordinates
|
||||
flat out int TextureIndex; // Passed texture index
|
||||
out vec2 TexCoord; // Passed to fragment shader
|
||||
out vec3 Normal; // Passed to fragment shader
|
||||
out vec3 FragPos; // Passed to fragment shader
|
||||
|
||||
void main()
|
||||
{
|
||||
// Transform vertex position to clip space
|
||||
// Compute the fragment position in world space
|
||||
FragPos = vec3(uModel * vec4(aPos, 1.0));
|
||||
|
||||
// Transform the normal vector
|
||||
Normal = mat3(transpose(inverse(uModel))) * aNormal;
|
||||
|
||||
// Pass through the texture coordinate
|
||||
TexCoord = aTexCoord;
|
||||
|
||||
// Final vertex position
|
||||
gl_Position = uMVP * vec4(aPos, 1.0);
|
||||
|
||||
// Transform vertex position to world space
|
||||
vec3 FragPos = vec3(uModel * vec4(aPos, 1.0));
|
||||
|
||||
// Transform normal to world space
|
||||
vec3 Normal = mat3(transpose(inverse(uModel))) * aNormal;
|
||||
|
||||
// Pass through texture coordinates
|
||||
TexCoords = aTexCoords;
|
||||
|
||||
// Pass through the texture index
|
||||
TextureIndex = aTexIndex;
|
||||
}
|
||||
|
97
imgui.ini
97
imgui.ini
@ -4,7 +4,8 @@ Size=1920,1177
|
||||
Collapsed=0
|
||||
|
||||
[Window][Debug##Default]
|
||||
Pos=468,549
|
||||
ViewportPos=926,1030
|
||||
ViewportId=0x16723995
|
||||
Size=400,400
|
||||
Collapsed=0
|
||||
|
||||
@ -73,28 +74,28 @@ Collapsed=0
|
||||
DockId=0x00000016,0
|
||||
|
||||
[Window][Editor##EditorWindow]
|
||||
Pos=274,27
|
||||
Size=1260,751
|
||||
Pos=410,27
|
||||
Size=1124,709
|
||||
Collapsed=0
|
||||
DockId=0x00000017,0
|
||||
|
||||
[Window][Performance##performance]
|
||||
Pos=8,594
|
||||
Size=264,575
|
||||
Pos=8,761
|
||||
Size=400,408
|
||||
Collapsed=0
|
||||
DockId=0x0000001C,0
|
||||
|
||||
[Window][Logger##logger]
|
||||
Pos=8,395
|
||||
Size=400,364
|
||||
Collapsed=0
|
||||
DockId=0x0000001A,0
|
||||
|
||||
[Window][Logger##logger]
|
||||
Pos=274,780
|
||||
Size=612,389
|
||||
Collapsed=0
|
||||
DockId=0x0000001B,0
|
||||
|
||||
[Window][Lua Text Editor##LuaEditor]
|
||||
Pos=888,780
|
||||
Size=646,389
|
||||
Pos=410,738
|
||||
Size=1124,431
|
||||
Collapsed=0
|
||||
DockId=0x0000001C,0
|
||||
DockId=0x00000018,0
|
||||
|
||||
[Window][Scene Window@SceneWindow]
|
||||
Pos=8,27
|
||||
@ -104,7 +105,7 @@ DockId=0x0000000F,0
|
||||
|
||||
[Window][Scene Window##SceneWindow]
|
||||
Pos=8,27
|
||||
Size=264,565
|
||||
Size=400,366
|
||||
Collapsed=0
|
||||
DockId=0x00000019,0
|
||||
|
||||
@ -115,10 +116,10 @@ Collapsed=0
|
||||
DockId=0x00000011,0
|
||||
|
||||
[Window][Profiler]
|
||||
Pos=888,780
|
||||
Size=646,389
|
||||
Pos=410,738
|
||||
Size=1124,431
|
||||
Collapsed=0
|
||||
DockId=0x0000001C,1
|
||||
DockId=0x00000018,1
|
||||
|
||||
[Table][0xE9E836E4,4]
|
||||
Column 0 Weight=1.2999
|
||||
@ -127,34 +128,34 @@ Column 2 Weight=0.6474
|
||||
Column 3 Weight=1.0088
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=8,27 Size=1904,1142 Split=X Selected=0xF7365A5A
|
||||
DockNode ID=0x00000013 Parent=0x14621557 SizeRef=264,1142 Split=Y Selected=0x818D04BB
|
||||
DockNode ID=0x00000019 Parent=0x00000013 SizeRef=264,565 HiddenTabBar=1 Selected=0x1D5D92B6
|
||||
DockNode ID=0x0000001A Parent=0x00000013 SizeRef=264,575 Selected=0x818D04BB
|
||||
DockNode ID=0x00000014 Parent=0x14621557 SizeRef=1638,1142 Split=X
|
||||
DockNode ID=0x00000015 Parent=0x00000014 SizeRef=1526,1142 Split=X
|
||||
DockNode ID=0x00000011 Parent=0x00000015 SizeRef=265,1142 Selected=0x1D5D92B6
|
||||
DockNode ID=0x00000012 Parent=0x00000015 SizeRef=1259,1142 Split=X
|
||||
DockNode ID=0x00000009 Parent=0x00000012 SizeRef=364,1142 Split=Y Selected=0x3DC5AC3F
|
||||
DockNode ID=0x00000005 Parent=0x00000009 SizeRef=364,745 Split=Y Selected=0x3DC5AC3F
|
||||
DockNode ID=0x0000000B Parent=0x00000005 SizeRef=364,452 HiddenTabBar=1 Selected=0x3DC5AC3F
|
||||
DockNode ID=0x0000000C Parent=0x00000005 SizeRef=364,291 Selected=0xAE3C694A
|
||||
DockNode ID=0x00000006 Parent=0x00000009 SizeRef=364,395 HiddenTabBar=1 Selected=0x726D8899
|
||||
DockNode ID=0x0000000A Parent=0x00000012 SizeRef=1538,1142 Split=X
|
||||
DockNode ID=0x00000007 Parent=0x0000000A SizeRef=357,1142 Selected=0x7737E8B2
|
||||
DockNode ID=0x00000008 Parent=0x0000000A SizeRef=1545,1142 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000008 SizeRef=1202,1142 Split=Y Selected=0xDF0EC458
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1202,849 Split=Y Selected=0xDF0EC458
|
||||
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=1202,571 Split=Y Selected=0xDFF75B3F
|
||||
DockNode ID=0x00000017 Parent=0x0000000D SizeRef=1303,751 CentralNode=1 HiddenTabBar=1 Selected=0xDFF75B3F
|
||||
DockNode ID=0x00000018 Parent=0x0000000D SizeRef=1303,389 Split=X Selected=0x9B5D3198
|
||||
DockNode ID=0x0000001B Parent=0x00000018 SizeRef=612,680 HiddenTabBar=1 Selected=0x1C0788A1
|
||||
DockNode ID=0x0000001C Parent=0x00000018 SizeRef=645,680 Selected=0x7D9E6BA2
|
||||
DockNode ID=0x0000000E Parent=0x00000003 SizeRef=1202,569 Selected=0xE98146C5
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1202,291 Selected=0x9DD4E196
|
||||
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=334,1142 HiddenTabBar=1 Selected=0x36DC96AB
|
||||
DockNode ID=0x00000016 Parent=0x00000014 SizeRef=376,1142 HiddenTabBar=1 Selected=0x8D0E8380
|
||||
DockSpace ID=0xC6145A92 Pos=8,27 Size=1904,1142 Split=X
|
||||
DockNode ID=0x0000000F Parent=0xC6145A92 SizeRef=301,1142 Selected=0xA8433A03
|
||||
DockNode ID=0x00000010 Parent=0xC6145A92 SizeRef=1601,1142 CentralNode=1
|
||||
DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=8,50 Size=1904,1142 Split=X Selected=0xF7365A5A
|
||||
DockNode ID=0x00000013 Parent=0x14621557 SizeRef=400,1142 Split=Y Selected=0x818D04BB
|
||||
DockNode ID=0x0000001B Parent=0x00000013 SizeRef=264,456 Split=Y Selected=0x1D5D92B6
|
||||
DockNode ID=0x00000019 Parent=0x0000001B SizeRef=264,366 HiddenTabBar=1 Selected=0x1D5D92B6
|
||||
DockNode ID=0x0000001A Parent=0x0000001B SizeRef=264,364 HiddenTabBar=1 Selected=0x1C0788A1
|
||||
DockNode ID=0x0000001C Parent=0x00000013 SizeRef=264,254 HiddenTabBar=1 Selected=0x818D04BB
|
||||
DockNode ID=0x00000014 Parent=0x14621557 SizeRef=862,1142 Split=X
|
||||
DockNode ID=0x00000015 Parent=0x00000014 SizeRef=484,1142 Split=X
|
||||
DockNode ID=0x00000011 Parent=0x00000015 SizeRef=265,1142 Selected=0x1D5D92B6
|
||||
DockNode ID=0x00000012 Parent=0x00000015 SizeRef=1259,1142 Split=X
|
||||
DockNode ID=0x00000009 Parent=0x00000012 SizeRef=364,1142 Split=Y Selected=0x3DC5AC3F
|
||||
DockNode ID=0x00000005 Parent=0x00000009 SizeRef=364,745 Split=Y Selected=0x3DC5AC3F
|
||||
DockNode ID=0x0000000B Parent=0x00000005 SizeRef=364,452 HiddenTabBar=1 Selected=0x3DC5AC3F
|
||||
DockNode ID=0x0000000C Parent=0x00000005 SizeRef=364,291 Selected=0xAE3C694A
|
||||
DockNode ID=0x00000006 Parent=0x00000009 SizeRef=364,395 HiddenTabBar=1 Selected=0x726D8899
|
||||
DockNode ID=0x0000000A Parent=0x00000012 SizeRef=1538,1142 Split=X
|
||||
DockNode ID=0x00000007 Parent=0x0000000A SizeRef=357,1142 Selected=0x7737E8B2
|
||||
DockNode ID=0x00000008 Parent=0x0000000A SizeRef=1545,1142 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000008 SizeRef=1202,1142 Split=Y Selected=0xDF0EC458
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1202,849 Split=Y Selected=0xDF0EC458
|
||||
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=1202,571 Split=Y Selected=0xDFF75B3F
|
||||
DockNode ID=0x00000017 Parent=0x0000000D SizeRef=1303,252 CentralNode=1 HiddenTabBar=1 Selected=0xDFF75B3F
|
||||
DockNode ID=0x00000018 Parent=0x0000000D SizeRef=1303,431 Selected=0x7D9E6BA2
|
||||
DockNode ID=0x0000000E Parent=0x00000003 SizeRef=1202,569 Selected=0xE98146C5
|
||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1202,291 Selected=0x9DD4E196
|
||||
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=334,1142 HiddenTabBar=1 Selected=0x36DC96AB
|
||||
DockNode ID=0x00000016 Parent=0x00000014 SizeRef=376,1142 HiddenTabBar=1 Selected=0x8D0E8380
|
||||
DockSpace ID=0xC6145A92 Pos=8,27 Size=1904,1142 Split=X
|
||||
DockNode ID=0x0000000F Parent=0xC6145A92 SizeRef=301,1142 Selected=0xA8433A03
|
||||
DockNode ID=0x00000010 Parent=0xC6145A92 SizeRef=1601,1142 CentralNode=1
|
||||
|
||||
|
@ -3,99 +3,161 @@ Entities:
|
||||
Name: Bacround
|
||||
Components:
|
||||
Transform:
|
||||
Position: [-0.200000003, 244.5, -220.699997]
|
||||
Rotation: [0, -88, 0]
|
||||
Position: [0, 400, 0]
|
||||
Rotation: [0, -90, 0]
|
||||
Scale: [1, 1, 1]
|
||||
Mesh:
|
||||
vao: 4
|
||||
indexCount: 786801
|
||||
textures:
|
||||
- id: 34
|
||||
type: texture_diffuse
|
||||
path: textures/lion.tga
|
||||
- id: 12
|
||||
type: texture_diffuse
|
||||
path: textures/background.tga
|
||||
- id: 13
|
||||
type: texture_diffuse
|
||||
path: textures/vase_plant.tga
|
||||
- id: 14
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_arch_diff.tga
|
||||
- id: 15
|
||||
type: texture_diffuse
|
||||
path: textures/spnza_bricks_a_diff.tga
|
||||
- id: 16
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_ceiling_a_diff.tga
|
||||
- id: 17
|
||||
type: texture_diffuse
|
||||
path: textures/chain_texture.tga
|
||||
- id: 18
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_column_a_diff.tga
|
||||
- id: 19
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_column_b_diff.tga
|
||||
- id: 20
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_column_c_diff.tga
|
||||
- id: 21
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_details_diff.tga
|
||||
- id: 22
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_fabric_diff.tga
|
||||
- id: 23
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_curtain_diff.tga
|
||||
- id: 24
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_fabric_blue_diff.tga
|
||||
- id: 25
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_fabric_green_diff.tga
|
||||
- id: 26
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_curtain_green_diff.tga
|
||||
- id: 27
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_curtain_blue_diff.tga
|
||||
- id: 28
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_flagpole_diff.tga
|
||||
- id: 29
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_floor_a_diff.tga
|
||||
- id: 30
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_thorn_diff.tga
|
||||
- id: 31
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_roof_diff.tga
|
||||
- id: 32
|
||||
type: texture_diffuse
|
||||
path: textures/vase_dif.tga
|
||||
- id: 33
|
||||
type: texture_diffuse
|
||||
path: textures/vase_hanging.tga
|
||||
- id: 34
|
||||
type: texture_diffuse
|
||||
path: textures/vase_round.tga
|
||||
submeshes:
|
||||
- vao: 3
|
||||
indexCount: 43452
|
||||
textures:
|
||||
- id: 30
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_roof_diff.tga
|
||||
- vao: 4
|
||||
indexCount: 27552
|
||||
textures:
|
||||
- id: 31
|
||||
type: texture_diffuse
|
||||
path: textures/vase_dif.tga
|
||||
- vao: 5
|
||||
indexCount: 33024
|
||||
textures:
|
||||
- id: 21
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_fabric_diff.tga
|
||||
- vao: 6
|
||||
indexCount: 54
|
||||
textures: ~
|
||||
- vao: 7
|
||||
indexCount: 12258
|
||||
textures:
|
||||
- id: 11
|
||||
type: texture_diffuse
|
||||
path: textures/background.tga
|
||||
- vao: 8
|
||||
indexCount: 10416
|
||||
textures:
|
||||
- id: 12
|
||||
type: texture_diffuse
|
||||
path: textures/vase_plant.tga
|
||||
- vao: 9
|
||||
indexCount: 49536
|
||||
textures:
|
||||
- id: 23
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_fabric_blue_diff.tga
|
||||
- vao: 10
|
||||
indexCount: 94308
|
||||
textures:
|
||||
- id: 29
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_thorn_diff.tga
|
||||
- vao: 11
|
||||
indexCount: 49536
|
||||
textures:
|
||||
- id: 24
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_fabric_green_diff.tga
|
||||
- vao: 12
|
||||
indexCount: 17628
|
||||
textures:
|
||||
- id: 15
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_ceiling_a_diff.tga
|
||||
- vao: 13
|
||||
indexCount: 30504
|
||||
textures:
|
||||
- id: 13
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_arch_diff.tga
|
||||
- vao: 14
|
||||
indexCount: 53064
|
||||
textures:
|
||||
- id: 33
|
||||
type: texture_diffuse
|
||||
path: textures/vase_round.tga
|
||||
- vao: 15
|
||||
indexCount: 69624
|
||||
textures:
|
||||
- id: 18
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_column_b_diff.tga
|
||||
- vao: 16
|
||||
indexCount: 2640
|
||||
textures:
|
||||
- id: 20
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_details_diff.tga
|
||||
- vao: 17
|
||||
indexCount: 43008
|
||||
textures:
|
||||
- id: 26
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_curtain_blue_diff.tga
|
||||
- vao: 18
|
||||
indexCount: 0
|
||||
textures: ~
|
||||
- vao: 19
|
||||
indexCount: 2388
|
||||
textures:
|
||||
- id: 14
|
||||
type: texture_diffuse
|
||||
path: textures/spnza_bricks_a_diff.tga
|
||||
- vao: 20
|
||||
indexCount: 21264
|
||||
textures:
|
||||
- id: 19
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_column_c_diff.tga
|
||||
- vao: 21
|
||||
indexCount: 63
|
||||
textures:
|
||||
- id: 28
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_floor_a_diff.tga
|
||||
- vao: 22
|
||||
indexCount: 43008
|
||||
textures:
|
||||
- id: 25
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_curtain_green_diff.tga
|
||||
- vao: 23
|
||||
indexCount: 9126
|
||||
textures:
|
||||
- id: 10
|
||||
type: texture_diffuse
|
||||
path: textures/lion.tga
|
||||
- vao: 24
|
||||
indexCount: 96
|
||||
textures:
|
||||
- id: 16
|
||||
type: texture_diffuse
|
||||
path: textures/chain_texture.tga
|
||||
- vao: 25
|
||||
indexCount: 56832
|
||||
textures:
|
||||
- id: 22
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_curtain_diff.tga
|
||||
- vao: 26
|
||||
indexCount: 8448
|
||||
textures:
|
||||
- id: 17
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_column_a_diff.tga
|
||||
- vao: 27
|
||||
indexCount: 49488
|
||||
textures:
|
||||
- id: 27
|
||||
type: texture_diffuse
|
||||
path: textures/sponza_flagpole_diff.tga
|
||||
- vao: 28
|
||||
indexCount: 59484
|
||||
textures:
|
||||
- id: 32
|
||||
type: texture_diffuse
|
||||
path: textures/vase_hanging.tga
|
||||
MeshPath: assets/models/sponza.obj
|
||||
ScriptComponent:
|
||||
ScriptPath: ""
|
||||
- ID: 1
|
||||
Name: Gun
|
||||
Components:
|
||||
ScriptComponent:
|
||||
ScriptPath: assets/scripts/BouncingItem.lua
|
||||
Mesh:
|
||||
vao: 5
|
||||
indexCount: 116445
|
||||
textures: ~
|
||||
MeshPath: assets/models/AK-47.obj
|
||||
Transform:
|
||||
Position: [0, 9.54316807, -50]
|
||||
Rotation: [0, 253.495804, 0]
|
||||
Scale: [0.100000001, 0.100000001, 0.100000001]
|
||||
ScriptPath: assets/scripts/BouncingItem.lua
|
@ -10,7 +10,7 @@ extern AssetManager g_AssetManager;
|
||||
const std::string MeshComponent::name = "Mesh";
|
||||
|
||||
MeshComponent::MeshComponent()
|
||||
: vao(0), indexCount(0), MeshPath("assets/models/DefaultMesh.obj")
|
||||
: MeshPath("assets/models/DefaultMesh.obj")
|
||||
{
|
||||
}
|
||||
|
||||
@ -26,29 +26,52 @@ const std::string &MeshComponent::GetStaticName()
|
||||
|
||||
void MeshComponent::Update(float deltaTime)
|
||||
{
|
||||
(void)deltaTime;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void MeshComponent::Draw(Shader* shader)
|
||||
{
|
||||
for (auto &submesh : submeshes)
|
||||
{
|
||||
submesh.Draw(shader);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
YAML::Node MeshComponent::Serialize()
|
||||
{
|
||||
YAML::Node node;
|
||||
|
||||
node["vao"] = static_cast<int>(vao);
|
||||
node["indexCount"] = static_cast<int>(indexCount);
|
||||
|
||||
// Serialize Textures
|
||||
YAML::Node texturesNode;
|
||||
for (const auto &texture : textures)
|
||||
{
|
||||
YAML::Node texNode;
|
||||
texNode["id"] = static_cast<int>(texture.id);
|
||||
texNode["type"] = texture.type;
|
||||
texNode["path"] = texture.path;
|
||||
texturesNode.push_back(texNode);
|
||||
}
|
||||
node["textures"] = texturesNode;
|
||||
|
||||
// Serialize each submesh
|
||||
node["MeshPath"] = MeshPath;
|
||||
|
||||
YAML::Node submeshesNode;
|
||||
for (const auto &submesh : submeshes)
|
||||
{
|
||||
YAML::Node submeshNode;
|
||||
submeshNode["vao"] = static_cast<int>(submesh.vao);
|
||||
submeshNode["indexCount"] = static_cast<int>(submesh.indices.size());
|
||||
|
||||
// Serialize Textures
|
||||
YAML::Node texturesNode;
|
||||
for (const auto &texture : submesh.textures)
|
||||
{
|
||||
YAML::Node texNode;
|
||||
texNode["id"] = static_cast<int>(texture.id);
|
||||
texNode["type"] = texture.type;
|
||||
texNode["path"] = texture.path;
|
||||
texturesNode.push_back(texNode);
|
||||
}
|
||||
submeshNode["textures"] = texturesNode;
|
||||
|
||||
submeshesNode.push_back(submeshNode);
|
||||
}
|
||||
node["submeshes"] = submeshesNode;
|
||||
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -60,7 +83,7 @@ void MeshComponent::Deserialize(const YAML::Node &node)
|
||||
|
||||
DEBUG_PRINT("Loading Mesh: %s", MeshPath.c_str());
|
||||
|
||||
Model *model = g_AssetManager.loadAsset<Model *>(AssetType::MODEL, MeshPath.c_str());
|
||||
std::shared_ptr<Model> model = g_AssetManager.loadAsset<Model>(AssetType::MODEL, MeshPath.c_str());
|
||||
|
||||
if (!model)
|
||||
{
|
||||
@ -68,67 +91,46 @@ void MeshComponent::Deserialize(const YAML::Node &node)
|
||||
return;
|
||||
}
|
||||
|
||||
DEBUG_PRINT("Model loaded successfully with %zu vertices and %zu indices.",
|
||||
model->vertices.size(), model->indices.size());
|
||||
DEBUG_PRINT("Model loaded successfully with %zu submeshes.", model->submeshes.size());
|
||||
|
||||
// Assign VAO and index count
|
||||
if (model->vao != 0)
|
||||
{
|
||||
vao = model->vao;
|
||||
}
|
||||
else if (node["vao"])
|
||||
{
|
||||
vao = node["vao"].as<int>();
|
||||
}
|
||||
|
||||
if (model->indices.size() != 0)
|
||||
{
|
||||
indexCount = static_cast<GLuint>(model->indices.size());
|
||||
}
|
||||
else if (node["indexCount"])
|
||||
{
|
||||
indexCount = node["indexCount"].as<int>();
|
||||
}
|
||||
|
||||
// Assign Textures
|
||||
if (!model->textures.empty())
|
||||
{
|
||||
textures = model->textures;
|
||||
}
|
||||
else if (node["textures"])
|
||||
{
|
||||
const YAML::Node &texturesNode = node["textures"];
|
||||
for (const auto &texNode : texturesNode)
|
||||
{
|
||||
Texture texture;
|
||||
texture.id = texNode["id"].as<int>();
|
||||
texture.type = texNode["type"].as<std::string>();
|
||||
texture.path = texNode["path"].as<std::string>();
|
||||
textures.push_back(texture);
|
||||
}
|
||||
}
|
||||
// Assign submeshes
|
||||
submeshes = std::move(model->submeshes);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (node["vao"])
|
||||
// Handle cases where submeshes are stored directly
|
||||
if (node["submeshes"])
|
||||
{
|
||||
vao = node["vao"].as<int>();
|
||||
}
|
||||
if (node["indexCount"])
|
||||
{
|
||||
indexCount = node["indexCount"].as<int>();
|
||||
}
|
||||
if (node["textures"])
|
||||
{
|
||||
const YAML::Node &texturesNode = node["textures"];
|
||||
for (const auto &texNode : texturesNode)
|
||||
const YAML::Node &submeshesNode = node["submeshes"];
|
||||
for (const auto &submeshNode : submeshesNode)
|
||||
{
|
||||
Texture texture;
|
||||
texture.id = texNode["id"].as<int>();
|
||||
texture.type = texNode["type"].as<std::string>();
|
||||
texture.path = texNode["path"].as<std::string>();
|
||||
textures.push_back(texture);
|
||||
Submesh submesh;
|
||||
|
||||
if (submeshNode["vao"])
|
||||
{
|
||||
submesh.vao = submeshNode["vao"].as<int>();
|
||||
}
|
||||
if (submeshNode["indexCount"])
|
||||
{
|
||||
submesh.indices.reserve(submeshNode["indexCount"].as<int>());
|
||||
// Assuming indices are stored elsewhere or need to be loaded
|
||||
}
|
||||
if (submeshNode["textures"])
|
||||
{
|
||||
const YAML::Node &texturesNode = submeshNode["textures"];
|
||||
for (const auto &texNode : texturesNode)
|
||||
{
|
||||
Texture texture;
|
||||
texture.id = texNode["id"].as<int>();
|
||||
texture.type = texNode["type"].as<std::string>();
|
||||
texture.path = texNode["path"].as<std::string>();
|
||||
submesh.textures.push_back(texture);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
submeshes.push_back(std::move(submesh));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,15 +10,18 @@
|
||||
#include <string>
|
||||
#include "Engine/AssetManager.h"
|
||||
|
||||
// In MeshComponent.h
|
||||
|
||||
class MeshComponent : public Component
|
||||
{
|
||||
public:
|
||||
GLuint vao = 0; // Vertex Array Object
|
||||
GLuint indexCount = 0; // Number of indices to draw
|
||||
std::vector<Texture> textures; // List of textures associated with the mesh
|
||||
|
||||
std::vector<Submesh> submeshes; // List of submeshes
|
||||
std::string MeshPath;
|
||||
|
||||
static const std::string name;
|
||||
|
||||
|
||||
|
||||
MeshComponent();
|
||||
virtual const std::string& GetName() const override;
|
||||
static const std::string& GetStaticName();
|
||||
@ -29,6 +32,9 @@ public:
|
||||
virtual YAML::Node Serialize() override;
|
||||
virtual void Deserialize(const YAML::Node& node) override;
|
||||
|
||||
private:
|
||||
static const std::string name;
|
||||
// Render the mesh
|
||||
void Draw(Shader* shader);
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -105,6 +105,11 @@ bool MyEngine::Init(int width, int height, const std::string &title)
|
||||
(void)io;
|
||||
// Enable docking
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
|
||||
#ifdef DEBUG
|
||||
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_ViewportsEnable;
|
||||
#endif
|
||||
|
||||
// (Optional) Multi-viewport
|
||||
// io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
|
||||
@ -148,35 +153,6 @@ void MyEngine::Run()
|
||||
DEBUG_PRINT("[START] Engine Run ");
|
||||
|
||||
DEBUG_PRINT("Transition to Editor");
|
||||
|
||||
g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/bricks.png");
|
||||
g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/default.png");
|
||||
g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/lush_grass.png");
|
||||
g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/vegetation_tree_bark_40.png");
|
||||
g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/ak-47.jpg");
|
||||
|
||||
g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/sky.png");
|
||||
|
||||
// Load a model
|
||||
Model *modelPtr = g_AssetManager.loadAsset<Model *>(AssetType::MODEL, "assets/models/LowPolyFiatUNO.obj");
|
||||
if (modelPtr == nullptr)
|
||||
{
|
||||
DEBUG_PRINT("Failed to load model.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Model *model = reinterpret_cast<Model *>(modelPtr);
|
||||
DEBUG_PRINT("Model loaded successfully with %lld vertices and %lld indices.", model->vertices.size(), model->indices.size());
|
||||
}
|
||||
|
||||
Model *modelPtr4 = g_AssetManager.loadAsset<Model *>(AssetType::MODEL, "assets/models/shopping-cart.obj");
|
||||
|
||||
Model *model4 = reinterpret_cast<Model *>(modelPtr4);
|
||||
|
||||
DEBUG_PRINT("Model loaded successfully with %lld vertices and %lld indices.", model4->vertices.size(), model4->indices.size());
|
||||
|
||||
DEBUG_PRINT("Put componenent into Global Componenets Subsystem");
|
||||
|
||||
// printf("%p\n", &g_GameObjects);
|
||||
|
||||
// Possibly create more GameObjects with different positions or textures
|
||||
@ -224,7 +200,7 @@ void MyEngine::Run()
|
||||
ScopedTimer timer("SaveScene");
|
||||
m_FirstTickGameRunning = false;
|
||||
|
||||
std::string savePath = createTempFolder().string() + "TesseractEngineTempScene.scene";
|
||||
std::string savePath = createTempFolder().string() + "/TesseractEngineTempScene.scene";
|
||||
DEBUG_PRINT("Save path: %s", savePath.c_str());
|
||||
g_SceneManager.SaveScene(g_GameObjects, savePath);
|
||||
|
||||
@ -249,7 +225,7 @@ void MyEngine::Run()
|
||||
ScopedTimer timer("LoadScene");
|
||||
m_FirstTickGameRunning = true;
|
||||
|
||||
std::string loadPath = createTempFolder().string() + "TesseractEngineTempScene.scene";
|
||||
std::string loadPath = createTempFolder().string() + "/TesseractEngineTempScene.scene";
|
||||
|
||||
DEBUG_PRINT("Load path: %s", loadPath.c_str());
|
||||
|
||||
|
@ -49,21 +49,44 @@ void AssetManager::DebugAssetMap()
|
||||
}
|
||||
}
|
||||
|
||||
// Implementation of AssetManager::loadAssetFromDisk
|
||||
AssetManager::AssetVariant AssetManager::loadAssetFromDisk(AssetType type, const std::string &path)
|
||||
{
|
||||
//DebugAssetMap();
|
||||
// DebugAssetMap();
|
||||
g_LoggerWindow->AddLog("[AssetManager] Loading asset: %s", path.c_str());
|
||||
LoadedAssets = m_AssetMap.size();
|
||||
switch (type)
|
||||
{
|
||||
case AssetType::TEXTURE:
|
||||
return LoadTextureFromList(path); // Returns GLuint
|
||||
{
|
||||
GLuint textureID = LoadTextureFromList(path); // Returns GLuint
|
||||
return std::make_shared<GLuint>(textureID); // Wrap in shared_ptr
|
||||
}
|
||||
case AssetType::SHADER:
|
||||
return LoadShaderFromList(path); // Returns Shader*
|
||||
case AssetType::SOUND:
|
||||
return std::string("Loaded sound: " + path); // Example placeholder for sound
|
||||
{
|
||||
Shader* shaderPtr = LoadShaderFromList(path); // Returns Shader*
|
||||
if (shaderPtr != nullptr)
|
||||
{
|
||||
// It's essential to ensure that shaderPtr is dynamically allocated and not managed elsewhere
|
||||
return std::shared_ptr<Shader>(shaderPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Failed to load shader: " + path);
|
||||
}
|
||||
}
|
||||
case AssetType::MODEL:
|
||||
return LoadModelFromList(path); // Returns Model*
|
||||
{
|
||||
Model* modelPtr = LoadModelFromList(path); // Returns Model*
|
||||
if (modelPtr != nullptr)
|
||||
{
|
||||
// It's essential to ensure that modelPtr is dynamically allocated and not managed elsewhere
|
||||
return std::shared_ptr<Model>(modelPtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::runtime_error("Failed to load model: " + path);
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw std::invalid_argument("Unknown AssetType");
|
||||
}
|
||||
@ -79,13 +102,11 @@ GLuint LoadTextureFromList(const std::string &path)
|
||||
// --------------------------------------------
|
||||
// Load a texture with stb_image
|
||||
// --------------------------------------------
|
||||
std::cout << "[AssetManager] Loading TEXTURE from: " << path << std::endl;
|
||||
|
||||
int width, height, channels;
|
||||
unsigned char *data = stbi_load(path.c_str(), &width, &height, &channels, 0);
|
||||
if (!data)
|
||||
{
|
||||
std::cerr << "[AssetManager] stb_image failed for: " << path << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -118,32 +139,24 @@ GLuint LoadTextureFromList(const std::string &path)
|
||||
return texID;
|
||||
}
|
||||
|
||||
Shader *LoadShaderFromList(const std::string &path)
|
||||
Shader* LoadShaderFromList(const std::string &path)
|
||||
{
|
||||
// --------------------------------------------
|
||||
// Load a shader using your existing "Shader" class
|
||||
// --------------------------------------------
|
||||
// Example usage: path = "shaders/UnlitMaterial" =>
|
||||
// loads "shaders/UnlitMaterial.vert" and "shaders/UnlitMaterial.frag"
|
||||
std::cout << "[AssetManager] Loading SHADER from: " << path << std::endl;
|
||||
|
||||
// Create a new Shader object on the heap
|
||||
Shader *newShader = new Shader();
|
||||
|
||||
// Build actual paths from the base path
|
||||
std::string vertPath = path + ".vert";
|
||||
std::string fragPath = path + ".frag";
|
||||
|
||||
// Attempt to load
|
||||
if (!newShader->Load(vertPath, fragPath))
|
||||
// Create a new Shader object using the constructor that takes vertex and fragment paths
|
||||
Shader *newShader = new Shader(vertPath.c_str(), fragPath.c_str());
|
||||
|
||||
// Check if shader compiled and linked successfully
|
||||
if (newShader->ID == 0)
|
||||
{
|
||||
std::cerr << "[AssetManager] Could not load shader: "
|
||||
<< vertPath << " / " << fragPath << std::endl;
|
||||
delete newShader; // Cleanup
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return as void*
|
||||
// Return the Shader pointer as void*
|
||||
return newShader;
|
||||
}
|
||||
|
||||
@ -160,7 +173,7 @@ GLuint LoadTexture(const std::string &path, const std::string &directory)
|
||||
unsigned char *data = stbi_load(fullPath.c_str(), &width, &height, &channels, 0);
|
||||
if (!data)
|
||||
{
|
||||
std::cerr << "[AssetManager] failed to load texture: " << fullPath << " " << stbi_failure_reason() << std::endl;
|
||||
DEBUG_PRINT("[AssetManager] failed to load texture: %s: %s", fullPath.c_str(),stbi_failure_reason());
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -203,30 +216,16 @@ GLuint LoadTexture(const std::string &path, const std::string &directory)
|
||||
|
||||
Model* LoadModelFromList(const std::string &path)
|
||||
{
|
||||
// --------------------------------------------
|
||||
// Load an OBJ model
|
||||
// --------------------------------------------
|
||||
std::cout << "[AssetManager] Loading MODEL from: " << path << std::endl;
|
||||
|
||||
std::ifstream objFile(path);
|
||||
if (!objFile.is_open())
|
||||
{
|
||||
std::cerr << "[AssetManager] Failed to open OBJ file: " << path << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<float> temp_positions;
|
||||
std::vector<float> temp_texCoords;
|
||||
std::vector<float> temp_normals;
|
||||
std::vector<unsigned int> vertexIndices, texCoordIndices, normalIndices;
|
||||
|
||||
// Preallocate vectors with estimated sizes for performance
|
||||
temp_positions.reserve(1000);
|
||||
temp_texCoords.reserve(500);
|
||||
temp_normals.reserve(500);
|
||||
vertexIndices.reserve(3000);
|
||||
texCoordIndices.reserve(3000);
|
||||
normalIndices.reserve(3000);
|
||||
|
||||
std::string directory;
|
||||
size_t lastSlash = path.find_last_of("/\\");
|
||||
@ -235,7 +234,12 @@ Model* LoadModelFromList(const std::string &path)
|
||||
else
|
||||
directory = "";
|
||||
|
||||
std::cout << "[AssetManager] Asset Directory: " << directory << std::endl;
|
||||
|
||||
std::string currentMaterial = "default";
|
||||
|
||||
// Map material name to Submesh
|
||||
std::unordered_map<std::string, Submesh> materialToSubmesh;
|
||||
materialToSubmesh[currentMaterial] = Submesh();
|
||||
|
||||
std::string line;
|
||||
std::string mtlFileName;
|
||||
@ -247,6 +251,7 @@ Model* LoadModelFromList(const std::string &path)
|
||||
std::istringstream iss(line);
|
||||
std::string prefix;
|
||||
iss >> prefix;
|
||||
|
||||
if (prefix == "v")
|
||||
{
|
||||
float x, y, z;
|
||||
@ -272,6 +277,18 @@ Model* LoadModelFromList(const std::string &path)
|
||||
temp_normals.push_back(-ny); // Inverted
|
||||
temp_normals.push_back(nz);
|
||||
}
|
||||
else if (prefix == "usemtl")
|
||||
{
|
||||
iss >> currentMaterial;
|
||||
if (materialToSubmesh.find(currentMaterial) == materialToSubmesh.end())
|
||||
{
|
||||
materialToSubmesh[currentMaterial] = Submesh();
|
||||
}
|
||||
}
|
||||
else if (prefix == "mtllib")
|
||||
{
|
||||
iss >> mtlFileName;
|
||||
}
|
||||
else if (prefix == "f")
|
||||
{
|
||||
std::string vertexStr;
|
||||
@ -313,38 +330,75 @@ Model* LoadModelFromList(const std::string &path)
|
||||
// Triangulate if the face has more than 3 vertices
|
||||
for (size_t i = 1; i + 1 < faceVertices.size(); ++i)
|
||||
{
|
||||
vertexIndices.push_back(std::get<0>(faceVertices[0]));
|
||||
texCoordIndices.push_back(std::get<1>(faceVertices[0]));
|
||||
normalIndices.push_back(std::get<2>(faceVertices[0]));
|
||||
// Current material's submesh
|
||||
Submesh ¤tSubmesh = materialToSubmesh[currentMaterial];
|
||||
|
||||
vertexIndices.push_back(std::get<0>(faceVertices[i]));
|
||||
texCoordIndices.push_back(std::get<1>(faceVertices[i]));
|
||||
normalIndices.push_back(std::get<2>(faceVertices[i]));
|
||||
auto addVertex = [&](unsigned int v, unsigned int t, unsigned int n) -> unsigned int {
|
||||
Vertex vertex;
|
||||
// OBJ indices are 1-based
|
||||
vertex.position[0] = temp_positions[(v - 1) * 3];
|
||||
vertex.position[1] = temp_positions[(v - 1) * 3 + 1];
|
||||
vertex.position[2] = temp_positions[(v - 1) * 3 + 2];
|
||||
|
||||
vertexIndices.push_back(std::get<0>(faceVertices[i + 1]));
|
||||
texCoordIndices.push_back(std::get<1>(faceVertices[i + 1]));
|
||||
normalIndices.push_back(std::get<2>(faceVertices[i + 1]));
|
||||
if (!temp_texCoords.empty() && t > 0)
|
||||
{
|
||||
vertex.texCoord[0] = temp_texCoords[(t - 1) * 2];
|
||||
vertex.texCoord[1] = temp_texCoords[(t - 1) * 2 + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex.texCoord[0] = 0.0f;
|
||||
vertex.texCoord[1] = 0.0f;
|
||||
}
|
||||
|
||||
if (!temp_normals.empty() && n > 0)
|
||||
{
|
||||
vertex.normal[0] = temp_normals[(n - 1) * 3];
|
||||
vertex.normal[1] = temp_normals[(n - 1) * 3 + 1];
|
||||
vertex.normal[2] = temp_normals[(n - 1) * 3 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex.normal[0] = 0.0f;
|
||||
vertex.normal[1] = 0.0f;
|
||||
vertex.normal[2] = 0.0f;
|
||||
}
|
||||
|
||||
// Check if the vertex already exists in the submesh
|
||||
auto it = std::find(currentSubmesh.vertices.begin(), currentSubmesh.vertices.end(), vertex);
|
||||
if (it != currentSubmesh.vertices.end())
|
||||
{
|
||||
return static_cast<unsigned int>(std::distance(currentSubmesh.vertices.begin(), it));
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSubmesh.vertices.push_back(vertex);
|
||||
return static_cast<unsigned int>(currentSubmesh.vertices.size() - 1);
|
||||
}
|
||||
};
|
||||
|
||||
unsigned int idx0 = addVertex(std::get<0>(faceVertices[0]), std::get<1>(faceVertices[0]), std::get<2>(faceVertices[0]));
|
||||
unsigned int idx1 = addVertex(std::get<0>(faceVertices[i]), std::get<1>(faceVertices[i]), std::get<2>(faceVertices[i]));
|
||||
unsigned int idx2 = addVertex(std::get<0>(faceVertices[i + 1]), std::get<1>(faceVertices[i + 1]), std::get<2>(faceVertices[i + 1]));
|
||||
|
||||
currentSubmesh.indices.push_back(idx0);
|
||||
currentSubmesh.indices.push_back(idx1);
|
||||
currentSubmesh.indices.push_back(idx2);
|
||||
}
|
||||
}
|
||||
else if (prefix == "mtllib")
|
||||
{
|
||||
iss >> mtlFileName;
|
||||
}
|
||||
}
|
||||
|
||||
objFile.close();
|
||||
|
||||
// Load MTL file if specified
|
||||
std::vector<Texture> textures;
|
||||
std::unordered_map<std::string, std::vector<Texture>> materialTexturesMap;
|
||||
if (!mtlFileName.empty())
|
||||
{
|
||||
std::ifstream mtlFile(directory + mtlFileName);
|
||||
if (mtlFile.is_open())
|
||||
{
|
||||
std::string mtlLine;
|
||||
std::string currentMaterial;
|
||||
std::unordered_map<std::string, std::string> materialTextures;
|
||||
|
||||
std::string currentMaterialName;
|
||||
while (std::getline(mtlFile, mtlLine))
|
||||
{
|
||||
if (mtlLine.empty() || mtlLine[0] == '#')
|
||||
@ -356,7 +410,7 @@ Model* LoadModelFromList(const std::string &path)
|
||||
|
||||
if (mtlPrefix == "newmtl")
|
||||
{
|
||||
mtlIss >> currentMaterial;
|
||||
mtlIss >> currentMaterialName;
|
||||
}
|
||||
else if (mtlPrefix == "map_Kd")
|
||||
{
|
||||
@ -371,7 +425,7 @@ Model* LoadModelFromList(const std::string &path)
|
||||
texture.id = texID;
|
||||
texture.type = "texture_diffuse";
|
||||
texture.path = texturePath;
|
||||
textures.push_back(texture);
|
||||
materialTexturesMap[currentMaterialName].push_back(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -388,7 +442,7 @@ Model* LoadModelFromList(const std::string &path)
|
||||
texture.id = texID;
|
||||
texture.type = "texture_specular";
|
||||
texture.path = texturePath;
|
||||
textures.push_back(texture);
|
||||
materialTexturesMap[currentMaterialName].push_back(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -405,7 +459,7 @@ Model* LoadModelFromList(const std::string &path)
|
||||
texture.id = texID;
|
||||
texture.type = "texture_normal";
|
||||
texture.path = texturePath;
|
||||
textures.push_back(texture);
|
||||
materialTexturesMap[currentMaterialName].push_back(texture);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -416,110 +470,47 @@ Model* LoadModelFromList(const std::string &path)
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "[AssetManager] Failed to open MTL file: " << mtlFileName << std::endl;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "[AssetManager] No MTL file specified for OBJ: " << path << std::endl;
|
||||
}
|
||||
|
||||
if (textures.empty())
|
||||
// Assign textures to submeshes based on their material
|
||||
for (auto &pair : materialToSubmesh)
|
||||
{
|
||||
std::cout << "[AssetManager] No textures found for OBJ: " << path << std::endl;
|
||||
const std::string &materialName = pair.first;
|
||||
Submesh &submesh = pair.second;
|
||||
|
||||
if (materialTexturesMap.find(materialName) != materialTexturesMap.end())
|
||||
{
|
||||
submesh.textures = materialTexturesMap[materialName];
|
||||
}
|
||||
else
|
||||
{
|
||||
// If no material textures found, you can assign default textures or leave it empty
|
||||
}
|
||||
|
||||
// Initialize OpenGL buffers for the submesh
|
||||
submesh.Initialize();
|
||||
}
|
||||
else
|
||||
|
||||
if (materialToSubmesh.empty())
|
||||
{
|
||||
std::cout << "[AssetManager] Loaded " << textures.size() << " textures for OBJ: " << path << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Create Model object
|
||||
Model *model = new Model();
|
||||
model->textures = textures;
|
||||
|
||||
// Populate vertices with unique vertices
|
||||
std::unordered_map<std::string, unsigned int> uniqueVertices;
|
||||
uniqueVertices.reserve(vertexIndices.size());
|
||||
|
||||
model->vertices.reserve(vertexIndices.size());
|
||||
model->indices.reserve(vertexIndices.size());
|
||||
|
||||
for (size_t i = 0; i < vertexIndices.size(); ++i)
|
||||
// Move submeshes to the model
|
||||
for (auto &pair : materialToSubmesh)
|
||||
{
|
||||
std::ostringstream keyStream;
|
||||
keyStream << vertexIndices[i] << "/" << texCoordIndices[i] << "/" << normalIndices[i];
|
||||
std::string key = keyStream.str();
|
||||
|
||||
auto it = uniqueVertices.find(key);
|
||||
if (it == uniqueVertices.end())
|
||||
{
|
||||
Vertex vertex;
|
||||
// OBJ indices are 1-based
|
||||
vertex.position[0] = temp_positions[(vertexIndices[i] - 1) * 3];
|
||||
vertex.position[1] = temp_positions[(vertexIndices[i] - 1) * 3 + 1];
|
||||
vertex.position[2] = temp_positions[(vertexIndices[i] - 1) * 3 + 2];
|
||||
|
||||
if (!temp_texCoords.empty() && texCoordIndices[i] > 0)
|
||||
{
|
||||
vertex.texCoord[0] = temp_texCoords[(texCoordIndices[i] - 1) * 2];
|
||||
vertex.texCoord[1] = temp_texCoords[(texCoordIndices[i] - 1) * 2 + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex.texCoord[0] = 0.0f;
|
||||
vertex.texCoord[1] = 0.0f;
|
||||
}
|
||||
|
||||
if (!temp_normals.empty() && normalIndices[i] > 0)
|
||||
{
|
||||
vertex.normal[0] = temp_normals[(normalIndices[i] - 1) * 3];
|
||||
vertex.normal[1] = temp_normals[(normalIndices[i] - 1) * 3 + 1];
|
||||
vertex.normal[2] = temp_normals[(normalIndices[i] - 1) * 3 + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
vertex.normal[0] = 0.0f;
|
||||
vertex.normal[1] = 0.0f;
|
||||
vertex.normal[2] = 0.0f;
|
||||
}
|
||||
|
||||
model->vertices.push_back(vertex);
|
||||
unsigned int newIndex = static_cast<unsigned int>(model->vertices.size() - 1);
|
||||
uniqueVertices[key] = newIndex;
|
||||
model->indices.push_back(newIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
model->indices.push_back(it->second);
|
||||
}
|
||||
model->submeshes.emplace_back(std::move(pair.second));
|
||||
}
|
||||
|
||||
// Generate OpenGL buffers
|
||||
glGenVertexArrays(1, &model->vao);
|
||||
glGenBuffers(1, &model->vbo);
|
||||
glGenBuffers(1, &model->ebo);
|
||||
DEBUG_PRINT("[AssetManager] Loaded model with %lld submeshes.", model->submeshes.size());
|
||||
|
||||
glBindVertexArray(model->vao);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, model->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, model->vertices.size() * sizeof(Vertex), model->vertices.data(), GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, model->indices.size() * sizeof(unsigned int), model->indices.data(), GL_STATIC_DRAW);
|
||||
|
||||
// Vertex positions
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
|
||||
// Texture coordinates
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(3 * sizeof(float)));
|
||||
// Normals
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)(5 * sizeof(float)));
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
// The textures are already loaded and stored in the model->textures vector
|
||||
|
||||
return model;
|
||||
}
|
||||
}
|
||||
|
@ -2,12 +2,17 @@
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <GL/glew.h>
|
||||
#include <vector>
|
||||
#include <variant>
|
||||
#include "gcml.h"
|
||||
#include "stdexcept"
|
||||
#include <iostream>
|
||||
#include "Rendering/Shader.h"
|
||||
#include <algorithm>
|
||||
#include <cmath> // For std::abs
|
||||
#include <memory>
|
||||
|
||||
// Forward-declare your Shader class
|
||||
class Shader;
|
||||
@ -32,20 +37,144 @@ struct Vertex
|
||||
float position[3];
|
||||
float texCoord[2];
|
||||
float normal[3];
|
||||
|
||||
// Equality operator to compare two Vertex instances
|
||||
bool operator==(const Vertex &other) const
|
||||
{
|
||||
// Compare positions
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (position[i] != other.position[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare texture coordinates
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
if (texCoord[i] != other.texCoord[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare normals
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if (normal[i] != other.normal[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Define a Texture structure
|
||||
struct Texture {
|
||||
struct Texture
|
||||
{
|
||||
GLuint id;
|
||||
std::string type;
|
||||
std::string path;
|
||||
};
|
||||
|
||||
struct Model {
|
||||
// In AssetManager.h or a separate header file
|
||||
|
||||
struct Submesh
|
||||
{
|
||||
std::vector<Vertex> vertices;
|
||||
std::vector<unsigned int> indices;
|
||||
std::vector<Texture> textures;
|
||||
GLuint vao, vbo, ebo;
|
||||
GLuint vao = 0, vbo = 0, ebo = 0;
|
||||
|
||||
// Initialize OpenGL buffers for the submesh
|
||||
void Initialize()
|
||||
{
|
||||
glGenVertexArrays(1, &vao);
|
||||
glGenBuffers(1, &vbo);
|
||||
glGenBuffers(1, &ebo);
|
||||
|
||||
glBindVertexArray(vao);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), vertices.data(), GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned int), indices.data(), GL_STATIC_DRAW);
|
||||
|
||||
// Vertex positions
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)0);
|
||||
// Texture coordinates
|
||||
glEnableVertexAttribArray(1);
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(3 * sizeof(float)));
|
||||
// Normals
|
||||
glEnableVertexAttribArray(2);
|
||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(5 * sizeof(float)));
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
// Render the submesh
|
||||
void Draw(Shader *shader)
|
||||
{
|
||||
// Bind appropriate textures
|
||||
unsigned int diffuseNr = 1;
|
||||
unsigned int specularNr = 1;
|
||||
unsigned int normalNr = 1;
|
||||
|
||||
for (unsigned int i = 0; i < textures.size(); i++)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + i); // Activate proper texture unit before binding
|
||||
// Retrieve texture number (the N in diffuse_textureN)
|
||||
std::string number;
|
||||
std::string name = textures[i].type;
|
||||
if (name == "texture_diffuse")
|
||||
number = std::to_string(diffuseNr++);
|
||||
else if (name == "texture_specular")
|
||||
number = std::to_string(specularNr++);
|
||||
else if (name == "texture_normal")
|
||||
number = std::to_string(normalNr++);
|
||||
|
||||
// Now set the sampler to the correct texture unit
|
||||
shader->SetInt((name + number).c_str(), i);
|
||||
glBindTexture(GL_TEXTURE_2D, textures[i].id);
|
||||
}
|
||||
|
||||
// Draw mesh
|
||||
glBindVertexArray(vao);
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(indices.size()), GL_UNSIGNED_INT, 0);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Always good practice to set everything back to defaults once configured.
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
};
|
||||
|
||||
// In AssetManager.h or a separate header file
|
||||
|
||||
struct Model
|
||||
{
|
||||
std::vector<Submesh> submeshes;
|
||||
|
||||
// Render all submeshes
|
||||
void Draw(Shader *shader)
|
||||
{
|
||||
for (auto &submesh : submeshes)
|
||||
{
|
||||
submesh.Draw(shader);
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup OpenGL resources
|
||||
void Cleanup()
|
||||
{
|
||||
for (auto &submesh : submeshes)
|
||||
{
|
||||
if (submesh.vao != 0)
|
||||
glDeleteVertexArrays(1, &submesh.vao);
|
||||
if (submesh.vbo != 0)
|
||||
glDeleteBuffers(1, &submesh.vbo);
|
||||
if (submesh.ebo != 0)
|
||||
glDeleteBuffers(1, &submesh.ebo);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// The main AssetManager
|
||||
@ -55,11 +184,11 @@ public:
|
||||
AssetManager() = default;
|
||||
~AssetManager() = default;
|
||||
|
||||
using AssetVariant = std::variant<GLuint, Shader *, std::string, Model *>;
|
||||
using AssetVariant = std::variant<std::shared_ptr<Model>, std::shared_ptr<Shader>, std::shared_ptr<GLuint>>;
|
||||
|
||||
// Template function to load an asset
|
||||
template <typename T>
|
||||
T loadAsset(AssetType type, const std::string &path)
|
||||
std::shared_ptr<T> loadAsset(AssetType type, const std::string &path)
|
||||
{
|
||||
// 1) Create a unique key for cache lookup
|
||||
std::string key = generateKey(type, path);
|
||||
@ -69,9 +198,13 @@ public:
|
||||
if (it != m_AssetMap.end())
|
||||
{
|
||||
// Debug: Log the variant type
|
||||
if (std::holds_alternative<T>(it->second))
|
||||
if (std::holds_alternative<std::shared_ptr<T>>(it->second))
|
||||
{
|
||||
return std::get<T>(it->second);
|
||||
#ifdef DEBUG
|
||||
DebugAssetMap();
|
||||
#endif
|
||||
std::cout << "[AssetManager] Retrieved asset from cache: " << key << std::endl;
|
||||
return std::get<std::shared_ptr<T>>(it->second);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -79,36 +212,27 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
// 3) Not loaded yet, load from disk
|
||||
// 3) Not loaded yet
|
||||
AssetVariant assetData = loadAssetFromDisk(type, path);
|
||||
|
||||
if (assetData.index() == std::variant_npos)
|
||||
if (assetData.valueless_by_exception())
|
||||
{
|
||||
DEBUG_PRINT("[AssetManager] Failed to load asset: %s", path.c_str());
|
||||
// Replace NULL with 0 for non-pointer types
|
||||
if constexpr (std::is_pointer_v<T>)
|
||||
{
|
||||
return nullptr; // For pointers
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0; // For non-pointer
|
||||
}
|
||||
return nullptr; // For smart pointers, return nullptr on failure
|
||||
}
|
||||
|
||||
// 4) Store in cache
|
||||
m_AssetMap[key] = assetData;
|
||||
|
||||
|
||||
// 5) Return the loaded asset
|
||||
return std::get<T>(assetData);
|
||||
return std::get<std::shared_ptr<T>>(assetData);
|
||||
}
|
||||
|
||||
void DebugAssetMap();
|
||||
|
||||
private:
|
||||
// Cache of already loaded assets: key = "type + path"
|
||||
std::unordered_map<std::string, AssetVariant> m_AssetMap;
|
||||
std::map<std::string, AssetVariant> m_AssetMap;
|
||||
|
||||
AssetVariant loadAssetFromDisk(AssetType type, const std::string &path);
|
||||
// Generate the unique key
|
||||
|
@ -1,95 +1,145 @@
|
||||
// Shader.cpp
|
||||
#include "Shader.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <glm/gtc/type_ptr.hpp> // For glm::value_ptr
|
||||
|
||||
// Constructor implementations
|
||||
Shader::Shader() : ID(0) {}
|
||||
|
||||
Shader::Shader(const char* vertexPath, const char* fragmentPath)
|
||||
{
|
||||
// 1. Retrieve the vertex/fragment source code from filePath
|
||||
std::string vertexCode;
|
||||
std::string fragmentCode;
|
||||
std::ifstream vShaderFile;
|
||||
std::ifstream fShaderFile;
|
||||
|
||||
// Ensure ifstream objects can throw exceptions
|
||||
vShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
|
||||
fShaderFile.exceptions (std::ifstream::failbit | std::ifstream::badbit);
|
||||
|
||||
try
|
||||
{
|
||||
// Open files
|
||||
vShaderFile.open(vertexPath);
|
||||
fShaderFile.open(fragmentPath);
|
||||
std::stringstream vShaderStream, fShaderStream;
|
||||
|
||||
// Read file's buffer contents into streams
|
||||
vShaderStream << vShaderFile.rdbuf();
|
||||
fShaderStream << fShaderFile.rdbuf();
|
||||
|
||||
// Close file handlers
|
||||
vShaderFile.close();
|
||||
fShaderFile.close();
|
||||
|
||||
// Convert stream into string
|
||||
vertexCode = vShaderStream.str();
|
||||
fragmentCode = fShaderStream.str();
|
||||
}
|
||||
catch (std::ifstream::failure& e)
|
||||
{
|
||||
std::cerr << "ERROR::SHADER::FILE_NOT_SUCCESSFULLY_READ: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
const char* vShaderCode = vertexCode.c_str();
|
||||
const char * fShaderCode = fragmentCode.c_str();
|
||||
|
||||
// 2. Compile shaders
|
||||
GLuint vertex, fragment;
|
||||
GLint success;
|
||||
GLchar infoLog[512];
|
||||
|
||||
// Vertex Shader
|
||||
vertex = glCreateShader(GL_VERTEX_SHADER);
|
||||
glShaderSource(vertex, 1, &vShaderCode, NULL);
|
||||
glCompileShader(vertex);
|
||||
// Print compile errors if any
|
||||
glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
|
||||
if(!success)
|
||||
{
|
||||
glGetShaderInfoLog(vertex, 512, NULL, infoLog);
|
||||
std::cerr << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
|
||||
// Fragment Shader
|
||||
fragment = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(fragment, 1, &fShaderCode, NULL);
|
||||
glCompileShader(fragment);
|
||||
// Print compile errors if any
|
||||
glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
|
||||
if(!success)
|
||||
{
|
||||
glGetShaderInfoLog(fragment, 512, NULL, infoLog);
|
||||
std::cerr << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
|
||||
// Shader Program
|
||||
ID = glCreateProgram();
|
||||
glAttachShader(ID, vertex);
|
||||
glAttachShader(ID, fragment);
|
||||
glLinkProgram(ID);
|
||||
// Print linking errors if any
|
||||
glGetProgramiv(ID, GL_LINK_STATUS, &success);
|
||||
if(!success)
|
||||
{
|
||||
glGetProgramInfoLog(ID, 512, NULL, infoLog);
|
||||
std::cerr << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
|
||||
}
|
||||
|
||||
// Delete the shaders as they're linked into our program now and no longer necessary
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
}
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
if (m_ProgramID)
|
||||
glDeleteProgram(m_ProgramID);
|
||||
glDeleteProgram(ID);
|
||||
}
|
||||
|
||||
bool Shader::Load(const std::string& vertexPath, const std::string& fragmentPath)
|
||||
void Shader::Use()
|
||||
{
|
||||
// 1) Create shader objects
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
// 2) Load sources
|
||||
std::string vertSource = LoadSourceFromFile(vertexPath);
|
||||
std::string fragSource = LoadSourceFromFile(fragmentPath);
|
||||
if (vertSource.empty() || fragSource.empty())
|
||||
{
|
||||
std::cerr << "[Shader] Failed to read shader files." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3) Compile vertex shader
|
||||
{
|
||||
const char* src = vertSource.c_str();
|
||||
glShaderSource(vertexShader, 1, &src, nullptr);
|
||||
glCompileShader(vertexShader);
|
||||
if (!CompileShader(vertexShader, vertexPath))
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4) Compile fragment shader
|
||||
{
|
||||
const char* src = fragSource.c_str();
|
||||
glShaderSource(fragmentShader, 1, &src, nullptr);
|
||||
glCompileShader(fragmentShader);
|
||||
if (!CompileShader(fragmentShader, fragmentPath))
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5) Create program and link
|
||||
m_ProgramID = glCreateProgram();
|
||||
glAttachShader(m_ProgramID, vertexShader);
|
||||
glAttachShader(m_ProgramID, fragmentShader);
|
||||
glLinkProgram(m_ProgramID);
|
||||
|
||||
// Check link status
|
||||
GLint success;
|
||||
glGetProgramiv(m_ProgramID, GL_LINK_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
char infoLog[1024];
|
||||
glGetProgramInfoLog(m_ProgramID, 1024, nullptr, infoLog);
|
||||
std::cerr << "[Shader] Program linking failed:\n" << infoLog << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cleanup shader objects after linking
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
return true;
|
||||
glUseProgram(ID);
|
||||
}
|
||||
|
||||
bool Shader::CompileShader(GLuint shaderID, const std::string& filePath)
|
||||
GLint Shader::GetUniformLocation(const std::string &name) const
|
||||
{
|
||||
GLint success;
|
||||
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
char infoLog[1024];
|
||||
glGetShaderInfoLog(shaderID, 1024, nullptr, infoLog);
|
||||
std::cerr << "[Shader] Compilation error in " << filePath << ":\n"
|
||||
<< infoLog << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
// Check if the location is already cached
|
||||
if (uniformLocationCache.find(name) != uniformLocationCache.end())
|
||||
return uniformLocationCache.at(name);
|
||||
|
||||
// Otherwise, query it
|
||||
GLint location = glGetUniformLocation(ID, name.c_str());
|
||||
if (location == -1)
|
||||
std::cerr << "Warning: uniform '" << name << "' doesn't exist or is not used in shader!" << std::endl;
|
||||
|
||||
// Cache the location
|
||||
uniformLocationCache[name] = location;
|
||||
return location;
|
||||
}
|
||||
|
||||
std::string Shader::LoadSourceFromFile(const std::string& filePath)
|
||||
void Shader::SetInt(const std::string &name, int value) const
|
||||
{
|
||||
std::ifstream file(filePath);
|
||||
if (!file.is_open())
|
||||
{
|
||||
std::cerr << "[Shader] Could not open file: " << filePath << std::endl;
|
||||
return "";
|
||||
}
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
return buffer.str();
|
||||
glUseProgram(ID); // Ensure the shader program is active
|
||||
glUniform1i(GetUniformLocation(name), value);
|
||||
}
|
||||
|
||||
void Shader::SetFloat(const std::string &name, float value) const
|
||||
{
|
||||
glUseProgram(ID); // Ensure the shader program is active
|
||||
glUniform1f(GetUniformLocation(name), value);
|
||||
}
|
||||
|
||||
void Shader::SetBool(const std::string &name, bool value) const
|
||||
{
|
||||
glUseProgram(ID); // Ensure the shader program is active
|
||||
glUniform1i(GetUniformLocation(name), static_cast<int>(value));
|
||||
}
|
||||
|
||||
void Shader::SetMat4(const std::string &name, const glm::mat4 &mat) const
|
||||
{
|
||||
glUseProgram(ID); // Ensure the shader program is active
|
||||
glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, glm::value_ptr(mat));
|
||||
}
|
||||
|
@ -1,25 +1,34 @@
|
||||
// Shader.h
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <GL/glew.h>
|
||||
#include <unordered_map>
|
||||
#include <GL/glew.h> // or appropriate OpenGL headers
|
||||
#include <glm/glm.hpp> // For glm::mat4
|
||||
|
||||
class Shader
|
||||
{
|
||||
public:
|
||||
Shader() = default;
|
||||
~Shader();
|
||||
GLuint ID;
|
||||
|
||||
// Load & compile from files (vertex & fragment)
|
||||
bool Load(const std::string& vertexPath, const std::string& fragmentPath);
|
||||
// Constructors
|
||||
Shader();
|
||||
Shader(const char* vertexPath, const char* fragmentPath);
|
||||
~Shader(); // Destructor to clean up shader program
|
||||
|
||||
void Use() const { glUseProgram(m_ProgramID); }
|
||||
// Use/activate the shader
|
||||
void Use();
|
||||
|
||||
// Uniform helper
|
||||
GLuint GetProgramID() const { return m_ProgramID; }
|
||||
// Utility functions to set uniforms
|
||||
void SetInt(const std::string &name, int value) const;
|
||||
void SetFloat(const std::string &name, float value) const;
|
||||
void SetBool(const std::string &name, bool value) const;
|
||||
void SetMat4(const std::string &name, const glm::mat4 &mat) const; // For setting 4x4 matrices
|
||||
|
||||
private:
|
||||
bool CompileShader(GLuint shaderID, const std::string& source);
|
||||
std::string LoadSourceFromFile(const std::string& filePath);
|
||||
// Caching uniform locations for performance
|
||||
mutable std::unordered_map<std::string, GLint> uniformLocationCache;
|
||||
|
||||
private:
|
||||
GLuint m_ProgramID = 0;
|
||||
// Retrieves the location of a uniform variable, with caching
|
||||
GLint GetUniformLocation(const std::string &name) const;
|
||||
};
|
||||
|
@ -10,6 +10,8 @@ extern std::vector<GameObject> g_GameObjects;
|
||||
extern GameObject *g_SelectedObject; // Pointer to the currently selected object
|
||||
extern std::shared_ptr<CameraComponent> g_RuntimeCameraObject;
|
||||
|
||||
#include "Engine/AssetManager.h"
|
||||
extern AssetManager *g_AssetManager;
|
||||
extern LoggerWindow *g_LoggerWindow;
|
||||
|
||||
void InspectorWindow::Show()
|
||||
@ -535,27 +537,16 @@ void InspectorWindow::Show()
|
||||
|
||||
if (mesh && g_SelectedObject)
|
||||
{
|
||||
// Set text color to white for visibility
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
|
||||
// Create a collapsing header for the MeshComponent
|
||||
bool meshOpen = ImGui::CollapsingHeader("Mesh##Main", ImGuiTreeNodeFlags_DefaultOpen);
|
||||
ImGui::PopStyleColor();
|
||||
|
||||
if (meshOpen)
|
||||
{
|
||||
// --- VAO ---
|
||||
int vao = static_cast<int>(mesh->vao);
|
||||
if (ImGui::InputInt("VAO", &vao, 1, 0))
|
||||
{
|
||||
mesh->vao = static_cast<GLuint>(vao);
|
||||
}
|
||||
|
||||
// --- Index Count ---
|
||||
int indexCount = static_cast<int>(mesh->indexCount);
|
||||
if (ImGui::InputInt("Index Count", &indexCount, 1, 0))
|
||||
{
|
||||
mesh->indexCount = static_cast<GLuint>(indexCount);
|
||||
}
|
||||
|
||||
// --- Mesh Path ---
|
||||
// --- Mesh Path (Editable) ---
|
||||
const size_t BUFFER_SIZE = 256;
|
||||
char buffer[BUFFER_SIZE];
|
||||
strncpy(buffer, mesh->MeshPath.c_str(), BUFFER_SIZE - 1);
|
||||
@ -565,100 +556,79 @@ void InspectorWindow::Show()
|
||||
{
|
||||
mesh->MeshPath = buffer;
|
||||
// Optionally, trigger reloading the mesh if the path changes
|
||||
// e.g., g_AssetManager.loadAsset<Model *>(AssetType::MODEL, mesh->MeshPath.c_str());
|
||||
// Example:
|
||||
std::shared_ptr<Model> model = g_AssetManager->loadAsset<Model>(AssetType::MODEL, mesh->MeshPath.c_str());
|
||||
|
||||
}
|
||||
|
||||
// --- Textures ---
|
||||
// --- Submeshes Information ---
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Textures:");
|
||||
ImGui::Text("Submeshes:");
|
||||
|
||||
// Display list of textures
|
||||
float availableWidth = ImGui::GetContentRegionAvail().x;
|
||||
|
||||
for (size_t i = 0; i < mesh->textures.size(); ++i)
|
||||
// Check if the model is loaded
|
||||
if (mesh)
|
||||
{
|
||||
Texture &texture = mesh->textures[i];
|
||||
|
||||
// Create a unique identifier for each texture section
|
||||
std::string header = "Texture " + std::to_string(i + 1) + "##" + std::to_string(i);
|
||||
|
||||
|
||||
// Collapsing header for each texture
|
||||
if (ImGui::CollapsingHeader(header.c_str(), ImGuiTreeNodeFlags_DefaultOpen))
|
||||
// Iterate through each Submesh
|
||||
for (size_t sm = 0; sm < mesh->submeshes.size(); ++sm)
|
||||
{
|
||||
// --- Texture Type ---
|
||||
char typeBuffer[32];
|
||||
strncpy(typeBuffer, texture.type.c_str(), sizeof(typeBuffer) - 1);
|
||||
typeBuffer[sizeof(typeBuffer) - 1] = '\0';
|
||||
const Submesh &submesh = mesh->submeshes[sm];
|
||||
std::string header = "Submesh " + std::to_string(sm + 1) + "##Submesh" + std::to_string(sm);
|
||||
|
||||
if (ImGui::InputText(("Type##" + std::to_string(i)).c_str(), typeBuffer, sizeof(typeBuffer)))
|
||||
// Create a collapsing header for each Submesh
|
||||
if (ImGui::CollapsingHeader(header.c_str(), ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
texture.type = std::string(typeBuffer);
|
||||
// Optionally, validate the type or restrict it to certain values
|
||||
}
|
||||
// --- Submesh VAO (Read-Only) ---
|
||||
ImGui::Text("VAO: %d", static_cast<int>(submesh.vao));
|
||||
|
||||
// --- Texture ID ---
|
||||
int texID = static_cast<int>(texture.id);
|
||||
if (ImGui::InputInt(("Texture ID##" + std::to_string(i)).c_str(), &texID, 1, 0))
|
||||
{
|
||||
texture.id = static_cast<GLuint>(texID);
|
||||
}
|
||||
// --- Submesh Index Count (Read-Only) ---
|
||||
ImGui::Text("Index Count: %d", static_cast<int>(submesh.indices.size()));
|
||||
|
||||
// --- Texture Path ---
|
||||
char pathBuffer[256];
|
||||
strncpy(pathBuffer, texture.path.c_str(), sizeof(pathBuffer) - 1);
|
||||
pathBuffer[sizeof(pathBuffer) - 1] = '\0';
|
||||
// --- Textures Associated with the Submesh ---
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Textures:");
|
||||
|
||||
if (ImGui::InputText(("Path##" + std::to_string(i)).c_str(), pathBuffer, sizeof(pathBuffer)))
|
||||
{
|
||||
texture.path = std::string(pathBuffer);
|
||||
// Optionally, trigger reloading the texture if the path changes
|
||||
// e.g., texture.id = g_AssetManager.loadTexture(texture.path, directory);
|
||||
}
|
||||
// Iterate through each Texture in the Submesh
|
||||
for (size_t i = 0; i < submesh.textures.size(); ++i)
|
||||
{
|
||||
const Texture &texture = submesh.textures[i];
|
||||
std::string texHeader = "Texture " + std::to_string(i + 1) + "##Submesh" + std::to_string(sm) + "_Texture" + std::to_string(i);
|
||||
|
||||
// --- Texture Preview ---
|
||||
if (texture.id != 0)
|
||||
{
|
||||
// Retrieve the texture's width and height if needed
|
||||
// For demonstration, using a fixed size
|
||||
|
||||
ImGui::Image(static_cast<ImTextureID>(texture.id), ImVec2(availableWidth, availableWidth), ImVec2(0, 0), ImVec2(1, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("No texture bound.");
|
||||
}
|
||||
// Create a collapsing header for each Texture
|
||||
if (ImGui::CollapsingHeader(texHeader.c_str(), ImGuiTreeNodeFlags_DefaultOpen))
|
||||
{
|
||||
// --- Texture Type (Read-Only) ---
|
||||
ImGui::Text("Type: %s", texture.type.c_str());
|
||||
|
||||
// --- Remove Texture Button ---
|
||||
std::string removeButtonLabel = "Remove##" + std::to_string(i);
|
||||
if (ImGui::Button(removeButtonLabel.c_str()))
|
||||
{
|
||||
mesh->textures.erase(mesh->textures.begin() + i);
|
||||
// Adjust index after removal
|
||||
ImGui::TreePop();
|
||||
break; // Exit the loop as the current index is invalidated
|
||||
}
|
||||
// --- Texture ID (Read-Only) ---
|
||||
ImGui::Text("Texture ID: %d", static_cast<int>(texture.id));
|
||||
|
||||
ImGui::Separator();
|
||||
// --- Texture Path (Read-Only) ---
|
||||
ImGui::Text("Path: %s", texture.path.c_str());
|
||||
|
||||
// --- Texture Preview ---
|
||||
if (texture.id != 0)
|
||||
{
|
||||
// Adjust the size as needed
|
||||
ImVec2 imageSize = ImVec2(100, 100); // Example size
|
||||
ImGui::Image(static_cast<ImTextureID>(texture.id), imageSize, ImVec2(0, 0), ImVec2(1, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("No texture bound.");
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- Add New Texture Button ---
|
||||
// if (ImGui::Button("Add Texture"))
|
||||
//{
|
||||
// // Define default values for the new texture
|
||||
// Texture newTexture;
|
||||
// newTexture.id = 0; // Assign a default or invalid texture ID
|
||||
// newTexture.type = "texture_diffuse"; // Default type
|
||||
// newTexture.path = "path/to/texture.png"; // Default path
|
||||
//
|
||||
// mesh->textures.push_back(newTexture);
|
||||
//}
|
||||
//
|
||||
// --- Display All Textures ---
|
||||
// Optionally, display all textures in a separate section or after the list
|
||||
|
||||
|
||||
else
|
||||
{
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.0f, 0.0f, 1.0f), "No model loaded.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,24 +10,22 @@ ProfilerWindow::ProfilerWindow()
|
||||
{
|
||||
// Initialize m_LastUpdateTime to force an immediate update on the first frame
|
||||
m_LastUpdateTime = std::chrono::steady_clock::now() - std::chrono::duration_cast<std::chrono::steady_clock::duration>(std::chrono::duration<double>(m_UpdateInterval));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::vector<float> ProfilerWindow::ExponentialMovingAverage(const std::deque<double>& data, float alpha) {
|
||||
std::vector<float> ProfilerWindow::ExponentialMovingAverage(const std::deque<double> &data, float alpha)
|
||||
{
|
||||
std::vector<float> ema;
|
||||
ema.reserve(data.size());
|
||||
float prev = 0.0f;
|
||||
for (const auto& val : data) {
|
||||
for (const auto &val : data)
|
||||
{
|
||||
prev = alpha * static_cast<float>(val) + (1.0f - alpha) * prev;
|
||||
ema.push_back(prev);
|
||||
}
|
||||
return ema;
|
||||
}
|
||||
|
||||
void ProfilerWindow::UpdateHistory(const std::unordered_map<std::string, ProfileResult>& data, double totalFrameTime)
|
||||
void ProfilerWindow::UpdateHistory(const std::unordered_map<std::string, ProfileResult> &data, double totalFrameTime)
|
||||
{
|
||||
// Update total frame time history
|
||||
m_TotalFrameTimeHistory.push_back(totalFrameTime);
|
||||
@ -35,9 +33,9 @@ void ProfilerWindow::UpdateHistory(const std::unordered_map<std::string, Profile
|
||||
m_TotalFrameTimeHistory.pop_front();
|
||||
|
||||
// Update each function's profiling history
|
||||
for (const auto& [name, result] : data)
|
||||
for (const auto &[name, result] : data)
|
||||
{
|
||||
auto& history = m_ProfileHistories[name];
|
||||
auto &history = m_ProfileHistories[name];
|
||||
|
||||
// Update total time history
|
||||
history.totalTimeHistory.push_back(result.TotalTime);
|
||||
@ -57,7 +55,7 @@ void ProfilerWindow::UpdateHistory(const std::unordered_map<std::string, Profile
|
||||
}
|
||||
|
||||
// Ensure that functions not present in the current frame retain their last TotalTime and AverageTime
|
||||
for (auto& [name, history] : m_ProfileHistories)
|
||||
for (auto &[name, history] : m_ProfileHistories)
|
||||
{
|
||||
if (data.find(name) == data.end())
|
||||
{
|
||||
@ -102,7 +100,7 @@ void ProfilerWindow::Show()
|
||||
// Begin ImGui window with improved styling
|
||||
ImGui::Begin("Profiler", nullptr, ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_HorizontalScrollbar);
|
||||
|
||||
const auto& data = Profiler::Get().GetLastFrameData();
|
||||
const auto &data = Profiler::Get().GetLastFrameData();
|
||||
|
||||
if (data.empty())
|
||||
{
|
||||
@ -115,7 +113,7 @@ void ProfilerWindow::Show()
|
||||
{
|
||||
// Calculate total frame time
|
||||
double totalFrameTime = 0.0;
|
||||
for (const auto& [name, result] : data)
|
||||
for (const auto &[name, result] : data)
|
||||
{
|
||||
totalFrameTime += result.TotalTime;
|
||||
}
|
||||
@ -151,9 +149,10 @@ void ProfilerWindow::RenderTable()
|
||||
|
||||
// Sort functions by last Total Time descending
|
||||
std::sort(allData.begin(), allData.end(),
|
||||
[](const std::pair<std::string, ProfileHistory>& a, const std::pair<std::string, ProfileHistory>& b) -> bool {
|
||||
return a.second.totalTimeHistory.back() > b.second.totalTimeHistory.back();
|
||||
});
|
||||
[](const std::pair<std::string, ProfileHistory> &a, const std::pair<std::string, ProfileHistory> &b) -> bool
|
||||
{
|
||||
return a.second.totalTimeHistory.back() > b.second.totalTimeHistory.back();
|
||||
});
|
||||
|
||||
// Add a filter input with enhanced styling
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4, 2));
|
||||
@ -166,7 +165,7 @@ void ProfilerWindow::RenderTable()
|
||||
|
||||
// Filtered data
|
||||
std::vector<std::pair<std::string, ProfileHistory>> filteredData;
|
||||
for (const auto& [name, history] : allData)
|
||||
for (const auto &[name, history] : allData)
|
||||
{
|
||||
if (filterStr.empty() || name.find(filterStr) != std::string::npos)
|
||||
filteredData.emplace_back(name, history);
|
||||
@ -188,7 +187,7 @@ void ProfilerWindow::RenderTable()
|
||||
// Alternate row colors for better readability
|
||||
bool rowBg = false;
|
||||
|
||||
for (const auto& [name, history] : filteredData)
|
||||
for (const auto &[name, history] : filteredData)
|
||||
{
|
||||
ImGui::TableNextRow();
|
||||
rowBg = !rowBg;
|
||||
@ -236,9 +235,10 @@ void ProfilerWindow::RenderGraphs()
|
||||
// Collect and sort functions by last Total Time descending
|
||||
std::vector<std::pair<std::string, ProfileHistory>> sortedData(m_ProfileHistories.begin(), m_ProfileHistories.end());
|
||||
std::sort(sortedData.begin(), sortedData.end(),
|
||||
[](const std::pair<std::string, ProfileHistory>& a, const std::pair<std::string, ProfileHistory>& b) -> bool {
|
||||
return a.second.totalTimeHistory.back() > b.second.totalTimeHistory.back();
|
||||
});
|
||||
[](const std::pair<std::string, ProfileHistory> &a, const std::pair<std::string, ProfileHistory> &b) -> bool
|
||||
{
|
||||
return a.second.totalTimeHistory.back() > b.second.totalTimeHistory.back();
|
||||
});
|
||||
|
||||
size_t displayCount = std::min<size_t>(5, sortedData.size()); // Limit to top 5 functions
|
||||
|
||||
@ -249,7 +249,7 @@ void ProfilerWindow::RenderGraphs()
|
||||
float alpha = 0.2f; // Smoothing factor for EMA
|
||||
for (size_t i = 0; i < displayCount; ++i)
|
||||
{
|
||||
const auto& [name, history] = sortedData[i];
|
||||
const auto &[name, history] = sortedData[i];
|
||||
functionNames.push_back(name);
|
||||
|
||||
// Smooth each function's data using EMA
|
||||
@ -259,7 +259,7 @@ void ProfilerWindow::RenderGraphs()
|
||||
// Find the longest data series and the maximum value for normalization
|
||||
size_t maxHistorySize = 0;
|
||||
float maxValue = 0.0f;
|
||||
for (const auto& series : plotData)
|
||||
for (const auto &series : plotData)
|
||||
{
|
||||
if (!series.empty())
|
||||
{
|
||||
@ -289,8 +289,7 @@ void ProfilerWindow::RenderGraphs()
|
||||
nullptr,
|
||||
0.0f,
|
||||
static_cast<float>(maxValue) * 1.1f, // Add some padding to the max value
|
||||
ImVec2(0, 100)
|
||||
);
|
||||
ImVec2(0, 100));
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
|
@ -309,14 +309,14 @@ void RenderWindow::InitGLResources()
|
||||
// ----------------------------------------------------
|
||||
|
||||
{
|
||||
Shader *shaderAsset = g_AssetManager.loadAsset<Shader *>(AssetType::SHADER, "assets/shaders/UnlitMaterial");
|
||||
std::shared_ptr<Shader> shaderAsset = g_AssetManager.loadAsset<Shader>(AssetType::SHADER, "assets/shaders/UnlitMaterial");
|
||||
if (!shaderAsset)
|
||||
{
|
||||
fprintf(stderr, "[RenderWindow] Failed to load shader via AssetManager.\n");
|
||||
return;
|
||||
}
|
||||
// Cast back to your Shader class
|
||||
m_ShaderPtr = static_cast<Shader *>(shaderAsset);
|
||||
m_ShaderPtr = shaderAsset.get();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
@ -348,7 +348,7 @@ void RenderWindow::InitGLResources()
|
||||
// 3) Load TEXTURE from the asset manager
|
||||
// ----------------------------------------------------
|
||||
{
|
||||
GLuint texAsset = g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/wood.png");
|
||||
std::shared_ptr<GLuint> texAsset = g_AssetManager.loadAsset<GLuint>(AssetType::TEXTURE, "assets/textures/wood.png");
|
||||
if (!texAsset)
|
||||
{
|
||||
fprintf(stderr, "[RenderWindow] Failed to load texture.\n");
|
||||
@ -356,7 +356,7 @@ void RenderWindow::InitGLResources()
|
||||
else
|
||||
{
|
||||
// Cast from void* to GLuint
|
||||
m_TextureID = texAsset;
|
||||
m_TextureID = *texAsset; // Assign the GLuint value
|
||||
}
|
||||
}
|
||||
|
||||
@ -384,6 +384,11 @@ void CheckOpenGLError(const std::string &location)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp> // For glm::value_ptr
|
||||
#include <algorithm> // Ensure <algorithm> is included
|
||||
|
||||
void RenderWindow::RenderSceneToFBO(bool *GameRunning)
|
||||
{
|
||||
m_RotationAngle += 0.001f; // Spin per frame
|
||||
@ -406,7 +411,6 @@ void RenderWindow::RenderSceneToFBO(bool *GameRunning)
|
||||
}
|
||||
|
||||
m_ShaderPtr->Use();
|
||||
GLuint programID = m_ShaderPtr->GetProgramID();
|
||||
|
||||
// Define view and projection matrices once
|
||||
std::shared_ptr<CameraComponent> activeCamera = nullptr;
|
||||
@ -442,18 +446,8 @@ void RenderWindow::RenderSceneToFBO(bool *GameRunning)
|
||||
std::shared_ptr<TransformComponent> transform = obj->GetComponent<TransformComponent>();
|
||||
std::shared_ptr<MeshComponent> mesh = obj->GetComponent<MeshComponent>();
|
||||
|
||||
if (transform && mesh)
|
||||
if (transform && mesh && mesh)
|
||||
{
|
||||
// Validate VAO
|
||||
if (mesh->vao == 0)
|
||||
{
|
||||
DEBUG_PRINT("[RenderWindow] Warning: Mesh VAO is not initialized.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Update triangle count
|
||||
g_GPU_Triangles_drawn_to_screen += static_cast<int>(mesh->indexCount);
|
||||
|
||||
// Apply transformations
|
||||
model = glm::translate(model, transform->position);
|
||||
model = glm::rotate(model, glm::radians(transform->rotation.x), glm::vec3(1.f, 0.f, 0.f));
|
||||
@ -461,108 +455,78 @@ void RenderWindow::RenderSceneToFBO(bool *GameRunning)
|
||||
model = glm::rotate(model, glm::radians(transform->rotation.z), glm::vec3(0.f, 0.f, 1.f));
|
||||
model = glm::scale(model, transform->scale);
|
||||
|
||||
// Compute MVP
|
||||
// Compute MVP matrix
|
||||
glm::mat4 mvp = proj * view * model;
|
||||
|
||||
// Pass MVP to the shader
|
||||
GLint mvpLoc = glGetUniformLocation(programID, "uMVP");
|
||||
if(mvpLoc != -1)
|
||||
{
|
||||
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvp));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_PRINT("[RenderWindow] Warning: Uniform 'uMVP' not found in shader.");
|
||||
}
|
||||
// Pass MVP and Model matrices to the shader
|
||||
m_ShaderPtr->SetMat4("uMVP", mvp);
|
||||
m_ShaderPtr->SetMat4("uModel", model);
|
||||
|
||||
// Pass Model matrix to the shader
|
||||
GLint modelLoc = glGetUniformLocation(programID, "uModel");
|
||||
if(modelLoc != -1)
|
||||
// Iterate through each submesh
|
||||
for (const auto &submesh : mesh->submeshes)
|
||||
{
|
||||
glUniformMatrix4fv(modelLoc, 1, GL_FALSE, glm::value_ptr(model));
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_PRINT("[RenderWindow] Warning: Uniform 'uModel' not found in shader.");
|
||||
}
|
||||
|
||||
// -----------------------------------
|
||||
// 2) Bind the object's diffuse textures
|
||||
// -----------------------------------
|
||||
// Define the maximum number of diffuse textures as per the shader
|
||||
const int MAX_DIFFUSE = 32; // Must match the shader's MAX_DIFFUSE
|
||||
int textureUnit = 0;
|
||||
|
||||
// Iterate through all textures and bind those with type "texture_diffuse"
|
||||
for (const auto &texture : mesh->textures)
|
||||
{
|
||||
if (texture.type == "texture_diffuse")
|
||||
// Validate VAO
|
||||
if (submesh.vao == 0)
|
||||
{
|
||||
if (textureUnit >= MAX_DIFFUSE)
|
||||
{
|
||||
DEBUG_PRINT("[RenderWindow] Warning: Exceeded maximum number of diffuse textures (%d) for shader.", MAX_DIFFUSE);
|
||||
break; // Prevent exceeding the array bounds in the shader
|
||||
}
|
||||
|
||||
// Activate the appropriate texture unit
|
||||
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, texture.id);
|
||||
|
||||
// Construct the uniform name dynamically (e.g., "uTextures.texture_diffuse[0]")
|
||||
std::string uniformName = "uTextures.texture_diffuse[" + std::to_string(textureUnit) + "]";
|
||||
GLint texLoc = glGetUniformLocation(programID, uniformName.c_str());
|
||||
|
||||
if (texLoc != -1)
|
||||
{
|
||||
glUniform1i(texLoc, textureUnit);
|
||||
}
|
||||
|
||||
textureUnit++;
|
||||
DEBUG_PRINT("[RenderWindow] Warning: Submesh VAO is not initialized.");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Assign default texture to unused texture slots
|
||||
for(int i = textureUnit; i < MAX_DIFFUSE; ++i)
|
||||
{
|
||||
std::string uniformName = "uTextures.texture_diffuse[" + std::to_string(i) + "]";
|
||||
GLint texLoc = glGetUniformLocation(programID, uniformName.c_str());
|
||||
if(texLoc != -1)
|
||||
// Update triangle count
|
||||
g_GPU_Triangles_drawn_to_screen += static_cast<int>(submesh.indices.size() / 3);
|
||||
|
||||
// Bind textures for the submesh
|
||||
// Assuming the shader has uniform arrays like uTextures.texture_diffuse[32]
|
||||
const int MAX_DIFFUSE = 32; // Must match the shader's MAX_DIFFUSE
|
||||
int textureUnit = 0;
|
||||
|
||||
// Iterate through all textures and bind those with type "texture_diffuse"
|
||||
for (const auto &texture : submesh.textures)
|
||||
{
|
||||
glUniform1i(texLoc, 0); // Assign texture unit 0 (ensure texture 0 is a valid default)
|
||||
CheckOpenGLError("After glUniform1i for default texture");
|
||||
if (texture.type == "texture_diffuse")
|
||||
{
|
||||
if (textureUnit >= MAX_DIFFUSE)
|
||||
{
|
||||
DEBUG_PRINT("[RenderWindow] Warning: Exceeded maximum number of diffuse textures (%d) for shader.", MAX_DIFFUSE);
|
||||
break; // Prevent exceeding the array bounds in the shader
|
||||
}
|
||||
|
||||
// Activate the appropriate texture unit
|
||||
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||
glBindTexture(GL_TEXTURE_2D, texture.id);
|
||||
|
||||
// Construct the uniform name dynamically (e.g., "uTextures.texture_diffuse[0]")
|
||||
std::string uniformName = "uTextures.texture_diffuse[" + std::to_string(textureUnit) + "]";
|
||||
m_ShaderPtr->SetInt(uniformName, textureUnit);
|
||||
|
||||
textureUnit++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the number of active diffuse textures
|
||||
GLint numDiffuseLoc = glGetUniformLocation(programID, "uNumDiffuseTextures");
|
||||
if(numDiffuseLoc != -1)
|
||||
{
|
||||
glUniform1i(numDiffuseLoc, textureUnit);
|
||||
CheckOpenGLError("After glUniform1i for uNumDiffuseTextures");
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_PRINT("[RenderWindow] Warning: Uniform 'uNumDiffuseTextures' not found in shader.");
|
||||
}
|
||||
// Assign default texture to unused texture slots to prevent shader errors
|
||||
for(int i = textureUnit; i < MAX_DIFFUSE; ++i)
|
||||
{
|
||||
std::string uniformName = "uTextures.texture_diffuse[" + std::to_string(i) + "]";
|
||||
m_ShaderPtr->SetInt(uniformName, 0); // Assign texture unit 0 (ensure texture 0 is a valid default)
|
||||
}
|
||||
|
||||
// -----------------------------------
|
||||
// 3) Draw the object's mesh
|
||||
// -----------------------------------
|
||||
glBindVertexArray(mesh->vao);
|
||||
glDrawElements(GL_TRIANGLES, mesh->indexCount, GL_UNSIGNED_INT, nullptr);
|
||||
glBindVertexArray(0);
|
||||
CheckOpenGLError("After glDrawElements");
|
||||
// Set the number of active diffuse textures
|
||||
m_ShaderPtr->SetInt("uNumDiffuseTextures", textureUnit);
|
||||
|
||||
// Reset active texture
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
CheckOpenGLError("After glActiveTexture(GL_TEXTURE0)");
|
||||
// Draw the submesh
|
||||
glBindVertexArray(submesh.vao);
|
||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(submesh.indices.size()), GL_UNSIGNED_INT, nullptr);
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Reset active texture to default
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
// Cleanup: Unbind the shader program
|
||||
glUseProgram(0);
|
||||
CheckOpenGLError("After glUseProgram(0)");
|
||||
|
||||
// Unbind the FBO
|
||||
m_FBO.Unbind();
|
||||
CheckOpenGLError("After FBO Unbind");
|
||||
}
|
||||
|
@ -22,14 +22,6 @@ std::shared_ptr<GameObject> CreateDefaultCube()
|
||||
int newId = g_GameObjects.size();
|
||||
auto newGameObject = std::make_shared<GameObject>(newId, ("New GameObject"));
|
||||
newGameObject->AddComponent(std::make_shared<TransformComponent>()); // Ensure each entity has a TransformComponent by default
|
||||
newGameObject->AddComponent(std::make_shared<MeshComponent>()); // Ensure each entity has a TransformComponent by default
|
||||
|
||||
// Suppose we loaded a VAO, an EBO with 36 indices for the cube,
|
||||
// and a texture ID from the asset manager
|
||||
std::shared_ptr<MeshComponent> mesh = newGameObject->GetComponent<MeshComponent>();
|
||||
|
||||
mesh->vao = CreateCubeVAO();
|
||||
mesh->indexCount = 36;
|
||||
|
||||
return newGameObject;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user