Merge remote-tracking branch 'origin/main' into SP3-2-Physics
This commit is contained in:
commit
10ba68b284
|
@ -0,0 +1,4 @@
|
|||
Start in Fullscreen: false
|
||||
Starting Scene ID: 94283040
|
||||
Window Size: {x: 1920, y: 1080}
|
||||
Window Title: SHADE Engine
|
Binary file not shown.
|
@ -1,3 +0,0 @@
|
|||
Name: Cube.003
|
||||
ID: 71245919
|
||||
Type: 4
|
|
@ -1,3 +0,0 @@
|
|||
Name: Cube.012
|
||||
ID: 80365422
|
||||
Type: 4
|
|
@ -1,16 +1,16 @@
|
|||
[Window][MainStatusBar]
|
||||
Pos=0,1060
|
||||
Pos=0,1007
|
||||
Size=1920,20
|
||||
Collapsed=0
|
||||
|
||||
[Window][SHEditorMenuBar]
|
||||
Pos=0,48
|
||||
Size=1920,1012
|
||||
Size=1920,959
|
||||
Collapsed=0
|
||||
|
||||
[Window][Hierarchy Panel]
|
||||
Pos=0,197
|
||||
Size=308,863
|
||||
Pos=0,189
|
||||
Size=308,818
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
|
@ -21,13 +21,13 @@ Collapsed=0
|
|||
|
||||
[Window][Inspector]
|
||||
Pos=1528,48
|
||||
Size=392,1012
|
||||
Size=392,959
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Profiler]
|
||||
Pos=0,48
|
||||
Size=308,147
|
||||
Size=308,139
|
||||
Collapsed=0
|
||||
DockId=0x00000003,0
|
||||
|
||||
|
@ -76,7 +76,7 @@ DockId=0x0000000B,0
|
|||
|
||||
[Window][ Viewport]
|
||||
Pos=310,48
|
||||
Size=1216,715
|
||||
Size=1216,662
|
||||
Collapsed=0
|
||||
DockId=0x0000000B,0
|
||||
|
||||
|
@ -93,13 +93,19 @@ Collapsed=0
|
|||
DockId=0x0000000A,0
|
||||
|
||||
[Window][ Asset Browser]
|
||||
Pos=310,765
|
||||
Pos=310,712
|
||||
Size=1216,295
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
|
||||
[Window][Material Inspector]
|
||||
Pos=1528,48
|
||||
Size=392,959
|
||||
Collapsed=0
|
||||
DockId=0x00000006,1
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Split=X
|
||||
DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=0,71 Size=1920,959 Split=X
|
||||
DockNode ID=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881
|
||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 Selected=0x1E6EB881
|
||||
|
@ -111,5 +117,5 @@ DockSpace ID=0xC5C9B8AB Window=0xBE4044E9 Pos=8,79 Size=1920,1012 Spli
|
|||
DockNode ID=0x0000000C Parent=0x00000009 SizeRef=1501,295 Selected=0xB128252A
|
||||
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6
|
||||
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532
|
||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=392,1036 Selected=0xE7039252
|
||||
DockNode ID=0x00000006 Parent=0xC5C9B8AB SizeRef=392,1036 Selected=0xD3697FB6
|
||||
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
- VertexShader: 39210065
|
||||
FragmentShader: 46377769
|
||||
SubPass: G-Buffer Write
|
||||
Properties:
|
||||
data.color: {x: 1, y: 1, z: 1, w: 1}
|
||||
data.textureIndex: 58303057
|
||||
data.alpha: 0
|
||||
data.beta: {x: 1, y: 1, z: 1}
|
|
@ -0,0 +1,3 @@
|
|||
Name: BagMaterial
|
||||
ID: 123745521
|
||||
Type: 7
|
|
@ -0,0 +1,8 @@
|
|||
- VertexShader: 39210065
|
||||
FragmentShader: 46377769
|
||||
SubPass: G-Buffer Write
|
||||
Properties:
|
||||
data.color: {x: 1, y: 1, z: 1, w: 1}
|
||||
data.textureIndex: 64651793
|
||||
data.alpha: 0
|
||||
data.beta: {x: 1, y: 1, z: 1}
|
|
@ -0,0 +1,3 @@
|
|||
Name: TestMat
|
||||
ID: 126974645
|
||||
Type: 7
|
|
@ -0,0 +1,8 @@
|
|||
- VertexShader: 39210065
|
||||
FragmentShader: 46377769
|
||||
SubPass: G-Buffer Write
|
||||
Properties:
|
||||
data.color: {x: 1, y: 1, z: 1, w: 1}
|
||||
data.textureIndex: 0
|
||||
data.alpha: 0
|
||||
data.beta: {x: 1, y: 1, z: 1}
|
|
@ -0,0 +1,3 @@
|
|||
Name: WhiteMat
|
||||
ID: 124370424
|
||||
Type: 7
|
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -0,0 +1,10 @@
|
|||
Name: racoon
|
||||
ID: 77816045
|
||||
Type: 4
|
||||
Sub Assets:
|
||||
Name: Bag
|
||||
ID: 144838771
|
||||
Type: 8
|
||||
Name: Raccoon
|
||||
ID: 149697411
|
||||
Type: 8
|
|
@ -0,0 +1,259 @@
|
|||
- EID: 0
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Camera Component:
|
||||
Position: {x: 0, y: 0, z: 0}
|
||||
Pitch: 0
|
||||
Yaw: 0
|
||||
Roll: 0
|
||||
Width: 1920
|
||||
Height: 1080
|
||||
Near: 0.00999999978
|
||||
Far: 10000
|
||||
Perspective: true
|
||||
Light Component:
|
||||
Position: {x: 0, y: 0, z: 0}
|
||||
Type: Directional
|
||||
Direction: {x: 1.79999995, y: 0, z: 1}
|
||||
Color: {x: 0.951541841, y: 0.921719015, z: 0.553319454, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0
|
||||
Scripts: ~
|
||||
- EID: 1
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -1.440328, y: -4.41369677, z: -5}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 49.4798889, y: 0.5, z: 17.5}
|
||||
Renderable Component:
|
||||
Mesh: 149697411
|
||||
Material: 126974645
|
||||
RigidBody Component:
|
||||
Type: Static
|
||||
Mass: 1
|
||||
Drag: 0
|
||||
Angular Drag: 0
|
||||
Use Gravity: true
|
||||
Interpolate: true
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: false
|
||||
Freeze Rotation Y: false
|
||||
Freeze Rotation Z: false
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Type: Box
|
||||
Half Extents: {x: 24.7399445, y: 0.25, z: 8.75}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0, z: 0}
|
||||
Scripts: ~
|
||||
- EID: 2
|
||||
Name: Player
|
||||
IsActive: true
|
||||
NumberOfChildren: 3
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -3.06177855, y: -2, z: -5}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 2, y: 2, z: 2}
|
||||
Renderable Component:
|
||||
Mesh: 149697411
|
||||
Material: 126974645
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Mass: 1
|
||||
Drag: 0
|
||||
Angular Drag: 0
|
||||
Use Gravity: true
|
||||
Interpolate: true
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: false
|
||||
Freeze Rotation Y: false
|
||||
Freeze Rotation Z: false
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
Scripts:
|
||||
- Type: PlayerController
|
||||
drag: 2
|
||||
currentState: 0
|
||||
maxMoveVel: 2
|
||||
moveForce: 50
|
||||
sprintMultiplier: 2
|
||||
rotationFactorPerFrame: 1
|
||||
maxJumpHeight: 4
|
||||
maxJumpTime: 0.75
|
||||
fallMultipler: 2
|
||||
lightMultiper: 0.75
|
||||
mediumMultiper: 0.5
|
||||
heavyMultiper: 0.25
|
||||
- Type: PickAndThrow
|
||||
throwForce: [200, 300, 200]
|
||||
item: 5
|
||||
- EID: 3
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -0.0094268322, y: 0, z: 0}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
Scripts: ~
|
||||
- EID: 4
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
Scripts:
|
||||
- Type: SHADE_Scripting.ThirdPersonCamera
|
||||
armLength: 2
|
||||
turnSpeedPitch: 0.300000012
|
||||
turnSpeedYaw: 0.5
|
||||
pitchClamp: 45
|
||||
- EID: 9
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
Renderable Component:
|
||||
Mesh: 144838771
|
||||
Material: 123745521
|
||||
Scripts: ~
|
||||
- EID: 5
|
||||
Name: item
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: -2, z: -5}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 2, y: 2, z: 2}
|
||||
Renderable Component:
|
||||
Mesh: 144838771
|
||||
Material: 123745521
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Mass: 1
|
||||
Drag: 0
|
||||
Angular Drag: 0
|
||||
Use Gravity: true
|
||||
Interpolate: false
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: true
|
||||
Freeze Rotation Y: true
|
||||
Freeze Rotation Z: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Type: Box
|
||||
Half Extents: {x: 1, y: 1, z: 1}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
- Is Trigger: true
|
||||
Type: Box
|
||||
Half Extents: {x: 2, y: 2, z: 2}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
Scripts:
|
||||
- Type: Item
|
||||
currCategory: 0
|
||||
- EID: 6
|
||||
Name: AI
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: -8, y: -2, z: 2.5}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
Renderable Component:
|
||||
Mesh: 149697411
|
||||
Material: 126974645
|
||||
RigidBody Component:
|
||||
Type: Dynamic
|
||||
Mass: 1
|
||||
Drag: 0
|
||||
Angular Drag: 0
|
||||
Use Gravity: true
|
||||
Interpolate: false
|
||||
Freeze Position X: false
|
||||
Freeze Position Y: false
|
||||
Freeze Position Z: false
|
||||
Freeze Rotation X: true
|
||||
Freeze Rotation Y: true
|
||||
Freeze Rotation Z: true
|
||||
Collider Component:
|
||||
Colliders:
|
||||
- Is Trigger: false
|
||||
Type: Box
|
||||
Half Extents: {x: 0.5, y: 0.5, z: 0.5}
|
||||
Friction: 0.400000006
|
||||
Bounciness: 0
|
||||
Density: 1
|
||||
Position Offset: {x: 0, y: 0.5, z: 0}
|
||||
Scripts:
|
||||
- Type: AIPrototype
|
||||
movementForceMultiplier: 100
|
||||
patrolSpeed: 0.400000006
|
||||
chaseSpeed: 0.800000012
|
||||
distanceToCapture: 1.20000005
|
||||
distanceToStartChase: 2
|
||||
distanceToEndChase: 2.5
|
||||
- EID: 7
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: -16.8647861, z: -14.039052}
|
||||
Rotate: {x: -0, y: 0, z: -0}
|
||||
Scale: {x: 28.1434975, y: 28.1434975, z: 28.1434975}
|
||||
Renderable Component:
|
||||
Mesh: 149697411
|
||||
Material: 126974645
|
||||
Scripts: ~
|
||||
- EID: 8
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Light Component:
|
||||
Position: {x: 0, y: 0, z: 0}
|
||||
Type: Ambient
|
||||
Direction: {x: 0, y: 0, z: 1}
|
||||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0.25
|
||||
Scripts: ~
|
|
@ -0,0 +1,3 @@
|
|||
Name: M2Scene
|
||||
ID: 94283040
|
||||
Type: 5
|
|
@ -0,0 +1,72 @@
|
|||
- EID: 0
|
||||
Name: Default
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0.304069757, z: 1.73034382}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
Camera Component:
|
||||
Position: {x: 0, y: 0.304069757, z: 1.73034382}
|
||||
Pitch: 0
|
||||
Yaw: 0
|
||||
Roll: 0
|
||||
Width: 1200
|
||||
Height: 1080
|
||||
Near: 0.00999999978
|
||||
Far: 10000
|
||||
Perspective: true
|
||||
Scripts: ~
|
||||
- EID: 1
|
||||
Name: Raccoon
|
||||
IsActive: true
|
||||
NumberOfChildren: 1
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0, y: 0, z: 0}
|
||||
Rotate: {x: 0, y: 0, z: 0}
|
||||
Scale: {x: 1, y: 1, z: 1}
|
||||
Renderable Component:
|
||||
Mesh: 149697411
|
||||
Material: 126974645
|
||||
Scripts: ~
|
||||
- EID: 3
|
||||
Name: Bag
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Transform Component:
|
||||
Translate: {x: 0.006237939, y: -0.000393368304, z: 0}
|
||||
Rotate: {x: -0, y: 2.79945588, z: 0}
|
||||
Scale: {x: 1.0000881, y: 1, z: 1.0000881}
|
||||
Renderable Component:
|
||||
Mesh: 144838771
|
||||
Material: 123745521
|
||||
Scripts: ~
|
||||
- EID: 2
|
||||
Name: DirectionalLight
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Light Component:
|
||||
Position: {x: 0, y: 0, z: 0}
|
||||
Type: Directional
|
||||
Direction: {x: 0, y: 0, z: 1}
|
||||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0
|
||||
Scripts: ~
|
||||
- EID: 4
|
||||
Name: AmbientLight
|
||||
IsActive: true
|
||||
NumberOfChildren: 0
|
||||
Components:
|
||||
Light Component:
|
||||
Position: {x: 0, y: 0, z: 0}
|
||||
Type: Ambient
|
||||
Direction: {x: 0, y: 0, z: 1}
|
||||
Color: {x: 1, y: 1, z: 1, w: 1}
|
||||
Layer: 4294967295
|
||||
Strength: 0.600000024
|
||||
Scripts: ~
|
|
@ -0,0 +1,3 @@
|
|||
Name: Scene2
|
||||
ID: 87285316
|
||||
Type: 5
|
|
@ -21,7 +21,8 @@ layout(set = 4, binding = 0, rgba32f) uniform image2D positions;
|
|||
layout(set = 4, binding = 1, rgba32f) uniform image2D normals;
|
||||
layout(set = 4, binding = 2, rgba8) uniform image2D albedo;
|
||||
layout(set = 4, binding = 3, r32ui) uniform uimage2D lightLayerData;
|
||||
layout(set = 4, binding = 4, rgba8) uniform image2D targetImage;
|
||||
layout(set = 4, binding = 4, r8) uniform image2D ssaoBlurredImage;
|
||||
layout(set = 4, binding = 5, rgba8) uniform image2D targetImage;
|
||||
|
||||
layout(set = 1, binding = 0) uniform LightCounts
|
||||
{
|
||||
|
@ -51,33 +52,46 @@ void main()
|
|||
vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb;
|
||||
|
||||
// Get position of fragment in world space
|
||||
vec3 positionWorld = imageLoad (positions, globalThread).rgb;
|
||||
vec3 positionView = imageLoad (positions, globalThread).rgb;
|
||||
|
||||
// normal of fragment
|
||||
vec3 normalWorld = imageLoad(normals, globalThread).rgb;
|
||||
vec3 normalView = imageLoad(normals, globalThread).rgb;
|
||||
|
||||
// light layer index
|
||||
uint lightLayer = imageLoad (lightLayerData, globalThread).r;
|
||||
|
||||
vec3 fragColor = vec3 (0.0f);
|
||||
|
||||
for (int i = 0; i < lightCounts.directionalLights; ++i)
|
||||
{
|
||||
if ((lightLayer & DirLightData.dLightData[i].cullingMask) != 0)
|
||||
{
|
||||
// get normalized direction of light
|
||||
vec3 dLightNormalized = normalize (DirLightData.dLightData[i].direction);
|
||||
|
||||
// Get diffuse strength
|
||||
float diffuseStrength = max (0, dot (dLightNormalized, normalWorld));
|
||||
float diffuseStrength = max (0, dot (dLightNormalized, normalView));
|
||||
|
||||
// Calculate the fragment color
|
||||
fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < lightCounts.ambientLights; ++i)
|
||||
{
|
||||
if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0)
|
||||
{
|
||||
// Just do some add
|
||||
//fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f);
|
||||
fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength);
|
||||
}
|
||||
}
|
||||
|
||||
float ssaoVal = imageLoad (ssaoBlurredImage, globalThread).r;
|
||||
fragColor *= ssaoVal;
|
||||
|
||||
// store result into result image
|
||||
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor, 1.0f));
|
||||
imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(fragColor.rgb, 1.0f));
|
||||
//imageStore(targetImage, ivec2(gl_GlobalInvocationID.xy), vec4(ssaoVal.rrr, 1.0f));
|
||||
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,58 @@
|
|||
#version 450
|
||||
|
||||
#define BLUR_WIDTH 5
|
||||
#define BLUR_HALF_WIDTH BLUR_WIDTH / 2
|
||||
#define SHM_WIDTH BLUR_WIDTH + 16 - 1
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16) in;
|
||||
layout(set = 4, binding = 0, r8) uniform image2D ssaoImage;
|
||||
layout(set = 4, binding = 1, r8) uniform image2D ssaoBlurImage;
|
||||
|
||||
|
||||
float GetSSAOValue(ivec2 uv, ivec2 imageSize)
|
||||
{
|
||||
if (uv.x >= 0 && uv.y >= 0 && uv.x < imageSize.x && uv.y < imageSize.y)
|
||||
{
|
||||
return imageLoad (ssaoImage, uv).r;
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
shared float sharedPixels[16 + BLUR_WIDTH - 1][16 + BLUR_WIDTH - 1];
|
||||
|
||||
void main()
|
||||
{
|
||||
ivec2 globalThread = ivec2 (gl_GlobalInvocationID.xy);
|
||||
ivec2 localThread = ivec2 (gl_LocalInvocationID.xy);
|
||||
ivec2 inputImageSize = imageSize(ssaoImage);
|
||||
|
||||
// Load color into shared memory
|
||||
ivec2 start = ivec2 (gl_WorkGroupID) * ivec2 (gl_WorkGroupSize) - (BLUR_HALF_WIDTH);
|
||||
for (int i = localThread.x; i < SHM_WIDTH; i += int (gl_WorkGroupSize.x))
|
||||
{
|
||||
for (int j = localThread.y; j < SHM_WIDTH; j += int (gl_WorkGroupSize.y))
|
||||
{
|
||||
float value = GetSSAOValue (start + ivec2 (i, j), inputImageSize);
|
||||
sharedPixels[i][j] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// wait for all shared memory to load
|
||||
barrier();
|
||||
|
||||
ivec2 shmStart = ivec2 (localThread + (BLUR_HALF_WIDTH));
|
||||
|
||||
float sum = 0;
|
||||
for (int i = -BLUR_HALF_WIDTH; i <= BLUR_HALF_WIDTH; ++i)
|
||||
{
|
||||
for (int j = -BLUR_HALF_WIDTH; j <= BLUR_HALF_WIDTH; ++j)
|
||||
{
|
||||
float sharedVal = sharedPixels[shmStart.x + i][shmStart.y + j];
|
||||
sum += sharedVal;
|
||||
}
|
||||
}
|
||||
|
||||
sum /= (BLUR_WIDTH * BLUR_WIDTH);
|
||||
imageStore(ssaoBlurImage, globalThread, vec4(sum.rrr, 1.0f));
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
Name: SSAOBlur_CS
|
||||
ID: 39760835
|
||||
Type: 2
|
|
@ -0,0 +1,104 @@
|
|||
#version 450
|
||||
|
||||
const uint NUM_SAMPLES = 64;
|
||||
const uint NUM_ROTATIONS = 16;
|
||||
const int ROTATION_KERNEL_W = 4;
|
||||
const int ROTATION_KERNEL_H = 4;
|
||||
|
||||
// can perhaps pass in as push constant.
|
||||
const float RADIUS = 0.5f;
|
||||
const float BIAS = 0.025f;
|
||||
|
||||
layout(local_size_x = 16, local_size_y = 16) in;
|
||||
layout(set = 4, binding = 0, rgba32f) uniform image2D positions;
|
||||
layout(set = 4, binding = 1, rgba32f) uniform image2D normals;
|
||||
layout(set = 4, binding = 2, rgba32f) uniform image2D outputImage;
|
||||
|
||||
|
||||
// SSAO data
|
||||
layout(std430, set = 5, binding = 0) buffer SSAOData
|
||||
{
|
||||
vec4 samples[NUM_SAMPLES];
|
||||
|
||||
} ssaoData;
|
||||
|
||||
layout (set = 5, binding = 1) uniform sampler2D noiseTexture;
|
||||
|
||||
layout(set = 2, binding = 0) uniform CameraData
|
||||
{
|
||||
vec4 position;
|
||||
mat4 vpMat;
|
||||
mat4 viewMat;
|
||||
mat4 projMat;
|
||||
|
||||
} cameraData;
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
// image size of the SSAO image
|
||||
ivec2 ssaoSize = imageSize (outputImage);
|
||||
|
||||
// global thread
|
||||
ivec2 globalThread = ivec2 (gl_GlobalInvocationID.xy);
|
||||
|
||||
// load all the necessary variables
|
||||
vec3 viewSpacePos = imageLoad (positions, globalThread).rgb;
|
||||
vec3 viewSpaceNormal = normalize (imageLoad (normals, globalThread).rgb);
|
||||
|
||||
// Get the noise dimension. This should be 4x4
|
||||
vec2 noiseDim = vec2 (textureSize(noiseTexture, 0));
|
||||
|
||||
// Get normlized thread UV coordinates
|
||||
vec2 threadUV = (vec2(globalThread)) / vec2(ssaoSize);
|
||||
vec2 noiseUVMult = vec2 (vec2(ssaoSize) / noiseDim);
|
||||
noiseUVMult *= threadUV;
|
||||
|
||||
// sample from the noise
|
||||
vec3 randomVec = texture(noiseTexture, noiseUVMult).rgb;
|
||||
|
||||
// Gram schmidt
|
||||
vec3 tangent = normalize (randomVec - (viewSpaceNormal * dot(viewSpaceNormal, randomVec)));
|
||||
vec3 bitangent = normalize (cross (tangent, viewSpaceNormal));
|
||||
|
||||
// matrix for tangent space to view space
|
||||
mat3 TBN = mat3(tangent, bitangent, viewSpaceNormal);
|
||||
|
||||
float occlusion = 0.0f;
|
||||
for (int i = 0; i < NUM_SAMPLES; ++i)
|
||||
{
|
||||
// We want to get a position at an offset from the view space position. Offset scaled by radius.
|
||||
vec3 displacementVector = TBN * ssaoData.samples[i].rgb;
|
||||
|
||||
// Why are we adding positions?
|
||||
displacementVector = viewSpacePos + displacementVector * RADIUS;
|
||||
|
||||
// Now we take that offset position and bring it to clip space
|
||||
vec4 offsetPos = vec4 (displacementVector, 1.0f);
|
||||
offsetPos = cameraData.projMat * offsetPos;
|
||||
|
||||
// then we do perspective division
|
||||
offsetPos.xyz /= offsetPos.w;
|
||||
|
||||
// and bring it from [-1, 1] to screen coordinates
|
||||
offsetPos.xyz = ((offsetPos.xyz * 0.5f) + 0.5f);
|
||||
offsetPos.xy *= vec2(ssaoSize.xy);
|
||||
|
||||
// Now we attempt to get a position at that point.
|
||||
float sampleDepth = imageLoad (positions, ivec2 (offsetPos.xy)).z;
|
||||
|
||||
// skip checks
|
||||
if (sampleDepth == 0.0f)
|
||||
continue;
|
||||
|
||||
// if sampled fragment is in front of current fragment, just occlude
|
||||
float rangeCheck = smoothstep (0.0f, 1.0f, RADIUS / abs (viewSpacePos.z - sampleDepth));
|
||||
occlusion += (sampleDepth <= displacementVector.z - BIAS ? 1.0f : 0.0f) * rangeCheck;
|
||||
}
|
||||
|
||||
occlusion = 1.0f - (occlusion / float(NUM_SAMPLES));
|
||||
|
||||
// store result into result image
|
||||
imageStore(outputImage, globalThread, occlusion.rrrr);
|
||||
|
||||
}
|
Binary file not shown.
|
@ -0,0 +1,3 @@
|
|||
Name: SSAO_CS
|
||||
ID: 38430899
|
||||
Type: 2
|
|
@ -43,7 +43,7 @@ void main()
|
|||
{
|
||||
position = In.vertPos;
|
||||
normals = In.normal;
|
||||
albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) + MatProp.data[In2.materialIndex].color / MatProp.data[In2.materialIndex].alpha;
|
||||
albedo = texture(textures[nonuniformEXT(MatProp.data[In2.materialIndex].textureIndex)], In.uv) * MatProp.data[In2.materialIndex].color;
|
||||
|
||||
outEntityID = In2.eid;
|
||||
lightLayerIndices = In2.lightLayerIndex;
|
||||
|
|
Binary file not shown.
|
@ -33,18 +33,31 @@ layout(set = 2, binding = 0) uniform CameraData
|
|||
{
|
||||
vec4 position;
|
||||
mat4 vpMat;
|
||||
mat4 viewMat;
|
||||
mat4 projMat;
|
||||
} cameraData;
|
||||
|
||||
void main()
|
||||
{
|
||||
|
||||
Out2.materialIndex = gl_InstanceIndex;
|
||||
Out2.eid = integerData[0];
|
||||
Out2.lightLayerIndex = integerData[1];
|
||||
|
||||
Out.vertPos = worldTransform * vec4(aVertexPos, 1.0f);
|
||||
// for transforming gBuffer position and normal data
|
||||
mat4 modelViewMat = cameraData.viewMat * worldTransform;
|
||||
|
||||
// gBuffer position will be in view space
|
||||
Out.vertPos = modelViewMat * vec4(aVertexPos, 1.0f);
|
||||
|
||||
// uvs for texturing in fragment shader
|
||||
Out.uv = aUV;
|
||||
Out.normal.rgb = mat3(transpose(inverse(worldTransform))) * aNormal.rgb;
|
||||
|
||||
mat3 transposeInv = mat3 (transpose(inverse(modelViewMat)));
|
||||
|
||||
// normals are also in view space
|
||||
Out.normal.rgb = transposeInv * aNormal.rgb;
|
||||
Out.normal.rgb = normalize (Out.normal.rgb);
|
||||
|
||||
// clip space for rendering
|
||||
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
|
||||
}
|
Binary file not shown.
|
@ -7,7 +7,7 @@ echo "SHADE DEPENDENCIES (Default - All in 10 Seconds)"
|
|||
echo "A - All"
|
||||
echo "B - VMA"
|
||||
echo "C - msdf"
|
||||
echo "D - assimp"
|
||||
echo "D - ModelCompiler"
|
||||
echo "E - spdlog"
|
||||
echo "F - reactphysics3d"
|
||||
echo "G - imgui"
|
||||
|
@ -29,7 +29,7 @@ set _e=%ERRORLEVEL%
|
|||
if %_e%==1 goto VMA
|
||||
if %_e%==2 goto VMA
|
||||
if %_e%==3 goto MSDF
|
||||
if %_e%==4 goto assimp
|
||||
if %_e%==4 goto ModelCompiler
|
||||
if %_e%==5 goto spdlog
|
||||
if %_e%==6 goto reactphysics3d
|
||||
if %_e%==7 goto imgui
|
||||
|
@ -53,12 +53,13 @@ if %_e%==2 (goto :done) else (goto :MSDF)
|
|||
echo -----------------------MSDF----------------------------
|
||||
rmdir "Dependencies/msdf" /S /Q
|
||||
git clone --recurse-submodules https://github.com/SHADE-DP/msdf-atlas-gen.git "Dependencies/msdf"
|
||||
if %_e%==3 (goto :done) else (goto :assimp)
|
||||
if %_e%==3 (goto :done) else (goto :ModelCompiler)
|
||||
|
||||
:assimp
|
||||
echo -----------------------assimp----------------------------
|
||||
rmdir "Dependencies/assimp" /S /Q
|
||||
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/assimp"
|
||||
:ModelCompiler
|
||||
echo -----------------------ModelCompiler----------------------------
|
||||
rmdir "Dependencies/ModelCompiler" /S /Q
|
||||
git clone https://github.com/SHADE-DP/ModelCompiler.git "Dependencies/ModelCompiler"
|
||||
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/ModelCompiler/Dependencies/assimp"
|
||||
if %_e%==4 (goto :done) else (goto :spdlog)
|
||||
|
||||
@REM :ktx
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
IncludeDir = {}
|
||||
IncludeDir["assimp"] = "%{wks.location}\\Dependencies\\assimp"
|
||||
IncludeDir["ModelCompiler"] = "%{wks.location}\\Dependencies\\ModelCompiler"
|
||||
IncludeDir["imgui"] = "%{wks.location}\\Dependencies\\imgui"
|
||||
IncludeDir["imguizmo"] = "%{wks.location}\\Dependencies\\imguizmo"
|
||||
IncludeDir["imnodes"] = "%{wks.location}\\Dependencies\\imnodes"
|
||||
|
|
|
@ -41,6 +41,8 @@
|
|||
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
#include "Scenes/SBMainScene.h"
|
||||
#include "Serialization/Configurations/SHConfigurationManager.h"
|
||||
|
||||
#include "Tools/SHLogger.h"
|
||||
#include "Tools/SHDebugDraw.h"
|
||||
|
@ -60,8 +62,9 @@ namespace Sandbox
|
|||
{
|
||||
// Set working directory
|
||||
SHFileUtilities::SetWorkDirToExecDir();
|
||||
|
||||
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow);
|
||||
WindowData wndData{};
|
||||
auto& appConfig = SHConfigurationManager::LoadApplicationConfig(&wndData);
|
||||
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
|
||||
|
||||
// Create Systems
|
||||
SHSystemManager::CreateSystem<SHGraphicsSystem>();
|
||||
|
@ -73,11 +76,18 @@ namespace Sandbox
|
|||
SHSystemManager::CreateSystem<SHCameraSystem>();
|
||||
SHSystemManager::CreateSystem<SHDebugDrawSystem>();
|
||||
|
||||
// Link up SHDebugDraw
|
||||
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
|
||||
|
||||
#ifdef SHEDITOR
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
|
||||
SHSystemManager::CreateSystem<SHEditor>();
|
||||
SHSystemManager::GetSystem<SHEditor>()->SetSDLWindow(sdlWindow);
|
||||
if(auto editor = SHSystemManager::GetSystem<SHEditor>())
|
||||
{
|
||||
editor->SetSDLWindow(sdlWindow);
|
||||
editor->SetSHWindow(&window);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create Routines
|
||||
|
@ -125,7 +135,7 @@ namespace Sandbox
|
|||
|
||||
SHSystemManager::Init();
|
||||
|
||||
SHSceneManager::InitSceneManager<SBTestScene>("TestScene");
|
||||
SHSceneManager::InitSceneManager<SBMainScene>(appConfig.startingSceneID);
|
||||
|
||||
SHFrameRateController::UpdateFRC();
|
||||
|
||||
|
@ -151,7 +161,7 @@ namespace Sandbox
|
|||
editor->PollPicking();
|
||||
|
||||
static bool drawColliders = false;
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::SPACE))
|
||||
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
|
||||
{
|
||||
drawColliders = !drawColliders;
|
||||
SHSystemManager::GetSystem<SHPhysicsSystem>()->SetDrawColliders(drawColliders);
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
#include "SBpch.h"
|
||||
#include "SBMainScene.h"
|
||||
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h"
|
||||
#include "ECS_Base/Managers/SHEntityManager.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHRenderable.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHGraphicsSystem.h"
|
||||
#include "Scripting/SHScriptEngine.h"
|
||||
#include "Math/Transform/SHTransformComponent.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMaterialInstance.h"
|
||||
#include "Physics/Components/SHRigidBodyComponent.h"
|
||||
#include "Physics/Components/SHColliderComponent.h"
|
||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
#include "Camera/SHCameraComponent.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
#include "Serialization/SHSerialization.h"
|
||||
|
||||
using namespace SHADE;
|
||||
|
||||
namespace Sandbox
|
||||
{
|
||||
|
||||
void SBMainScene::WindowFocusFunc([[maybe_unused]] void* window, int focused)
|
||||
{
|
||||
if (focused)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
void SBMainScene::Load()
|
||||
{
|
||||
}
|
||||
|
||||
void SBMainScene::Init()
|
||||
{
|
||||
sceneName = SHSerialization::DeserializeSceneFromFile(sceneAssetID);
|
||||
}
|
||||
|
||||
void SBMainScene::Update(float dt)
|
||||
{
|
||||
}
|
||||
|
||||
void SBMainScene::Render()
|
||||
{
|
||||
}
|
||||
|
||||
void SBMainScene::Unload()
|
||||
{
|
||||
}
|
||||
|
||||
void SBMainScene::Free()
|
||||
{
|
||||
//SHSerialization::SerializeScene("resources/scenes/Scene01.SHADE");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
|
||||
#include "Scene/SHScene.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
|
||||
namespace Sandbox
|
||||
{
|
||||
class SBMainScene : public SHADE::SHScene
|
||||
{
|
||||
private:
|
||||
EntityID camera;
|
||||
EntityID testObj;
|
||||
std::vector<EntityID> stressTestObjects;
|
||||
|
||||
public:
|
||||
virtual void Load();
|
||||
virtual void Init();
|
||||
virtual void Update(float dt);
|
||||
virtual void Render();
|
||||
virtual void Free();
|
||||
virtual void Unload();
|
||||
|
||||
//TODO: Change to new window DO IT IN CPP TOO
|
||||
void WindowFocusFunc(void* window, int focused);
|
||||
|
||||
SBMainScene(void) = default;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -53,7 +53,7 @@ namespace Sandbox
|
|||
switch (asset.type)
|
||||
{
|
||||
case AssetType::MESH:
|
||||
if (asset.name == "Cube.012")
|
||||
if (asset.name == "Raccoon")
|
||||
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
|
||||
break;
|
||||
case AssetType::TEXTURE:
|
||||
|
@ -65,58 +65,20 @@ namespace Sandbox
|
|||
SHResourceManager::FinaliseChanges();
|
||||
|
||||
// Create Materials
|
||||
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance();
|
||||
auto customMat = graphicsSystem->AddMaterialInstanceCopy(matInst);
|
||||
customMat->SetProperty("data.color", SHVec4(0.0f, 1.0f, 1.0f, 1.0f));
|
||||
customMat->SetProperty("data.textureIndex", 0);
|
||||
customMat->SetProperty("data.alpha", 0.1f);
|
||||
auto baseRaccoonMat = graphicsSystem->AddOrGetBaseMaterialInstance();
|
||||
auto baseRaccoonMatInstant = graphicsSystem->AddMaterialInstanceCopy(baseRaccoonMat);
|
||||
baseRaccoonMatInstant->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
baseRaccoonMatInstant->SetProperty("data.textureIndex", 0);
|
||||
baseRaccoonMatInstant->SetProperty("data.alpha", 0.1f);
|
||||
|
||||
// Create Stress Test Objects
|
||||
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One;
|
||||
constexpr int NUM_ROWS = 3;
|
||||
constexpr int NUM_COLS = 1;
|
||||
static const SHVec3 TEST_OBJ_SPACING = { 0.1f, 0.1f, 0.1f };
|
||||
static const SHVec3 TEST_OBJ_START_POS = { -(NUM_COLS / 2 * TEST_OBJ_SPACING.x) + 1.0f, -2.0f, -1.0f };
|
||||
auto baseFloorMatInstant = graphicsSystem->AddMaterialInstanceCopy(baseRaccoonMat);
|
||||
baseFloorMatInstant->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
baseFloorMatInstant->SetProperty("data.textureIndex", 0);
|
||||
baseFloorMatInstant->SetProperty("data.alpha", 0.1f);
|
||||
|
||||
for (int y = 0; y < NUM_ROWS; ++y)
|
||||
for (int x = 0; x < NUM_COLS; ++x)
|
||||
{
|
||||
auto entity = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>();
|
||||
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(entity);
|
||||
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(entity);
|
||||
auto& collider = *SHComponentManager::GetComponent_s<SHColliderComponent>(entity);
|
||||
auto dummy = SHEntityManager::CreateEntity<>();
|
||||
|
||||
//renderable.Mesh = handles.front();
|
||||
renderable.SetMesh(CUBE_MESH);
|
||||
renderable.SetMaterial(customMat);
|
||||
|
||||
if (y == 50)
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 0.0f, 0.0f, 1.0f));
|
||||
|
||||
//Set initial positions
|
||||
transform.SetWorldPosition(TEST_OBJ_START_POS + SHVec3{ x * TEST_OBJ_SPACING.x, y * TEST_OBJ_SPACING.y, SHMath::GenerateRandomNumber(-3.5f, -5.0f) });
|
||||
//transform.SetWorldPosition({-1.0f, -1.0f, -1.0f});
|
||||
transform.SetWorldRotation(SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f), SHMath::GenerateRandomNumber(0.0f, 360.0f));
|
||||
transform.SetWorldScale(TEST_OBJ_SCALE);
|
||||
|
||||
collider.AddBoundingBox(SHVec3::One, SHVec3::Zero);
|
||||
stressTestObjects.emplace_back(entity);
|
||||
}
|
||||
|
||||
auto raccoonSpin = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
auto& renderable = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonSpin);
|
||||
auto& transform = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonSpin);
|
||||
|
||||
renderable.SetMesh(handles.front());
|
||||
renderable.SetMaterial(customMat);
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||
renderable.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
|
||||
|
||||
transform.SetWorldPosition({ -3.0f, -1.0f, -1.0f });
|
||||
transform.SetLocalScale({ 5.0f, 5.0f, 5.0f });
|
||||
|
||||
auto floor = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>();
|
||||
auto floor = SHEntityManager::CreateEntity<SHTransformComponent,SHRenderable, SHRigidBodyComponent, SHColliderComponent>();
|
||||
auto& floorRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(floor);
|
||||
auto& floorTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(floor);
|
||||
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
|
||||
|
@ -125,7 +87,7 @@ namespace Sandbox
|
|||
floorRenderable.SetMesh(CUBE_MESH);
|
||||
floorRenderable.SetMaterial(graphicsSystem->GetDefaultMaterialInstance());
|
||||
|
||||
floorTransform.SetWorldScale({ 7.5f, 0.5f, 7.5 });
|
||||
floorTransform.SetWorldScale({ 17.5f, 0.5f, 17.5f });
|
||||
floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f });
|
||||
|
||||
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
|
||||
|
@ -138,17 +100,97 @@ namespace Sandbox
|
|||
//testObjRenderable.Mesh = CUBE_MESH;
|
||||
//testObjRenderable.SetMaterial(matInst);
|
||||
|
||||
//raccoon =======================================================================================================================
|
||||
auto racoon = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>(MAX_EID, "Player");
|
||||
auto& racoonRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(racoon);
|
||||
auto& racoonTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoon);
|
||||
auto& racoonRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(racoon);
|
||||
auto& racoonCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(racoon);
|
||||
|
||||
racoonRenderable.SetMesh(handles.front());
|
||||
racoonRenderable.SetMaterial(baseRaccoonMatInstant);
|
||||
|
||||
racoonTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
|
||||
racoonTransform.SetWorldPosition({ -3.0f, -2.0f, -5.0f });
|
||||
|
||||
racoonCollider.AddBoundingBox();
|
||||
racoonCollider.GetCollider(0).SetPositionOffset(SHVec3(0.0f,0.5f,0.0f));
|
||||
racoonCollider.GetCollider(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
|
||||
|
||||
auto racoonItemLocation = SHEntityManager::CreateEntity<SHTransformComponent>();
|
||||
auto& racoonItemLocationTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(racoonItemLocation);
|
||||
SHSceneManager::GetCurrentSceneGraph().SetParent(racoonItemLocation, racoon);
|
||||
|
||||
auto racoonCamera = SHEntityManager::CreateEntity<SHTransformComponent>();
|
||||
SHSceneManager::GetCurrentSceneGraph().SetParent(racoonCamera, racoon);
|
||||
//================================================================================================================================
|
||||
|
||||
//item ===========================================================================================================================
|
||||
auto item = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>(MAX_EID, "item");
|
||||
auto& itemRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(item);
|
||||
auto& itemTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(item);
|
||||
auto& itemRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(item);
|
||||
auto& itemCollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(item);
|
||||
|
||||
itemRenderable.SetMesh(handles.front());
|
||||
itemRenderable.SetMaterial(baseRaccoonMatInstant);
|
||||
|
||||
itemTransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
|
||||
itemTransform.SetWorldPosition({ 0.0f, -2.0f, -5.0f });
|
||||
|
||||
itemCollider.AddBoundingBox();
|
||||
itemCollider.AddBoundingBox(SHVec3(2.0f,2.0f,2.0f));
|
||||
itemCollider.GetCollider(1).SetIsTrigger(true);
|
||||
|
||||
itemCollider.GetCollider(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
|
||||
itemCollider.GetCollider(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
|
||||
|
||||
itemCollider.GetCollider(1).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
|
||||
itemCollider.GetCollider(1).SetBoundingBox(SHVec3(1.0f, 1.0f, 1.0f));
|
||||
|
||||
itemRigidBody.SetInterpolate(false);
|
||||
itemRigidBody.SetFreezeRotationX(true);
|
||||
itemRigidBody.SetFreezeRotationY(true);
|
||||
itemRigidBody.SetFreezeRotationZ(true);
|
||||
//================================================================================================================================
|
||||
|
||||
//AI =============================================================================================================================
|
||||
auto AI = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent, SHRigidBodyComponent, SHColliderComponent>(MAX_EID, "AI");
|
||||
auto& AIRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(AI);
|
||||
auto& AITransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(AI);
|
||||
auto& AIRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(AI);
|
||||
auto& AICollider = *SHComponentManager::GetComponent_s<SHColliderComponent>(AI);
|
||||
|
||||
AIRenderable.SetMesh(handles.front());
|
||||
AIRenderable.SetMaterial(baseRaccoonMatInstant);
|
||||
|
||||
AITransform.SetWorldScale({ 2.0f, 2.0f, 2.0f });
|
||||
AITransform.SetWorldPosition({ -8.0f, -2.0f, 2.5f });
|
||||
|
||||
AICollider.AddBoundingBox();
|
||||
AICollider.GetCollider(0).SetPositionOffset(SHVec3(0.0f, 0.5f, 0.0f));
|
||||
AICollider.GetCollider(0).SetBoundingBox(SHVec3(0.5f, 0.5f, 0.5f));
|
||||
|
||||
AIRigidBody.SetInterpolate(false);
|
||||
AIRigidBody.SetFreezeRotationX(true);
|
||||
AIRigidBody.SetFreezeRotationY(true);
|
||||
AIRigidBody.SetFreezeRotationZ(true);
|
||||
//================================================================================================================================
|
||||
|
||||
SHADE::SHScriptEngine* scriptEngine = static_cast<SHADE::SHScriptEngine*>(SHADE::SHSystemManager::GetSystem<SHADE::SHScriptEngine>());
|
||||
scriptEngine->AddScript(raccoonSpin, "RaccoonSpin");
|
||||
scriptEngine->AddScript(racoon, "PlayerController");
|
||||
scriptEngine->AddScript(racoon, "PickAndThrow");
|
||||
scriptEngine->AddScript(racoonCamera, "ThirdPersonCamera");
|
||||
scriptEngine->AddScript(AI, "AIPrototype");
|
||||
scriptEngine->AddScript(item, "Item");
|
||||
|
||||
auto raccoonShowcase = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
|
||||
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
|
||||
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
|
||||
|
||||
renderableShowcase.SetMesh(handles.front());
|
||||
renderableShowcase.SetMaterial(customMat);
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f));
|
||||
renderableShowcase.SetMaterial(baseRaccoonMatInstant);
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.alpha", 1.0f);
|
||||
renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ project "SHADE_Engine"
|
|||
|
||||
externalincludedirs
|
||||
{
|
||||
"%{IncludeDir.assimp}\\include",
|
||||
"%{IncludeDir.imgui}",
|
||||
"%{IncludeDir.imguizmo}",
|
||||
"%{IncludeDir.imnodes}",
|
||||
|
@ -52,8 +51,6 @@ project "SHADE_Engine"
|
|||
{
|
||||
"%{prj.location}/libs",
|
||||
"%{IncludeDir.VULKAN}/Lib",
|
||||
"%{IncludeDir.assimp}/lib/Debug",
|
||||
"%{IncludeDir.assimp}/lib/Release",
|
||||
"%{IncludeDir.RTTR}/lib",
|
||||
"%{IncludeDir.SDL}/lib",
|
||||
"%{IncludeDir.spdlog}/lib",
|
||||
|
@ -119,7 +116,8 @@ project "SHADE_Engine"
|
|||
filter "configurations:Debug"
|
||||
postbuildcommands
|
||||
{
|
||||
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Debug\\assimp-vc142-mtd.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Debug\\assimp-vc142-mtd.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Debug\\ModelCompiler.exe\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodL.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudioL.dll\" \"$(OutDir)\""
|
||||
}
|
||||
|
@ -127,7 +125,8 @@ project "SHADE_Engine"
|
|||
filter "configurations:Release"
|
||||
postbuildcommands
|
||||
{
|
||||
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Release\\ModelCompiler.exe\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
|
||||
}
|
||||
|
@ -135,32 +134,35 @@ project "SHADE_Engine"
|
|||
filter "configurations:Publish"
|
||||
postbuildcommands
|
||||
{
|
||||
"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
|
||||
--"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
|
||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
|
||||
}
|
||||
|
||||
filter "configurations:Publish"
|
||||
postbuildcommands {"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\""}
|
||||
postbuildcommands
|
||||
{
|
||||
--"xcopy /r /y /q \"%{IncludeDir.assimp}\\bin\\Release\\assimp-vc142-mt.dll\" \"$(OutDir)\""
|
||||
}
|
||||
|
||||
warnings 'Extra'
|
||||
|
||||
filter "configurations:Debug"
|
||||
symbols "On"
|
||||
defines {"_DEBUG", "SHEDITOR"}
|
||||
links{"assimp-vc142-mtd.lib", "librttr_core_d.lib", "spdlogd.lib"}
|
||||
links{"librttr_core_d.lib", "spdlogd.lib"}
|
||||
links{"fmodstudioL_vc.lib", "fmodL_vc.lib"}
|
||||
|
||||
filter "configurations:Release"
|
||||
optimize "On"
|
||||
defines{"_RELEASE", "SHEDITOR"}
|
||||
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
|
||||
links{"librttr_core.lib", "spdlog.lib"}
|
||||
links{"fmodstudio_vc.lib", "fmod_vc.lib"}
|
||||
|
||||
filter "configurations:Publish"
|
||||
optimize "On"
|
||||
defines{"_RELEASE", "_PUBLISH"}
|
||||
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"}
|
||||
links{"librttr_core.lib", "spdlog.lib"}
|
||||
excludes
|
||||
{
|
||||
-- "%{prj.location}/src/Editor/**.cpp",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
#include "SHMeshAsset.h"
|
||||
#include "SHModelAsset.h"
|
||||
#include "SHTextureAsset.h"
|
|
@ -18,24 +18,31 @@
|
|||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SH_API SHMeshAssetHeader
|
||||
struct SHMeshAssetHeader
|
||||
{
|
||||
uint32_t vertexCount;
|
||||
uint32_t indexCount;
|
||||
std::string name;
|
||||
};
|
||||
|
||||
struct SH_API SHMeshAsset : SHAssetData
|
||||
struct SHModelAssetHeader
|
||||
{
|
||||
bool compiled;
|
||||
bool changed;
|
||||
size_t meshCount;
|
||||
};
|
||||
|
||||
struct SH_API SHMeshData : SHAssetData
|
||||
{
|
||||
SHMeshAssetHeader header;
|
||||
std::vector<SHVec3> VertexPositions;
|
||||
std::vector<SHVec3> VertexTangents;
|
||||
std::vector<SHVec3> VertexNormals;
|
||||
std::vector<SHVec2> VertexTexCoords;
|
||||
std::vector<uint32_t> Indices;
|
||||
};
|
||||
|
||||
std::vector<SHVec3> vertexPosition;
|
||||
std::vector<SHVec3> vertexTangent;
|
||||
std::vector<SHVec3> vertexNormal;
|
||||
std::vector<SHVec2> texCoords;
|
||||
std::vector<uint32_t> indices;
|
||||
struct SH_API SHModelAsset : SHAssetData
|
||||
{
|
||||
SHModelAssetHeader header;
|
||||
std::vector<SHMeshData*> subMeshes;
|
||||
};
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshCompiler.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHMeshAsset into binary file for faster
|
||||
* loading in the future
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHMeshCompiler.h"
|
||||
#include "Graphics/MiddleEnd/Meshes/SHMeshData.h"
|
||||
#include <assimp/postprocess.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
||||
Assimp::Importer SHMeshCompiler::aiImporter;
|
||||
|
||||
void SHMeshCompiler::ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept
|
||||
{
|
||||
for (size_t i{ 0 }; i < node.mNumMeshes; ++i)
|
||||
{
|
||||
aiMesh* mesh = scene.mMeshes[node.mMeshes[i]];
|
||||
meshes.push_back(ProcessMesh(*mesh));
|
||||
}
|
||||
|
||||
for (size_t i{ 0 }; i < node.mNumChildren; ++i)
|
||||
{
|
||||
ProcessNode(*node.mChildren[i], scene, meshes);
|
||||
}
|
||||
}
|
||||
|
||||
void SHMeshCompiler::ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept
|
||||
{
|
||||
if (scene.HasAnimations())
|
||||
{
|
||||
std::vector<SHAnimationAsset> anims(scene.mNumAnimations);
|
||||
for (auto i{ 0 }; i < scene.mNumAnimations; ++i)
|
||||
{
|
||||
auto const& anim{ *scene.mAnimations[i] };
|
||||
|
||||
anims[i].name = anim.mName.C_Str();
|
||||
|
||||
anims[i].duration = anim.mDuration;
|
||||
anims[i].ticksPerSecond = anim.mTicksPerSecond;
|
||||
|
||||
std::copy_n(anim.mChannels, anim.mNumChannels, anims[i].nodeChannels.data());
|
||||
std::copy_n(anim.mMeshChannels, anim.mNumMeshChannels, anims[i].meshChannels.data());
|
||||
std::copy_n(anim.mMorphMeshChannels, anim.mNumMorphMeshChannels, anims[i].morphMeshChannels.data());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SHMeshAsset* SHMeshCompiler::ProcessMesh(aiMesh const& mesh) noexcept
|
||||
{
|
||||
SHMeshAsset* result = new SHMeshAsset();
|
||||
result->compiled = false;
|
||||
result->changed = false;
|
||||
|
||||
for (size_t i{ 0 }; i < mesh.mNumVertices; ++i)
|
||||
{
|
||||
// Vertex position
|
||||
SHVec3 vertex;
|
||||
vertex.x = mesh.mVertices[i].x;
|
||||
vertex.y = mesh.mVertices[i].y;
|
||||
vertex.z = mesh.mVertices[i].z;
|
||||
result->vertexPosition.push_back(vertex);
|
||||
|
||||
// Tex coords
|
||||
SHVec2 texCoord{ 0.f, 0.f };
|
||||
if (mesh.mTextureCoords[0])
|
||||
{
|
||||
texCoord.x = mesh.mTextureCoords[0][i].x;
|
||||
texCoord.y = mesh.mTextureCoords[0][i].y;
|
||||
}
|
||||
result->texCoords.push_back(texCoord);
|
||||
|
||||
// Normals
|
||||
SHVec3 normal{ 0.f, 0.f, 0.f };
|
||||
if (mesh.mNormals)
|
||||
{
|
||||
normal.x = mesh.mNormals[i].x;
|
||||
normal.y = mesh.mNormals[i].y;
|
||||
normal.z = mesh.mNormals[i].z;
|
||||
}
|
||||
result->vertexNormal.push_back(normal);
|
||||
|
||||
// Tangent
|
||||
SHVec3 tangent{ 0.f, 0.f, 0.f };
|
||||
if (mesh.mTangents)
|
||||
{
|
||||
tangent.x = mesh.mTangents[i].x;
|
||||
tangent.y = mesh.mTangents[i].y;
|
||||
tangent.z = mesh.mTangents[i].z;
|
||||
}
|
||||
result->vertexTangent.push_back(tangent);
|
||||
}
|
||||
|
||||
for (size_t i{ 0 }; i < mesh.mNumFaces; ++i)
|
||||
{
|
||||
aiFace face = mesh.mFaces[i];
|
||||
for (size_t j{ 0 }; j < face.mNumIndices; ++j)
|
||||
{
|
||||
result->indices.push_back(face.mIndices[j]);
|
||||
}
|
||||
}
|
||||
|
||||
result->header.vertexCount = static_cast<uint32_t>(result->vertexPosition.size());
|
||||
result->header.indexCount = static_cast<uint32_t>(result->indices.size());
|
||||
result->header.name = mesh.mName.C_Str();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHMeshCompiler::LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept
|
||||
{
|
||||
const aiScene* scene = aiImporter.ReadFile(path.string().c_str(),
|
||||
aiProcess_Triangulate // Make sure we get triangles rather than nvert polygons
|
||||
| aiProcess_GenUVCoords // Convert any type of mapping to uv mapping
|
||||
| aiProcess_TransformUVCoords // preprocess UV transformations (scaling, translation ...)
|
||||
| aiProcess_FindInstances // search for instanced meshes and remove them by references to one master
|
||||
| aiProcess_CalcTangentSpace // calculate tangents and bitangents if possible
|
||||
| aiProcess_JoinIdenticalVertices // join identical vertices/ optimize indexing
|
||||
| aiProcess_RemoveRedundantMaterials // remove redundant materials
|
||||
| aiProcess_FindInvalidData // detect invalid model data, such as invalid normal vectors
|
||||
| aiProcess_FlipUVs // flip the V to match the Vulkans way of doing UVs
|
||||
);
|
||||
|
||||
if (!scene || !scene->HasMeshes())
|
||||
{
|
||||
SHLOG_ERROR("ERROR in GLTF::ASSIMP: {}\nFile: {}", aiImporter.GetErrorString(), path.string());
|
||||
return;
|
||||
}
|
||||
|
||||
//ExtractAnimations(*scene, anims);
|
||||
|
||||
ProcessNode(*scene->mRootNode, *scene, meshes);
|
||||
|
||||
aiImporter.FreeScene();
|
||||
}
|
||||
|
||||
std::optional<AssetPath> SHMeshCompiler::CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept
|
||||
{
|
||||
std::string newPath{ path.parent_path().string() + '/' };
|
||||
newPath += asset.header.name + MESH_EXTENSION.data();
|
||||
|
||||
std::ofstream file{ newPath, std::ios::out | std::ios::binary | std::ios::trunc };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
|
||||
}
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<const char*>(&(asset.header.indexCount)),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
auto const vertexVec3Byte{ sizeof(SHVec3) * asset.header.vertexCount };
|
||||
auto const vertexVec2Byte{ sizeof(SHVec2) * asset.header.vertexCount };
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.texCoords.data()),
|
||||
vertexVec2Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.indices.data()),
|
||||
sizeof(uint32_t) * asset.header.indexCount
|
||||
);
|
||||
|
||||
file.close();
|
||||
|
||||
return newPath;
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshCompiler.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to write data in SHMeshAsset into binary file for faster
|
||||
* loading in the future
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <assimp/Importer.hpp>
|
||||
#include <assimp/scene.h>
|
||||
#include <vector>
|
||||
|
||||
#include "Assets/Asset Types/SHAnimationAsset.h"
|
||||
#include "Assets/Asset Types/SHMeshAsset.h"
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHMeshCompiler
|
||||
{
|
||||
|
||||
using MeshVectorRef = std::vector<SHMeshAsset*>&;
|
||||
using AnimVectorRef = std::vector<SHAnimationAsset*>&;
|
||||
|
||||
static Assimp::Importer aiImporter;
|
||||
static void ProcessNode(aiNode const& node, aiScene const& scene, MeshVectorRef meshes) noexcept;
|
||||
static void ExtractAnimations(aiScene const& scene, AnimVectorRef anims) noexcept;
|
||||
static SHMeshAsset* ProcessMesh(aiMesh const& mesh) noexcept;
|
||||
|
||||
public:
|
||||
static void LoadFromFile(AssetPath path, MeshVectorRef meshes, AnimVectorRef anims) noexcept;
|
||||
static std::optional<AssetPath> CompileMeshBinary(SHMeshAsset const& asset, AssetPath path) noexcept;
|
||||
};
|
||||
}
|
|
@ -1,130 +0,0 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshLoader.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Implementation for Mesh loader. Accounts for custom binary format
|
||||
* as well as GLTF file format.
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHMeshLoader.h"
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
void SHMeshLoader::LoadSHMesh(AssetPath path, SHMeshAsset& mesh) noexcept
|
||||
{
|
||||
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
|
||||
return;
|
||||
}
|
||||
|
||||
const std::string name{ path.stem().string() };
|
||||
|
||||
file.seekg(0);
|
||||
|
||||
uint32_t vertCount, indexCount;
|
||||
std::vector<SHVec3> vertPos, vertTan, vertNorm;
|
||||
std::vector<SHVec2> texCoord;
|
||||
std::vector<uint32_t> indices;
|
||||
|
||||
file.read(reinterpret_cast<char*>(&vertCount), sizeof(uint32_t));
|
||||
file.read(reinterpret_cast<char*>(&indexCount), sizeof(uint32_t));
|
||||
|
||||
auto const vertexVec3Byte{ sizeof(SHVec3) * vertCount };
|
||||
auto const vertexVec2Byte{ sizeof(SHVec2) * vertCount };
|
||||
|
||||
vertPos.resize(vertCount);
|
||||
vertTan.resize(vertCount);
|
||||
vertNorm.resize(vertCount);
|
||||
texCoord.resize(vertCount);
|
||||
indices.resize(indexCount);
|
||||
|
||||
file.read(reinterpret_cast<char *>(vertPos.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(vertTan.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(vertNorm.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char *>(texCoord.data()), vertexVec2Byte);
|
||||
file.read(reinterpret_cast<char *>(indices.data()), sizeof(uint32_t) * indexCount);
|
||||
|
||||
mesh.compiled = true;
|
||||
mesh.changed = false;
|
||||
|
||||
mesh.header.indexCount = indexCount;
|
||||
mesh.header.vertexCount = vertCount;
|
||||
mesh.header.name = name;
|
||||
|
||||
mesh.vertexPosition = std::move(vertPos);
|
||||
mesh.vertexTangent = std::move(vertTan);
|
||||
mesh.vertexNormal = std::move(vertNorm);
|
||||
mesh.texCoords = std::move(texCoord);
|
||||
mesh.indices = std::move(indices);
|
||||
|
||||
file.close();
|
||||
}
|
||||
|
||||
SHAssetData* SHMeshLoader::Load(AssetPath path)
|
||||
{
|
||||
auto result = new SHMeshAsset();
|
||||
|
||||
LoadSHMesh(path, *result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHMeshLoader::Write(SHAssetData const* data, AssetPath path)
|
||||
{
|
||||
std::ofstream file{ path, std::ios::out | std::ios::binary | std::ios::trunc };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open file for writing mesh file: {}", path.string());
|
||||
}
|
||||
|
||||
auto asset = *dynamic_cast<SHMeshAsset const*>(data);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(&(asset.header.vertexCount)),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<const char*>(&(asset.header.indexCount)),
|
||||
sizeof(uint32_t)
|
||||
);
|
||||
|
||||
auto const vertexVec3Byte{ sizeof(SHVec3) * asset.header.vertexCount };
|
||||
auto const vertexVec2Byte{ sizeof(SHVec2) * asset.header.vertexCount };
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexPosition.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexTangent.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.vertexNormal.data()),
|
||||
vertexVec3Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.texCoords.data()),
|
||||
vertexVec2Byte
|
||||
);
|
||||
|
||||
file.write(
|
||||
reinterpret_cast<char const*>(asset.indices.data()),
|
||||
sizeof(uint32_t) * asset.header.indexCount
|
||||
);
|
||||
|
||||
file.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHModelLoader.cpp
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Implementation for Mesh loader. Accounts for custom binary format
|
||||
* as well as GLTF file format.
|
||||
*
|
||||
*
|
||||
* Copyright (C) 2022 DigiPen Institute of Technology. Reproduction or
|
||||
* disclosure of this file or its contents without the prior written consent
|
||||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHModelLoader.h"
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
void SHModelLoader::ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept
|
||||
{
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&header),
|
||||
sizeof(SHMeshLoaderHeader)
|
||||
);
|
||||
}
|
||||
|
||||
void SHModelLoader::ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshData& data) noexcept
|
||||
{
|
||||
auto const vertexVec3Byte{ sizeof(SHVec3) * header.vertexCount };
|
||||
auto const vertexVec2Byte{ sizeof(SHVec2) * header.vertexCount };
|
||||
|
||||
data.VertexPositions.resize(header.vertexCount);
|
||||
data.VertexTangents.resize(header.vertexCount);
|
||||
data.VertexNormals.resize(header.vertexCount);
|
||||
data.VertexTexCoords.resize(header.vertexCount);
|
||||
data.Indices.resize(header.indexCount);
|
||||
data.header.name.resize(header.charCount);
|
||||
|
||||
file.read(data.header.name.data(), header.charCount);
|
||||
file.read(reinterpret_cast<char*>(data.VertexPositions.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char*>(data.VertexTangents.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char*>(data.VertexNormals.data()), vertexVec3Byte);
|
||||
file.read(reinterpret_cast<char*>(data.VertexTexCoords.data()), vertexVec2Byte);
|
||||
file.read(reinterpret_cast<char*>(data.Indices.data()), sizeof(uint32_t) * header.indexCount);
|
||||
|
||||
data.header.vertexCount = header.vertexCount;
|
||||
data.header.indexCount = header.indexCount;
|
||||
}
|
||||
|
||||
void SHModelLoader::LoadSHMesh(AssetPath path, SHModelAsset& model) noexcept
|
||||
{
|
||||
std::ifstream file{ path.string(), std::ios::in | std::ios::binary };
|
||||
if (!file.is_open())
|
||||
{
|
||||
SHLOG_ERROR("Unable to open SHMesh File: {}", path.string());
|
||||
return;
|
||||
}
|
||||
|
||||
file.seekg(0);
|
||||
|
||||
file.read(
|
||||
reinterpret_cast<char*>(&model.header),
|
||||
sizeof(SHModelAssetHeader)
|
||||
);
|
||||
|
||||
std::vector<SHMeshLoaderHeader> headers(model.header.meshCount);
|
||||
model.subMeshes.resize(model.header.meshCount);
|
||||
|
||||
for (auto i{ 0 }; i < model.header.meshCount; ++i)
|
||||
{
|
||||
model.subMeshes[i] = new SHMeshData();
|
||||
ReadHeader(file, headers[i]);
|
||||
ReadData(file, headers[i], *model.subMeshes[i]);
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
SHAssetData* SHModelLoader::Load(AssetPath path)
|
||||
{
|
||||
auto result = new SHModelAsset();
|
||||
|
||||
LoadSHMesh(path, *result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void SHModelLoader::Write(SHAssetData const* data, AssetPath path)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*************************************************************************//**
|
||||
* \file SHMeshLoader.h
|
||||
* \file SHModelLoader.h
|
||||
* \author Loh Xiao Qi
|
||||
* \date 30 September 2022
|
||||
* \brief Library to load gltf mesh files and custom binary format
|
||||
|
@ -10,14 +10,27 @@
|
|||
* of DigiPen Institute of Technology is prohibited.
|
||||
*****************************************************************************/
|
||||
#pragma once
|
||||
#include "Assets/Asset Types/SHMeshAsset.h"
|
||||
#include "Assets/Asset Types/SHModelAsset.h"
|
||||
#include "SHAssetLoader.h"
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
struct SHMeshLoader : SHAssetLoader
|
||||
class SHModelLoader : public SHAssetLoader
|
||||
{
|
||||
void LoadSHMesh(AssetPath path, SHMeshAsset& meshes) noexcept;
|
||||
struct SHMeshLoaderHeader
|
||||
{
|
||||
uint32_t vertexCount;
|
||||
uint32_t indexCount;
|
||||
uint32_t charCount;
|
||||
};
|
||||
|
||||
|
||||
void ReadHeader(std::ifstream& file, SHMeshLoaderHeader& header) noexcept;
|
||||
void ReadData(std::ifstream& file, SHMeshLoaderHeader const& header, SHMeshData& data) noexcept;
|
||||
|
||||
public:
|
||||
void LoadSHMesh(AssetPath path, SHModelAsset& model) noexcept;
|
||||
SHAssetData* Load(AssetPath path) override;
|
||||
void Write(SHAssetData const* data, AssetPath path) override;
|
||||
};
|
|
@ -22,5 +22,10 @@ namespace SHADE
|
|||
AssetID id;
|
||||
AssetType type;
|
||||
AssetPath path;
|
||||
bool isSubAsset;
|
||||
|
||||
std::vector<SHAsset*> subAssets;
|
||||
|
||||
AssetID parent;
|
||||
};
|
||||
}
|
|
@ -47,10 +47,11 @@ enum class AssetType : AssetTypeMeta
|
|||
SHADER,
|
||||
SHADER_BUILT_IN,
|
||||
TEXTURE,
|
||||
MESH,
|
||||
MODEL,
|
||||
SCENE,
|
||||
PREFAB,
|
||||
MATERIAL,
|
||||
MESH,
|
||||
MAX_COUNT
|
||||
};
|
||||
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::MAX_COUNT) };
|
||||
|
@ -64,6 +65,9 @@ constexpr std::string_view ASSET_ROOT {"../../Assets"};
|
|||
constexpr std::string_view BUILT_IN_ASSET_ROOT{ "../../Built_In" };
|
||||
#endif
|
||||
|
||||
// COMPILER PATHS
|
||||
constexpr std::string_view MODEL_COMPILER_EXE{ "ModelCompiler.exe" };
|
||||
|
||||
// INTERNAL ASSET PATHS
|
||||
constexpr std::string_view SCENE_FOLDER{ "/Scenes/" };
|
||||
constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" };
|
||||
|
@ -81,7 +85,7 @@ constexpr std::string_view SCENE_EXTENSION {".shade"};
|
|||
constexpr std::string_view PREFAB_EXTENSION {".shprefab"};
|
||||
constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
|
||||
constexpr std::string_view TEXTURE_EXTENSION {".shtex"};
|
||||
constexpr std::string_view MESH_EXTENSION {".shmesh"};
|
||||
constexpr std::string_view MODEL_EXTENSION {".shmodel"};
|
||||
|
||||
constexpr std::string_view EXTENSIONS[] = {
|
||||
AUDIO_EXTENSION,
|
||||
|
@ -89,7 +93,7 @@ constexpr std::string_view EXTENSIONS[] = {
|
|||
SHADER_BUILT_IN_EXTENSION,
|
||||
MATERIAL_EXTENSION,
|
||||
TEXTURE_EXTENSION,
|
||||
MESH_EXTENSION,
|
||||
MODEL_EXTENSION,
|
||||
SCRIPT_EXTENSION,
|
||||
SCENE_EXTENSION,
|
||||
PREFAB_EXTENSION,
|
||||
|
|
|
@ -11,15 +11,17 @@
|
|||
#include <random>
|
||||
#include <chrono>
|
||||
#include <ranges>
|
||||
#include <cstdlib>
|
||||
|
||||
#include "SHAssetManager.h"
|
||||
#include "SHAssetMetaHandler.h"
|
||||
|
||||
#include "Libraries/Loaders/SHMeshLoader.h"
|
||||
#include "Libraries/Loaders/SHModelLoader.h"
|
||||
#include "Libraries/Loaders/SHTextureLoader.h"
|
||||
#include "Libraries/Loaders/SHShaderSourceLoader.h"
|
||||
#include "Libraries/Loaders/SHTextBasedLoader.h"
|
||||
|
||||
#include "Libraries/Compilers/SHMeshCompiler.h"
|
||||
//#include "Libraries/Compilers/SHMeshCompiler.h"
|
||||
#include "Libraries/Compilers/SHTextureCompiler.h"
|
||||
#include "Libraries/Compilers/SHShaderSourceCompiler.h"
|
||||
|
||||
|
@ -157,16 +159,22 @@ namespace SHADE
|
|||
{
|
||||
case AssetType::PREFAB:
|
||||
newPath += PREFAB_FOLDER;
|
||||
newPath += name;
|
||||
newPath += PREFAB_EXTENSION;
|
||||
data = new SHPrefabAsset();
|
||||
break;
|
||||
|
||||
case AssetType::SCENE:
|
||||
newPath += SCENE_FOLDER;
|
||||
newPath += name;
|
||||
newPath += SCENE_EXTENSION;
|
||||
data = new SHSceneAsset();
|
||||
break;
|
||||
|
||||
case AssetType::MATERIAL:
|
||||
newPath += MATERIAL_FOLDER;
|
||||
newPath += name;
|
||||
newPath += MATERIAL_EXTENSION;
|
||||
data = new SHMaterialAsset();
|
||||
break;
|
||||
|
||||
|
@ -180,7 +188,8 @@ namespace SHADE
|
|||
name,
|
||||
id,
|
||||
type,
|
||||
newPath
|
||||
newPath,
|
||||
false
|
||||
};
|
||||
|
||||
assetCollection.insert({
|
||||
|
@ -189,7 +198,8 @@ namespace SHADE
|
|||
name,
|
||||
id,
|
||||
type,
|
||||
newPath
|
||||
newPath,
|
||||
false
|
||||
)
|
||||
});
|
||||
|
||||
|
@ -328,25 +338,32 @@ namespace SHADE
|
|||
return result;
|
||||
}
|
||||
|
||||
AssetID SHAssetManager::CompileAsset(AssetPath const& path) noexcept
|
||||
void SHAssetManager::CompileAsset(AssetPath const& path) noexcept
|
||||
{
|
||||
SHAsset newAsset
|
||||
if (!std::filesystem::exists(path))
|
||||
{
|
||||
.name = path.stem().string()
|
||||
};
|
||||
|
||||
SHLOG_ERROR("Path provided does not point to a file: {}", path.string());
|
||||
return;
|
||||
}
|
||||
AssetPath newPath;
|
||||
auto const ext{ path.extension().string() };
|
||||
if (ext == GLSL_EXTENSION.data())
|
||||
{
|
||||
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
|
||||
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN);
|
||||
newAsset.type = AssetType::SHADER_BUILT_IN;
|
||||
newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
|
||||
}
|
||||
else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data())
|
||||
{
|
||||
std::string command = MODEL_COMPILER_EXE.data();
|
||||
command += " " + path.string();
|
||||
std::system(command.c_str());
|
||||
|
||||
std::string modelPath = path.string().substr(0, path.string().find_last_of('.'));
|
||||
modelPath += MODEL_EXTENSION;
|
||||
newPath = modelPath;
|
||||
|
||||
GenerateNewMeta(newPath);
|
||||
}
|
||||
|
||||
assetCollection.insert({ newAsset.id, newAsset });
|
||||
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||
|
||||
return newAsset.id;
|
||||
}
|
||||
|
||||
FolderPointer SHAssetManager::GetRootFolder() noexcept
|
||||
|
@ -399,46 +416,28 @@ namespace SHADE
|
|||
|
||||
for (auto const& path : paths)
|
||||
{
|
||||
SHAsset newAsset
|
||||
{
|
||||
.name = path.stem().string()
|
||||
};
|
||||
|
||||
AssetPath newPath;
|
||||
auto const ext{ path.extension().string() };
|
||||
if (ext == GLSL_EXTENSION.data())
|
||||
{
|
||||
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
|
||||
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN);
|
||||
newAsset.type = AssetType::SHADER_BUILT_IN;
|
||||
newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
|
||||
}
|
||||
else if (ext == DDS_EXTENSION.data())
|
||||
{
|
||||
newAsset.path = SHTextureCompiler::CompileTextureAsset(path).value();
|
||||
newAsset.id = GenerateAssetID(AssetType::TEXTURE);
|
||||
newAsset.type = AssetType::TEXTURE;
|
||||
newPath = SHTextureCompiler::CompileTextureAsset(path).value();
|
||||
}
|
||||
else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data())
|
||||
{
|
||||
std::vector<SHMeshAsset*> meshes;
|
||||
std::vector<SHAnimationAsset*> anims;
|
||||
SHMeshCompiler::LoadFromFile(path, meshes, anims);
|
||||
std::string command = MODEL_COMPILER_EXE.data();
|
||||
command += " " + path.string();
|
||||
std::system(command.c_str());
|
||||
|
||||
for (auto const& mesh : meshes)
|
||||
{
|
||||
SHAsset meshAsset{
|
||||
.name = mesh->header.name
|
||||
};
|
||||
meshAsset.path = SHMeshCompiler::CompileMeshBinary(*mesh, path).value();
|
||||
meshAsset.id = GenerateAssetID(AssetType::MESH);
|
||||
meshAsset.type = AssetType::MESH;
|
||||
assetCollection.insert({ meshAsset.id, meshAsset });
|
||||
SHAssetMetaHandler::WriteMetaData(meshAsset);
|
||||
}
|
||||
continue;
|
||||
std::string modelPath = path.string().substr(0, path.string().find_last_of('.'));
|
||||
modelPath += MODEL_EXTENSION;
|
||||
newPath = modelPath;
|
||||
}
|
||||
|
||||
assetCollection.insert({ newAsset.id, newAsset });
|
||||
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||
GenerateNewMeta(newPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,10 +452,11 @@ namespace SHADE
|
|||
loaders[static_cast<size_t>(AssetType::SHADER)] = dynamic_cast<SHAssetLoader*>(new SHShaderSourceLoader());
|
||||
loaders[static_cast<size_t>(AssetType::SHADER_BUILT_IN)] = loaders[static_cast<size_t>(AssetType::SHADER)];
|
||||
loaders[static_cast<size_t>(AssetType::TEXTURE)] = dynamic_cast<SHAssetLoader*>(new SHTextureLoader());
|
||||
loaders[static_cast<size_t>(AssetType::MESH)] = dynamic_cast<SHAssetLoader*>(new SHMeshLoader());
|
||||
loaders[static_cast<size_t>(AssetType::MODEL)] = dynamic_cast<SHAssetLoader*>(new SHModelLoader());
|
||||
loaders[static_cast<size_t>(AssetType::SCENE)] = dynamic_cast<SHAssetLoader*>(new SHTextBasedLoader());
|
||||
loaders[static_cast<size_t>(AssetType::PREFAB)] = loaders[static_cast<size_t>(AssetType::SCENE)];
|
||||
loaders[static_cast<size_t>(AssetType::MATERIAL)] = loaders[static_cast<size_t>(AssetType::SCENE)];
|
||||
loaders[static_cast<size_t>(AssetType::MESH)] = nullptr;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -464,9 +464,9 @@ namespace SHADE
|
|||
****************************************************************************/
|
||||
void SHAssetManager::Load() noexcept
|
||||
{
|
||||
//CompileAll();
|
||||
BuildAssetCollection();
|
||||
InitLoaders();
|
||||
//CompileAll();
|
||||
//LoadAllData();
|
||||
}
|
||||
|
||||
|
@ -484,8 +484,12 @@ namespace SHADE
|
|||
|
||||
SHAssetData* SHAssetManager::LoadData(SHAsset const& asset) noexcept
|
||||
{
|
||||
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||
if (asset.isSubAsset)
|
||||
{
|
||||
return LoadSubData(asset);
|
||||
}
|
||||
|
||||
SHAssetData* data = loaders[static_cast<size_t>(asset.type)]->Load(asset.path);
|
||||
if (data == nullptr)
|
||||
{
|
||||
SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string());
|
||||
|
@ -498,8 +502,120 @@ namespace SHADE
|
|||
return data;
|
||||
}
|
||||
|
||||
SHAssetData* SHAssetManager::LoadSubData(SHAsset const& asset) noexcept
|
||||
{
|
||||
auto const& parent = assetCollection[asset.parent];
|
||||
auto parentData = loaders[static_cast<size_t>(parent.type)]->Load(parent.path);
|
||||
|
||||
if (parentData == nullptr)
|
||||
{
|
||||
SHLOG_ERROR("Unable to load asset into memory: {}\n", parent.path.string());
|
||||
}
|
||||
else
|
||||
{
|
||||
assetData.emplace(parent.id, parentData);
|
||||
if (parent.type == AssetType::MODEL)
|
||||
{
|
||||
auto parentModel = reinterpret_cast<SHModelAsset*>(parentData);
|
||||
for (auto i {0}; i < parent.subAssets.size(); ++i)
|
||||
{
|
||||
assetData.emplace(
|
||||
parent.subAssets[i]->id,
|
||||
parentModel->subMeshes[i]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return assetData[asset.id];
|
||||
}
|
||||
|
||||
return parentData;
|
||||
}
|
||||
|
||||
void SHAssetManager::LoadNewData(AssetPath path) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void SHAssetManager::GenerateNewMeta(AssetPath path) noexcept
|
||||
{
|
||||
auto const ext = path.extension().string();
|
||||
if (ext == SHADER_BUILT_IN_EXTENSION.data())
|
||||
{
|
||||
SHAsset newAsset{
|
||||
path.stem().string(),
|
||||
GenerateAssetID(AssetType::SHADER_BUILT_IN),
|
||||
AssetType::SHADER_BUILT_IN,
|
||||
path,
|
||||
false
|
||||
};
|
||||
|
||||
assetCollection.emplace(newAsset.id, newAsset);
|
||||
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||
}
|
||||
else if (ext == TEXTURE_EXTENSION.data())
|
||||
{
|
||||
SHAsset newAsset{
|
||||
path.stem().string(),
|
||||
GenerateAssetID(AssetType::SHADER_BUILT_IN),
|
||||
AssetType::SHADER_BUILT_IN,
|
||||
path,
|
||||
false
|
||||
};
|
||||
|
||||
assetCollection.emplace(newAsset.id, newAsset);
|
||||
SHAssetMetaHandler::WriteMetaData(newAsset);
|
||||
}
|
||||
else if (ext == MODEL_EXTENSION)
|
||||
{
|
||||
SHAsset newAsset{
|
||||
path.stem().string(),
|
||||
GenerateAssetID(AssetType::MODEL),
|
||||
AssetType::MODEL,
|
||||
path,
|
||||
false
|
||||
};
|
||||
|
||||
assetCollection.emplace(newAsset.id, newAsset);
|
||||
|
||||
SHModelAsset* const data = reinterpret_cast<SHModelAsset*>(LoadData(newAsset));
|
||||
assetData.emplace(newAsset.id, data);
|
||||
for(auto const& subMesh : data->subMeshes)
|
||||
{
|
||||
SHAsset subAsset{
|
||||
.name = subMesh->header.name,
|
||||
.id = GenerateAssetID(AssetType::MESH),
|
||||
.type = AssetType::MESH,
|
||||
.isSubAsset = true,
|
||||
.parent = newAsset.id
|
||||
};
|
||||
|
||||
assetCollection.emplace(subAsset.id, subAsset);
|
||||
assetCollection[newAsset.id].subAssets.push_back(&assetCollection[subAsset.id]);
|
||||
|
||||
assetData.emplace(subAsset.id, subMesh);
|
||||
}
|
||||
|
||||
SHAssetMetaHandler::WriteMetaData(assetCollection[newAsset.id]);
|
||||
}
|
||||
}
|
||||
|
||||
void SHAssetManager::BuildAssetCollection() noexcept
|
||||
{
|
||||
SHFileSystem::BuildDirectory(ASSET_ROOT.data(), folderRoot, assetCollection);
|
||||
|
||||
for (auto& asset : std::ranges::views::values(assetCollection))
|
||||
{
|
||||
if (!asset.subAssets.empty())
|
||||
{
|
||||
// Add subasset data into map, replace pointer and free heap memory
|
||||
for (auto i{ 0 }; i < asset.subAssets.size(); ++i)
|
||||
{
|
||||
auto const id = asset.subAssets[i]->id;
|
||||
assetCollection[id] = *asset.subAssets[i];
|
||||
delete asset.subAssets[i];
|
||||
asset.subAssets[i] = &assetCollection[id];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace SHADE
|
|||
static std::vector<SHAssetData const*> GetAllDataOfType(AssetType type) noexcept;
|
||||
static std::vector<SHAsset> GetAllRecordOfType(AssetType type) noexcept;
|
||||
|
||||
static AssetID CompileAsset(AssetPath const& path) noexcept;
|
||||
static void CompileAsset(AssetPath const& path) noexcept;
|
||||
|
||||
static FolderPointer GetRootFolder() noexcept;
|
||||
|
||||
|
@ -96,6 +96,10 @@ namespace SHADE
|
|||
static void InitLoaders() noexcept;
|
||||
static void LoadAllData() noexcept;
|
||||
static SHAssetData* LoadData(SHAsset const& asset) noexcept;
|
||||
static SHAssetData* LoadSubData(SHAsset const& asset) noexcept;
|
||||
static void LoadNewData(AssetPath path) noexcept;
|
||||
static void GenerateNewMeta(AssetPath path) noexcept;
|
||||
|
||||
inline static void BuildAssetCollection() noexcept;
|
||||
|
||||
static bool IsRecognised(char const*) noexcept;
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
******************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHAssetMetaHandler.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
namespace SHADE
|
||||
|
@ -21,11 +20,15 @@ namespace SHADE
|
|||
* \brief Helper function to retrieve field value from meta data file
|
||||
* for processing
|
||||
****************************************************************************/
|
||||
void GetFieldValue(std::ifstream& file, std::string& line) noexcept
|
||||
bool GetFieldValue(std::ifstream& file, std::string& line) noexcept
|
||||
{
|
||||
line = "";
|
||||
std::getline(file, line);
|
||||
if (std::getline(file, line))
|
||||
{
|
||||
line = line.substr(line.find_last_of(':') + 2, line.length());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -66,7 +69,8 @@ namespace SHADE
|
|||
std::ifstream metaFile{ path.string(), std::ios_base::in };
|
||||
if (!metaFile.is_open())
|
||||
{
|
||||
// Error unable to open
|
||||
SHLOG_ERROR("Unable to open meta file: {}", path.string());
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string line;
|
||||
|
@ -93,6 +97,43 @@ namespace SHADE
|
|||
typeStream >> type;
|
||||
meta.type = static_cast<AssetType>(type);
|
||||
|
||||
meta.isSubAsset = false;
|
||||
|
||||
// Burn Line
|
||||
if (std::getline(metaFile, line))
|
||||
{
|
||||
// Name Line
|
||||
while(GetFieldValue(metaFile, line))
|
||||
{
|
||||
auto subAsset = new SHAsset();
|
||||
|
||||
// Get resource name
|
||||
std::stringstream nameStream{ line };
|
||||
AssetName name;
|
||||
nameStream >> name;
|
||||
subAsset->name = name;
|
||||
|
||||
// Get resource id
|
||||
GetFieldValue(metaFile, line);
|
||||
std::stringstream idStream{ line };
|
||||
AssetID id;
|
||||
idStream >> id;
|
||||
subAsset->id = id;
|
||||
|
||||
// Get resource type
|
||||
GetFieldValue(metaFile, line);
|
||||
std::stringstream typeStream{ line };
|
||||
AssetTypeMeta type;
|
||||
typeStream >> type;
|
||||
subAsset->type = static_cast<AssetType>(type);
|
||||
|
||||
subAsset->isSubAsset = true;
|
||||
subAsset->parent = meta.id;
|
||||
|
||||
meta.subAssets.push_back(subAsset);
|
||||
}
|
||||
}
|
||||
|
||||
metaFile.close();
|
||||
|
||||
meta.path = path.parent_path().string() + "/" + path.stem().string();
|
||||
|
@ -108,6 +149,12 @@ namespace SHADE
|
|||
****************************************************************************/
|
||||
void SHAssetMetaHandler::WriteMetaData(SHAsset const& meta) noexcept
|
||||
{
|
||||
if (meta.isSubAsset)
|
||||
{
|
||||
SHLOG_WARNING("Cannot write subasset meta: {}", meta.name);
|
||||
return;
|
||||
}
|
||||
|
||||
//TODO: Write into binary eventually
|
||||
std::string path{ meta.path.string() };
|
||||
path.append(META_EXTENSION);
|
||||
|
@ -124,7 +171,23 @@ namespace SHADE
|
|||
metaFile << "ID: " << meta.id << "\n";
|
||||
metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl;
|
||||
|
||||
if (!meta.subAssets.empty())
|
||||
{
|
||||
metaFile << "Sub Assets:\n";
|
||||
|
||||
for (auto const& subAsset : meta.subAssets)
|
||||
{
|
||||
WriteSubAssetMeta(metaFile, *subAsset);
|
||||
}
|
||||
}
|
||||
|
||||
metaFile.close();
|
||||
}
|
||||
|
||||
void SHAssetMetaHandler::WriteSubAssetMeta(std::ofstream& metaFile, SHAsset const& subAsset) noexcept
|
||||
{
|
||||
metaFile << "Name: " << subAsset.name << "\n";
|
||||
metaFile << "ID: " << subAsset.id << "\n";
|
||||
metaFile << "Type: " << static_cast<AssetTypeMeta>(subAsset.type) << std::endl;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
|
||||
#include "SHAssetMacros.h"
|
||||
#include "SHAsset.h"
|
||||
#include <fstream>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -45,6 +46,8 @@ namespace SHADE
|
|||
* \brief Writes meta data into text file
|
||||
****************************************************************************/
|
||||
static void WriteMetaData(SHAsset const&) noexcept;
|
||||
|
||||
static void WriteSubAssetMeta(std::ofstream&, SHAsset const&) noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,15 +5,19 @@
|
|||
#include "Editor/SHImGuiHelpers.hpp"
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <misc/cpp/imgui_stdlib.h>
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "Editor/IconsFontAwesome6.h"
|
||||
#include "Editor/SHEditor.h"
|
||||
#include "Editor/DragDrop/SHDragDrop.hpp"
|
||||
#include "Editor/EditorWindow/MaterialInspector/SHMaterialInspector.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHAssetBrowser::SHAssetBrowser()
|
||||
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder)
|
||||
:SHEditorWindow("\xee\x8b\x87 Asset Browser", ImGuiWindowFlags_MenuBar), rootFolder(SHAssetManager::GetRootFolder()), prevFolder(rootFolder), currentFolder(rootFolder), assetBeingCreated(std::nullopt)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -55,12 +59,31 @@ namespace SHADE
|
|||
flags |= ImGuiTreeNodeFlags_DefaultOpen;
|
||||
|
||||
bool isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data());
|
||||
ImGuiID folderID = ImGui::GetItemID();
|
||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||
if(ImGui::IsItemClicked())
|
||||
|
||||
if (ImGui::BeginPopupContextItem())
|
||||
{
|
||||
if (ImGui::BeginMenu("Create Asset"))
|
||||
{
|
||||
//TODO: Change to rttr type enum align
|
||||
if (ImGui::Selectable("Material"))
|
||||
{
|
||||
assetBeingCreated = { folder, AssetType::MATERIAL, "New Material" };
|
||||
ImGui::TreeNodeSetOpen(folderID, true);
|
||||
isOpen = true;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
selectedFolders.clear();
|
||||
selectedFolders.push_back(folder);
|
||||
}
|
||||
|
||||
if (isOpen)
|
||||
{
|
||||
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
|
||||
|
@ -79,13 +102,18 @@ namespace SHADE
|
|||
}
|
||||
for (auto const& file : files)
|
||||
{
|
||||
if(file.assetMeta == nullptr)
|
||||
continue;
|
||||
const float horizontalLineSize = 25.0f;
|
||||
const ImRect childRect = DrawFile(file);
|
||||
const ImRect childRect = DrawFile(file.assetMeta);
|
||||
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
||||
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
||||
vertLineEnd.y = midPoint;
|
||||
}
|
||||
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
|
||||
if(assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder)
|
||||
DrawAssetBeingCreated();
|
||||
|
||||
ImGui::TreePop();
|
||||
}
|
||||
return nodeRect;
|
||||
|
@ -120,45 +148,111 @@ namespace SHADE
|
|||
//}
|
||||
}
|
||||
|
||||
ImRect SHAssetBrowser::DrawFile(SHFile const& file) noexcept
|
||||
ImRect SHAssetBrowser::DrawFile(SHAsset const* const asset) noexcept
|
||||
{
|
||||
if (file.assetMeta == nullptr)
|
||||
if (asset == nullptr)
|
||||
return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||
const bool isSelected = std::ranges::find(selectedAssets, file.assetMeta->id) != selectedAssets.end();
|
||||
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf;
|
||||
const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end();
|
||||
ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf;
|
||||
if (isSelected)
|
||||
flags |= ImGuiTreeNodeFlags_Selected;
|
||||
std::string icon{};
|
||||
|
||||
switch(file.assetMeta->type)
|
||||
switch (asset->type)
|
||||
{
|
||||
case AssetType::INVALID: break;
|
||||
case AssetType::SHADER: icon = ICON_FA_FILE_CODE; break;
|
||||
case AssetType::SHADER_BUILT_IN: icon = ICON_FA_FILE_CODE; break;
|
||||
case AssetType::TEXTURE: icon = ICON_FA_IMAGES; break;
|
||||
case AssetType::MESH: icon = ICON_FA_CUBES; break;
|
||||
case AssetType::MODEL: icon = ICON_FA_CUBES_STACKED; break;
|
||||
case AssetType::SCENE: icon = ICON_MD_IMAGE; break;
|
||||
case AssetType::PREFAB: icon = ICON_FA_BOX_OPEN; break;
|
||||
case AssetType::MATERIAL: break;
|
||||
case AssetType::MESH: icon = ICON_FA_CUBES; break;
|
||||
case AssetType::MAX_COUNT: break;
|
||||
default: ;
|
||||
default:;
|
||||
}
|
||||
|
||||
ImGui::TreeNodeEx(file.assetMeta, flags, "%s %s", icon.data(), file.assetMeta->name.data());
|
||||
bool const isOpen = ImGui::TreeNodeEx(asset, flags, "%s %s", icon.data(), asset->name.data());
|
||||
const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
|
||||
if(SHDragDrop::BeginSource())
|
||||
if (SHDragDrop::BeginSource())
|
||||
{
|
||||
auto id = file.assetMeta->id;
|
||||
ImGui::Text("Moving Asset: %s [%zu]", file.name.data(), file.assetMeta->id);
|
||||
auto id = asset->id;
|
||||
ImGui::Text("Moving Asset: %s [%zu]", asset->name.data(), asset->id);
|
||||
SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id);
|
||||
SHDragDrop::EndSource();
|
||||
}
|
||||
if(ImGui::IsItemClicked())
|
||||
if (ImGui::IsItemClicked())
|
||||
{
|
||||
selectedAssets.clear();
|
||||
selectedAssets.push_back(file.assetMeta->id);
|
||||
selectedAssets.push_back(asset->id);
|
||||
}
|
||||
if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
|
||||
{
|
||||
switch (asset->type)
|
||||
{
|
||||
case AssetType::INVALID: break;
|
||||
case AssetType::SHADER: break;
|
||||
case AssetType::SHADER_BUILT_IN: break;
|
||||
case AssetType::TEXTURE: break;
|
||||
case AssetType::MESH: break;
|
||||
case AssetType::SCENE:
|
||||
if(auto editor = SHSystemManager::GetSystem<SHEditor>())
|
||||
{
|
||||
editor->LoadScene(asset->id);
|
||||
}
|
||||
break;
|
||||
case AssetType::PREFAB: break;
|
||||
case AssetType::MATERIAL:
|
||||
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
|
||||
{
|
||||
matInspector->OpenMaterial(asset->id);
|
||||
}
|
||||
break;
|
||||
case AssetType::MAX_COUNT: break;
|
||||
default:;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//TODO: Combine Draw asset and Draw Folder recursive drawing
|
||||
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
|
||||
const float horizontalOffset = 0.0f;
|
||||
ImDrawList* drawList = ImGui::GetWindowDrawList();
|
||||
ImVec2 vertLineStart = ImGui::GetCursorScreenPos();
|
||||
vertLineStart.x += horizontalOffset;
|
||||
ImVec2 vertLineEnd = vertLineStart;
|
||||
if(isOpen)
|
||||
{
|
||||
for(auto const& subAsset : asset->subAssets)
|
||||
{
|
||||
const float horizontalLineSize = 25.0f;
|
||||
const ImRect childRect = DrawFile(subAsset);
|
||||
const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
|
||||
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
|
||||
vertLineEnd.y = midPoint;
|
||||
}
|
||||
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
|
||||
ImGui::TreePop();
|
||||
}
|
||||
return nodeRect;
|
||||
}
|
||||
|
||||
void SHAssetBrowser::DrawAssetBeingCreated() noexcept
|
||||
{
|
||||
if (!assetBeingCreated.has_value())
|
||||
return;
|
||||
auto& path = std::get<0>(assetBeingCreated.value());
|
||||
auto& type = std::get<1>(assetBeingCreated.value());
|
||||
auto& assetName = std::get<2>(assetBeingCreated.value());
|
||||
if (ImGui::InputText("##newAssetName", &assetName, ImGuiInputTextFlags_EnterReturnsTrue))
|
||||
{
|
||||
AssetID assetId = SHAssetManager::CreateNewAsset(type, assetName);
|
||||
if (auto matInspector = SHEditorWindowManager::GetEditorWindow<SHMaterialInspector>())
|
||||
{
|
||||
matInspector->OpenMaterial(assetId, true);
|
||||
}
|
||||
assetBeingCreated.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace SHADE
|
|||
class SHAssetBrowser final : public SHEditorWindow
|
||||
{
|
||||
public:
|
||||
using AssetEntry = std::tuple<FolderPointer, AssetType, std::string>;
|
||||
SHAssetBrowser();
|
||||
|
||||
void Init();
|
||||
|
@ -20,12 +21,13 @@ namespace SHADE
|
|||
void DrawMenuBar();
|
||||
ImRect RecursivelyDrawTree(FolderPointer folder);
|
||||
void DrawCurrentFolder();
|
||||
ImRect DrawFile(SHFile const& file) noexcept;
|
||||
ImRect DrawFile(SHAsset const* const asset) noexcept;
|
||||
void DrawAssetBeingCreated() noexcept;
|
||||
|
||||
FolderPointer rootFolder, prevFolder, currentFolder;
|
||||
std::optional<AssetEntry> assetBeingCreated;
|
||||
std::vector<FolderPointer> selectedFolders;
|
||||
std::vector<AssetID> selectedAssets;
|
||||
static constexpr float tileWidth = 50.0f;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -108,6 +108,12 @@ namespace SHADE
|
|||
}
|
||||
|
||||
}
|
||||
if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||
{
|
||||
ParentSelectedEntities(MAX_EID, draggingEntities);
|
||||
draggingEntities.clear();
|
||||
ImGui::ClearDragDrop();
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
@ -195,7 +201,7 @@ namespace SHADE
|
|||
if (SHDragDrop::BeginSource())
|
||||
{
|
||||
std::string moveLabel = "Moving EID: ";
|
||||
static std::vector<EntityID> draggingEntities = editor->selectedEntities;
|
||||
draggingEntities = editor->selectedEntities;
|
||||
if (!isSelected)
|
||||
{
|
||||
draggingEntities.clear();
|
||||
|
@ -217,7 +223,8 @@ namespace SHADE
|
|||
{
|
||||
if (const std::vector<EntityID>* eidPayload = SHDragDrop::AcceptPayload<std::vector<EntityID>>(SHDragDrop::DRAG_EID)) //If payload is valid
|
||||
{
|
||||
ParentSelectedEntities(eid);
|
||||
ParentSelectedEntities(eid, draggingEntities);
|
||||
draggingEntities.clear();
|
||||
SHDragDrop::EndTarget();
|
||||
}
|
||||
}
|
||||
|
@ -255,7 +262,7 @@ namespace SHADE
|
|||
|
||||
if ((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data()))
|
||||
{
|
||||
ParentSelectedEntities(MAX_EID);
|
||||
ParentSelectedEntities(MAX_EID, editor->selectedEntities);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
@ -323,14 +330,16 @@ namespace SHADE
|
|||
SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID);
|
||||
}
|
||||
|
||||
void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID) const noexcept
|
||||
void SHHierarchyPanel::ParentSelectedEntities(EntityID parentEID, std::vector<EntityID> const& entities) const noexcept
|
||||
{
|
||||
auto const& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
|
||||
auto const editor = SHSystemManager::GetSystem<SHEditor>();
|
||||
//auto const editor = SHSystemManager::GetSystem<SHEditor>();
|
||||
SHEntityParentCommand::EntityParentData entityParentData;
|
||||
std::vector<EntityID> parentedEIDS;
|
||||
for (auto const& eid : editor->selectedEntities)
|
||||
for (auto const& eid : entities)
|
||||
{
|
||||
if(eid == parentEID)
|
||||
continue;
|
||||
if (sceneGraph.GetChild(eid, parentEID) == nullptr)
|
||||
{
|
||||
parentedEIDS.push_back(eid);
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace SHADE
|
|||
void DrawMenuBar() const noexcept;
|
||||
ImRect RecursivelyDrawEntityNode(SHSceneNode* const);
|
||||
void CreateChildEntity(EntityID parentEID) const noexcept;
|
||||
void ParentSelectedEntities(EntityID parentEID) const noexcept;
|
||||
void ParentSelectedEntities(EntityID parentEID, std::vector<EntityID> const& entities) const noexcept;
|
||||
void SelectRangeOfEntities(EntityID beginEID, EntityID EndEID);
|
||||
void SelectAllEntities();
|
||||
void CopySelectedEntities();
|
||||
|
@ -37,6 +37,8 @@ namespace SHADE
|
|||
std::string filter;
|
||||
bool isAnyNodeSelected = false;
|
||||
EntityID scrollTo = MAX_EID;
|
||||
std::vector<EntityID> draggingEntities;
|
||||
|
||||
};//class SHHierarchyPanel
|
||||
|
||||
//Might move to a different file
|
||||
|
|
|
@ -244,9 +244,12 @@ namespace SHADE
|
|||
SHCollider* collider = &component->GetCollider(i);
|
||||
auto cursorPos = ImGui::GetCursorPos();
|
||||
|
||||
//collider->IsTrigger
|
||||
|
||||
if (collider->GetType() == SHCollider::Type::BOX)
|
||||
{
|
||||
SHEditorWidgets::BeginPanel(std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||
SHEditorWidgets::CheckBox("Is Trigger", [collider]() {return collider->IsTrigger(); }, [collider](bool const& value) {collider->SetIsTrigger(value); }, "Is Trigger");
|
||||
auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
|
||||
SHEditorWidgets::DragVec3
|
||||
(
|
||||
|
@ -257,6 +260,7 @@ namespace SHADE
|
|||
else if (collider->GetType() == SHCollider::Type::SPHERE)
|
||||
{
|
||||
SHEditorWidgets::BeginPanel(std::format("{} Sphere Collider #{}", ICON_MD_CIRCLE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y });
|
||||
SHEditorWidgets::CheckBox("Is Trigger", [collider]() {return collider->IsTrigger(); }, [collider](bool const& value) {collider->SetIsTrigger(value); }, "Is Trigger");
|
||||
auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
|
||||
SHEditorWidgets::DragFloat
|
||||
(
|
||||
|
@ -372,6 +376,7 @@ namespace SHADE
|
|||
{
|
||||
DrawContextMenu(component);
|
||||
Handle<SHMesh> const& mesh = component->GetMesh();
|
||||
Handle<SHMaterialInstance> const& mat = component->GetMaterial();
|
||||
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Mesh", std::to_string(SHResourceManager::GetAssetID<SHMesh>(mesh).value_or(0)).data(), [component]()
|
||||
{
|
||||
|
@ -383,6 +388,19 @@ namespace SHADE
|
|||
component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id));
|
||||
SHResourceManager::FinaliseChanges();
|
||||
}, SHDragDrop::DRAG_RESOURCE);
|
||||
|
||||
SHEditorWidgets::DragDropReadOnlyField<AssetID>("Material", mat ? std::to_string(SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0)).data() : "", [component]()
|
||||
{
|
||||
Handle<SHMaterialInstance> const& mat = component->GetMaterial();
|
||||
if(!mat)
|
||||
return static_cast<AssetID>(0);
|
||||
return SHResourceManager::GetAssetID<SHMaterial>(mat->GetBaseMaterial()).value_or(0);
|
||||
},
|
||||
[component](AssetID const& id)
|
||||
{
|
||||
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||
component->SetMaterial(gfxSystem->AddOrGetBaseMaterialInstance(SHResourceManager::LoadOrGet<SHMaterial>(id)));
|
||||
}, SHDragDrop::DRAG_RESOURCE);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,257 @@
|
|||
#include "SHpch.h"
|
||||
#include "Serialization/SHSerializationHelper.hpp"
|
||||
#include "SHMaterialInspector.h"
|
||||
#include "Editor/SHImGuiHelpers.hpp"
|
||||
#include <imgui.h>
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
#include "Editor/IconsMaterialDesign.h"
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
SHMaterialInspector::SHMaterialInspector()
|
||||
:SHEditorWindow("Material Inspector", ImGuiWindowFlags_MenuBar), isDirty(false), isNewMaterial(false), currentViewedMaterial(0)
|
||||
{
|
||||
}
|
||||
|
||||
void SHMaterialInspector::OpenMaterial(AssetID const& assetId, bool isNew) noexcept
|
||||
{
|
||||
//Get mat data
|
||||
if(isDirty)
|
||||
return;
|
||||
isDirty = isNew;
|
||||
isOpen = true;
|
||||
SetFocusToWindow();
|
||||
currentViewedMaterial = assetId;
|
||||
|
||||
//currentMatSpec = //Get mat spec
|
||||
|
||||
currentMatSpec = SHResourceManager::LoadOrGet<SHMaterialSpec>(assetId);
|
||||
currentMaterial = SHResourceManager::LoadOrGet<SHMaterial>(assetId);
|
||||
}
|
||||
|
||||
void SHMaterialInspector::Init()
|
||||
{
|
||||
SHEditorWindow::Init();
|
||||
}
|
||||
|
||||
void SHMaterialInspector::Update()
|
||||
{
|
||||
SHEditorWindow::Update();
|
||||
|
||||
if (Begin())
|
||||
{
|
||||
if(currentViewedMaterial)
|
||||
{
|
||||
DrawMenuBar();
|
||||
|
||||
//if (SHEditorWidgets::DragDropReadOnlyField<AssetID>("Vertex Shader", std::to_string(currentMatSpec->vertexShader), [&]() {return currentMatSpec->vertexShader; }, [&](AssetID const& id) {currentMatSpec->vertexShader = id; }, SHDragDrop::DRAG_RESOURCE))
|
||||
//{
|
||||
// isDirty = true;
|
||||
// vertShaderHandle = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->vertexShader);
|
||||
//}
|
||||
//if (SHEditorWidgets::DragDropReadOnlyField<AssetID>("Fragment Shader", std::to_string(currentMatSpec->fragShader), [&]() {return currentMatSpec->fragShader; }, [&](AssetID const& id) {currentMatSpec->fragShader = id; }, SHDragDrop::DRAG_RESOURCE))
|
||||
//{
|
||||
// isDirty = true;
|
||||
// fragShaderHandle = SHResourceManager::LoadOrGet<SHVkShaderModule>(currentMatSpec->fragShader);
|
||||
//}
|
||||
|
||||
DrawShaderProperties(/*fragShaderHandle*/);
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void SHMaterialInspector::Exit()
|
||||
{
|
||||
SHEditorWindow::Exit();
|
||||
}
|
||||
|
||||
void SHMaterialInspector::DrawMenuBar()
|
||||
{
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
ImGui::BeginDisabled(!isDirty);
|
||||
if(ImGui::Button(std::format("{} Save", ICON_MD_SAVE).data()))
|
||||
{
|
||||
//save
|
||||
if(auto matAsset = SHAssetManager::GetData<SHMaterialAsset>(currentViewedMaterial))
|
||||
{
|
||||
YAML::Emitter out;
|
||||
out << YAML::BeginSeq;
|
||||
out << YAML::convert<SHMaterialSpec>::encode(*currentMatSpec);
|
||||
out << YAML::EndSeq;
|
||||
matAsset->data = out.c_str();
|
||||
|
||||
Handle<SHShaderBlockInterface> pipelineProperties = currentMaterial->GetShaderBlockInterface();
|
||||
for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i)
|
||||
{
|
||||
const std::string& PROP_NAME = pipelineProperties->GetVariableName(i);
|
||||
const YAML::Node& PROP_NODE = currentMatSpec->properties[PROP_NAME.data()];
|
||||
if (PROP_NODE.IsDefined())
|
||||
{
|
||||
const std::string& VAR_NAME = pipelineProperties->GetVariableName(i);
|
||||
const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i);
|
||||
switch (VARIABLE->type)
|
||||
{
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT:
|
||||
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<float>());
|
||||
break;
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
|
||||
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<int>());
|
||||
break;
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
|
||||
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec2>());
|
||||
break;
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3:
|
||||
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec3>());
|
||||
break;
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4:
|
||||
currentMaterial->SetProperty(VARIABLE->offset, PROP_NODE.as<SHVec4>());
|
||||
break;
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::OTHER:
|
||||
default:
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(SHAssetManager::SaveAsset(currentViewedMaterial))
|
||||
{
|
||||
isDirty = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
void SHMaterialInspector::DrawShaderProperties(/*Handle<SHVkShaderModule> shaderModule*/)
|
||||
{
|
||||
/*if(!shaderModule)
|
||||
return;*/
|
||||
auto gfxSystem = SHSystemManager::GetSystem<SHGraphicsSystem>();
|
||||
auto interface = gfxSystem->GetDefaultMaterialInstance()->GetBaseMaterial()->GetShaderBlockInterface();
|
||||
//auto interface = shaderModule->GetReflectedData().GetDescriptorBindingInfo().GetShaderBlockInterface(SHGraphicsConstants::DescriptorSetIndex::PER_INSTANCE, SHGraphicsConstants::DescriptorSetBindings::BATCHED_PER_INST_DATA);
|
||||
|
||||
int const varCount = static_cast<int>(interface->GetVariableCount());
|
||||
|
||||
for (int i = 0; i < varCount; ++i)
|
||||
{
|
||||
auto variable = interface->GetVariable(i);
|
||||
const std::string& VAR_NAME = interface->GetVariableName(i);
|
||||
if(VAR_NAME.empty())
|
||||
continue;
|
||||
switch (variable->type)
|
||||
{
|
||||
case SHShaderBlockInterface::Variable::Type::FLOAT:
|
||||
isDirty |= SHEditorWidgets::DragFloat(VAR_NAME,
|
||||
[&]()
|
||||
{
|
||||
if (currentMatSpec->properties[VAR_NAME].IsDefined())
|
||||
return currentMatSpec->properties[VAR_NAME].as<float>();
|
||||
else
|
||||
return 0.0f;
|
||||
},
|
||||
[&](float const& value)
|
||||
{
|
||||
currentMatSpec->properties[VAR_NAME] = value;
|
||||
}
|
||||
);
|
||||
break;
|
||||
case SHShaderBlockInterface::Variable::Type::INT:
|
||||
isDirty |= SHEditorWidgets::DragInt(VAR_NAME,
|
||||
[&]()
|
||||
{
|
||||
if (currentMatSpec->properties[VAR_NAME].IsDefined())
|
||||
return currentMatSpec->properties[VAR_NAME].as<int>();
|
||||
else
|
||||
return 0;
|
||||
},
|
||||
[&](int const& value)
|
||||
{
|
||||
currentMatSpec->properties[VAR_NAME] = value;
|
||||
}
|
||||
);
|
||||
if(SHDragDrop::BeginTarget())
|
||||
{
|
||||
if(AssetID* payload = SHDragDrop::AcceptPayload<AssetID>(SHDragDrop::DRAG_RESOURCE))
|
||||
{
|
||||
currentMatSpec->properties[VAR_NAME] = *payload;
|
||||
isDirty = true;
|
||||
SHDragDrop::EndTarget();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SHShaderBlockInterface::Variable::Type::VECTOR2:
|
||||
isDirty |= SHEditorWidgets::DragVec2(VAR_NAME, { "X", "Y" },
|
||||
[&]()
|
||||
{
|
||||
if (currentMatSpec->properties[VAR_NAME].IsDefined())
|
||||
return currentMatSpec->properties[VAR_NAME].as<SHVec2>();
|
||||
else
|
||||
return SHVec2::Zero;
|
||||
},
|
||||
[&](SHVec2 const& value)
|
||||
{
|
||||
currentMatSpec->properties[VAR_NAME] = value;
|
||||
}
|
||||
);
|
||||
break;
|
||||
case SHShaderBlockInterface::Variable::Type::VECTOR3:
|
||||
isDirty |= SHEditorWidgets::DragVec3(VAR_NAME, { "X", "Y", "Z" },
|
||||
[&]()
|
||||
{
|
||||
if (currentMatSpec->properties[VAR_NAME].IsDefined())
|
||||
return currentMatSpec->properties[VAR_NAME].as<SHVec3>();
|
||||
else
|
||||
return SHVec3::Zero;
|
||||
},
|
||||
[&](SHVec3 const& value)
|
||||
{
|
||||
currentMatSpec->properties[VAR_NAME] = value;
|
||||
}
|
||||
);
|
||||
break;
|
||||
case SHShaderBlockInterface::Variable::Type::VECTOR4:
|
||||
isDirty |= SHEditorWidgets::DragVec4(VAR_NAME, { "X", "Y", "Z", "W" },
|
||||
[&]()
|
||||
{
|
||||
if (currentMatSpec->properties[VAR_NAME].IsDefined())
|
||||
return currentMatSpec->properties[VAR_NAME].as<SHVec4>();
|
||||
else
|
||||
return SHVec4::Zero;
|
||||
},
|
||||
[&](SHVec4 const& value)
|
||||
{
|
||||
currentMatSpec->properties[VAR_NAME] = value;
|
||||
}
|
||||
);
|
||||
break;
|
||||
case SHShaderBlockInterface::Variable::Type::OTHER:
|
||||
isDirty |= SHEditorWidgets::InputText(VAR_NAME,
|
||||
[&]()
|
||||
{
|
||||
if (currentMatSpec->properties[VAR_NAME].IsDefined())
|
||||
return currentMatSpec->properties[VAR_NAME].as<std::string>();
|
||||
else
|
||||
return std::string();
|
||||
},
|
||||
[&](std::string const& value)
|
||||
{
|
||||
currentMatSpec->properties[VAR_NAME] = value;
|
||||
}
|
||||
);
|
||||
default:
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
#pragma once
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
#include "Editor/EditorWindow/SHEditorWindow.h"
|
||||
#include "Graphics/MiddleEnd/Materials/SHMaterialSpec.h"
|
||||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHMaterialInspector final : public SHEditorWindow
|
||||
{
|
||||
public:
|
||||
SHMaterialInspector();
|
||||
~SHMaterialInspector() = default;
|
||||
|
||||
void Init() override;
|
||||
void Update() override;
|
||||
void Exit() override;
|
||||
|
||||
void OpenMaterial(AssetID const& assetId, bool isNew = false) noexcept;
|
||||
private:
|
||||
void DrawMenuBar();
|
||||
void DrawShaderProperties(/*Handle<SHVkShaderModule> shaderModule*/);
|
||||
|
||||
bool isDirty;
|
||||
bool isNewMaterial;
|
||||
AssetID currentViewedMaterial;
|
||||
Handle<SHMaterialSpec> currentMatSpec;
|
||||
Handle<SHMaterial> currentMaterial;
|
||||
Handle<SHVkShaderModule> vertShaderHandle, fragShaderHandle;
|
||||
};
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
//#==============================================================#
|
||||
//|| SHADE Includes ||
|
||||
//#==============================================================#
|
||||
#include "Editor/SHEditorWidgets.hpp"
|
||||
#include "Editor/SHEditor.h"
|
||||
#include "SHEditorMenuBar.h"
|
||||
#include "Editor/IconsMaterialDesign.h"
|
||||
|
@ -17,7 +18,11 @@
|
|||
#include <imgui_internal.h>
|
||||
#include <rttr/type>
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
#include "Assets/Asset Types/SHSceneAsset.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Serialization/SHSerialization.h"
|
||||
#include "Serialization/Configurations/SHConfigurationManager.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -75,13 +80,17 @@ namespace SHADE
|
|||
{
|
||||
if (ImGui::BeginMenu("File"))
|
||||
{
|
||||
if(ImGui::Selectable("New Scene"))
|
||||
{
|
||||
SHSystemManager::GetSystem<SHEditor>()->NewScene();
|
||||
}
|
||||
if(ImGui::Selectable("Save"))
|
||||
{
|
||||
SHSerialization::SerializeSceneToFile("../../Assets/Scenes/Test.SHADE");
|
||||
SHSystemManager::GetSystem<SHEditor>()->SaveScene();
|
||||
}
|
||||
if(ImGui::Selectable("Load"))
|
||||
{
|
||||
SHSerialization::DeserializeSceneFromFile("../../Assets/Scenes/Test.SHADE");
|
||||
//SHSystemManager::GetSystem<SHEditor>()->LoadScene()
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
@ -108,16 +117,22 @@ namespace SHADE
|
|||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
scriptEngine->GenerateScriptsCsProjFile();
|
||||
}
|
||||
ImGui::BeginDisabled(SHSystemManager::GetSystem<SHEditor>()->editorState != SHEditor::State::STOP);
|
||||
if (ImGui::Selectable("Build Scripts - Debug"))
|
||||
{
|
||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
|
||||
scriptEngine->BuildScriptAssembly(true, true);
|
||||
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
|
||||
}
|
||||
if (ImGui::Selectable("Build Scripts - Release"))
|
||||
{
|
||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
|
||||
scriptEngine->BuildScriptAssembly(false, true);
|
||||
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
|
@ -155,6 +170,35 @@ namespace SHADE
|
|||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
if (ImGui::BeginMenu("Application Config"))
|
||||
{
|
||||
auto& appConfig = SHConfigurationManager::applicationConfig;
|
||||
ImGui::InputText("Window Title", &appConfig.windowTitle);
|
||||
ImGui::Checkbox("Start in Fullscreen", &appConfig.startInFullScreen);
|
||||
SHEditorWidgets::DragN<float, 2>("Window Size", { "Width", "Height" }, { &appConfig.windowSize.x, &appConfig.windowSize.y });
|
||||
//ImGui::InputScalar("Starting Scene", ImGuiDataType_U32, &appConfig.startingSceneID);
|
||||
auto sceneAsset = SHAssetManager::GetData<SHSceneAsset>(appConfig.startingSceneID);
|
||||
|
||||
if(ImGui::BeginCombo("Starting Scne", sceneAsset ? sceneAsset->name.data() : ""))
|
||||
{
|
||||
auto scenes = SHAssetManager::GetAllRecordOfType(AssetType::SCENE);
|
||||
for(auto const& scene : scenes)
|
||||
{
|
||||
if(ImGui::Selectable(scene.name.data()))
|
||||
{
|
||||
appConfig.startingSceneID = scene.id;
|
||||
}
|
||||
}
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
if (ImGui::Button("Save"))
|
||||
{
|
||||
SHConfigurationManager::SaveApplicationConfig();
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
|
||||
|
@ -174,6 +218,8 @@ namespace SHADE
|
|||
const auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY);
|
||||
if(ImGui::SmallButton(ICON_MD_PLAY_ARROW))
|
||||
{
|
||||
if(editor->SaveScene())
|
||||
{
|
||||
const SHEditorStateChangeEvent STATE_CHANGE_EVENT
|
||||
{
|
||||
|
@ -183,6 +229,7 @@ namespace SHADE
|
|||
|
||||
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
|
||||
if(ImGui::SmallButton(ICON_MD_PAUSE))
|
||||
|
@ -206,6 +253,7 @@ namespace SHADE
|
|||
editor->editorState = SHEditor::State::STOP;
|
||||
|
||||
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
|
||||
editor->LoadScene(SHSceneManager::GetCurrentSceneAssetID());
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::EndMenuBar();
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace SHADE
|
|||
//|| Public Member Functions ||
|
||||
//#==============================================================#
|
||||
SHEditorWindow::SHEditorWindow(std::string_view const& name, ImGuiWindowFlags const& inFlags)
|
||||
: windowName(name), windowFlags(inFlags), io(ImGui::GetIO())
|
||||
:isOpen(true), isWindowHovered(false), windowName(name), windowFlags(inFlags), io(ImGui::GetIO())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -68,5 +68,10 @@ namespace SHADE
|
|||
void SHEditorWindow::OnPosChange()
|
||||
{
|
||||
}
|
||||
|
||||
void SHEditorWindow::SetFocusToWindow()
|
||||
{
|
||||
ImGui::SetWindowFocus(windowName.data());
|
||||
}
|
||||
}//namespace SHADE
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace SHADE
|
|||
virtual bool Begin();
|
||||
virtual void OnResize();
|
||||
virtual void OnPosChange();
|
||||
virtual void SetFocusToWindow();
|
||||
|
||||
ImGuiWindowFlags windowFlags = 0;
|
||||
ImGuiIO& io;
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
#include "Profiling/SHEditorProfiler.h" //Profiler
|
||||
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
|
||||
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
|
||||
#include "MaterialInspector/SHMaterialInspector.h" //Material Inspector
|
|
@ -45,7 +45,12 @@
|
|||
#include <backends/imgui_impl_sdl.h>
|
||||
#include <backends/imgui_impl_vulkan.h>
|
||||
|
||||
#include "Assets/SHAssetManager.h"
|
||||
#include "Assets/Asset Types/SHSceneAsset.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
|
||||
#include "Scene/SHSceneManager.h"
|
||||
#include "Serialization/SHSerialization.h"
|
||||
#include "Tools/SHDebugDraw.h"
|
||||
|
||||
RTTR_REGISTRATION
|
||||
{
|
||||
|
@ -77,7 +82,6 @@ namespace SHADE
|
|||
//#==============================================================#
|
||||
void SHEditor::Init()
|
||||
{
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
if(auto context = ImGui::CreateContext())
|
||||
{
|
||||
|
@ -93,6 +97,8 @@ namespace SHADE
|
|||
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
|
||||
SHEditorWindowManager::CreateEditorWindow<SHMaterialInspector>();
|
||||
|
||||
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
|
||||
|
||||
io = &ImGui::GetIO();
|
||||
|
@ -120,6 +126,17 @@ namespace SHADE
|
|||
window->Init();
|
||||
}
|
||||
|
||||
/* Editor View Gridlines */
|
||||
SetUpGridLines(true, true);
|
||||
// Handle state changes so that we only show in edit mode
|
||||
std::shared_ptr<SHEventReceiverSpec<SHEditor>> stateChangeEventReceiver
|
||||
{
|
||||
std::make_shared<SHEventReceiverSpec<SHEditor>>(this, &SHEditor::onEditorStateChanged)
|
||||
};
|
||||
SHEventManager::SubscribeTo(SH_EDITOR_ON_PLAY_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(stateChangeEventReceiver));
|
||||
SHEventManager::SubscribeTo(SH_EDITOR_ON_PAUSE_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(stateChangeEventReceiver));
|
||||
SHEventManager::SubscribeTo(SH_EDITOR_ON_STOP_EVENT, std::dynamic_pointer_cast<SHEventReceiver>(stateChangeEventReceiver));
|
||||
|
||||
SHLOG_INFO("Successfully initialised SHADE Engine Editor")
|
||||
}
|
||||
|
||||
|
@ -135,6 +152,8 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
RenderSceneNamePrompt();
|
||||
RenderUnsavedChangesPrompt();
|
||||
//PollPicking();
|
||||
|
||||
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||
|
@ -159,6 +178,60 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHEditor::RenderSceneNamePrompt() noexcept
|
||||
{
|
||||
if(isSceneNamePromptOpen)
|
||||
{
|
||||
ImGui::OpenPopup(sceneNamePromptName.data());
|
||||
}
|
||||
|
||||
if(ImGui::BeginPopupModal(sceneNamePromptName.data(), &isSceneNamePromptOpen))
|
||||
{
|
||||
static std::string newSceneName{};
|
||||
ImGui::Text("Enter new scene name");
|
||||
ImGui::InputText("##name", &newSceneName);
|
||||
ImGui::BeginDisabled(newSceneName.empty());
|
||||
if(ImGui::Button("Save"))
|
||||
{
|
||||
SaveScene(newSceneName);
|
||||
newSceneName.clear();
|
||||
isSceneNamePromptOpen = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Cancel"))
|
||||
{
|
||||
isSceneNamePromptOpen = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
void SHEditor::RenderUnsavedChangesPrompt() noexcept
|
||||
{
|
||||
if(isUnsavedChangesPromptOpen)
|
||||
{
|
||||
ImGui::OpenPopup(unsavedChangesPromptName.data());
|
||||
}
|
||||
|
||||
if(ImGui::BeginPopupModal(unsavedChangesPromptName.data(), &isUnsavedChangesPromptOpen))
|
||||
{
|
||||
ImGui::Text("You have unsaved changes!");
|
||||
if(ImGui::Button("Save"))
|
||||
{
|
||||
isSceneNamePromptOpen = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if(ImGui::Button("Cancel"))
|
||||
{
|
||||
isUnsavedChangesPromptOpen = false;
|
||||
ImGui::CloseCurrentPopup();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SHEditor::InitLayout() noexcept
|
||||
{
|
||||
if(!std::filesystem::exists(io->IniFilename))
|
||||
|
@ -180,6 +253,97 @@ namespace SHADE
|
|||
io->Fonts->Build();
|
||||
}
|
||||
|
||||
void SHEditor::SetUpGridLines(bool drawGrid, bool drawAxes)
|
||||
{
|
||||
// Clear existing lines
|
||||
SHDebugDraw::ClearPersistentDraws();
|
||||
|
||||
static constexpr float DELTA = 1.0f;
|
||||
static constexpr int EXTENT_COUNT = static_cast<int>(500.0f /* TODO: Remove hard code */ / DELTA);
|
||||
static constexpr float LINE_HALF_LENGTH = (DELTA * static_cast<float>(EXTENT_COUNT)) * 0.5f;
|
||||
|
||||
// Render Grid
|
||||
static const SHColour GRID_COL = { 0.2f, 0.2f, 0.2f, 1.0f };
|
||||
if (drawGrid)
|
||||
{
|
||||
for (int i = 1; i < EXTENT_COUNT; ++i)
|
||||
{
|
||||
// X-Axis Lines
|
||||
SHDebugDraw::PersistentLine
|
||||
(
|
||||
GRID_COL,
|
||||
SHVec3 { -LINE_HALF_LENGTH, 0.0f, i * DELTA },
|
||||
SHVec3 { LINE_HALF_LENGTH, 0.0f, i * DELTA }
|
||||
);
|
||||
SHDebugDraw::PersistentLine
|
||||
(
|
||||
GRID_COL,
|
||||
SHVec3 { -LINE_HALF_LENGTH, 0.0f, i * -DELTA },
|
||||
SHVec3 { LINE_HALF_LENGTH, 0.0f, i * -DELTA }
|
||||
);
|
||||
// Y-Axis Lines
|
||||
SHDebugDraw::PersistentLine
|
||||
(
|
||||
GRID_COL,
|
||||
SHVec3 { i * DELTA, 0.0f, -LINE_HALF_LENGTH },
|
||||
SHVec3 { i * DELTA, 0.0f, LINE_HALF_LENGTH }
|
||||
);
|
||||
SHDebugDraw::PersistentLine
|
||||
(
|
||||
GRID_COL,
|
||||
SHVec3 { -i * DELTA, 0.0f, -LINE_HALF_LENGTH },
|
||||
SHVec3 { -i * DELTA, 0.0f, LINE_HALF_LENGTH }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Render World Axes
|
||||
if (drawAxes || drawGrid)
|
||||
{
|
||||
const SHColour X_AXIS_COL = drawAxes ? SHColour::RED : GRID_COL;
|
||||
const SHColour Y_AXIS_COL = drawAxes ? SHColour::GREEN : GRID_COL;
|
||||
const SHColour Z_AXIS_COL = drawAxes ? SHColour::BLUE : GRID_COL;
|
||||
// X
|
||||
SHDebugDraw::PersistentLine
|
||||
(
|
||||
X_AXIS_COL,
|
||||
SHVec3 { -LINE_HALF_LENGTH, 0.0f, 0.0f },
|
||||
SHVec3 { LINE_HALF_LENGTH, 0.0f, 0.0f }
|
||||
);
|
||||
// Y
|
||||
SHDebugDraw::PersistentLine
|
||||
(
|
||||
Y_AXIS_COL,
|
||||
SHVec3 { 0.0f, -LINE_HALF_LENGTH, 0.0f },
|
||||
SHVec3 { 0.0f, LINE_HALF_LENGTH, 0.0f }
|
||||
);
|
||||
// Z
|
||||
SHDebugDraw::PersistentLine
|
||||
(
|
||||
Z_AXIS_COL,
|
||||
SHVec3 { 0.0f, 0.0f, -LINE_HALF_LENGTH },
|
||||
SHVec3 { 0.0f, 0.0f, LINE_HALF_LENGTH }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
SHEventHandle SHEditor::onEditorStateChanged(SHEventPtr eventPtr)
|
||||
{
|
||||
auto eventData = reinterpret_cast<const SHEventSpec<SHEditorStateChangeEvent>*>(eventPtr.get());
|
||||
switch (editorState)
|
||||
{
|
||||
case State::PAUSE:
|
||||
case State::STOP:
|
||||
SetUpGridLines(true, true);
|
||||
break;
|
||||
case State::PLAY:
|
||||
default:
|
||||
SHDebugDraw::ClearPersistentDraws();
|
||||
break;
|
||||
}
|
||||
return eventData->handle;
|
||||
}
|
||||
|
||||
void SHEditor::Exit()
|
||||
{
|
||||
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
|
||||
|
@ -366,6 +530,66 @@ namespace SHADE
|
|||
}
|
||||
}
|
||||
|
||||
void SHEditor::NewScene()
|
||||
{
|
||||
if(shWindow->IsUnsavedChanges())
|
||||
{
|
||||
//Unsaved changes prompt
|
||||
sceneToLoad = 0;
|
||||
isUnsavedChangesPromptOpen = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
SHSceneManager::RestartScene(0);
|
||||
shWindow->ToggleUnsavedChanges();
|
||||
}
|
||||
}
|
||||
|
||||
bool SHEditor::SaveScene(std::string const& newSceneName)
|
||||
{
|
||||
auto const data = SHAssetManager::GetData<SHSceneAsset>(SHSceneManager::GetCurrentSceneAssetID());
|
||||
if (!data)
|
||||
{
|
||||
if (newSceneName.empty())
|
||||
{
|
||||
//Prompt for scene name
|
||||
isSceneNamePromptOpen = true;
|
||||
return false;
|
||||
}
|
||||
//Else We have a new name
|
||||
|
||||
SHSceneManager::SetCurrentSceneName(newSceneName);
|
||||
SHSceneManager::SetCurrentSceneAssetID(SHAssetManager::CreateNewAsset(AssetType::SCENE, newSceneName));
|
||||
}
|
||||
//Get data, if data is null, asset doesn't exist, prompt for a name and create a new asset with the name
|
||||
|
||||
//serialize the scene
|
||||
if(SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID()))
|
||||
{
|
||||
if(shWindow->IsUnsavedChanges())
|
||||
shWindow->ToggleUnsavedChanges();
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SHEditor::LoadScene(AssetID const& assetID) noexcept
|
||||
{
|
||||
if(shWindow->IsUnsavedChanges())
|
||||
{
|
||||
//Unsaved changes prompt
|
||||
isUnsavedChangesPromptOpen = true;
|
||||
sceneToLoad = assetID;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Load the scene
|
||||
sceneToLoad = 0;
|
||||
SHSceneManager::RestartScene(assetID);
|
||||
}
|
||||
}
|
||||
|
||||
void SHEditor::NewFrame()
|
||||
{
|
||||
SDL_Event event;
|
||||
|
|
|
@ -17,13 +17,17 @@
|
|||
#include "EditorWindow/SHEditorWindow.h"
|
||||
#include "Tools/SHLog.h"
|
||||
#include "Gizmos/SHTransformGizmo.h"
|
||||
|
||||
#include "Events/SHEventDefines.h"
|
||||
#include "Events/SHEvent.h"
|
||||
#include "Graphics/Windowing/SHWindow.h"
|
||||
|
||||
//#==============================================================#
|
||||
//|| Library Includes ||
|
||||
//#==============================================================#
|
||||
#include <SDL_video.h>
|
||||
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
//#==============================================================#
|
||||
|
@ -170,9 +174,16 @@ namespace SHADE
|
|||
void InitBackend();
|
||||
|
||||
void SetSDLWindow(SDL_Window* inSDLWindow){sdlWindow = inSDLWindow;};
|
||||
void SetSHWindow(SHWindow* inWindow){shWindow = inWindow;}
|
||||
|
||||
void PollPicking();
|
||||
|
||||
void NewScene();
|
||||
|
||||
bool SaveScene(std::string const& newSceneName = {});
|
||||
|
||||
void LoadScene(AssetID const& assetID) noexcept;
|
||||
|
||||
// List of selected entities
|
||||
std::vector<EntityID> selectedEntities;
|
||||
|
||||
|
@ -190,16 +201,34 @@ namespace SHADE
|
|||
*/
|
||||
void Render();
|
||||
|
||||
void RenderSceneNamePrompt() noexcept;
|
||||
|
||||
void RenderUnsavedChangesPrompt() noexcept;
|
||||
|
||||
void InitLayout() noexcept;
|
||||
|
||||
void InitFonts() noexcept;
|
||||
|
||||
void SetUpGridLines(bool drawGrid, bool drawAxes);
|
||||
|
||||
SHEventHandle onEditorStateChanged(SHEventPtr eventPtr);
|
||||
|
||||
bool isSceneNamePromptOpen = false;
|
||||
|
||||
bool isUnsavedChangesPromptOpen = false;
|
||||
|
||||
static constexpr std::string_view sceneNamePromptName = "Save scene as...";
|
||||
static constexpr std::string_view unsavedChangesPromptName = "Unsaved Changes";
|
||||
|
||||
AssetID sceneToLoad = 0;
|
||||
|
||||
// Handle to command pool used for ImGui Vulkan Backend
|
||||
Handle<SHVkCommandPool> imguiCommandPool;
|
||||
// Handle to command buffer used for ImGui Vulkan Backend
|
||||
Handle<SHVkCommandBuffer> imguiCommandBuffer;
|
||||
|
||||
SDL_Window* sdlWindow {nullptr};
|
||||
SHWindow* shWindow {nullptr};
|
||||
|
||||
ImGuiIO* io{nullptr};
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ namespace SHADE
|
|||
if (isHovered)
|
||||
*isHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
return ImGui::Checkbox("#", &value);
|
||||
return ImGui::Checkbox("##", &value);
|
||||
}
|
||||
bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered)
|
||||
{
|
||||
|
@ -165,7 +165,7 @@ namespace SHADE
|
|||
if (isHovered)
|
||||
*isHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputInt("#", &value,
|
||||
return ImGui::InputInt("##", &value,
|
||||
1, 10,
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
|
@ -176,7 +176,7 @@ namespace SHADE
|
|||
if (isHovered)
|
||||
*isHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
const bool CHANGED = InputInt("#", signedVal);
|
||||
const bool CHANGED = InputInt("##", signedVal);
|
||||
if (CHANGED)
|
||||
{
|
||||
signedVal = std::clamp(signedVal, 0, std::numeric_limits<int>::max());
|
||||
|
@ -190,7 +190,7 @@ namespace SHADE
|
|||
if (isHovered)
|
||||
*isHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputFloat("#", &value,
|
||||
return ImGui::InputFloat("##", &value,
|
||||
0.1f, 1.0f, "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ namespace SHADE
|
|||
if (isHovered)
|
||||
*isHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputDouble("#", &value,
|
||||
return ImGui::InputDouble("##", &value,
|
||||
0.1, 1.0, "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
|
@ -210,7 +210,7 @@ namespace SHADE
|
|||
if (isHovered)
|
||||
*isHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
return ImGui::InputDouble("#", &value,
|
||||
return ImGui::InputDouble("##", &value,
|
||||
1.0, 45.0, "%.3f",
|
||||
ImGuiInputTextFlags_EnterReturnsTrue);
|
||||
}
|
||||
|
@ -280,7 +280,7 @@ namespace SHADE
|
|||
if (isHovered)
|
||||
*isHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
const bool CHANGED = ImGui::InputText("#", &buffer[0], TEXT_FIELD_MAX_LENGTH);
|
||||
const bool CHANGED = ImGui::InputText("##", &buffer[0], TEXT_FIELD_MAX_LENGTH);
|
||||
if (CHANGED)
|
||||
{
|
||||
value = std::string(buffer.data(), buffer.data() + TEXT_FIELD_MAX_LENGTH);
|
||||
|
@ -327,7 +327,7 @@ namespace SHADE
|
|||
if (isHovered)
|
||||
*isHovered = ImGui::IsItemHovered();
|
||||
ImGui::SameLine();
|
||||
if (ImGui::BeginCombo("#", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
|
||||
if (ImGui::BeginCombo("##", INITIAL_NAME.c_str(), ImGuiComboFlags_None))
|
||||
{
|
||||
for (int i = 0; i < enumNames.size(); ++i)
|
||||
{
|
||||
|
|
|
@ -422,12 +422,13 @@ namespace SHADE
|
|||
ImGui::BeginGroup();
|
||||
ImGui::PushID(label.data());
|
||||
TextLabel(label);
|
||||
bool const changed = ImGui::InputText("##", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr);
|
||||
bool changed = ImGui::InputText("##", &text, ImGuiInputTextFlags_ReadOnly, nullptr, nullptr);
|
||||
if(SHDragDrop::BeginTarget())
|
||||
{
|
||||
if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag))
|
||||
{
|
||||
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), *payload, set)), false);
|
||||
changed = true;
|
||||
SHDragDrop::EndTarget();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,6 +64,11 @@ namespace SHADE
|
|||
return bufferUsageFlags;
|
||||
}
|
||||
|
||||
uint32_t SHVkBuffer::GetSizeStored(void) const noexcept
|
||||
{
|
||||
return sizeStored;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
|
||||
|
|
|
@ -104,6 +104,7 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------*/
|
||||
vk::Buffer GetVkBuffer (void) const noexcept;
|
||||
vk::BufferUsageFlags GetUsageBits(void) const noexcept;
|
||||
uint32_t GetSizeStored (void) const noexcept;
|
||||
|
||||
template <typename T>
|
||||
T GetDataFromMappedPointer(uint32_t index) const noexcept
|
||||
|
|
|
@ -119,6 +119,18 @@ namespace SHADE
|
|||
return setIndex;
|
||||
}
|
||||
|
||||
uint32_t SHVkDescriptorSetLayout::GetNumDynamicOffsetsRequired(void) const noexcept
|
||||
{
|
||||
uint32_t numDynamicBindings = 0;
|
||||
for (auto& binding : layoutDesc)
|
||||
{
|
||||
if (binding.Type == vk::DescriptorType::eUniformBufferDynamic || binding.Type == vk::DescriptorType::eStorageBufferDynamic)
|
||||
++numDynamicBindings;
|
||||
}
|
||||
|
||||
return numDynamicBindings;
|
||||
}
|
||||
|
||||
SHVkDescriptorSetLayout& SHVkDescriptorSetLayout::operator=(SHVkDescriptorSetLayout&& rhs) noexcept
|
||||
{
|
||||
if (&rhs == this)
|
||||
|
|
|
@ -99,6 +99,7 @@ namespace SHADE
|
|||
inline const vk::DescriptorSetLayout& GetVkHandle() const { return setLayout; }
|
||||
std::vector<Binding> const& GetBindings (void) const noexcept;
|
||||
SetIndex GetSetIndex (void) const noexcept;
|
||||
uint32_t GetNumDynamicOffsetsRequired (void) const noexcept;
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -88,6 +88,7 @@ namespace SHADE
|
|||
/* Getter Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; };
|
||||
bool IsEmpty() const noexcept { return subBatches.empty(); }
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -68,6 +68,10 @@ namespace SHADE
|
|||
return;
|
||||
|
||||
batch->Remove(renderable);
|
||||
|
||||
// If batch is empty, remove batch
|
||||
if (batch->IsEmpty())
|
||||
batches.erase(batch);
|
||||
}
|
||||
|
||||
void SHSuperBatch::Clear() noexcept
|
||||
|
|
|
@ -79,7 +79,7 @@ namespace SHADE
|
|||
SHVkDescriptorSetLayout::Binding cameraDataBinding
|
||||
{
|
||||
.Type = vk::DescriptorType::eUniformBufferDynamic,
|
||||
.Stage = vk::ShaderStageFlagBits::eVertex,
|
||||
.Stage = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eCompute,
|
||||
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA,
|
||||
.DescriptorCount = 1,
|
||||
};
|
||||
|
|
|
@ -14,7 +14,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
// STL Includes
|
||||
#include <algorithm>
|
||||
// Project Includes
|
||||
#include "../Meshes/SHMeshData.h"
|
||||
#include "Assets/Asset Types/SHModelAsset.h"
|
||||
#include "../Meshes/SHPrimitiveGenerator.h"
|
||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||
#include "SHGraphicsSystem.h"
|
||||
|
@ -43,11 +43,14 @@ namespace SHADE
|
|||
return;
|
||||
}
|
||||
|
||||
// Get the system
|
||||
SHDebugDrawSystem* system = static_cast<SHDebugDrawSystem*>(GetSystem());
|
||||
|
||||
// Get current frame index
|
||||
const uint32_t FRAME_IDX = gfxSys->GetCurrentFrameIndex();
|
||||
|
||||
// Create the buffer if it doesn't exist or just update it
|
||||
SHDebugDrawSystem* system = static_cast<SHDebugDrawSystem*>(GetSystem());
|
||||
/* Non-Persistent Buffer */
|
||||
// Update the buffer
|
||||
system->numPoints[FRAME_IDX] = system->points.size();
|
||||
const uint32_t DATA_SIZE = sizeof(PointVertex) * system->points.size();
|
||||
if (DATA_SIZE > 0)
|
||||
|
@ -57,6 +60,24 @@ namespace SHADE
|
|||
|
||||
// Reset for next frame
|
||||
system->points.clear();
|
||||
|
||||
/* Persistent Buffer */
|
||||
// Check if there are changes
|
||||
if (system->persistentBuffersCleared[FRAME_IDX]
|
||||
||
|
||||
system->numPersistentPoints[FRAME_IDX] != system->persistentPoints.size())
|
||||
{
|
||||
// Update Buffer
|
||||
system->numPersistentPoints[FRAME_IDX] = system->persistentPoints.size();
|
||||
const uint32_t DATA_SIZE = sizeof(PointVertex) * system->persistentPoints.size();
|
||||
if (DATA_SIZE > 0)
|
||||
{
|
||||
system->persistentVertexBuffers[FRAME_IDX]->WriteToMemory(system->persistentPoints.data(), DATA_SIZE, 0, 0);
|
||||
}
|
||||
|
||||
// Reset Flag
|
||||
system->persistentBuffersCleared[FRAME_IDX] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -75,19 +96,38 @@ namespace SHADE
|
|||
const uint32_t FRAME_IDX = GFX_SYSTEM->GetCurrentFrameIndex();
|
||||
|
||||
// Don't draw if no points
|
||||
if (numPoints[FRAME_IDX] <= 0)
|
||||
return;
|
||||
|
||||
if (numPoints[FRAME_IDX] > 0)
|
||||
{
|
||||
cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawPipeline());
|
||||
cmdBuffer->SetLineWidth(LineWidth);
|
||||
cmdBuffer->BindVertexBuffer(0, vertexBuffers[FRAME_IDX], 0);
|
||||
cmdBuffer->DrawArrays(numPoints[FRAME_IDX], 1, 0, 0);
|
||||
}
|
||||
});
|
||||
auto subPassWithDepth = renderGraph->GetNode("Debug Draw with Depth")->GetSubpass("Debug Draw with Depth");
|
||||
subPassWithDepth->AddExteriorDrawCalls([this, GFX_SYSTEM](Handle<SHVkCommandBuffer>& cmdBuffer)
|
||||
{
|
||||
// Get Current frame index
|
||||
const uint32_t FRAME_IDX = GFX_SYSTEM->GetCurrentFrameIndex();
|
||||
|
||||
// Don't draw if no points
|
||||
if (numPersistentPoints[FRAME_IDX] > 0)
|
||||
{
|
||||
cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawDepthPipeline());
|
||||
cmdBuffer->SetLineWidth(LineWidth);
|
||||
cmdBuffer->BindVertexBuffer(0, persistentVertexBuffers[FRAME_IDX], 0);
|
||||
cmdBuffer->DrawArrays(numPersistentPoints[FRAME_IDX], 1, 0, 0);
|
||||
}
|
||||
});
|
||||
|
||||
// Reset trackers
|
||||
std::fill_n(numPoints.begin(), numPoints.size(), 0);
|
||||
std::fill_n(numPersistentPoints.begin(), numPersistentPoints.size(), 0);
|
||||
for (bool& cleared : persistentBuffersCleared)
|
||||
cleared = true;
|
||||
|
||||
// Allocate buffers
|
||||
// - Non-Persistent Draws
|
||||
static constexpr uint32_t BUFFER_SIZE = MAX_POINTS * sizeof(PointVertex);
|
||||
for (Handle<SHVkBuffer>& bufHandle : vertexBuffers)
|
||||
{
|
||||
|
@ -101,6 +141,19 @@ namespace SHADE
|
|||
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT
|
||||
);
|
||||
}
|
||||
// - Persistent Draws
|
||||
for (Handle<SHVkBuffer>& bufHandle : persistentVertexBuffers)
|
||||
{
|
||||
bufHandle = GFX_SYSTEM->GetDevice()->CreateBuffer
|
||||
(
|
||||
BUFFER_SIZE,
|
||||
nullptr,
|
||||
0,
|
||||
vk::BufferUsageFlagBits::eVertexBuffer,
|
||||
VmaMemoryUsage::VMA_MEMORY_USAGE_AUTO,
|
||||
VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT | VmaAllocationCreateFlagBits::VMA_ALLOCATION_CREATE_MAPPED_BIT
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::Exit()
|
||||
|
@ -110,6 +163,11 @@ namespace SHADE
|
|||
if (vertexBuffer)
|
||||
vertexBuffer.Free();
|
||||
}
|
||||
for (auto vertexBuffer : persistentVertexBuffers)
|
||||
{
|
||||
if (vertexBuffer)
|
||||
vertexBuffer.Free();
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -117,42 +175,107 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
void SHDebugDrawSystem::DrawLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt)
|
||||
{
|
||||
if (points.size() > MAX_POINTS)
|
||||
drawLine(points, color, startPt, endPt);
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3)
|
||||
{
|
||||
drawPoly(points, color, { pt1, pt2, pt3 });
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4)
|
||||
{
|
||||
drawPoly(points, color, { pt1, pt2, pt3, pt4 });
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList)
|
||||
{
|
||||
drawPoly(points, color, pointList.begin(), pointList.end());
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size)
|
||||
{
|
||||
drawCube(points, color, pos, size);
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawSphere(const SHVec4& color, const SHVec3& pos, double radius)
|
||||
{
|
||||
drawSphere(points, color, pos, radius);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Persistent Draw Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void SHDebugDrawSystem::DrawPersistentLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt)
|
||||
{
|
||||
drawLine(persistentPoints, color, startPt, endPt);
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawPersistentTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3)
|
||||
{
|
||||
drawPoly(persistentPoints, color, { pt1, pt2, pt3 });
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawPersistentQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4)
|
||||
{
|
||||
drawPoly(persistentPoints, color, { pt1, pt2, pt3, pt4 });
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawPersistentPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList)
|
||||
{
|
||||
drawPoly(persistentPoints, color, pointList.begin(), pointList.end());
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawPersistentCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size)
|
||||
{
|
||||
drawCube(persistentPoints, color, pos, size);
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawPersistentSphere(const SHVec4& color, const SHVec3& pos, double radius)
|
||||
{
|
||||
drawSphere(persistentPoints, color, pos, radius);
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::ClearPersistentDraws()
|
||||
{
|
||||
persistentPoints.clear();
|
||||
for (bool& cleared : persistentBuffersCleared)
|
||||
cleared = true;
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::drawLine(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt)
|
||||
{
|
||||
if (storage.size() > MAX_POINTS)
|
||||
{
|
||||
SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements.");
|
||||
return;
|
||||
}
|
||||
|
||||
points.emplace_back(PointVertex{ startPt, color });
|
||||
points.emplace_back(PointVertex{ endPt, color });
|
||||
storage.emplace_back(PointVertex{ startPt, color });
|
||||
storage.emplace_back(PointVertex{ endPt, color });
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3)
|
||||
void SHDebugDrawSystem::drawLineSet(std::vector<PointVertex>& storage, const SHVec4& color, std::initializer_list<SHVec3> pointList)
|
||||
{
|
||||
DrawPoly(color, { pt1, pt2, pt3 });
|
||||
drawLineSet(storage, color, pointList.begin(), pointList.end());
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4)
|
||||
void SHDebugDrawSystem::drawPoly(std::vector<PointVertex>& storage, const SHVec4& color, std::initializer_list<SHVec3> pointList)
|
||||
{
|
||||
DrawPoly(color, { pt1, pt2, pt3, pt4 });
|
||||
drawPoly(storage, color, pointList.begin(), pointList.end());
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList)
|
||||
void SHDebugDrawSystem::drawCube(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, const SHVec3& size)
|
||||
{
|
||||
DrawPoly(color, pointList.begin(), pointList.end());
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size)
|
||||
{
|
||||
static const SHVec3 EXTENTS = SHVec3 { 0.5f, 0.5f, 0.5f };
|
||||
static const SHVec3 UNIT_BOT_LEFT_FRONT = SHVec3 { pos - EXTENTS };
|
||||
static const SHVec3 UNIT_BOT_RIGHT_FRONT = SHVec3 { pos + SHVec3 { EXTENTS.x, -EXTENTS.y, -EXTENTS.z } };
|
||||
static const SHVec3 UNIT_BOT_RIGHT_BACK = SHVec3 { pos + SHVec3 { EXTENTS.x, -EXTENTS.y, EXTENTS.z } };
|
||||
static const SHVec3 UNIT_BOT_LEFT_BACK = SHVec3 { pos + SHVec3 { -EXTENTS.x, -EXTENTS.y, EXTENTS.z } };
|
||||
static const SHVec3 UNIT_TOP_LEFT_BACK = SHVec3 { pos + SHVec3 { -EXTENTS.x, EXTENTS.y, EXTENTS.z } };
|
||||
static const SHVec3 UNIT_TOP_RIGHT_FRONT = SHVec3 { pos + SHVec3 { EXTENTS.x, EXTENTS.y, -EXTENTS.z } };
|
||||
static const SHVec3 UNIT_TOP_LEFT_FRONT = SHVec3 { pos + SHVec3 { -EXTENTS.x, EXTENTS.y, -EXTENTS.z } };
|
||||
static const SHVec3 UNIT_TOP_RIGHT_BACK = SHVec3 { pos + EXTENTS };
|
||||
static const SHVec3 EXTENTS = SHVec3{ 0.5f, 0.5f, 0.5f };
|
||||
static const SHVec3 UNIT_BOT_LEFT_FRONT = SHVec3{ pos - EXTENTS };
|
||||
static const SHVec3 UNIT_BOT_RIGHT_FRONT = SHVec3{ pos + SHVec3 { EXTENTS.x, -EXTENTS.y, -EXTENTS.z } };
|
||||
static const SHVec3 UNIT_BOT_RIGHT_BACK = SHVec3{ pos + SHVec3 { EXTENTS.x, -EXTENTS.y, EXTENTS.z } };
|
||||
static const SHVec3 UNIT_BOT_LEFT_BACK = SHVec3{ pos + SHVec3 { -EXTENTS.x, -EXTENTS.y, EXTENTS.z } };
|
||||
static const SHVec3 UNIT_TOP_LEFT_BACK = SHVec3{ pos + SHVec3 { -EXTENTS.x, EXTENTS.y, EXTENTS.z } };
|
||||
static const SHVec3 UNIT_TOP_RIGHT_FRONT = SHVec3{ pos + SHVec3 { EXTENTS.x, EXTENTS.y, -EXTENTS.z } };
|
||||
static const SHVec3 UNIT_TOP_LEFT_FRONT = SHVec3{ pos + SHVec3 { -EXTENTS.x, EXTENTS.y, -EXTENTS.z } };
|
||||
static const SHVec3 UNIT_TOP_RIGHT_BACK = SHVec3{ pos + EXTENTS };
|
||||
|
||||
const SHVec3 BOT_LEFT_BACK = UNIT_BOT_LEFT_BACK * size;
|
||||
const SHVec3 BOT_RIGHT_BACK = UNIT_BOT_RIGHT_BACK * size;
|
||||
|
@ -163,8 +286,9 @@ namespace SHADE
|
|||
const SHVec3 TOP_LEFT_FRONT = UNIT_TOP_LEFT_FRONT * size;
|
||||
const SHVec3 TOP_RIGHT_FRONT = UNIT_TOP_RIGHT_FRONT * size;
|
||||
|
||||
DrawPoly
|
||||
drawLineSet
|
||||
(
|
||||
storage,
|
||||
color,
|
||||
{
|
||||
// Bottom Square
|
||||
|
@ -186,7 +310,7 @@ namespace SHADE
|
|||
);
|
||||
}
|
||||
|
||||
void SHDebugDrawSystem::DrawSphere(const SHVec4& color, const SHVec3& pos, double radius)
|
||||
void SHDebugDrawSystem::drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, double radius)
|
||||
{
|
||||
if (spherePoints.empty())
|
||||
{
|
||||
|
@ -197,6 +321,6 @@ namespace SHADE
|
|||
spherePoints.emplace_back(SPHERE.VertexPositions[idx]);
|
||||
}
|
||||
}
|
||||
DrawPoly(color, spherePoints.begin(), spherePoints.end());
|
||||
drawLineSet(storage, color, spherePoints.begin(), spherePoints.end());
|
||||
}
|
||||
}
|
|
@ -126,6 +126,82 @@ namespace SHADE
|
|||
/// <param name="size">Size of the rendered sphere.</param>
|
||||
void DrawSphere(const SHVec4& color, const SHVec3& pos, double radius);
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Persistent Draw Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/// <summary>
|
||||
/// Renders a line between two points in world space that will persist until
|
||||
/// ClearPersistentDraws() is called. These lines are depth tested.
|
||||
/// </summary>
|
||||
/// <param name="color">Colour of the line.</param>
|
||||
/// <param name="startPt">First point of the line.</param>
|
||||
/// <param name="endPt">Second point of the line.</param>
|
||||
void DrawPersistentLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt);
|
||||
/// <summary>
|
||||
/// Renders a triangle indicated by three points in world space that will persist
|
||||
/// until ClearPersistentDraws() is called. These lines are depth tested.
|
||||
/// </summary>
|
||||
/// <param name="color">Colour of the triangle.</param>
|
||||
/// <param name="pt1">First point of the triangle.</param>
|
||||
/// <param name="pt2">Second point of the triangle.</param>
|
||||
/// <param name="pt3">Third point of the triangle.</param>
|
||||
void DrawPersistentTri(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3);
|
||||
/// <summary>
|
||||
/// Renders a quadrilateral indicated by four points in world space that will persist
|
||||
/// until ClearPersistentDraws() is called. These lines are depth tested.
|
||||
/// </summary>
|
||||
/// <param name="color">Colour of the quadrilateral.</param>
|
||||
/// <param name="pt1">First point of the triangle.</param>
|
||||
/// <param name="pt2">Second point of the quadrilateral.</param>
|
||||
/// <param name="pt3">Third point of the quadrilateral.</param>
|
||||
/// <param name="pt4">Third point of the quadrilateral.</param>
|
||||
void DrawPersistentQuad(const SHVec4& color, const SHVec3& pt1, const SHVec3& pt2, const SHVec3& pt3, const SHVec3& pt4);
|
||||
/// <summary>
|
||||
/// Renders a polygon indicated by the specified set of points in world space that
|
||||
/// will persist until ClearPersistentDraws() is called. These lines are depth
|
||||
/// tested.
|
||||
/// </summary>
|
||||
/// <param name="color">Colour of the polygon.</param>
|
||||
/// <param name="pointList">List of points for the polygon.</param>
|
||||
void DrawPersistentPoly(const SHVec4& color, std::initializer_list<SHVec3> pointList);
|
||||
/// <summary>
|
||||
/// Renders a polygon indicated by the specified set of points in world space that
|
||||
/// will persist until ClearPersistentDraws() is called. These lines are depth
|
||||
/// tested.
|
||||
/// </summary>
|
||||
/// <typeparam name="IterType">Iterator for a STL-like container.</typeparam>
|
||||
/// <param name="color">Colour of the polygon.</param>
|
||||
/// <param name="pointListBegin">
|
||||
/// Iterator to the first point of the point container.
|
||||
/// </param>
|
||||
/// <param name="pointListEnd">
|
||||
/// One past last iterator of the point container.
|
||||
/// </param>
|
||||
template<typename IterType>
|
||||
void DrawPersistentPoly(const SHVec4& color, IterType pointListBegin, IterType pointListEnd);
|
||||
/// <summary>
|
||||
/// Renders a wireframe cube centered around the position specified in world space
|
||||
/// that will persist until ClearPersistentDraws() is called. These lines are depth
|
||||
/// tested.
|
||||
/// </summary>
|
||||
/// <param name="color">Colour of the cube.</param>
|
||||
/// <param name="pos">Position where the cube wil be centered at.</param>
|
||||
/// <param name="size">Size of the rendered cube.</param>
|
||||
void DrawPersistentCube(const SHVec4& color, const SHVec3& pos, const SHVec3& size);
|
||||
/// <summary>
|
||||
/// Renders a wireframe sphere centered around the position specified in world space
|
||||
/// that will persist until ClearPersistentDraws() is called. These lines are depth
|
||||
/// tested.
|
||||
/// </summary>
|
||||
/// <param name="color">Colour of the sphere.</param>
|
||||
/// <param name="pos">Position where the sphere wil be centered at.</param>
|
||||
/// <param name="size">Size of the rendered sphere.</param>
|
||||
void DrawPersistentSphere(const SHVec4& color, const SHVec3& pos, double radius);
|
||||
/// <summary>
|
||||
/// Clears any persistent drawn debug primitives.
|
||||
/// </summary>
|
||||
void ClearPersistentDraws();
|
||||
|
||||
private:
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
|
@ -136,7 +212,8 @@ namespace SHADE
|
|||
SHVec4 Color;
|
||||
};
|
||||
using TripleBuffer = std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||
using TripleUInt = std::array<uint32_t, SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||
using TripleUInt = std::array<uint32_t , SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||
using TripleBool = std::array<bool , SHGraphicsConstants::NUM_FRAME_BUFFERS>;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constants */
|
||||
|
@ -148,11 +225,28 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
// CPU Buffers
|
||||
std::vector<PointVertex> points;
|
||||
std::vector<PointVertex> persistentPoints;
|
||||
// GPU Buffers
|
||||
TripleBuffer vertexBuffers;
|
||||
TripleUInt numPoints;
|
||||
TripleBuffer persistentVertexBuffers;
|
||||
TripleUInt numPersistentPoints;
|
||||
TripleBool persistentBuffersCleared;
|
||||
// Cached Points for polygon drawing
|
||||
std::vector<SHVec3> spherePoints;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Draw Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
void drawLine(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt);
|
||||
void drawLineSet(std::vector<PointVertex>& storage, const SHVec4& color, std::initializer_list<SHVec3> pointList);
|
||||
template<typename IterType>
|
||||
void drawLineSet(std::vector<PointVertex>& storage, const SHVec4& color, IterType pointListBegin, IterType pointListEnd);
|
||||
void drawPoly(std::vector<PointVertex>& storage, const SHVec4& color, std::initializer_list<SHVec3> pointList);
|
||||
template<typename IterType>
|
||||
void drawPoly(std::vector<PointVertex>& storage, const SHVec4& color, IterType pointListBegin, IterType pointListEnd);
|
||||
void drawCube(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, const SHVec3& size);
|
||||
void drawSphere(std::vector<PointVertex>& storage, const SHVec4& color, const SHVec3& pos, double radius);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -20,12 +20,21 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------------*/
|
||||
template<typename IterType>
|
||||
void SHDebugDrawSystem::DrawPoly(const SHVec4& color, IterType pointListBegin, IterType pointListEnd)
|
||||
{
|
||||
drawPoly(points, color, pointListBegin, pointListEnd);
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Helper Draw Functions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
template<typename IterType>
|
||||
void SHDebugDrawSystem::drawLineSet(std::vector<PointVertex>& storage, const SHVec4& color, IterType pointListBegin, IterType pointListEnd)
|
||||
{
|
||||
// Ensure dereferenced type is SHVec3
|
||||
static_assert(std::is_same_v<SHVec3, std::remove_cvref_t<decltype(*pointListBegin)>>, "Parameters to DrawPoly must be SHVec3.");
|
||||
|
||||
// Check if points exceeded max
|
||||
if (points.size() > MAX_POINTS)
|
||||
if (storage.size() > MAX_POINTS)
|
||||
{
|
||||
SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements.");
|
||||
return;
|
||||
|
@ -42,7 +51,39 @@ namespace SHADE
|
|||
const size_t POINTS_ROUNDED_COUNT = POINTS_COUNT / 2 * 2;
|
||||
for (auto pointIter = pointListBegin; pointIter != (pointListBegin + POINTS_ROUNDED_COUNT); ++pointIter)
|
||||
{
|
||||
points.emplace_back(PointVertex{ *pointIter, color });
|
||||
storage.emplace_back(PointVertex{ *pointIter, color });
|
||||
}
|
||||
}
|
||||
template<typename IterType>
|
||||
void SHDebugDrawSystem::drawPoly(std::vector<PointVertex>& storage, const SHVec4& color, IterType pointListBegin, IterType pointListEnd)
|
||||
{
|
||||
// Ensure dereferenced type is SHVec3
|
||||
static_assert(std::is_same_v<SHVec3, std::remove_cvref_t<decltype(*pointListBegin)>>, "Parameters to DrawPoly must be SHVec3.");
|
||||
|
||||
// Check if points exceeded max
|
||||
if (storage.size() > MAX_POINTS)
|
||||
{
|
||||
SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements.");
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t POINTS_COUNT = pointListEnd - pointListBegin;
|
||||
// Invalid polygon
|
||||
if (POINTS_COUNT < 2)
|
||||
{
|
||||
SHLOG_WARNING("[SHDebugDraw] Invalid polygon provided to DrawPoly().");
|
||||
return;
|
||||
}
|
||||
|
||||
// Trace the polygon
|
||||
for (auto pointIter = pointListBegin + 1; pointIter != pointListEnd; ++pointIter)
|
||||
{
|
||||
storage.emplace_back(PointVertex{ *(pointIter - 1), color });
|
||||
storage.emplace_back(PointVertex{ *pointIter , color });
|
||||
}
|
||||
|
||||
// Close the line loop
|
||||
storage.emplace_back(PointVertex{ *(pointListEnd - 1), color });
|
||||
storage.emplace_back(PointVertex{ *pointListBegin , color });
|
||||
}
|
||||
}
|
|
@ -70,7 +70,17 @@ namespace SHADE
|
|||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t RENDERGRAPH_RESOURCE = 4;
|
||||
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
DescriptorSet Index for render graph node compute resources. For data
|
||||
that we wish to pass to compute shaders in the render graph, this is
|
||||
the set to use. Unlike the sets from 1 to 3, this set index does not have
|
||||
hard coded bindings and is NOT part of the layouts included in the global
|
||||
data.
|
||||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t RENDERGRAPH_NODE_COMPUTE_RESOURCE = 5;
|
||||
|
||||
};
|
||||
|
||||
|
@ -119,6 +129,7 @@ namespace SHADE
|
|||
*/
|
||||
/***************************************************************************/
|
||||
static constexpr uint32_t BATCHED_PER_INST_DATA = 0;
|
||||
|
||||
};
|
||||
|
||||
struct VertexBufferBindings
|
||||
|
|
|
@ -40,6 +40,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "Assets/SHAssetManager.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
#include "Graphics/SHVkUtil.h"
|
||||
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
|
||||
#include "../Meshes/SHPrimitiveGenerator.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -51,7 +53,11 @@ namespace SHADE
|
|||
/* BACKEND BOILERPLATE */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Set Up Instance
|
||||
#ifdef _DEBUG
|
||||
SHVkInstance::Init(true, true, true);
|
||||
#else
|
||||
SHVkInstance::Init(true, false, true);
|
||||
#endif
|
||||
|
||||
// Get Physical Device and Construct Logical Device
|
||||
physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST);
|
||||
|
@ -115,6 +121,8 @@ namespace SHADE
|
|||
static constexpr AssetID VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG);
|
||||
static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_DEBUG);
|
||||
static constexpr AssetID CS_COMPOSITE = 45072428; deferredCompositeShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(CS_COMPOSITE);
|
||||
static constexpr AssetID SSAO = 38430899; ssaoShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO);
|
||||
static constexpr AssetID SSAO_BLUR = 39760835; ssaoBlurShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(SSAO_BLUR);
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
|
||||
|
@ -153,109 +161,117 @@ namespace SHADE
|
|||
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SCENE RENDER GRAPH RESOURCES */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Initialize world render graph
|
||||
worldRenderGraph->Init(device, swapchain);
|
||||
worldRenderGraph->AddResource("Position", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
worldRenderGraph->AddResource("Normals", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
//worldRenderGraph->AddResource("Tangents", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32G32B32A32Sfloat);
|
||||
worldRenderGraph->AddResource("Albedo", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||
worldRenderGraph->AddResource("Depth Buffer", { SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL }, windowDims.first, windowDims.second, vk::Format::eD32SfloatS8Uint);
|
||||
worldRenderGraph->AddResource("Entity ID", { SH_ATT_DESC_TYPE_FLAGS::COLOR }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
worldRenderGraph->AddResource("Light Layer Indices", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR32Uint, 1, vk::ImageUsageFlagBits::eTransferSrc);
|
||||
worldRenderGraph->AddResource("Scene", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second);
|
||||
worldRenderGraph->AddResource("SSAO", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
|
||||
worldRenderGraph->AddResource("SSAO Blur", { SH_ATT_DESC_TYPE_FLAGS::COLOR, SH_ATT_DESC_TYPE_FLAGS::INPUT, SH_ATT_DESC_TYPE_FLAGS::STORAGE }, windowDims.first, windowDims.second, vk::Format::eR8Unorm);
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* MAIN NODE */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
auto gBufferNode = worldRenderGraph->AddNode("G-Buffer",
|
||||
{
|
||||
"Position",
|
||||
"Entity ID",
|
||||
"Light Layer Indices",
|
||||
"Normals",
|
||||
//"Tangents",
|
||||
"Albedo",
|
||||
"Depth Buffer",
|
||||
"Scene"
|
||||
"Scene",
|
||||
"SSAO",
|
||||
"SSAO Blur"
|
||||
},
|
||||
{}); // no predecessors
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* G-BUFFER SUBPASS INIT */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write");
|
||||
gBufferSubpass->AddColorOutput("Position");
|
||||
gBufferSubpass->AddColorOutput("Entity ID");
|
||||
gBufferSubpass->AddColorOutput("Light Layer Indices");
|
||||
gBufferSubpass->AddColorOutput("Normals");
|
||||
//gBufferSubpass->AddColorOutput("Tangents");
|
||||
gBufferSubpass->AddColorOutput("Albedo");
|
||||
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL);
|
||||
|
||||
// deferred composite
|
||||
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "Scene" });
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* SSAO PASS AND DATA INIT */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
ssaoStorage = resourceManager.Create<SHSSAO>();
|
||||
|
||||
// Set up Debug Draw Pass
|
||||
auto debugDrawNode = worldRenderGraph->AddNode("Debug Draw", { "Scene" }, {"G-Buffer"});
|
||||
ssaoTransferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
|
||||
ssaoTransferCmdBuffer->BeginRecording();
|
||||
|
||||
ssaoStorage->Init(device, ssaoTransferCmdBuffer);
|
||||
|
||||
ssaoTransferCmdBuffer->EndRecording();
|
||||
graphicsQueue->SubmitCommandBuffer({ ssaoTransferCmdBuffer });
|
||||
// Set up Debug Draw Passes
|
||||
// - Depth Tested
|
||||
auto debugDrawNodeDepth = worldRenderGraph->AddNode("Debug Draw with Depth", { "Scene", "Depth Buffer" }, {"G-Buffer"});
|
||||
auto debugDrawDepthSubpass = debugDrawNodeDepth->AddSubpass("Debug Draw with Depth");
|
||||
debugDrawDepthSubpass->AddColorOutput("Scene");
|
||||
debugDrawDepthSubpass->AddDepthOutput("Depth Buffer");
|
||||
// - No Depth Test
|
||||
auto debugDrawNode = worldRenderGraph->AddNode("Debug Draw", { "Scene" }, { "Debug Draw with Depth" });
|
||||
auto debugDrawSubpass = debugDrawNode->AddSubpass("Debug Draw");
|
||||
debugDrawSubpass->AddColorOutput("Scene");
|
||||
|
||||
graphicsQueue->WaitIdle();
|
||||
|
||||
ssaoStorage->PrepareRotationVectorsVkData(device);
|
||||
|
||||
Handle<SHRenderGraphNodeCompute> ssaoPass = gBufferNode->AddNodeCompute(ssaoShader, {"Position", "Normals", "SSAO"});
|
||||
auto ssaoDataBuffer = ssaoStorage->GetBuffer();
|
||||
ssaoPass->ModifyWriteDescBufferComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_BUFFER_BINDING, { &ssaoDataBuffer, 1 }, 0, ssaoStorage->GetBuffer()->GetSizeStored());
|
||||
auto viewSamplerLayout = ssaoStorage->GetViewSamplerLayout();
|
||||
|
||||
ssaoPass->ModifyWriteDescImageComputeResource(SHGraphicsConstants::DescriptorSetIndex::RENDERGRAPH_NODE_COMPUTE_RESOURCE, SHSSAO::DESC_SET_IMAGE_BINDING, {&viewSamplerLayout, 1});
|
||||
|
||||
|
||||
Handle<SHRenderGraphNodeCompute> ssaoBlurPass = gBufferNode->AddNodeCompute(ssaoBlurShader, { "SSAO", "SSAO Blur"});
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* DEFERRED COMPOSITE SUBPASS INIT */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
gBufferNode->AddNodeCompute(deferredCompositeShader, { "Position", "Normals", "Albedo", "Light Layer Indices", "SSAO Blur", "Scene" });
|
||||
|
||||
// Dummy Node
|
||||
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Debug Draw" }); // no predecessors
|
||||
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
|
||||
dummySubpass->AddInput("Scene");
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* GENERATE RENDER GRAPH */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Generate world render graph
|
||||
worldRenderGraph->Generate();
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* BIND RENDER GRAPH TO RENDERER */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
// Add world renderer to default viewport
|
||||
worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
|
||||
worldRenderer->SetCamera(worldCamera);
|
||||
|
||||
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
|
||||
|
||||
// Create default materials
|
||||
defaultMaterial = AddMaterial(defaultVertShader, defaultFragShader, gBufferSubpass);
|
||||
|
||||
// Create debug draw pipeline
|
||||
auto debugDrawPipelineLayout = resourceManager.Create<SHVkPipelineLayout>
|
||||
(
|
||||
device, SHPipelineLayoutParams
|
||||
{
|
||||
.shaderModules = { debugVertShader, debugFragShader },
|
||||
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
|
||||
}
|
||||
);
|
||||
debugDrawPipeline = resourceManager.Create<SHVkPipeline>(device, debugDrawPipelineLayout, nullptr, debugDrawNode->GetRenderpass(), debugDrawSubpass);
|
||||
debugDrawPipeline->GetPipelineState().SetRasterizationState(SHRasterizationState
|
||||
{
|
||||
.polygonMode = vk::PolygonMode::eLine,
|
||||
.cull_mode = vk::CullModeFlagBits::eNone
|
||||
});
|
||||
debugDrawPipeline->GetPipelineState().SetInputAssemblyState(SHInputAssemblyState
|
||||
{
|
||||
.topology = vk::PrimitiveTopology::eLineList
|
||||
});
|
||||
|
||||
SHVertexInputState debugDrawVertexInputState;
|
||||
debugDrawVertexInputState.AddBinding(false, true, { SHVertexAttribute(SHAttribFormat::FLOAT_4D), SHVertexAttribute(SHAttribFormat::FLOAT_4D) });
|
||||
debugDrawPipeline->GetPipelineState().SetVertexInputState(debugDrawVertexInputState);
|
||||
SHColorBlendState colorBlendState{};
|
||||
colorBlendState.logic_op_enable = VK_FALSE;
|
||||
colorBlendState.logic_op = vk::LogicOp::eCopy;
|
||||
|
||||
auto const& subpassColorReferences = debugDrawSubpass->GetColorAttachmentReferences();
|
||||
colorBlendState.attachments.reserve(subpassColorReferences.size());
|
||||
|
||||
for (auto& att : subpassColorReferences)
|
||||
{
|
||||
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
|
||||
{
|
||||
.blendEnable = SHVkUtil::IsBlendCompatible(debugDrawSubpass->GetFormatFromAttachmentReference(att.attachment)),
|
||||
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
|
||||
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
|
||||
.colorBlendOp = vk::BlendOp::eAdd,
|
||||
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
|
||||
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
|
||||
.alphaBlendOp = vk::BlendOp::eAdd,
|
||||
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
debugDrawPipeline->GetPipelineState().SetColorBlenState(colorBlendState);
|
||||
debugDrawPipeline->ConstructPipeline();
|
||||
debugDrawPipeline = createDebugDrawPipeline(debugDrawNode->GetRenderpass(), debugDrawSubpass);
|
||||
debugDrawDepthPipeline = createDebugDrawPipeline(debugDrawNodeDepth->GetRenderpass(), debugDrawDepthSubpass);
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::InitMiddleEnd(void) noexcept
|
||||
|
@ -296,6 +312,29 @@ namespace SHADE
|
|||
lightingSubSystem->Init(device, descPool);
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::InitBuiltInResources(void)
|
||||
{
|
||||
// Create default texture
|
||||
std::array<SHTexture::PixelChannel, 4> defaultTextureData = { 255, 255, 255, 255 };
|
||||
std::vector<uint32_t> mipOffsets{};
|
||||
mipOffsets.push_back(0);
|
||||
defaultTexture = AddTexture(4, defaultTextureData.data(), 1, 1, SHTexture::TextureFormat::eR8G8B8A8Unorm, mipOffsets);
|
||||
BuildTextures();
|
||||
|
||||
// Create default meshes
|
||||
primitiveMeshes[static_cast<int>(PrimitiveType::Cube)] = SHPrimitiveGenerator::Cube(meshLibrary);
|
||||
primitiveMeshes[static_cast<int>(PrimitiveType::Sphere)] = SHPrimitiveGenerator::Sphere(meshLibrary);
|
||||
BuildMeshBuffers();
|
||||
|
||||
// Create default materials
|
||||
defaultMaterial = AddMaterial
|
||||
(
|
||||
defaultVertShader, defaultFragShader,
|
||||
worldRenderGraph->GetNode("G-Buffer")->GetSubpass("G-Buffer Write")
|
||||
);
|
||||
defaultMaterial->SetProperty("data.textureIndex", defaultTexture->TextureArrayIndex);
|
||||
}
|
||||
|
||||
#ifdef SHEDITOR
|
||||
void SHGraphicsSystem::InitEditorRenderGraph(void) noexcept
|
||||
{
|
||||
|
@ -336,8 +375,7 @@ namespace SHADE
|
|||
InitBoilerplate();
|
||||
InitMiddleEnd();
|
||||
InitSubsystems();
|
||||
|
||||
|
||||
InitBuiltInResources();
|
||||
}
|
||||
|
||||
void SHGraphicsSystem::Exit(void)
|
||||
|
@ -399,6 +437,17 @@ namespace SHADE
|
|||
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||
|
||||
|
||||
{
|
||||
#ifdef SHEDITOR
|
||||
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
|
||||
if (editorSystem->editorState != SHEditor::State::PLAY)
|
||||
lightingSubSystem->Run(cameraSystem->GetEditorCamera()->GetViewMatrix(), frameIndex);
|
||||
else
|
||||
lightingSubSystem->Run(worldRenderer->GetCameraDirector()->GetViewMatrix(), frameIndex);
|
||||
#else
|
||||
lightingSubSystem->Run(worldRenderer->GetCameraDirector()->GetViewMatrix(), frameIndex);
|
||||
#endif
|
||||
}
|
||||
|
||||
// For every viewport
|
||||
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
|
||||
|
@ -435,8 +484,7 @@ namespace SHADE
|
|||
currentCmdBuffer->BindIndexBuffer(buffer, 0);
|
||||
}
|
||||
|
||||
// Bind the descriptor set for lights
|
||||
lightingSubSystem->Run(currentCmdBuffer, frameIndex);
|
||||
lightingSubSystem->BindDescSet(currentCmdBuffer, frameIndex);
|
||||
|
||||
// Bind textures
|
||||
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
|
||||
|
@ -460,7 +508,7 @@ namespace SHADE
|
|||
{
|
||||
auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
|
||||
if (editorSystem->editorState != SHEditor::State::PLAY)
|
||||
worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, SHMatrix::Transpose(cameraSystem->GetEditorCamera()->GetProjMatrix() * cameraSystem->GetEditorCamera()->GetViewMatrix()));
|
||||
worldRenderer->UpdateDataAndBind(currentCmdBuffer, frameIndex, cameraSystem->GetEditorCamera()->GetViewMatrix(), cameraSystem->GetEditorCamera()->GetProjMatrix());
|
||||
else
|
||||
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
|
||||
}
|
||||
|
@ -685,6 +733,18 @@ namespace SHADE
|
|||
transferCmdBuffer.Free(); transferCmdBuffer = {};
|
||||
}
|
||||
|
||||
Handle<SHMesh> SHGraphicsSystem::GetMeshPrimitive(PrimitiveType type) const noexcept
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case PrimitiveType::Cube:
|
||||
case PrimitiveType::Sphere:
|
||||
return primitiveMeshes[static_cast<int>(type)];
|
||||
default:
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Texture Registration Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -717,6 +777,11 @@ namespace SHADE
|
|||
graphicsTexCmdBuffer.Free(); graphicsTexCmdBuffer = {};
|
||||
}
|
||||
|
||||
Handle<SHTexture> SHGraphicsSystem::GetTextureHandle(SHTexture::Index textureId) const
|
||||
{
|
||||
return texLibrary.GetTextureHandle(textureId);
|
||||
}
|
||||
|
||||
#pragma endregion ADD_REMOVE
|
||||
|
||||
#pragma region ROUTINES
|
||||
|
@ -729,6 +794,7 @@ namespace SHADE
|
|||
|
||||
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
|
||||
{
|
||||
SHResourceManager::FinaliseChanges();
|
||||
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
|
||||
}
|
||||
|
||||
|
@ -754,7 +820,6 @@ namespace SHADE
|
|||
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
|
||||
{
|
||||
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
|
||||
SHResourceManager::FinaliseChanges();
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
@ -772,11 +837,6 @@ namespace SHADE
|
|||
if (!renderable.HasChanged())
|
||||
continue;
|
||||
|
||||
if (!renderable.GetMesh())
|
||||
{
|
||||
SHLOG_CRITICAL("NULL Mesh provided!");
|
||||
}
|
||||
|
||||
// Remove from the SuperBatch it is previously in (prevMat if mat has changed)
|
||||
Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial();
|
||||
if (prevMaterial)
|
||||
|
@ -786,8 +846,9 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Add to new SuperBatch if there is a material
|
||||
// Add to new SuperBatch if there is a material and a mesh to render
|
||||
Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
|
||||
if (newMatInstance)
|
||||
if (newMatInstance && renderable.GetMesh())
|
||||
{
|
||||
Handle<SHSuperBatch> newSuperBatch = newMatInstance->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
|
||||
newSuperBatch->Add(&renderable);
|
||||
|
@ -867,5 +928,57 @@ namespace SHADE
|
|||
return worldRenderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data());
|
||||
}
|
||||
|
||||
Handle<SHVkPipeline> SHGraphicsSystem::createDebugDrawPipeline(Handle<SHVkRenderpass> renderPass, Handle<SHSubpass> subpass)
|
||||
{
|
||||
auto pipelineLayout = resourceManager.Create<SHVkPipelineLayout>
|
||||
(
|
||||
device, SHPipelineLayoutParams
|
||||
{
|
||||
.shaderModules = { debugVertShader, debugFragShader },
|
||||
.globalDescSetLayouts = SHGraphicsGlobalData::GetDescSetLayouts()
|
||||
}
|
||||
);
|
||||
auto pipeline = resourceManager.Create<SHVkPipeline>(device, pipelineLayout, nullptr, renderPass, subpass);
|
||||
pipeline->GetPipelineState().SetRasterizationState(SHRasterizationState
|
||||
{
|
||||
.polygonMode = vk::PolygonMode::eLine,
|
||||
.cull_mode = vk::CullModeFlagBits::eNone
|
||||
});
|
||||
pipeline->GetPipelineState().SetInputAssemblyState(SHInputAssemblyState
|
||||
{
|
||||
.topology = vk::PrimitiveTopology::eLineList
|
||||
});
|
||||
|
||||
SHVertexInputState debugDrawVertexInputState;
|
||||
debugDrawVertexInputState.AddBinding(false, true, { SHVertexAttribute(SHAttribFormat::FLOAT_4D), SHVertexAttribute(SHAttribFormat::FLOAT_4D) });
|
||||
pipeline->GetPipelineState().SetVertexInputState(debugDrawVertexInputState);
|
||||
SHColorBlendState colorBlendState{};
|
||||
colorBlendState.logic_op_enable = VK_FALSE;
|
||||
colorBlendState.logic_op = vk::LogicOp::eCopy;
|
||||
|
||||
auto const& subpassColorReferences = subpass->GetColorAttachmentReferences();
|
||||
colorBlendState.attachments.reserve(subpassColorReferences.size());
|
||||
|
||||
for (auto& att : subpassColorReferences)
|
||||
{
|
||||
colorBlendState.attachments.push_back(vk::PipelineColorBlendAttachmentState
|
||||
{
|
||||
.blendEnable = SHVkUtil::IsBlendCompatible(subpass->GetFormatFromAttachmentReference(att.attachment)),
|
||||
.srcColorBlendFactor = vk::BlendFactor::eSrcAlpha,
|
||||
.dstColorBlendFactor = vk::BlendFactor::eOneMinusSrcAlpha,
|
||||
.colorBlendOp = vk::BlendOp::eAdd,
|
||||
.srcAlphaBlendFactor = vk::BlendFactor::eOne,
|
||||
.dstAlphaBlendFactor = vk::BlendFactor::eZero,
|
||||
.alphaBlendOp = vk::BlendOp::eAdd,
|
||||
.colorWriteMask = vk::ColorComponentFlagBits::eR | vk::ColorComponentFlagBits::eG | vk::ColorComponentFlagBits::eB | vk::ColorComponentFlagBits::eA,
|
||||
});
|
||||
}
|
||||
|
||||
pipeline->GetPipelineState().SetColorBlenState(colorBlendState);
|
||||
pipeline->ConstructPipeline();
|
||||
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
#pragma endregion MISC
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include "../Textures/SHVkSamplerCache.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
|
||||
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
|
||||
#include "Graphics/MiddleEnd/PostProcessing/SHSSAO.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -57,6 +58,19 @@ namespace SHADE
|
|||
/*---------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/***********************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Type of built-in primitive meshes that are available.
|
||||
*/
|
||||
/***********************************************************************************/
|
||||
enum class PrimitiveType
|
||||
{
|
||||
Cube,
|
||||
Sphere
|
||||
};
|
||||
static constexpr int MAX_PRIMITIVE_TYPES = 2;
|
||||
|
||||
/***********************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
|
@ -71,6 +85,7 @@ namespace SHADE
|
|||
void InitSceneRenderGraph (void) noexcept;
|
||||
void InitMiddleEnd (void) noexcept;
|
||||
void InitSubsystems (void) noexcept;
|
||||
void InitBuiltInResources (void);
|
||||
|
||||
#ifdef SHEDITOR
|
||||
void InitEditorRenderGraph (void) noexcept;
|
||||
|
@ -206,6 +221,21 @@ namespace SHADE
|
|||
*/
|
||||
/***************************************************************************/
|
||||
void BuildMeshBuffers();
|
||||
/*******************************************************************************/
|
||||
/*!
|
||||
|
||||
\brief
|
||||
Retrieves the built-in mesh specified.
|
||||
|
||||
\param type
|
||||
Type of built-in mesh to retrieve.
|
||||
|
||||
\returns
|
||||
Handle to the mesh that was specfied. However, if an invalid type is specified,
|
||||
a null Handle will be returned.
|
||||
*/
|
||||
/*******************************************************************************/
|
||||
Handle<SHMesh> GetMeshPrimitive(PrimitiveType type) const noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Texture Registration Functions */
|
||||
|
@ -262,6 +292,33 @@ namespace SHADE
|
|||
*/
|
||||
/***************************************************************************/
|
||||
void BuildTextures();
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
*
|
||||
\brief
|
||||
Retrieves the texture handle at the specified texture index.
|
||||
|
||||
\param textureId
|
||||
Index of the texture to look for.
|
||||
|
||||
\returns
|
||||
Handle to the texture
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHTexture> GetTextureHandle(SHTexture::Index textureId) const;
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
*
|
||||
\brief
|
||||
Retrieves the handle to the default texture. A white 1x1 texture.
|
||||
|
||||
\returns
|
||||
Handle to the default texture.
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHTexture> GetDefaultTexture() const noexcept { return defaultTexture; }
|
||||
|
||||
void PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept;
|
||||
void HandleResize(void) noexcept;
|
||||
|
@ -289,6 +346,7 @@ namespace SHADE
|
|||
Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
|
||||
Handle<SHRenderGraphNode> GetPrimaryRenderpass() const noexcept;
|
||||
Handle<SHVkPipeline> GetDebugDrawPipeline(void) const noexcept { return debugDrawPipeline; }
|
||||
Handle<SHVkPipeline> GetDebugDrawDepthPipeline(void) const noexcept { return debugDrawDepthPipeline; }
|
||||
uint32_t GetCurrentFrameIndex(void) const noexcept { return renderContext.GetCurrentFrame(); }
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
@ -315,6 +373,7 @@ namespace SHADE
|
|||
Handle<SHVkDescriptorPool> descPool;
|
||||
Handle<SHVkCommandPool> graphicsCmdPool;
|
||||
Handle<SHVkCommandBuffer> transferCmdBuffer;
|
||||
Handle<SHVkCommandBuffer> ssaoTransferCmdBuffer;
|
||||
Handle<SHVkCommandBuffer> graphicsTexCmdBuffer;
|
||||
SHRenderContext renderContext;
|
||||
std::array<Handle<SHVkSemaphore>, 2> graphSemaphores;
|
||||
|
@ -351,21 +410,37 @@ namespace SHADE
|
|||
Handle<SHVkShaderModule> debugVertShader;
|
||||
Handle<SHVkShaderModule> debugFragShader;
|
||||
Handle<SHVkShaderModule> deferredCompositeShader;
|
||||
Handle<SHVkShaderModule> ssaoShader;
|
||||
Handle<SHVkShaderModule> ssaoBlurShader;
|
||||
|
||||
|
||||
// Built-In Materials
|
||||
Handle<SHMaterial> defaultMaterial;
|
||||
Handle<SHVkPipeline> debugDrawPipeline;
|
||||
Handle<SHVkPipeline> debugDrawDepthPipeline;
|
||||
|
||||
// Built-In Textures
|
||||
Handle<SHTexture> defaultTexture;
|
||||
|
||||
// Built-In Meshes
|
||||
std::array<Handle<SHMesh>, MAX_PRIMITIVE_TYPES> primitiveMeshes;
|
||||
|
||||
// Render Graphs
|
||||
Handle<SHRenderGraph> worldRenderGraph;
|
||||
|
||||
// Sub systems
|
||||
Handle<SHMousePickSystem> mousePickSystem;
|
||||
Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
|
||||
Handle<SHLightingSubSystem> lightingSubSystem;
|
||||
Handle<SHSSAO> ssaoStorage;
|
||||
|
||||
uint32_t resizeWidth;
|
||||
uint32_t resizeHeight;
|
||||
uint32_t resizeWidth = 1;
|
||||
uint32_t resizeHeight = 1;
|
||||
bool restoredFromMinimize = false;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Helper Functions */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
Handle<SHVkPipeline> createDebugDrawPipeline(Handle<SHVkRenderpass> renderPass, Handle<SHSubpass> subpass);
|
||||
};
|
||||
}
|
|
@ -83,13 +83,14 @@ namespace SHADE
|
|||
{
|
||||
if (camera && cameraDirector)
|
||||
{
|
||||
UpdateDataAndBind(cmdBuffer, frameIndex, SHMatrix::Transpose(cameraDirector->GetVPMatrix()));
|
||||
//UpdateDataAndBind(cmdBuffer, frameIndex, SHMatrix::Transpose(cameraDirector->GetVPMatrix()));
|
||||
UpdateDataAndBind(cmdBuffer, frameIndex, cameraDirector->GetViewMatrix(), cameraDirector->GetProjMatrix());
|
||||
}
|
||||
}
|
||||
|
||||
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept
|
||||
void SHRenderer::UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept
|
||||
{
|
||||
SetViewProjectionMatrix(exteriorMatrix);
|
||||
SetViewProjectionMatrix(viewMatrix, projMatrix);
|
||||
|
||||
//cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
|
||||
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
|
||||
|
@ -97,16 +98,19 @@ namespace SHADE
|
|||
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize };
|
||||
|
||||
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::GRAPHICS, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
|
||||
cmdBuffer->BindDescriptorSet(cameraDescriptorSet, SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS, std::span{ dynamicOffsets.data(), 1 });
|
||||
}
|
||||
|
||||
void SHRenderer::UpdateCameraDataToBuffer(void) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
void SHRenderer::SetViewProjectionMatrix(SHMatrix const& vpMatrix) noexcept
|
||||
void SHRenderer::SetViewProjectionMatrix(SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept
|
||||
{
|
||||
//cpuCameraData.viewProjectionMatrix = camera->GetViewMatrix() * camera->GetProjectionMatrix();
|
||||
cpuCameraData.viewProjectionMatrix = vpMatrix;
|
||||
cpuCameraData.viewProjectionMatrix = SHMatrix::Transpose(projMatrix * viewMatrix);
|
||||
cpuCameraData.viewMatrix = SHMatrix::Transpose(viewMatrix);
|
||||
cpuCameraData.projectionMatrix = SHMatrix::Transpose(projMatrix);
|
||||
}
|
||||
|
||||
Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept
|
||||
|
@ -119,4 +123,9 @@ namespace SHADE
|
|||
return commandBuffers[frameIndex];
|
||||
}
|
||||
|
||||
Handle<SHCameraDirector> SHRenderer::GetCameraDirector(void) const noexcept
|
||||
{
|
||||
return cameraDirector;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@ namespace SHADE
|
|||
{
|
||||
SHVec4 cameraPosition;
|
||||
SHMatrix viewProjectionMatrix;
|
||||
SHMatrix viewMatrix;
|
||||
SHMatrix projectionMatrix;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
|
@ -79,15 +81,16 @@ namespace SHADE
|
|||
/*-----------------------------------------------------------------------------*/
|
||||
void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix exteriorMatrix) noexcept;
|
||||
void UpdateDataAndBind(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex, SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept;
|
||||
void UpdateCameraDataToBuffer (void) noexcept;
|
||||
void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept;
|
||||
void SetViewProjectionMatrix (SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept;
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/* Setters and Getters */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHRenderGraph> GetRenderGraph (void) const noexcept;
|
||||
Handle<SHVkCommandBuffer> GetCommandBuffer(uint32_t frameIndex) const noexcept;
|
||||
Handle<SHCameraDirector> GetCameraDirector (void) const noexcept;
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -9,9 +9,9 @@ namespace SHADE
|
|||
{
|
||||
lightData.Reset();
|
||||
SetType(SH_LIGHT_TYPE::DIRECTIONAL);
|
||||
indexInBuffer = std::numeric_limits<uint32_t>::max();
|
||||
//indexInBuffer = std::numeric_limits<uint32_t>::max();
|
||||
isActive = true;
|
||||
Unbind();
|
||||
//Unbind();
|
||||
}
|
||||
|
||||
|
||||
|
@ -23,28 +23,28 @@ namespace SHADE
|
|||
void SHLightComponent::SetPosition(SHVec3 const& position) noexcept
|
||||
{
|
||||
lightData.position = position;
|
||||
MakeDirty();
|
||||
//MakeDirty();
|
||||
}
|
||||
|
||||
|
||||
void SHLightComponent::SetType(SH_LIGHT_TYPE type) noexcept
|
||||
{
|
||||
lightData.type = type;
|
||||
MakeDirty();
|
||||
//MakeDirty();
|
||||
}
|
||||
|
||||
|
||||
void SHLightComponent::SetDirection(SHVec3 const& direction) noexcept
|
||||
{
|
||||
lightData.direction = direction;
|
||||
MakeDirty();
|
||||
//MakeDirty();
|
||||
}
|
||||
|
||||
|
||||
void SHLightComponent::SetColor(SHVec4 const& color) noexcept
|
||||
{
|
||||
lightData.color = color;
|
||||
MakeDirty();
|
||||
//MakeDirty();
|
||||
}
|
||||
|
||||
void SHLightComponent::ModifyCullingMask(uint8_t layerIndex, bool value) noexcept
|
||||
|
@ -54,7 +54,7 @@ namespace SHADE
|
|||
else
|
||||
lightData.cullingMask &= ~(1u << layerIndex);
|
||||
|
||||
MakeDirty();
|
||||
//MakeDirty();
|
||||
}
|
||||
|
||||
void SHLightComponent::SetCullingMask(uint32_t const& value) noexcept
|
||||
|
@ -65,43 +65,43 @@ namespace SHADE
|
|||
void SHLightComponent::SetAllLayers(void) noexcept
|
||||
{
|
||||
lightData.cullingMask = std::numeric_limits<uint32_t>::max();
|
||||
MakeDirty();
|
||||
//MakeDirty();
|
||||
}
|
||||
|
||||
|
||||
void SHLightComponent::ClearAllLayers(void) noexcept
|
||||
{
|
||||
lightData.cullingMask = 0;
|
||||
MakeDirty();
|
||||
//MakeDirty();
|
||||
}
|
||||
|
||||
void SHLightComponent::MakeDirty(void) noexcept
|
||||
{
|
||||
dirty = true;
|
||||
}
|
||||
//void SHLightComponent::MakeDirty(void) noexcept
|
||||
//{
|
||||
// dirty = true;
|
||||
//}
|
||||
|
||||
void SHLightComponent::ClearDirtyFlag(void) noexcept
|
||||
{
|
||||
dirty = false;
|
||||
}
|
||||
//void SHLightComponent::ClearDirtyFlag(void) noexcept
|
||||
//{
|
||||
// dirty = false;
|
||||
//}
|
||||
|
||||
void SHLightComponent::Unbind(void) noexcept
|
||||
{
|
||||
bound = false;
|
||||
MakeDirty();
|
||||
}
|
||||
|
||||
void SHLightComponent::SetBound(uint32_t inIndexInBuffer) noexcept
|
||||
{
|
||||
bound = true;
|
||||
indexInBuffer = inIndexInBuffer;
|
||||
}
|
||||
// void SHLightComponent::Unbind(void) noexcept
|
||||
// {
|
||||
// bound = false;
|
||||
// MakeDirty();
|
||||
// }
|
||||
//
|
||||
// void SHLightComponent::SetBound(uint32_t inIndexInBuffer) noexcept
|
||||
//{
|
||||
// bound = true;
|
||||
// indexInBuffer = inIndexInBuffer;
|
||||
// }
|
||||
|
||||
|
||||
void SHLightComponent::SetStrength(float value) noexcept
|
||||
{
|
||||
lightData.strength = value;
|
||||
MakeDirty();
|
||||
//MakeDirty();
|
||||
}
|
||||
|
||||
SHLightData const& SHLightComponent::GetLightData(void) const noexcept
|
||||
|
@ -135,20 +135,20 @@ namespace SHADE
|
|||
}
|
||||
|
||||
|
||||
bool SHLightComponent::IsDirty(void) const noexcept
|
||||
{
|
||||
return dirty;
|
||||
}
|
||||
//bool SHLightComponent::IsDirty(void) const noexcept
|
||||
//{
|
||||
// return dirty;
|
||||
//}
|
||||
|
||||
bool SHLightComponent::GetBound(void) const noexcept
|
||||
{
|
||||
return bound;
|
||||
}
|
||||
//bool SHLightComponent::GetBound(void) const noexcept
|
||||
//{
|
||||
// return bound;
|
||||
//}
|
||||
|
||||
uint32_t SHLightComponent::GetIndexInBuffer(void) const noexcept
|
||||
{
|
||||
return indexInBuffer;
|
||||
}
|
||||
//uint32_t SHLightComponent::GetIndexInBuffer(void) const noexcept
|
||||
//{
|
||||
// return indexInBuffer;
|
||||
//}
|
||||
|
||||
float SHLightComponent::GetStrength(void) const noexcept
|
||||
{
|
||||
|
|
|
@ -17,13 +17,13 @@ namespace SHADE
|
|||
//! Since the lighting system is gonna be self contained and light weight, we store this
|
||||
//! so that we only write this to the CPU buffer when this light component change, we don't
|
||||
//! rewrite everything. However we still write to the GPU buffer when everything changes.
|
||||
uint32_t indexInBuffer;
|
||||
//uint32_t indexInBuffer;
|
||||
|
||||
//! If the light component changed some value we mark this true.
|
||||
bool dirty;
|
||||
////! If the light component changed some value we mark this true.
|
||||
//bool dirty;
|
||||
|
||||
//! If the light's data is already in the buffers, this will be set to true.
|
||||
bool bound;
|
||||
////! If the light's data is already in the buffers, this will be set to true.
|
||||
//bool bound;
|
||||
|
||||
|
||||
public:
|
||||
|
@ -44,10 +44,10 @@ namespace SHADE
|
|||
void SetCullingMask (uint32_t const& value) noexcept;
|
||||
void SetAllLayers (void) noexcept; // serialized
|
||||
void ClearAllLayers (void) noexcept; // serialized
|
||||
void MakeDirty (void) noexcept;
|
||||
void ClearDirtyFlag (void) noexcept;
|
||||
void Unbind (void) noexcept;
|
||||
void SetBound (uint32_t inIndexInBuffer) noexcept;
|
||||
//void MakeDirty (void) noexcept;
|
||||
//void ClearDirtyFlag (void) noexcept;
|
||||
//void Unbind (void) noexcept;
|
||||
//void SetBound (uint32_t inIndexInBuffer) noexcept;
|
||||
void SetStrength (float value) noexcept; // serialized
|
||||
|
||||
|
||||
|
@ -57,8 +57,8 @@ namespace SHADE
|
|||
SHVec3 const& GetDirection (void) const noexcept; // serialized
|
||||
SHVec4 const& GetColor (void) const noexcept; // serialized
|
||||
uint32_t const& GetCullingMask (void) const noexcept; // serialized
|
||||
bool IsDirty (void) const noexcept;
|
||||
bool GetBound (void) const noexcept;
|
||||
//bool IsDirty (void) const noexcept;
|
||||
//bool GetBound (void) const noexcept;
|
||||
uint32_t GetIndexInBuffer (void) const noexcept;
|
||||
float GetStrength (void) const noexcept;
|
||||
RTTR_ENABLE()
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "SHLightComponent.h"
|
||||
#include "ECS_Base/Managers/SHComponentManager.h"
|
||||
#include "SHLightComponent.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "Math/SHMatrix.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -31,7 +33,7 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHLightingSubSystem::PerTypeData::WriteLightToAddress(void* address, SHLightComponent* lightComp) noexcept
|
||||
void SHLightingSubSystem::PerTypeData::WriteLightToAddress(void* address, SHMatrix const& viewMat, SHLightComponent* lightComp) noexcept
|
||||
{
|
||||
auto const& lightData = lightComp->GetLightData();
|
||||
switch (lightData.type)
|
||||
|
@ -40,8 +42,12 @@ namespace SHADE
|
|||
{
|
||||
SHDirectionalLightData* lightPtr = reinterpret_cast<SHDirectionalLightData*>(address);
|
||||
|
||||
// #NoteToSelf: NEED TO TRANSPOSE HERE BECAUSE MULTIPLICATION IS ROW MAJOR.
|
||||
SHVec4 transformedDir = SHMatrix::Transpose(viewMat) * SHVec4(lightData.direction[0], lightData.direction[1], lightData.direction[2], 0.0f);
|
||||
|
||||
lightPtr->cullingMask = lightData.cullingMask;
|
||||
lightPtr->direction = lightData.direction;
|
||||
lightPtr->direction = SHVec3 (transformedDir.x, transformedDir.y, transformedDir.z);
|
||||
//lightPtr->direction = lightData.direction;
|
||||
lightPtr->diffuseColor = lightData.color;
|
||||
lightPtr->active = lightComp->isActive;
|
||||
break;
|
||||
|
@ -240,7 +246,7 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHLightingSubSystem::PerTypeData::AddLight(Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept
|
||||
void SHLightingSubSystem::PerTypeData::AddLight(Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, SHMatrix const& viewMat, bool& expanded) noexcept
|
||||
{
|
||||
if (unboundLight)
|
||||
{
|
||||
|
@ -259,10 +265,10 @@ namespace SHADE
|
|||
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * numLights);
|
||||
|
||||
// Write the light data to address
|
||||
WriteLightToAddress(writeLocation, unboundLight);
|
||||
WriteLightToAddress(writeLocation, viewMat, unboundLight);
|
||||
|
||||
// Set the light component to be bound to that location
|
||||
unboundLight->SetBound(numLights);
|
||||
//unboundLight->SetBound(numLights);
|
||||
|
||||
// Increase light count
|
||||
++numLights;
|
||||
|
@ -280,11 +286,11 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept
|
||||
{
|
||||
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * lightComp->GetIndexInBuffer());
|
||||
WriteLightToAddress(writeLocation, lightComp);
|
||||
}
|
||||
//void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept
|
||||
//{
|
||||
// void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * lightComp->GetIndexInBuffer());
|
||||
// WriteLightToAddress(writeLocation, lightComp);
|
||||
//}
|
||||
|
||||
void SHLightingSubSystem::PerTypeData::WriteToGPU(uint32_t frameIndex) noexcept
|
||||
{
|
||||
|
@ -406,7 +412,7 @@ namespace SHADE
|
|||
dynamicOffsets[i].resize(NUM_LIGHT_TYPES + 1); // +1 for the count
|
||||
}
|
||||
|
||||
numLightComponents = 0;
|
||||
//numLightComponents = 0;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
|
@ -419,21 +425,25 @@ namespace SHADE
|
|||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
void SHLightingSubSystem::Run(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||
void SHLightingSubSystem::Run(SHMatrix const& viewMat, uint32_t frameIndex) noexcept
|
||||
{
|
||||
static uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
|
||||
|
||||
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
|
||||
bool expanded = false;
|
||||
bool rewrite = false;
|
||||
|
||||
if (numLightComponents > lightComps.size())
|
||||
{
|
||||
rewrite = true;
|
||||
// First we reset the number of lights. We do this every frame so that we can count how many lights we have
|
||||
ResetNumLights();
|
||||
}
|
||||
|
||||
numLightComponents = lightComps.size();
|
||||
//bool rewrite = false;
|
||||
|
||||
//if (numLightComponents > lightComps.size())
|
||||
//{
|
||||
// rewrite = true;
|
||||
// ResetNumLights();
|
||||
//}
|
||||
|
||||
//numLightComponents = lightComps.size();
|
||||
|
||||
for (auto& light : lightComps)
|
||||
{
|
||||
|
@ -441,22 +451,22 @@ namespace SHADE
|
|||
|
||||
// First we want to make sure the light is already bound to the system. if it
|
||||
// isn't, we write it to the correct buffer.
|
||||
if (!light.GetBound() || rewrite)
|
||||
//if (!light.GetBound() || rewrite)
|
||||
{
|
||||
perTypeData[enumValue].AddLight(logicalDevice, &light, expanded);
|
||||
perTypeData[enumValue].AddLight(logicalDevice, &light, viewMat, expanded);
|
||||
|
||||
//// add to light count
|
||||
// add to light count
|
||||
//++lightCountsData[enumValue];
|
||||
}
|
||||
|
||||
// if there was modification to the light data
|
||||
if (light.IsDirty())
|
||||
//if (light.IsDirty())
|
||||
{
|
||||
// Write the data to the CPU
|
||||
perTypeData[enumValue].ModifyLight(&light);
|
||||
//perTypeData[enumValue].ModifyLight(&light);
|
||||
|
||||
// Light is now updated in the container
|
||||
light.ClearDirtyFlag();
|
||||
//light.ClearDirtyFlag();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -488,8 +498,6 @@ namespace SHADE
|
|||
// so we do it anyway. #NoteToSelf: if at any point it affects performance, do a check before computing.
|
||||
ComputeDynamicOffsets();
|
||||
|
||||
// Bind descriptor set (We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data).
|
||||
cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, {dynamicOffsets[frameIndex]});
|
||||
|
||||
}
|
||||
|
||||
|
@ -505,4 +513,12 @@ namespace SHADE
|
|||
{
|
||||
|
||||
}
|
||||
|
||||
void SHLightingSubSystem::BindDescSet(Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept
|
||||
{
|
||||
//Bind descriptor set(We bind at an offset because the buffer holds NUM_FRAME_BUFFERS sets of data).
|
||||
cmdBuffer->BindDescriptorSet(lightingDataDescSet, SH_PIPELINE_TYPE::COMPUTE, SHGraphicsConstants::DescriptorSetIndex::DYNAMIC_GLOBALS, { dynamicOffsets[frameIndex] });
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -95,15 +95,15 @@ namespace SHADE
|
|||
//! to the GPU that stores NUM_FRAME_BUFFERS copies.
|
||||
std::unique_ptr<uint8_t[]> intermediateData;
|
||||
|
||||
void WriteLightToAddress (void* address, SHLightComponent* lightComp) noexcept;
|
||||
void WriteLightToAddress (void* address, SHMatrix const& viewMat, SHLightComponent* lightComp) noexcept;
|
||||
public:
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void InitializeData (Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept;
|
||||
void Expand (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
void AddLight (Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept;
|
||||
void ModifyLight (SHLightComponent* lightComp) noexcept;
|
||||
void AddLight (Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, SHMatrix const& viewMat, bool& expanded) noexcept;
|
||||
//void ModifyLight (SHLightComponent* lightComp) noexcept;
|
||||
void WriteToGPU (uint32_t frameIndex) noexcept;
|
||||
void ResetNumLights (void) noexcept;
|
||||
|
||||
|
@ -144,7 +144,7 @@ namespace SHADE
|
|||
//! Number of SHLightComponents recorded. If at the beginning of the run function the size returned by the dense
|
||||
//! set is less than the size recorded, rewrite all light components into the its respective buffers. If its more,
|
||||
//! don't do anything.
|
||||
uint32_t numLightComponents;
|
||||
//uint32_t numLightComponents;
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
/* PRIVATE MEMBER FUNCTIONS */
|
||||
|
@ -159,8 +159,10 @@ namespace SHADE
|
|||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept;
|
||||
void Run (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
void Run (SHMatrix const& viewMat, uint32_t frameIndex) noexcept;
|
||||
void Exit (void) noexcept;
|
||||
|
||||
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHMaterialSpec.cpp
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Nov 2, 2022
|
||||
\brief Contains the function definitions of SHMaterialSpec.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#include "SHpch.h"
|
||||
#include "SHMaterialSpec.h"
|
||||
#include "Graphics/Shaders/SHVkShaderModule.h"
|
||||
#include "Resource/SHResourceManager.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMaterial.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
SHMaterialSpec::SHMaterialSpec(const SHMaterial& material)
|
||||
{
|
||||
// Get Shader Handles
|
||||
const auto& SHADERS = material.GetPipeline()->GetPipelineLayout()->GetShaderModules();
|
||||
Handle<SHVkShaderModule> vShaderMod, fShaderMod;
|
||||
for (const auto& shader : SHADERS)
|
||||
{
|
||||
const auto FLAG_BITS = shader->GetShaderStageFlagBits();
|
||||
if (FLAG_BITS & vk::ShaderStageFlagBits::eVertex)
|
||||
vShaderMod = shader;
|
||||
else if (FLAG_BITS & vk::ShaderStageFlagBits::eFragment)
|
||||
fShaderMod = shader;
|
||||
}
|
||||
vertexShader = SHResourceManager::GetAssetID<SHVkShaderModule>(vShaderMod).value_or(0);
|
||||
fragShader = SHResourceManager::GetAssetID<SHVkShaderModule>(fShaderMod).value_or(0);
|
||||
subpassName = material.GetPipeline()->GetPipelineState().GetSubpass()->GetName();
|
||||
|
||||
// Write Properties
|
||||
Handle<SHShaderBlockInterface> pipelineProperties = material.GetShaderBlockInterface();
|
||||
for (int i = 0; i < static_cast<int>(pipelineProperties->GetVariableCount()); ++i)
|
||||
{
|
||||
const SHShaderBlockInterface::Variable* VARIABLE = pipelineProperties->GetVariable(i);
|
||||
if (!VARIABLE)
|
||||
break;
|
||||
const std::string& VAR_NAME = pipelineProperties->GetVariableName(i);
|
||||
YAML::Node propNode;
|
||||
switch (VARIABLE->type)
|
||||
{
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::FLOAT:
|
||||
propNode = material.GetProperty<float>(VARIABLE->offset);
|
||||
break;
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::INT:
|
||||
propNode = material.GetProperty<int>(VARIABLE->offset);
|
||||
break;
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR2:
|
||||
propNode = material.GetProperty<SHVec2>(VARIABLE->offset);
|
||||
break;
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR3:
|
||||
propNode = material.GetProperty<SHVec3>(VARIABLE->offset);
|
||||
break;
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::VECTOR4:
|
||||
propNode = material.GetProperty<SHVec4>(VARIABLE->offset);
|
||||
break;
|
||||
case SHADE::SHShaderBlockInterface::Variable::Type::OTHER:
|
||||
default:
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
properties[VAR_NAME.data()] = propNode;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,9 +16,18 @@ of DigiPen Institute of Technology is prohibited.
|
|||
#include <utility>
|
||||
// Project Includes
|
||||
#include "Assets/SHAssetMacros.h"
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Forward Declaration */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
class SHMaterial;
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/* Type Definitions */
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
/*************************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
|
@ -32,5 +41,11 @@ namespace SHADE
|
|||
AssetID fragShader;
|
||||
std::string subpassName;
|
||||
YAML::Node properties;
|
||||
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
/* Constructors */
|
||||
/*---------------------------------------------------------------------------------*/
|
||||
SHMaterialSpec() = default;
|
||||
explicit SHMaterialSpec(const SHMaterial& material);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,36 +0,0 @@
|
|||
/************************************************************************************//*!
|
||||
\file SHPrimitiveGenerator.h
|
||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||
\par email: kahwei.tng\@digipen.edu
|
||||
\date Sep 18, 2022
|
||||
\brief Contains the static class definition of SHPrimitiveGenerator.
|
||||
|
||||
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||
of DigiPen Institute of Technology is prohibited.
|
||||
*//*************************************************************************************/
|
||||
#pragma once
|
||||
|
||||
// STL Includes
|
||||
#include <vector>
|
||||
// Project Includes
|
||||
#include "Math/SHMath.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
/*************************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
Static class that contains functions for generating 3D primitives.
|
||||
*/
|
||||
/*************************************************************************************/
|
||||
struct SHMeshData
|
||||
{
|
||||
std::vector<SHMesh::VertexPosition> VertexPositions;
|
||||
std::vector<SHMesh::VertexTexCoord> VertexTexCoords;
|
||||
std::vector<SHMesh::VertexTangent> VertexTangents;
|
||||
std::vector<SHMesh::VertexNormal> VertexNormals;
|
||||
std::vector<SHMesh::Index> Indices;
|
||||
};
|
||||
}
|
|
@ -13,7 +13,8 @@ of DigiPen Institute of Technology is prohibited.
|
|||
|
||||
// Project Includes
|
||||
#include "Math/SHMath.h"
|
||||
#include "SHMeshData.h"
|
||||
#include "Assets/Asset Types/SHModelAsset.h"
|
||||
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
|
||||
#include "SH_API.h"
|
||||
|
||||
namespace SHADE
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
#include "SHpch.h"
|
||||
#include "SHSSAO.h"
|
||||
#include "Graphics/Devices/SHVkLogicalDevice.h"
|
||||
#include "Graphics/Buffers/SHVkBuffer.h"
|
||||
#include "Graphics/Images/SHVkImage.h"
|
||||
#include "Graphics/Images/SHVkSampler.h"
|
||||
#include <random>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
void SHSSAO::Init(Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept
|
||||
{
|
||||
// Initialize a distribution to get values from 0 to 1
|
||||
std::uniform_real_distribution<float> distrib{0.0f, 1.0f};
|
||||
|
||||
// generator for random number
|
||||
std::default_random_engine generator;
|
||||
|
||||
// generate samples
|
||||
for (uint32_t i = 0; i < NUM_SAMPLES; ++i)
|
||||
{
|
||||
//SHVec3 temp
|
||||
//{
|
||||
// distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
|
||||
// distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
|
||||
// distrib(generator), // 0.0f - 1.0f so that sample space is a hemisphere
|
||||
//};
|
||||
|
||||
//temp = SHVec3::Normalise(temp);
|
||||
//temp *= distrib(generator);
|
||||
|
||||
//// This makes sure that most points are closer to fragment's position
|
||||
//float scale = 1.0f / static_cast<float>(NUM_SAMPLES);
|
||||
//scale = std::lerp(0.1f, 1.0f, scale * scale);
|
||||
//temp *= scale;
|
||||
//samples[i] = SHVec4 (temp.x, temp.y, temp.z, 0.0f);
|
||||
|
||||
|
||||
samples[i] = SHVec4
|
||||
{
|
||||
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
|
||||
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
|
||||
distrib(generator), // 0.0f - 1.0f so that sample space is a hemisphere
|
||||
0.0f
|
||||
};
|
||||
|
||||
// This makes sure that most points are closer to fragment's position
|
||||
float scale = 1.0f / static_cast<float>(NUM_SAMPLES);
|
||||
scale = std::lerp(0.1f, 1.0f, scale * scale);
|
||||
samples[i] *= scale;
|
||||
}
|
||||
|
||||
// generate rotation vector
|
||||
for (uint32_t i = 0; i < NUM_ROTATION_VECTORS; ++i)
|
||||
{
|
||||
rotationVectors[i] = SHVec4
|
||||
{
|
||||
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
|
||||
distrib(generator) * 2.0f - 1.0f, // -1.0f - 1.0f
|
||||
0.0f, // we want to rotate about the z axis in tangent space
|
||||
0.0f
|
||||
};
|
||||
}
|
||||
|
||||
SHImageCreateParams imageDetails =
|
||||
{
|
||||
.imageType = vk::ImageType::e2D,
|
||||
.width = NUM_ROTATION_VECTORS_W,
|
||||
.height = NUM_ROTATION_VECTORS_H,
|
||||
.depth = 1,
|
||||
.levels = 1,
|
||||
.arrayLayers = 1,
|
||||
.imageFormat = vk::Format::eR32G32B32A32Sfloat,
|
||||
.usageFlags = vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst,
|
||||
.createFlags = {}
|
||||
};
|
||||
|
||||
uint32_t mipOffset = 0;
|
||||
rotationVectorsImage = logicalDevice->CreateImage(imageDetails, reinterpret_cast<unsigned char*>( rotationVectors.data()), static_cast<uint32_t>(sizeof(rotationVectors)), {&mipOffset, 1}, VMA_MEMORY_USAGE_AUTO, {});
|
||||
|
||||
vk::ImageMemoryBarrier transferBarrier{};
|
||||
rotationVectorsImage->PrepareImageTransitionInfo(vk::ImageLayout::eUndefined, vk::ImageLayout::eTransferDstOptimal, transferBarrier);
|
||||
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTopOfPipe, vk::PipelineStageFlagBits::eTransfer, {}, {}, {}, {transferBarrier});
|
||||
|
||||
rotationVectorsImage->TransferToDeviceResource(cmdBuffer);
|
||||
|
||||
vk::ImageMemoryBarrier shaderReadBarrier{};
|
||||
rotationVectorsImage->PrepareImageTransitionInfo(vk::ImageLayout::eTransferDstOptimal, vk::ImageLayout::eShaderReadOnlyOptimal, shaderReadBarrier);
|
||||
cmdBuffer->PipelineBarrier(vk::PipelineStageFlagBits::eTransfer, vk::PipelineStageFlagBits::eComputeShader, {}, {}, {}, { shaderReadBarrier });
|
||||
|
||||
|
||||
// Get aligned size for buffer
|
||||
uint32_t alignedSize = logicalDevice->PadSSBOSize(sizeof (samples));
|
||||
|
||||
// Create buffer
|
||||
ssaoDataBuffer = logicalDevice->CreateBuffer(alignedSize, samples.data(), alignedSize, vk::BufferUsageFlagBits::eStorageBuffer | vk::BufferUsageFlagBits::eTransferDst, VMA_MEMORY_USAGE_AUTO, {});
|
||||
|
||||
ssaoDataBuffer->TransferToDeviceResource(cmdBuffer);
|
||||
}
|
||||
|
||||
void SHSSAO::PrepareRotationVectorsVkData(Handle<SHVkLogicalDevice> logicalDevice) noexcept
|
||||
{
|
||||
SHImageViewDetails DETAILS =
|
||||
{
|
||||
.viewType = vk::ImageViewType::e2D,
|
||||
.format = vk::Format::eR32G32B32A32Sfloat,
|
||||
.imageAspectFlags = vk::ImageAspectFlagBits::eColor,
|
||||
.baseMipLevel = 0,
|
||||
.mipLevelCount = 1,
|
||||
.baseArrayLayer = 0,
|
||||
.layerCount = 1
|
||||
};
|
||||
rotationVectorsImageView = rotationVectorsImage->CreateImageView(logicalDevice, rotationVectorsImage, DETAILS);
|
||||
|
||||
SHVkSamplerParams samplerParams
|
||||
{
|
||||
.minFilter = vk::Filter::eNearest,
|
||||
.magFilter = vk::Filter::eNearest,
|
||||
.addressMode = vk::SamplerAddressMode::eRepeat,
|
||||
.mipmapMode = vk::SamplerMipmapMode::eNearest,
|
||||
.maxLod = 1u
|
||||
};
|
||||
|
||||
rotationVectorsSampler = logicalDevice->CreateSampler(samplerParams);
|
||||
}
|
||||
|
||||
SHVkDescriptorSetGroup::viewSamplerLayout SHSSAO::GetViewSamplerLayout(void) const noexcept
|
||||
{
|
||||
return std::make_tuple(rotationVectorsImageView, rotationVectorsSampler, vk::ImageLayout::eShaderReadOnlyOptimal);
|
||||
}
|
||||
|
||||
Handle<SHVkBuffer> SHSSAO::GetBuffer(void) const noexcept
|
||||
{
|
||||
return ssaoDataBuffer;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
#include "Math/Vector/SHVec4.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetGroup.h"
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
class SHVkBuffer;
|
||||
class SHVkLogicalDevice;
|
||||
class SHVkCommandBuffer;
|
||||
class SHVkImage;
|
||||
class SHVkImageView;
|
||||
class SHVkSampler;
|
||||
|
||||
class SHSSAO
|
||||
{
|
||||
public:
|
||||
static constexpr uint32_t DESC_SET_BUFFER_BINDING = 0;
|
||||
static constexpr uint32_t DESC_SET_IMAGE_BINDING = 1;
|
||||
|
||||
private:
|
||||
static constexpr uint32_t NUM_SAMPLES = 64;
|
||||
static constexpr uint32_t NUM_ROTATION_VECTORS_W = 4;
|
||||
static constexpr uint32_t NUM_ROTATION_VECTORS_H = 4;
|
||||
static constexpr uint32_t NUM_ROTATION_VECTORS = NUM_ROTATION_VECTORS_W * NUM_ROTATION_VECTORS_H;
|
||||
|
||||
private:
|
||||
//! distances from a pixel we want to sample
|
||||
std::array<SHVec4, NUM_SAMPLES> samples;
|
||||
|
||||
//! For passing SSAO samples and kernel to GPU
|
||||
Handle<SHVkBuffer> ssaoDataBuffer;
|
||||
|
||||
std::array<SHVec4, NUM_ROTATION_VECTORS> rotationVectors;
|
||||
|
||||
Handle<SHVkImage> rotationVectorsImage;
|
||||
Handle<SHVkImageView> rotationVectorsImageView;
|
||||
Handle<SHVkSampler> rotationVectorsSampler;
|
||||
|
||||
public:
|
||||
void Init (Handle<SHVkLogicalDevice> logicalDevice, Handle<SHVkCommandBuffer> cmdBuffer) noexcept;
|
||||
void PrepareRotationVectorsVkData (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
|
||||
SHVkDescriptorSetGroup::viewSamplerLayout GetViewSamplerLayout (void) const noexcept;
|
||||
|
||||
Handle<SHVkBuffer> GetBuffer (void) const noexcept;
|
||||
};
|
||||
}
|
|
@ -156,14 +156,15 @@ namespace SHADE
|
|||
/* Build Descriptor Set with all the Textures only if there are textures */
|
||||
if (!texOrder.empty())
|
||||
{
|
||||
if (!texDescriptors)
|
||||
if (texDescriptors)
|
||||
{
|
||||
texDescriptors.Free();
|
||||
}
|
||||
texDescriptors = descPool->Allocate
|
||||
(
|
||||
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS] },
|
||||
{ static_cast<uint32_t>(texOrder.size()) }
|
||||
);
|
||||
}
|
||||
texDescriptors->ModifyWriteDescImage
|
||||
(
|
||||
SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,
|
||||
|
|
|
@ -129,6 +129,21 @@ namespace SHADE
|
|||
/* Getter Functions */
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
Handle<SHVkDescriptorSetGroup> GetTextureDescriptorSetGroup() const noexcept { return texDescriptors; }
|
||||
/***************************************************************************/
|
||||
/*!
|
||||
*
|
||||
\brief
|
||||
Retrieves the texture handle at the specified texture index.
|
||||
|
||||
\param textureId
|
||||
Index of the texture to look for.
|
||||
|
||||
\returns
|
||||
Handle to the texture
|
||||
|
||||
*/
|
||||
/***************************************************************************/
|
||||
Handle<SHTexture> GetTextureHandle(SHTexture::Index textureId) const { return texOrder[textureId]; };
|
||||
|
||||
private:
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
|
|
|
@ -2,8 +2,10 @@
|
|||
#define SH_PIPELINE_LAYOUT_PARAMS_H
|
||||
|
||||
#include "Graphics/SHVulkanIncludes.h"
|
||||
#include "Graphics/SHVulkanDefines.h"
|
||||
#include "Resource/SHHandle.h"
|
||||
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace SHADE
|
||||
{
|
||||
|
@ -24,6 +26,12 @@ namespace SHADE
|
|||
//! want to use the layout to initialize the pipeline layout but we do not
|
||||
//! want to use it for allocating descriptor sets.
|
||||
std::vector<Handle<SHVkDescriptorSetLayout>> const& globalDescSetLayouts = {};
|
||||
|
||||
//! Since both SPIRV-Reflect and GLSL don't provide ways to describe UBOs or
|
||||
//! SSBOs as dynamic, we need to do it ourselves. This will store bindings
|
||||
//! which we will use when parsing for descriptor set layouts. If a parsed
|
||||
//! binding is in this container, we make that binding's descriptor dynamic.
|
||||
std::unordered_set<BindingAndSetHash> dynamicBufferBindings;
|
||||
};
|
||||
|
||||
struct SHPipelineLayoutParamsDummy
|
||||
|
|
|
@ -165,6 +165,28 @@ namespace SHADE
|
|||
newBinding.Stage = shaderModule->GetShaderStageFlagBits();
|
||||
newBinding.Type = descBindingInfo.ConvertFromReflectDescType(reflectedBinding->descriptor_type);
|
||||
|
||||
// Here we want to check if a binding is supposed to be dynamic. If it is, make it dynamic.
|
||||
if (newBinding.Type == vk::DescriptorType::eUniformBuffer || newBinding.Type == vk::DescriptorType::eStorageBuffer)
|
||||
{
|
||||
for (auto& bsHash : dynamicBufferBindings)
|
||||
{
|
||||
uint32_t set = static_cast<uint32_t>(bsHash >> 32);
|
||||
uint32_t binding = static_cast<uint32_t>(bsHash & 0xFFFFFFFF);
|
||||
if (set == CURRENT_SET && binding == newBinding.BindPoint)
|
||||
{
|
||||
switch (newBinding.Type)
|
||||
{
|
||||
case vk::DescriptorType::eUniformBuffer:
|
||||
newBinding.Type = vk::DescriptorType::eUniformBufferDynamic;
|
||||
break;
|
||||
case vk::DescriptorType::eStorageBuffer:
|
||||
newBinding.Type = vk::DescriptorType::eStorageBufferDynamic;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In reality, the check for variable descriptor sets do not exists in spirv-reflect. Fortunately, when a shader
|
||||
// defines a boundless descriptor binding in the shader, the information reflected makes the array dimensions
|
||||
// contain a 1 element of value 1. Knowing that having an array [1] doesn't make sense, we can use this to
|
||||
|
@ -300,6 +322,7 @@ namespace SHADE
|
|||
, vkDescriptorSetLayoutsAllocate{}
|
||||
, descriptorSetLayoutsPipeline{}
|
||||
, vkDescriptorSetLayoutsPipeline{}
|
||||
, dynamicBufferBindings{std::move (pipelineLayoutParams.dynamicBufferBindings)}
|
||||
{
|
||||
for (auto& mod : shaderModules)
|
||||
{
|
||||
|
|
|
@ -29,6 +29,9 @@ namespace SHADE
|
|||
//! Push constant interface
|
||||
SHPushConstantInterface pushConstantInterface;
|
||||
|
||||
//! See SHPipelineLayoutParams for details
|
||||
std::unordered_set<BindingAndSetHash> dynamicBufferBindings;
|
||||
|
||||
//! Push constant ranges
|
||||
std::vector<vk::PushConstantRange> vkPcRanges;
|
||||
|
||||
|
|
|
@ -129,4 +129,9 @@ namespace SHADE
|
|||
return vkQueue;
|
||||
}
|
||||
|
||||
void SHVkQueue::WaitIdle(void) const noexcept
|
||||
{
|
||||
vkQueue.waitIdle();
|
||||
}
|
||||
|
||||
}
|
|
@ -50,6 +50,8 @@ namespace SHADE
|
|||
void SubmitCommandBuffer (std::initializer_list<Handle<SHVkCommandBuffer>> cmdBuffers, std::initializer_list<Handle<SHVkSemaphore>> signalSems = {}, std::initializer_list<Handle<SHVkSemaphore>> waitSems = {}, vk::PipelineStageFlags waitDstStageMask = {}, Handle<SHVkFence> const& fence = {}) noexcept;
|
||||
vk::Result Present (Handle<SHVkSwapchain> const& swapchain, std::initializer_list<Handle<SHVkSemaphore>> waitSems, uint32_t frameIndex) noexcept;
|
||||
vk::Queue GetVkQueue() noexcept;
|
||||
|
||||
void WaitIdle (void) const noexcept;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -263,7 +263,7 @@ namespace SHADE
|
|||
return subpass;
|
||||
}
|
||||
|
||||
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale/* = 1.0f*/) noexcept
|
||||
Handle<SHRenderGraphNodeCompute> SHRenderGraphNode::AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings, float numWorkGroupScale/* = 1.0f*/) noexcept
|
||||
{
|
||||
// Look for the required resources in the graph
|
||||
std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{};
|
||||
|
@ -276,7 +276,7 @@ namespace SHADE
|
|||
}
|
||||
|
||||
// Create the subpass compute with the resources
|
||||
auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources), nodeComputes.empty());
|
||||
auto nodeCompute = graphStorage->resourceManager->Create<SHRenderGraphNodeCompute>(graphStorage, computeShaderModule, std::move(nodeComputeResources), std::move (dynamicBufferBindings), nodeComputes.empty());
|
||||
nodeComputes.push_back(nodeCompute);
|
||||
|
||||
return nodeCompute;
|
||||
|
|
|
@ -100,7 +100,7 @@ namespace SHADE
|
|||
/* PUBLIC MEMBER FUNCTIONS */
|
||||
/*-----------------------------------------------------------------------*/
|
||||
Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept;
|
||||
Handle<SHRenderGraphNodeCompute> AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, float numWorkGroupScale = 1.0f) noexcept;
|
||||
Handle<SHRenderGraphNodeCompute> AddNodeCompute(Handle<SHVkShaderModule> computeShaderModule, std::initializer_list<std::string> resources, std::unordered_set<BindingAndSetHash>&& dynamicBufferBindings = {}, float numWorkGroupScale = 1.0f) noexcept;
|
||||
void AddDummySubpassIfNeeded (void) noexcept;
|
||||
|
||||
// TODO: RemoveSubpass()
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue