Merge remote-tracking branch 'origin/main' into SP3-2-Physics

This commit is contained in:
Diren D Bharwani 2022-11-07 13:29:17 +08:00
commit 10ba68b284
141 changed files with 9862 additions and 16050 deletions

View File

@ -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.

View File

@ -1,3 +0,0 @@
Name: Cube.003
ID: 71245919
Type: 4

View File

@ -1,3 +0,0 @@
Name: Cube.012
ID: 80365422
Type: 4

View File

@ -1,16 +1,16 @@
[Window][MainStatusBar] [Window][MainStatusBar]
Pos=0,1060 Pos=0,1007
Size=1920,20 Size=1920,20
Collapsed=0 Collapsed=0
[Window][SHEditorMenuBar] [Window][SHEditorMenuBar]
Pos=0,48 Pos=0,48
Size=1920,1012 Size=1920,959
Collapsed=0 Collapsed=0
[Window][Hierarchy Panel] [Window][Hierarchy Panel]
Pos=0,197 Pos=0,189
Size=308,863 Size=308,818
Collapsed=0 Collapsed=0
DockId=0x00000004,0 DockId=0x00000004,0
@ -21,13 +21,13 @@ Collapsed=0
[Window][Inspector] [Window][Inspector]
Pos=1528,48 Pos=1528,48
Size=392,1012 Size=392,959
Collapsed=0 Collapsed=0
DockId=0x00000006,0 DockId=0x00000006,0
[Window][Profiler] [Window][Profiler]
Pos=0,48 Pos=0,48
Size=308,147 Size=308,139
Collapsed=0 Collapsed=0
DockId=0x00000003,0 DockId=0x00000003,0
@ -76,7 +76,7 @@ DockId=0x0000000B,0
[Window][ Viewport] [Window][ Viewport]
Pos=310,48 Pos=310,48
Size=1216,715 Size=1216,662
Collapsed=0 Collapsed=0
DockId=0x0000000B,0 DockId=0x0000000B,0
@ -93,13 +93,19 @@ Collapsed=0
DockId=0x0000000A,0 DockId=0x0000000A,0
[Window][ Asset Browser] [Window][ Asset Browser]
Pos=310,765 Pos=310,712
Size=1216,295 Size=1216,295
Collapsed=0 Collapsed=0
DockId=0x0000000C,0 DockId=0x0000000C,0
[Window][Material Inspector]
Pos=1528,48
Size=392,959
Collapsed=0
DockId=0x00000006,1
[Docking][Data] [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=0x00000005 Parent=0xC5C9B8AB SizeRef=1526,1036 Split=X
DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881 DockNode ID=0x00000001 Parent=0x00000005 SizeRef=308,1036 Split=Y Selected=0x1E6EB881
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=225,147 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=0x0000000C Parent=0x00000009 SizeRef=1501,295 Selected=0xB128252A
DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6 DockNode ID=0x0000000A Parent=0x00000007 SizeRef=1501,310 Selected=0xD446F7B6
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=1501,338 Selected=0xD9F31532 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

View File

@ -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}

View File

@ -0,0 +1,3 @@
Name: BagMaterial
ID: 123745521
Type: 7

View File

@ -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}

View File

@ -0,0 +1,3 @@
Name: TestMat
ID: 126974645
Type: 7

View File

@ -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}

View File

@ -0,0 +1,3 @@
Name: WhiteMat
ID: 124370424
Type: 7

BIN
Assets/Models/racoon.fbx Normal file

Binary file not shown.

4993
Assets/Models/racoon.gltf Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,10 @@
Name: racoon
ID: 77816045
Type: 4
Sub Assets:
Name: Bag
ID: 144838771
Type: 8
Name: Raccoon
ID: 149697411
Type: 8

259
Assets/Scenes/M2Scene.shade Normal file
View File

@ -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: ~

View File

@ -0,0 +1,3 @@
Name: M2Scene
ID: 94283040
Type: 5

View File

@ -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: ~

View File

@ -0,0 +1,3 @@
Name: Scene2
ID: 87285316
Type: 5

View File

@ -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 = 1, rgba32f) uniform image2D normals;
layout(set = 4, binding = 2, rgba8) uniform image2D albedo; layout(set = 4, binding = 2, rgba8) uniform image2D albedo;
layout(set = 4, binding = 3, r32ui) uniform uimage2D lightLayerData; 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 layout(set = 1, binding = 0) uniform LightCounts
{ {
@ -51,33 +52,46 @@ void main()
vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb; vec3 pixelDiffuse = imageLoad (albedo, globalThread).rgb;
// Get position of fragment in world space // Get position of fragment in world space
vec3 positionWorld = imageLoad (positions, globalThread).rgb; vec3 positionView = imageLoad (positions, globalThread).rgb;
// normal of fragment // 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); vec3 fragColor = vec3 (0.0f);
for (int i = 0; i < lightCounts.directionalLights; ++i) for (int i = 0; i < lightCounts.directionalLights; ++i)
{
if ((lightLayer & DirLightData.dLightData[i].cullingMask) != 0)
{ {
// get normalized direction of light // get normalized direction of light
vec3 dLightNormalized = normalize (DirLightData.dLightData[i].direction); vec3 dLightNormalized = normalize (DirLightData.dLightData[i].direction);
// Get diffuse strength // Get diffuse strength
float diffuseStrength = max (0, dot (dLightNormalized, normalWorld)); float diffuseStrength = max (0, dot (dLightNormalized, normalView));
// Calculate the fragment color // Calculate the fragment color
fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse; fragColor += DirLightData.dLightData[i].diffuseColor.rgb * diffuseStrength.rrr * pixelDiffuse;
} }
}
for (int i = 0; i < lightCounts.ambientLights; ++i) for (int i = 0; i < lightCounts.ambientLights; ++i)
{
if ((lightLayer & AmbLightData.aLightData[i].cullingMask) != 0)
{ {
// Just do some add // Just do some add
//fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f); //fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (0.5f);
fragColor += pixelDiffuse.rgb * AmbLightData.aLightData[i].ambientColor.rgb * vec3 (AmbLightData.aLightData[i].strength); 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 // 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));
} }

View File

@ -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.

View File

@ -0,0 +1,3 @@
Name: SSAOBlur_CS
ID: 39760835
Type: 2

104
Assets/Shaders/SSAO_CS.glsl Normal file
View File

@ -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.

View File

@ -0,0 +1,3 @@
Name: SSAO_CS
ID: 38430899
Type: 2

View File

@ -43,7 +43,7 @@ void main()
{ {
position = In.vertPos; position = In.vertPos;
normals = In.normal; 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; outEntityID = In2.eid;
lightLayerIndices = In2.lightLayerIndex; lightLayerIndices = In2.lightLayerIndex;

Binary file not shown.

View File

@ -33,18 +33,31 @@ layout(set = 2, binding = 0) uniform CameraData
{ {
vec4 position; vec4 position;
mat4 vpMat; mat4 vpMat;
mat4 viewMat;
mat4 projMat;
} cameraData; } cameraData;
void main() void main()
{ {
Out2.materialIndex = gl_InstanceIndex; Out2.materialIndex = gl_InstanceIndex;
Out2.eid = integerData[0]; Out2.eid = integerData[0];
Out2.lightLayerIndex = integerData[1]; 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.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); Out.normal.rgb = normalize (Out.normal.rgb);
// clip space for rendering
gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f); gl_Position = cameraData.vpMat * worldTransform * vec4 (aVertexPos, 1.0f);
} }

Binary file not shown.

View File

@ -7,7 +7,7 @@ echo "SHADE DEPENDENCIES (Default - All in 10 Seconds)"
echo "A - All" echo "A - All"
echo "B - VMA" echo "B - VMA"
echo "C - msdf" echo "C - msdf"
echo "D - assimp" echo "D - ModelCompiler"
echo "E - spdlog" echo "E - spdlog"
echo "F - reactphysics3d" echo "F - reactphysics3d"
echo "G - imgui" echo "G - imgui"
@ -29,7 +29,7 @@ set _e=%ERRORLEVEL%
if %_e%==1 goto VMA if %_e%==1 goto VMA
if %_e%==2 goto VMA if %_e%==2 goto VMA
if %_e%==3 goto MSDF if %_e%==3 goto MSDF
if %_e%==4 goto assimp if %_e%==4 goto ModelCompiler
if %_e%==5 goto spdlog if %_e%==5 goto spdlog
if %_e%==6 goto reactphysics3d if %_e%==6 goto reactphysics3d
if %_e%==7 goto imgui if %_e%==7 goto imgui
@ -53,12 +53,13 @@ if %_e%==2 (goto :done) else (goto :MSDF)
echo -----------------------MSDF---------------------------- echo -----------------------MSDF----------------------------
rmdir "Dependencies/msdf" /S /Q rmdir "Dependencies/msdf" /S /Q
git clone --recurse-submodules https://github.com/SHADE-DP/msdf-atlas-gen.git "Dependencies/msdf" 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 :ModelCompiler
echo -----------------------assimp---------------------------- echo -----------------------ModelCompiler----------------------------
rmdir "Dependencies/assimp" /S /Q rmdir "Dependencies/ModelCompiler" /S /Q
git clone https://github.com/SHADE-DP/assimp.git "Dependencies/assimp" 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) if %_e%==4 (goto :done) else (goto :spdlog)
@REM :ktx @REM :ktx

View File

@ -1,5 +1,5 @@
IncludeDir = {} IncludeDir = {}
IncludeDir["assimp"] = "%{wks.location}\\Dependencies\\assimp" IncludeDir["ModelCompiler"] = "%{wks.location}\\Dependencies\\ModelCompiler"
IncludeDir["imgui"] = "%{wks.location}\\Dependencies\\imgui" IncludeDir["imgui"] = "%{wks.location}\\Dependencies\\imgui"
IncludeDir["imguizmo"] = "%{wks.location}\\Dependencies\\imguizmo" IncludeDir["imguizmo"] = "%{wks.location}\\Dependencies\\imguizmo"
IncludeDir["imnodes"] = "%{wks.location}\\Dependencies\\imnodes" IncludeDir["imnodes"] = "%{wks.location}\\Dependencies\\imnodes"

View File

@ -41,6 +41,8 @@
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Scenes/SBMainScene.h"
#include "Serialization/Configurations/SHConfigurationManager.h"
#include "Tools/SHLogger.h" #include "Tools/SHLogger.h"
#include "Tools/SHDebugDraw.h" #include "Tools/SHDebugDraw.h"
@ -60,8 +62,9 @@ namespace Sandbox
{ {
// Set working directory // Set working directory
SHFileUtilities::SetWorkDirToExecDir(); SHFileUtilities::SetWorkDirToExecDir();
WindowData wndData{};
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow); auto& appConfig = SHConfigurationManager::LoadApplicationConfig(&wndData);
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
// Create Systems // Create Systems
SHSystemManager::CreateSystem<SHGraphicsSystem>(); SHSystemManager::CreateSystem<SHGraphicsSystem>();
@ -73,11 +76,18 @@ namespace Sandbox
SHSystemManager::CreateSystem<SHCameraSystem>(); SHSystemManager::CreateSystem<SHCameraSystem>();
SHSystemManager::CreateSystem<SHDebugDrawSystem>(); SHSystemManager::CreateSystem<SHDebugDrawSystem>();
// Link up SHDebugDraw
SHDebugDraw::Init(SHSystemManager::GetSystem<SHDebugDrawSystem>());
#ifdef SHEDITOR #ifdef SHEDITOR
SDL_Init(SDL_INIT_VIDEO); SDL_Init(SDL_INIT_VIDEO);
sdlWindow = SDL_CreateWindowFrom(window.GetHWND()); sdlWindow = SDL_CreateWindowFrom(window.GetHWND());
SHSystemManager::CreateSystem<SHEditor>(); SHSystemManager::CreateSystem<SHEditor>();
SHSystemManager::GetSystem<SHEditor>()->SetSDLWindow(sdlWindow); if(auto editor = SHSystemManager::GetSystem<SHEditor>())
{
editor->SetSDLWindow(sdlWindow);
editor->SetSHWindow(&window);
}
#endif #endif
// Create Routines // Create Routines
@ -125,7 +135,7 @@ namespace Sandbox
SHSystemManager::Init(); SHSystemManager::Init();
SHSceneManager::InitSceneManager<SBTestScene>("TestScene"); SHSceneManager::InitSceneManager<SBMainScene>(appConfig.startingSceneID);
SHFrameRateController::UpdateFRC(); SHFrameRateController::UpdateFRC();
@ -151,7 +161,7 @@ namespace Sandbox
editor->PollPicking(); editor->PollPicking();
static bool drawColliders = false; static bool drawColliders = false;
if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::SPACE)) if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::F10))
{ {
drawColliders = !drawColliders; drawColliders = !drawColliders;
SHSystemManager::GetSystem<SHPhysicsSystem>()->SetDrawColliders(drawColliders); SHSystemManager::GetSystem<SHPhysicsSystem>()->SetDrawColliders(drawColliders);

View File

@ -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");
}
}

View File

@ -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;
};
}

View File

@ -53,7 +53,7 @@ namespace Sandbox
switch (asset.type) switch (asset.type)
{ {
case AssetType::MESH: case AssetType::MESH:
if (asset.name == "Cube.012") if (asset.name == "Raccoon")
handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id)); handles.emplace_back(SHResourceManager::LoadOrGet<SHMesh>(asset.id));
break; break;
case AssetType::TEXTURE: case AssetType::TEXTURE:
@ -65,58 +65,20 @@ namespace Sandbox
SHResourceManager::FinaliseChanges(); SHResourceManager::FinaliseChanges();
// Create Materials // Create Materials
auto matInst = graphicsSystem->AddOrGetBaseMaterialInstance(); auto baseRaccoonMat = graphicsSystem->AddOrGetBaseMaterialInstance();
auto customMat = graphicsSystem->AddMaterialInstanceCopy(matInst); auto baseRaccoonMatInstant = graphicsSystem->AddMaterialInstanceCopy(baseRaccoonMat);
customMat->SetProperty("data.color", SHVec4(0.0f, 1.0f, 1.0f, 1.0f)); baseRaccoonMatInstant->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
customMat->SetProperty("data.textureIndex", 0); baseRaccoonMatInstant->SetProperty("data.textureIndex", 0);
customMat->SetProperty("data.alpha", 0.1f); baseRaccoonMatInstant->SetProperty("data.alpha", 0.1f);
// Create Stress Test Objects auto baseFloorMatInstant = graphicsSystem->AddMaterialInstanceCopy(baseRaccoonMat);
static const SHVec3 TEST_OBJ_SCALE = SHVec3::One; baseFloorMatInstant->SetProperty("data.color", SHVec4(1.0f, 1.0f, 1.0f, 1.0f));
constexpr int NUM_ROWS = 3; baseFloorMatInstant->SetProperty("data.textureIndex", 0);
constexpr int NUM_COLS = 1; baseFloorMatInstant->SetProperty("data.alpha", 0.1f);
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 };
for (int y = 0; y < NUM_ROWS; ++y) auto dummy = SHEntityManager::CreateEntity<>();
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);
//renderable.Mesh = handles.front(); auto floor = SHEntityManager::CreateEntity<SHTransformComponent,SHRenderable, SHRigidBodyComponent, SHColliderComponent>();
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& floorRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(floor); auto& floorRenderable = *SHComponentManager::GetComponent_s<SHRenderable>(floor);
auto& floorTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(floor); auto& floorTransform = *SHComponentManager::GetComponent_s<SHTransformComponent>(floor);
auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor); auto& floorRigidBody = *SHComponentManager::GetComponent_s<SHRigidBodyComponent>(floor);
@ -125,7 +87,7 @@ namespace Sandbox
floorRenderable.SetMesh(CUBE_MESH); floorRenderable.SetMesh(CUBE_MESH);
floorRenderable.SetMaterial(graphicsSystem->GetDefaultMaterialInstance()); 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 }); floorTransform.SetWorldPosition({ 0.0f, -3.0f, -5.0f });
floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC); floorRigidBody.SetType(SHRigidBodyComponent::Type::STATIC);
@ -138,17 +100,97 @@ namespace Sandbox
//testObjRenderable.Mesh = CUBE_MESH; //testObjRenderable.Mesh = CUBE_MESH;
//testObjRenderable.SetMaterial(matInst); //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>()); 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 raccoonShowcase = SHEntityManager::CreateEntity<SHRenderable, SHTransformComponent>();
auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase); auto& renderableShowcase = *SHComponentManager::GetComponent_s<SHRenderable>(raccoonShowcase);
auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase); auto& transformShowcase = *SHComponentManager::GetComponent_s<SHTransformComponent>(raccoonShowcase);
renderableShowcase.SetMesh(handles.front()); renderableShowcase.SetMesh(handles.front());
renderableShowcase.SetMaterial(customMat); renderableShowcase.SetMaterial(baseRaccoonMatInstant);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.color", SHVec4(0.0f, 0.0f, 0.0f, 0.0f)); 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.alpha", 1.0f);
renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 0); renderableShowcase.GetModifiableMaterial()->SetProperty("data.textureIndex", 0);

View File

@ -26,7 +26,6 @@ project "SHADE_Engine"
externalincludedirs externalincludedirs
{ {
"%{IncludeDir.assimp}\\include",
"%{IncludeDir.imgui}", "%{IncludeDir.imgui}",
"%{IncludeDir.imguizmo}", "%{IncludeDir.imguizmo}",
"%{IncludeDir.imnodes}", "%{IncludeDir.imnodes}",
@ -52,8 +51,6 @@ project "SHADE_Engine"
{ {
"%{prj.location}/libs", "%{prj.location}/libs",
"%{IncludeDir.VULKAN}/Lib", "%{IncludeDir.VULKAN}/Lib",
"%{IncludeDir.assimp}/lib/Debug",
"%{IncludeDir.assimp}/lib/Release",
"%{IncludeDir.RTTR}/lib", "%{IncludeDir.RTTR}/lib",
"%{IncludeDir.SDL}/lib", "%{IncludeDir.SDL}/lib",
"%{IncludeDir.spdlog}/lib", "%{IncludeDir.spdlog}/lib",
@ -119,7 +116,8 @@ project "SHADE_Engine"
filter "configurations:Debug" filter "configurations:Debug"
postbuildcommands 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\\fmodL.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudioL.dll\" \"$(OutDir)\"" "xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudioL.dll\" \"$(OutDir)\""
} }
@ -127,7 +125,8 @@ project "SHADE_Engine"
filter "configurations:Release" filter "configurations:Release"
postbuildcommands 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\\fmod.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\"" "xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
} }
@ -135,32 +134,35 @@ project "SHADE_Engine"
filter "configurations:Publish" filter "configurations:Publish"
postbuildcommands 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\\fmod.dll\" \"$(OutDir)\"",
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\"" "xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
} }
filter "configurations:Publish" 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' warnings 'Extra'
filter "configurations:Debug" filter "configurations:Debug"
symbols "On" symbols "On"
defines {"_DEBUG", "SHEDITOR"} 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"} links{"fmodstudioL_vc.lib", "fmodL_vc.lib"}
filter "configurations:Release" filter "configurations:Release"
optimize "On" optimize "On"
defines{"_RELEASE", "SHEDITOR"} 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"} links{"fmodstudio_vc.lib", "fmod_vc.lib"}
filter "configurations:Publish" filter "configurations:Publish"
optimize "On" optimize "On"
defines{"_RELEASE", "_PUBLISH"} defines{"_RELEASE", "_PUBLISH"}
links{"assimp-vc142-mt.lib", "librttr_core.lib", "spdlog.lib"} links{"librttr_core.lib", "spdlog.lib"}
excludes excludes
{ {
-- "%{prj.location}/src/Editor/**.cpp", -- "%{prj.location}/src/Editor/**.cpp",

View File

@ -1,4 +1,4 @@
#pragma once #pragma once
#include "SHMeshAsset.h" #include "SHModelAsset.h"
#include "SHTextureAsset.h" #include "SHTextureAsset.h"

View File

@ -18,24 +18,31 @@
namespace SHADE namespace SHADE
{ {
struct SH_API SHMeshAssetHeader struct SHMeshAssetHeader
{ {
uint32_t vertexCount; uint32_t vertexCount;
uint32_t indexCount; uint32_t indexCount;
std::string name; std::string name;
}; };
struct SH_API SHMeshAsset : SHAssetData struct SHModelAssetHeader
{ {
bool compiled; size_t meshCount;
bool changed; };
struct SH_API SHMeshData : SHAssetData
{
SHMeshAssetHeader header; 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; struct SH_API SHModelAsset : SHAssetData
std::vector<SHVec3> vertexTangent; {
std::vector<SHVec3> vertexNormal; SHModelAssetHeader header;
std::vector<SHVec2> texCoords; std::vector<SHMeshData*> subMeshes;
std::vector<uint32_t> indices;
}; };
} }

View File

@ -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;
}
}

View File

@ -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;
};
}

View File

@ -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();
}
}

View File

@ -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)
{
}
}

View File

@ -1,5 +1,5 @@
/*************************************************************************//** /*************************************************************************//**
* \file SHMeshLoader.h * \file SHModelLoader.h
* \author Loh Xiao Qi * \author Loh Xiao Qi
* \date 30 September 2022 * \date 30 September 2022
* \brief Library to load gltf mesh files and custom binary format * \brief Library to load gltf mesh files and custom binary format
@ -10,14 +10,27 @@
* of DigiPen Institute of Technology is prohibited. * of DigiPen Institute of Technology is prohibited.
*****************************************************************************/ *****************************************************************************/
#pragma once #pragma once
#include "Assets/Asset Types/SHMeshAsset.h" #include "Assets/Asset Types/SHModelAsset.h"
#include "SHAssetLoader.h" #include "SHAssetLoader.h"
#include <fstream>
namespace SHADE 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; SHAssetData* Load(AssetPath path) override;
void Write(SHAssetData const* data, AssetPath path) override; void Write(SHAssetData const* data, AssetPath path) override;
}; };

View File

@ -22,5 +22,10 @@ namespace SHADE
AssetID id; AssetID id;
AssetType type; AssetType type;
AssetPath path; AssetPath path;
bool isSubAsset;
std::vector<SHAsset*> subAssets;
AssetID parent;
}; };
} }

View File

@ -47,10 +47,11 @@ enum class AssetType : AssetTypeMeta
SHADER, SHADER,
SHADER_BUILT_IN, SHADER_BUILT_IN,
TEXTURE, TEXTURE,
MESH, MODEL,
SCENE, SCENE,
PREFAB, PREFAB,
MATERIAL, MATERIAL,
MESH,
MAX_COUNT MAX_COUNT
}; };
constexpr size_t TYPE_COUNT{ static_cast<size_t>(AssetType::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" }; constexpr std::string_view BUILT_IN_ASSET_ROOT{ "../../Built_In" };
#endif #endif
// COMPILER PATHS
constexpr std::string_view MODEL_COMPILER_EXE{ "ModelCompiler.exe" };
// INTERNAL ASSET PATHS // INTERNAL ASSET PATHS
constexpr std::string_view SCENE_FOLDER{ "/Scenes/" }; constexpr std::string_view SCENE_FOLDER{ "/Scenes/" };
constexpr std::string_view PREFAB_FOLDER{ "/Prefabs/" }; 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 PREFAB_EXTENSION {".shprefab"};
constexpr std::string_view MATERIAL_EXTENSION {".shmat"}; constexpr std::string_view MATERIAL_EXTENSION {".shmat"};
constexpr std::string_view TEXTURE_EXTENSION {".shtex"}; 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[] = { constexpr std::string_view EXTENSIONS[] = {
AUDIO_EXTENSION, AUDIO_EXTENSION,
@ -89,7 +93,7 @@ constexpr std::string_view EXTENSIONS[] = {
SHADER_BUILT_IN_EXTENSION, SHADER_BUILT_IN_EXTENSION,
MATERIAL_EXTENSION, MATERIAL_EXTENSION,
TEXTURE_EXTENSION, TEXTURE_EXTENSION,
MESH_EXTENSION, MODEL_EXTENSION,
SCRIPT_EXTENSION, SCRIPT_EXTENSION,
SCENE_EXTENSION, SCENE_EXTENSION,
PREFAB_EXTENSION, PREFAB_EXTENSION,

View File

@ -11,15 +11,17 @@
#include <random> #include <random>
#include <chrono> #include <chrono>
#include <ranges> #include <ranges>
#include <cstdlib>
#include "SHAssetManager.h" #include "SHAssetManager.h"
#include "SHAssetMetaHandler.h" #include "SHAssetMetaHandler.h"
#include "Libraries/Loaders/SHMeshLoader.h" #include "Libraries/Loaders/SHModelLoader.h"
#include "Libraries/Loaders/SHTextureLoader.h" #include "Libraries/Loaders/SHTextureLoader.h"
#include "Libraries/Loaders/SHShaderSourceLoader.h" #include "Libraries/Loaders/SHShaderSourceLoader.h"
#include "Libraries/Loaders/SHTextBasedLoader.h" #include "Libraries/Loaders/SHTextBasedLoader.h"
#include "Libraries/Compilers/SHMeshCompiler.h" //#include "Libraries/Compilers/SHMeshCompiler.h"
#include "Libraries/Compilers/SHTextureCompiler.h" #include "Libraries/Compilers/SHTextureCompiler.h"
#include "Libraries/Compilers/SHShaderSourceCompiler.h" #include "Libraries/Compilers/SHShaderSourceCompiler.h"
@ -157,16 +159,22 @@ namespace SHADE
{ {
case AssetType::PREFAB: case AssetType::PREFAB:
newPath += PREFAB_FOLDER; newPath += PREFAB_FOLDER;
newPath += name;
newPath += PREFAB_EXTENSION;
data = new SHPrefabAsset(); data = new SHPrefabAsset();
break; break;
case AssetType::SCENE: case AssetType::SCENE:
newPath += SCENE_FOLDER; newPath += SCENE_FOLDER;
newPath += name;
newPath += SCENE_EXTENSION;
data = new SHSceneAsset(); data = new SHSceneAsset();
break; break;
case AssetType::MATERIAL: case AssetType::MATERIAL:
newPath += MATERIAL_FOLDER; newPath += MATERIAL_FOLDER;
newPath += name;
newPath += MATERIAL_EXTENSION;
data = new SHMaterialAsset(); data = new SHMaterialAsset();
break; break;
@ -180,7 +188,8 @@ namespace SHADE
name, name,
id, id,
type, type,
newPath newPath,
false
}; };
assetCollection.insert({ assetCollection.insert({
@ -189,7 +198,8 @@ namespace SHADE
name, name,
id, id,
type, type,
newPath newPath,
false
) )
}); });
@ -328,25 +338,32 @@ namespace SHADE
return result; 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() }; auto const ext{ path.extension().string() };
if (ext == GLSL_EXTENSION.data()) if (ext == GLSL_EXTENSION.data())
{ {
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value(); newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN); }
newAsset.type = AssetType::SHADER_BUILT_IN; 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 FolderPointer SHAssetManager::GetRootFolder() noexcept
@ -399,46 +416,28 @@ namespace SHADE
for (auto const& path : paths) for (auto const& path : paths)
{ {
SHAsset newAsset AssetPath newPath;
{
.name = path.stem().string()
};
auto const ext{ path.extension().string() }; auto const ext{ path.extension().string() };
if (ext == GLSL_EXTENSION.data()) if (ext == GLSL_EXTENSION.data())
{ {
newAsset.path = SHShaderSourceCompiler::LoadAndCompileShader(path).value(); newPath = SHShaderSourceCompiler::LoadAndCompileShader(path).value();
newAsset.id = GenerateAssetID(AssetType::SHADER_BUILT_IN);
newAsset.type = AssetType::SHADER_BUILT_IN;
} }
else if (ext == DDS_EXTENSION.data()) else if (ext == DDS_EXTENSION.data())
{ {
newAsset.path = SHTextureCompiler::CompileTextureAsset(path).value(); newPath = SHTextureCompiler::CompileTextureAsset(path).value();
newAsset.id = GenerateAssetID(AssetType::TEXTURE);
newAsset.type = AssetType::TEXTURE;
} }
else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data()) else if (ext == GLTF_EXTENSION.data() || ext == FBX_EXTENSION.data())
{ {
std::vector<SHMeshAsset*> meshes; std::string command = MODEL_COMPILER_EXE.data();
std::vector<SHAnimationAsset*> anims; command += " " + path.string();
SHMeshCompiler::LoadFromFile(path, meshes, anims); std::system(command.c_str());
for (auto const& mesh : meshes) std::string modelPath = path.string().substr(0, path.string().find_last_of('.'));
{ modelPath += MODEL_EXTENSION;
SHAsset meshAsset{ newPath = modelPath;
.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;
} }
assetCollection.insert({ newAsset.id, newAsset }); GenerateNewMeta(newPath);
SHAssetMetaHandler::WriteMetaData(newAsset);
} }
} }
@ -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)] = 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::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::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::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::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::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 void SHAssetManager::Load() noexcept
{ {
//CompileAll();
BuildAssetCollection(); BuildAssetCollection();
InitLoaders(); InitLoaders();
//CompileAll();
//LoadAllData(); //LoadAllData();
} }
@ -484,8 +484,12 @@ namespace SHADE
SHAssetData* SHAssetManager::LoadData(SHAsset const& asset) noexcept 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) if (data == nullptr)
{ {
SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string()); SHLOG_ERROR("Unable to load asset into memory: {}\n", asset.path.string());
@ -498,8 +502,120 @@ namespace SHADE
return data; 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 void SHAssetManager::BuildAssetCollection() noexcept
{ {
SHFileSystem::BuildDirectory(ASSET_ROOT.data(), folderRoot, assetCollection); 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];
}
}
}
} }
} }

View File

@ -87,7 +87,7 @@ namespace SHADE
static std::vector<SHAssetData const*> GetAllDataOfType(AssetType type) noexcept; static std::vector<SHAssetData const*> GetAllDataOfType(AssetType type) noexcept;
static std::vector<SHAsset> GetAllRecordOfType(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; static FolderPointer GetRootFolder() noexcept;
@ -96,6 +96,10 @@ namespace SHADE
static void InitLoaders() noexcept; static void InitLoaders() noexcept;
static void LoadAllData() noexcept; static void LoadAllData() noexcept;
static SHAssetData* LoadData(SHAsset const& asset) 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; inline static void BuildAssetCollection() noexcept;
static bool IsRecognised(char const*) noexcept; static bool IsRecognised(char const*) noexcept;

View File

@ -9,7 +9,6 @@
******************************************************************************/ ******************************************************************************/
#include "SHpch.h" #include "SHpch.h"
#include "SHAssetMetaHandler.h" #include "SHAssetMetaHandler.h"
#include <fstream>
#include <sstream> #include <sstream>
namespace SHADE namespace SHADE
@ -21,11 +20,15 @@ namespace SHADE
* \brief Helper function to retrieve field value from meta data file * \brief Helper function to retrieve field value from meta data file
* for processing * for processing
****************************************************************************/ ****************************************************************************/
void GetFieldValue(std::ifstream& file, std::string& line) noexcept bool GetFieldValue(std::ifstream& file, std::string& line) noexcept
{ {
line = ""; line = "";
std::getline(file, line); if (std::getline(file, line))
{
line = line.substr(line.find_last_of(':') + 2, line.length()); 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 }; std::ifstream metaFile{ path.string(), std::ios_base::in };
if (!metaFile.is_open()) if (!metaFile.is_open())
{ {
// Error unable to open SHLOG_ERROR("Unable to open meta file: {}", path.string());
return {};
} }
std::string line; std::string line;
@ -93,6 +97,43 @@ namespace SHADE
typeStream >> type; typeStream >> type;
meta.type = static_cast<AssetType>(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(); metaFile.close();
meta.path = path.parent_path().string() + "/" + path.stem().string(); meta.path = path.parent_path().string() + "/" + path.stem().string();
@ -108,6 +149,12 @@ namespace SHADE
****************************************************************************/ ****************************************************************************/
void SHAssetMetaHandler::WriteMetaData(SHAsset const& meta) noexcept void SHAssetMetaHandler::WriteMetaData(SHAsset const& meta) noexcept
{ {
if (meta.isSubAsset)
{
SHLOG_WARNING("Cannot write subasset meta: {}", meta.name);
return;
}
//TODO: Write into binary eventually //TODO: Write into binary eventually
std::string path{ meta.path.string() }; std::string path{ meta.path.string() };
path.append(META_EXTENSION); path.append(META_EXTENSION);
@ -124,7 +171,23 @@ namespace SHADE
metaFile << "ID: " << meta.id << "\n"; metaFile << "ID: " << meta.id << "\n";
metaFile << "Type: " << static_cast<AssetTypeMeta>(meta.type) << std::endl; 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(); 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;
}
} }

View File

@ -12,6 +12,7 @@
#include "SHAssetMacros.h" #include "SHAssetMacros.h"
#include "SHAsset.h" #include "SHAsset.h"
#include <fstream>
namespace SHADE namespace SHADE
{ {
@ -45,6 +46,8 @@ namespace SHADE
* \brief Writes meta data into text file * \brief Writes meta data into text file
****************************************************************************/ ****************************************************************************/
static void WriteMetaData(SHAsset const&) noexcept; static void WriteMetaData(SHAsset const&) noexcept;
static void WriteSubAssetMeta(std::ofstream&, SHAsset const&) noexcept;
}; };
} }

View File

@ -5,15 +5,19 @@
#include "Editor/SHImGuiHelpers.hpp" #include "Editor/SHImGuiHelpers.hpp"
#include <imgui.h> #include <imgui.h>
#include <imgui_internal.h> #include <imgui_internal.h>
#include <misc/cpp/imgui_stdlib.h>
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "ECS_Base/Managers/SHSystemManager.h"
#include "Editor/IconsFontAwesome6.h" #include "Editor/IconsFontAwesome6.h"
#include "Editor/SHEditor.h"
#include "Editor/DragDrop/SHDragDrop.hpp" #include "Editor/DragDrop/SHDragDrop.hpp"
#include "Editor/EditorWindow/MaterialInspector/SHMaterialInspector.h"
namespace SHADE namespace SHADE
{ {
SHAssetBrowser::SHAssetBrowser() 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; flags |= ImGuiTreeNodeFlags_DefaultOpen;
bool isOpen = ImGui::TreeNodeEx(folder, flags, "%s %s", ICON_MD_FOLDER, folder->name.data()); 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()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
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()) if (ImGui::IsItemClicked())
{ {
selectedFolders.clear(); selectedFolders.clear();
selectedFolders.push_back(folder); selectedFolders.push_back(folder);
} }
if (isOpen) if (isOpen)
{ {
const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark); const ImColor treeLineColor = ImGui::GetColorU32(ImGuiCol_CheckMark);
@ -79,13 +102,18 @@ namespace SHADE
} }
for (auto const& file : files) for (auto const& file : files)
{ {
if(file.assetMeta == nullptr)
continue;
const float horizontalLineSize = 25.0f; 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; const float midPoint = (childRect.Min.y + childRect.Max.y) * 0.5f;
drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1); drawList->AddLine(ImVec2(vertLineStart.x, midPoint), ImVec2(vertLineStart.x + horizontalLineSize, midPoint), treeLineColor, 1);
vertLineEnd.y = midPoint; vertLineEnd.y = midPoint;
} }
drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1); drawList->AddLine(vertLineStart, vertLineEnd, treeLineColor, 1);
if(assetBeingCreated.has_value() && std::get<0>(assetBeingCreated.value()) == folder)
DrawAssetBeingCreated();
ImGui::TreePop(); ImGui::TreePop();
} }
return nodeRect; 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()); return ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
const bool isSelected = std::ranges::find(selectedAssets, file.assetMeta->id) != selectedAssets.end(); const bool isSelected = std::ranges::find(selectedAssets, asset->id) != selectedAssets.end();
ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf; ImGuiTreeNodeFlags flags = (!asset->subAssets.empty()) ? ImGuiTreeNodeFlags_OpenOnArrow : ImGuiTreeNodeFlags_Leaf;
if (isSelected) if (isSelected)
flags |= ImGuiTreeNodeFlags_Selected; flags |= ImGuiTreeNodeFlags_Selected;
std::string icon{}; std::string icon{};
switch(file.assetMeta->type) switch (asset->type)
{ {
case AssetType::INVALID: break; case AssetType::INVALID: break;
case AssetType::SHADER: icon = ICON_FA_FILE_CODE; break; case AssetType::SHADER: icon = ICON_FA_FILE_CODE; break;
case AssetType::SHADER_BUILT_IN: 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::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::SCENE: icon = ICON_MD_IMAGE; break;
case AssetType::PREFAB: icon = ICON_FA_BOX_OPEN; break; case AssetType::PREFAB: icon = ICON_FA_BOX_OPEN; break;
case AssetType::MATERIAL: break; case AssetType::MATERIAL: break;
case AssetType::MESH: icon = ICON_FA_CUBES; break;
case AssetType::MAX_COUNT: 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()); const ImRect nodeRect = ImRect(ImGui::GetItemRectMin(), ImGui::GetItemRectMax());
if (SHDragDrop::BeginSource()) if (SHDragDrop::BeginSource())
{ {
auto id = file.assetMeta->id; auto id = asset->id;
ImGui::Text("Moving Asset: %s [%zu]", file.name.data(), file.assetMeta->id); ImGui::Text("Moving Asset: %s [%zu]", asset->name.data(), asset->id);
SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id); SHDragDrop::SetPayload<AssetID>(SHDragDrop::DRAG_RESOURCE, &id);
SHDragDrop::EndSource(); SHDragDrop::EndSource();
} }
if (ImGui::IsItemClicked()) if (ImGui::IsItemClicked())
{ {
selectedAssets.clear(); 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(); ImGui::TreePop();
}
return nodeRect; 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();
}
}
} }

View File

@ -10,6 +10,7 @@ namespace SHADE
class SHAssetBrowser final : public SHEditorWindow class SHAssetBrowser final : public SHEditorWindow
{ {
public: public:
using AssetEntry = std::tuple<FolderPointer, AssetType, std::string>;
SHAssetBrowser(); SHAssetBrowser();
void Init(); void Init();
@ -20,12 +21,13 @@ namespace SHADE
void DrawMenuBar(); void DrawMenuBar();
ImRect RecursivelyDrawTree(FolderPointer folder); ImRect RecursivelyDrawTree(FolderPointer folder);
void DrawCurrentFolder(); void DrawCurrentFolder();
ImRect DrawFile(SHFile const& file) noexcept; ImRect DrawFile(SHAsset const* const asset) noexcept;
void DrawAssetBeingCreated() noexcept;
FolderPointer rootFolder, prevFolder, currentFolder; FolderPointer rootFolder, prevFolder, currentFolder;
std::optional<AssetEntry> assetBeingCreated;
std::vector<FolderPointer> selectedFolders; std::vector<FolderPointer> selectedFolders;
std::vector<AssetID> selectedAssets; std::vector<AssetID> selectedAssets;
static constexpr float tileWidth = 50.0f; static constexpr float tileWidth = 50.0f;
}; };
} }

View File

@ -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(); ImGui::End();
} }
@ -195,7 +201,7 @@ namespace SHADE
if (SHDragDrop::BeginSource()) if (SHDragDrop::BeginSource())
{ {
std::string moveLabel = "Moving EID: "; std::string moveLabel = "Moving EID: ";
static std::vector<EntityID> draggingEntities = editor->selectedEntities; draggingEntities = editor->selectedEntities;
if (!isSelected) if (!isSelected)
{ {
draggingEntities.clear(); 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 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(); SHDragDrop::EndTarget();
} }
} }
@ -255,7 +262,7 @@ namespace SHADE
if ((currentNode->GetParent() != sceneGraph.GetRoot()) && ImGui::Selectable(std::format("{} Unparent Selected", ICON_MD_NORTH_WEST).data())) 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(); ImGui::EndPopup();
} }
@ -323,14 +330,16 @@ namespace SHADE
SHEntityManager::CreateEntity(MAX_EID, "DefaultChild", parentEID); 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& sceneGraph = SHSceneManager::GetCurrentSceneGraph();
auto const editor = SHSystemManager::GetSystem<SHEditor>(); //auto const editor = SHSystemManager::GetSystem<SHEditor>();
SHEntityParentCommand::EntityParentData entityParentData; SHEntityParentCommand::EntityParentData entityParentData;
std::vector<EntityID> parentedEIDS; 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) if (sceneGraph.GetChild(eid, parentEID) == nullptr)
{ {
parentedEIDS.push_back(eid); parentedEIDS.push_back(eid);

View File

@ -28,7 +28,7 @@ namespace SHADE
void DrawMenuBar() const noexcept; void DrawMenuBar() const noexcept;
ImRect RecursivelyDrawEntityNode(SHSceneNode* const); ImRect RecursivelyDrawEntityNode(SHSceneNode* const);
void CreateChildEntity(EntityID parentEID) const noexcept; 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 SelectRangeOfEntities(EntityID beginEID, EntityID EndEID);
void SelectAllEntities(); void SelectAllEntities();
void CopySelectedEntities(); void CopySelectedEntities();
@ -37,6 +37,8 @@ namespace SHADE
std::string filter; std::string filter;
bool isAnyNodeSelected = false; bool isAnyNodeSelected = false;
EntityID scrollTo = MAX_EID; EntityID scrollTo = MAX_EID;
std::vector<EntityID> draggingEntities;
};//class SHHierarchyPanel };//class SHHierarchyPanel
//Might move to a different file //Might move to a different file

View File

@ -244,9 +244,12 @@ namespace SHADE
SHCollider* collider = &component->GetCollider(i); SHCollider* collider = &component->GetCollider(i);
auto cursorPos = ImGui::GetCursorPos(); auto cursorPos = ImGui::GetCursorPos();
//collider->IsTrigger
if (collider->GetType() == SHCollider::Type::BOX) if (collider->GetType() == SHCollider::Type::BOX)
{ {
SHEditorWidgets::BeginPanel(std::format("{} Box Collider #{}", ICON_FA_CUBE, i).data(), { ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y }); 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()); auto box = reinterpret_cast<SHBoundingBox*>(collider->GetShape());
SHEditorWidgets::DragVec3 SHEditorWidgets::DragVec3
( (
@ -257,6 +260,7 @@ namespace SHADE
else if (collider->GetType() == SHCollider::Type::SPHERE) 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::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()); auto sphere = reinterpret_cast<SHBoundingSphere*>(collider->GetShape());
SHEditorWidgets::DragFloat SHEditorWidgets::DragFloat
( (
@ -372,6 +376,7 @@ namespace SHADE
{ {
DrawContextMenu(component); DrawContextMenu(component);
Handle<SHMesh> const& mesh = component->GetMesh(); 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]() 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)); component->SetMesh(SHResourceManager::LoadOrGet<SHMesh>(id));
SHResourceManager::FinaliseChanges(); SHResourceManager::FinaliseChanges();
}, SHDragDrop::DRAG_RESOURCE); }, 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 else
{ {

View File

@ -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;
}
}
}
}

View File

@ -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;
};
}

View File

@ -3,6 +3,7 @@
//#==============================================================# //#==============================================================#
//|| SHADE Includes || //|| SHADE Includes ||
//#==============================================================# //#==============================================================#
#include "Editor/SHEditorWidgets.hpp"
#include "Editor/SHEditor.h" #include "Editor/SHEditor.h"
#include "SHEditorMenuBar.h" #include "SHEditorMenuBar.h"
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
@ -17,7 +18,11 @@
#include <imgui_internal.h> #include <imgui_internal.h>
#include <rttr/type> #include <rttr/type>
#include "Assets/SHAssetManager.h"
#include "Assets/Asset Types/SHSceneAsset.h"
#include "Scene/SHSceneManager.h"
#include "Serialization/SHSerialization.h" #include "Serialization/SHSerialization.h"
#include "Serialization/Configurations/SHConfigurationManager.h"
namespace SHADE namespace SHADE
{ {
@ -75,13 +80,17 @@ namespace SHADE
{ {
if (ImGui::BeginMenu("File")) if (ImGui::BeginMenu("File"))
{ {
if(ImGui::Selectable("New Scene"))
{
SHSystemManager::GetSystem<SHEditor>()->NewScene();
}
if(ImGui::Selectable("Save")) if(ImGui::Selectable("Save"))
{ {
SHSerialization::SerializeSceneToFile("../../Assets/Scenes/Test.SHADE"); SHSystemManager::GetSystem<SHEditor>()->SaveScene();
} }
if(ImGui::Selectable("Load")) if(ImGui::Selectable("Load"))
{ {
SHSerialization::DeserializeSceneFromFile("../../Assets/Scenes/Test.SHADE"); //SHSystemManager::GetSystem<SHEditor>()->LoadScene()
} }
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -108,16 +117,22 @@ namespace SHADE
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>()); auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->GenerateScriptsCsProjFile(); scriptEngine->GenerateScriptsCsProjFile();
} }
ImGui::BeginDisabled(SHSystemManager::GetSystem<SHEditor>()->editorState != SHEditor::State::STOP);
if (ImGui::Selectable("Build Scripts - Debug")) if (ImGui::Selectable("Build Scripts - Debug"))
{ {
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>()); auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
scriptEngine->BuildScriptAssembly(true, true); scriptEngine->BuildScriptAssembly(true, true);
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
} }
if (ImGui::Selectable("Build Scripts - Release")) if (ImGui::Selectable("Build Scripts - Release"))
{ {
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>()); auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
scriptEngine->BuildScriptAssembly(false, true); scriptEngine->BuildScriptAssembly(false, true);
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
} }
ImGui::EndDisabled();
ImGui::EndMenu(); ImGui::EndMenu();
} }
@ -155,6 +170,35 @@ namespace SHADE
} }
ImGui::EndMenu(); 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(); ImGui::EndMainMenuBar();
} }
@ -174,6 +218,8 @@ namespace SHADE
const auto editor = SHSystemManager::GetSystem<SHEditor>(); const auto editor = SHSystemManager::GetSystem<SHEditor>();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY); ImGui::BeginDisabled(editor->editorState == SHEditor::State::PLAY);
if(ImGui::SmallButton(ICON_MD_PLAY_ARROW)) if(ImGui::SmallButton(ICON_MD_PLAY_ARROW))
{
if(editor->SaveScene())
{ {
const SHEditorStateChangeEvent STATE_CHANGE_EVENT const SHEditorStateChangeEvent STATE_CHANGE_EVENT
{ {
@ -183,6 +229,7 @@ namespace SHADE
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT); SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_PLAY_EVENT);
} }
}
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE); ImGui::BeginDisabled(editor->editorState == SHEditor::State::PAUSE);
if(ImGui::SmallButton(ICON_MD_PAUSE)) if(ImGui::SmallButton(ICON_MD_PAUSE))
@ -206,6 +253,7 @@ namespace SHADE
editor->editorState = SHEditor::State::STOP; editor->editorState = SHEditor::State::STOP;
SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT); SHEventManager::BroadcastEvent<SHEditorStateChangeEvent>(STATE_CHANGE_EVENT, SH_EDITOR_ON_STOP_EVENT);
editor->LoadScene(SHSceneManager::GetCurrentSceneAssetID());
} }
ImGui::EndDisabled(); ImGui::EndDisabled();
ImGui::EndMenuBar(); ImGui::EndMenuBar();

View File

@ -19,7 +19,7 @@ namespace SHADE
//|| Public Member Functions || //|| Public Member Functions ||
//#==============================================================# //#==============================================================#
SHEditorWindow::SHEditorWindow(std::string_view const& name, ImGuiWindowFlags const& inFlags) 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::OnPosChange()
{ {
} }
void SHEditorWindow::SetFocusToWindow()
{
ImGui::SetWindowFocus(windowName.data());
}
}//namespace SHADE }//namespace SHADE

View File

@ -34,6 +34,7 @@ namespace SHADE
virtual bool Begin(); virtual bool Begin();
virtual void OnResize(); virtual void OnResize();
virtual void OnPosChange(); virtual void OnPosChange();
virtual void SetFocusToWindow();
ImGuiWindowFlags windowFlags = 0; ImGuiWindowFlags windowFlags = 0;
ImGuiIO& io; ImGuiIO& io;

View File

@ -5,3 +5,4 @@
#include "Profiling/SHEditorProfiler.h" //Profiler #include "Profiling/SHEditorProfiler.h" //Profiler
#include "ViewportWindow/SHEditorViewport.h" //Editor Viewport #include "ViewportWindow/SHEditorViewport.h" //Editor Viewport
#include "AssetBrowser/SHAssetBrowser.h" //Asset Browser #include "AssetBrowser/SHAssetBrowser.h" //Asset Browser
#include "MaterialInspector/SHMaterialInspector.h" //Material Inspector

View File

@ -45,7 +45,12 @@
#include <backends/imgui_impl_sdl.h> #include <backends/imgui_impl_sdl.h>
#include <backends/imgui_impl_vulkan.h> #include <backends/imgui_impl_vulkan.h>
#include "Assets/SHAssetManager.h"
#include "Assets/Asset Types/SHSceneAsset.h"
#include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h" #include "Graphics/MiddleEnd/Interface/SHMousePickSystem.h"
#include "Scene/SHSceneManager.h"
#include "Serialization/SHSerialization.h"
#include "Tools/SHDebugDraw.h"
RTTR_REGISTRATION RTTR_REGISTRATION
{ {
@ -77,7 +82,6 @@ namespace SHADE
//#==============================================================# //#==============================================================#
void SHEditor::Init() void SHEditor::Init()
{ {
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
if(auto context = ImGui::CreateContext()) if(auto context = ImGui::CreateContext())
{ {
@ -93,6 +97,8 @@ namespace SHADE
SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>(); SHEditorWindowManager::CreateEditorWindow<SHEditorInspector>();
SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>(); SHEditorWindowManager::CreateEditorWindow<SHEditorProfiler>();
SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>(); SHEditorWindowManager::CreateEditorWindow<SHAssetBrowser>();
SHEditorWindowManager::CreateEditorWindow<SHMaterialInspector>();
SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>(); SHEditorWindowManager::CreateEditorWindow<SHEditorViewport>();
io = &ImGui::GetIO(); io = &ImGui::GetIO();
@ -120,6 +126,17 @@ namespace SHADE
window->Init(); 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") SHLOG_INFO("Successfully initialised SHADE Engine Editor")
} }
@ -135,6 +152,8 @@ namespace SHADE
} }
} }
RenderSceneNamePrompt();
RenderUnsavedChangesPrompt();
//PollPicking(); //PollPicking();
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z)) 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 void SHEditor::InitLayout() noexcept
{ {
if(!std::filesystem::exists(io->IniFilename)) if(!std::filesystem::exists(io->IniFilename))
@ -180,6 +253,97 @@ namespace SHADE
io->Fonts->Build(); 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() void SHEditor::Exit()
{ {
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values) 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() void SHEditor::NewFrame()
{ {
SDL_Event event; SDL_Event event;

View File

@ -17,13 +17,17 @@
#include "EditorWindow/SHEditorWindow.h" #include "EditorWindow/SHEditorWindow.h"
#include "Tools/SHLog.h" #include "Tools/SHLog.h"
#include "Gizmos/SHTransformGizmo.h" #include "Gizmos/SHTransformGizmo.h"
#include "Events/SHEventDefines.h"
#include "Events/SHEvent.h"
#include "Graphics/Windowing/SHWindow.h"
//#==============================================================# //#==============================================================#
//|| Library Includes || //|| Library Includes ||
//#==============================================================# //#==============================================================#
#include <SDL_video.h> #include <SDL_video.h>
#include "Assets/SHAssetMacros.h"
namespace SHADE namespace SHADE
{ {
//#==============================================================# //#==============================================================#
@ -170,9 +174,16 @@ namespace SHADE
void InitBackend(); void InitBackend();
void SetSDLWindow(SDL_Window* inSDLWindow){sdlWindow = inSDLWindow;}; void SetSDLWindow(SDL_Window* inSDLWindow){sdlWindow = inSDLWindow;};
void SetSHWindow(SHWindow* inWindow){shWindow = inWindow;}
void PollPicking(); void PollPicking();
void NewScene();
bool SaveScene(std::string const& newSceneName = {});
void LoadScene(AssetID const& assetID) noexcept;
// List of selected entities // List of selected entities
std::vector<EntityID> selectedEntities; std::vector<EntityID> selectedEntities;
@ -190,16 +201,34 @@ namespace SHADE
*/ */
void Render(); void Render();
void RenderSceneNamePrompt() noexcept;
void RenderUnsavedChangesPrompt() noexcept;
void InitLayout() noexcept; void InitLayout() noexcept;
void InitFonts() 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 to command pool used for ImGui Vulkan Backend
Handle<SHVkCommandPool> imguiCommandPool; Handle<SHVkCommandPool> imguiCommandPool;
// Handle to command buffer used for ImGui Vulkan Backend // Handle to command buffer used for ImGui Vulkan Backend
Handle<SHVkCommandBuffer> imguiCommandBuffer; Handle<SHVkCommandBuffer> imguiCommandBuffer;
SDL_Window* sdlWindow {nullptr}; SDL_Window* sdlWindow {nullptr};
SHWindow* shWindow {nullptr};
ImGuiIO* io{nullptr}; ImGuiIO* io{nullptr};

View File

@ -157,7 +157,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::Checkbox("#", &value); return ImGui::Checkbox("##", &value);
} }
bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered) bool SHEditorUI::InputInt(const std::string& label, int& value, bool* isHovered)
{ {
@ -165,7 +165,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputInt("#", &value, return ImGui::InputInt("##", &value,
1, 10, 1, 10,
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -176,7 +176,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
const bool CHANGED = InputInt("#", signedVal); const bool CHANGED = InputInt("##", signedVal);
if (CHANGED) if (CHANGED)
{ {
signedVal = std::clamp(signedVal, 0, std::numeric_limits<int>::max()); signedVal = std::clamp(signedVal, 0, std::numeric_limits<int>::max());
@ -190,7 +190,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputFloat("#", &value, return ImGui::InputFloat("##", &value,
0.1f, 1.0f, "%.3f", 0.1f, 1.0f, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -200,7 +200,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputDouble("#", &value, return ImGui::InputDouble("##", &value,
0.1, 1.0, "%.3f", 0.1, 1.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -210,7 +210,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); ImGui::SameLine();
return ImGui::InputDouble("#", &value, return ImGui::InputDouble("##", &value,
1.0, 45.0, "%.3f", 1.0, 45.0, "%.3f",
ImGuiInputTextFlags_EnterReturnsTrue); ImGuiInputTextFlags_EnterReturnsTrue);
} }
@ -280,7 +280,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); 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) if (CHANGED)
{ {
value = std::string(buffer.data(), buffer.data() + TEXT_FIELD_MAX_LENGTH); value = std::string(buffer.data(), buffer.data() + TEXT_FIELD_MAX_LENGTH);
@ -327,7 +327,7 @@ namespace SHADE
if (isHovered) if (isHovered)
*isHovered = ImGui::IsItemHovered(); *isHovered = ImGui::IsItemHovered();
ImGui::SameLine(); 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) for (int i = 0; i < enumNames.size(); ++i)
{ {

View File

@ -422,12 +422,13 @@ namespace SHADE
ImGui::BeginGroup(); ImGui::BeginGroup();
ImGui::PushID(label.data()); ImGui::PushID(label.data());
TextLabel(label); 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(SHDragDrop::BeginTarget())
{ {
if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag)) if(T* payload = SHDragDrop::AcceptPayload<T>(dragDropTag))
{ {
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), *payload, set)), false); SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCommand<T>>(get(), *payload, set)), false);
changed = true;
SHDragDrop::EndTarget(); SHDragDrop::EndTarget();
} }
} }

View File

@ -64,6 +64,11 @@ namespace SHADE
return bufferUsageFlags; return bufferUsageFlags;
} }
uint32_t SHVkBuffer::GetSizeStored(void) const noexcept
{
return sizeStored;
}
/***************************************************************************/ /***************************************************************************/
/*! /*!

View File

@ -104,6 +104,7 @@ namespace SHADE
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
vk::Buffer GetVkBuffer (void) const noexcept; vk::Buffer GetVkBuffer (void) const noexcept;
vk::BufferUsageFlags GetUsageBits(void) const noexcept; vk::BufferUsageFlags GetUsageBits(void) const noexcept;
uint32_t GetSizeStored (void) const noexcept;
template <typename T> template <typename T>
T GetDataFromMappedPointer(uint32_t index) const noexcept T GetDataFromMappedPointer(uint32_t index) const noexcept

View File

@ -119,6 +119,18 @@ namespace SHADE
return setIndex; 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 SHVkDescriptorSetLayout& SHVkDescriptorSetLayout::operator=(SHVkDescriptorSetLayout&& rhs) noexcept
{ {
if (&rhs == this) if (&rhs == this)

View File

@ -99,6 +99,7 @@ namespace SHADE
inline const vk::DescriptorSetLayout& GetVkHandle() const { return setLayout; } inline const vk::DescriptorSetLayout& GetVkHandle() const { return setLayout; }
std::vector<Binding> const& GetBindings (void) const noexcept; std::vector<Binding> const& GetBindings (void) const noexcept;
SetIndex GetSetIndex (void) const noexcept; SetIndex GetSetIndex (void) const noexcept;
uint32_t GetNumDynamicOffsetsRequired (void) const noexcept;
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -88,6 +88,7 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; }; Handle<SHVkPipeline> GetPipeline() const noexcept { return pipeline; };
bool IsEmpty() const noexcept { return subBatches.empty(); }
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -68,6 +68,10 @@ namespace SHADE
return; return;
batch->Remove(renderable); batch->Remove(renderable);
// If batch is empty, remove batch
if (batch->IsEmpty())
batches.erase(batch);
} }
void SHSuperBatch::Clear() noexcept void SHSuperBatch::Clear() noexcept

View File

@ -79,7 +79,7 @@ namespace SHADE
SHVkDescriptorSetLayout::Binding cameraDataBinding SHVkDescriptorSetLayout::Binding cameraDataBinding
{ {
.Type = vk::DescriptorType::eUniformBufferDynamic, .Type = vk::DescriptorType::eUniformBufferDynamic,
.Stage = vk::ShaderStageFlagBits::eVertex, .Stage = vk::ShaderStageFlagBits::eVertex | vk::ShaderStageFlagBits::eCompute,
.BindPoint = SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA, .BindPoint = SHGraphicsConstants::DescriptorSetBindings::CAMERA_DATA,
.DescriptorCount = 1, .DescriptorCount = 1,
}; };

View File

@ -14,7 +14,7 @@ of DigiPen Institute of Technology is prohibited.
// STL Includes // STL Includes
#include <algorithm> #include <algorithm>
// Project Includes // Project Includes
#include "../Meshes/SHMeshData.h" #include "Assets/Asset Types/SHModelAsset.h"
#include "../Meshes/SHPrimitiveGenerator.h" #include "../Meshes/SHPrimitiveGenerator.h"
#include "ECS_Base/Managers/SHSystemManager.h" #include "ECS_Base/Managers/SHSystemManager.h"
#include "SHGraphicsSystem.h" #include "SHGraphicsSystem.h"
@ -43,11 +43,14 @@ namespace SHADE
return; return;
} }
// Get the system
SHDebugDrawSystem* system = static_cast<SHDebugDrawSystem*>(GetSystem());
// Get current frame index // Get current frame index
const uint32_t FRAME_IDX = gfxSys->GetCurrentFrameIndex(); const uint32_t FRAME_IDX = gfxSys->GetCurrentFrameIndex();
// Create the buffer if it doesn't exist or just update it /* Non-Persistent Buffer */
SHDebugDrawSystem* system = static_cast<SHDebugDrawSystem*>(GetSystem()); // Update the buffer
system->numPoints[FRAME_IDX] = system->points.size(); system->numPoints[FRAME_IDX] = system->points.size();
const uint32_t DATA_SIZE = sizeof(PointVertex) * system->points.size(); const uint32_t DATA_SIZE = sizeof(PointVertex) * system->points.size();
if (DATA_SIZE > 0) if (DATA_SIZE > 0)
@ -57,6 +60,24 @@ namespace SHADE
// Reset for next frame // Reset for next frame
system->points.clear(); 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(); const uint32_t FRAME_IDX = GFX_SYSTEM->GetCurrentFrameIndex();
// Don't draw if no points // Don't draw if no points
if (numPoints[FRAME_IDX] <= 0) if (numPoints[FRAME_IDX] > 0)
return; {
cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawPipeline()); cmdBuffer->BindPipeline(GFX_SYSTEM->GetDebugDrawPipeline());
cmdBuffer->SetLineWidth(LineWidth); cmdBuffer->SetLineWidth(LineWidth);
cmdBuffer->BindVertexBuffer(0, vertexBuffers[FRAME_IDX], 0); cmdBuffer->BindVertexBuffer(0, vertexBuffers[FRAME_IDX], 0);
cmdBuffer->DrawArrays(numPoints[FRAME_IDX], 1, 0, 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 // Reset trackers
std::fill_n(numPoints.begin(), numPoints.size(), 0); std::fill_n(numPoints.begin(), numPoints.size(), 0);
std::fill_n(numPersistentPoints.begin(), numPersistentPoints.size(), 0);
for (bool& cleared : persistentBuffersCleared)
cleared = true;
// Allocate buffers // Allocate buffers
// - Non-Persistent Draws
static constexpr uint32_t BUFFER_SIZE = MAX_POINTS * sizeof(PointVertex); static constexpr uint32_t BUFFER_SIZE = MAX_POINTS * sizeof(PointVertex);
for (Handle<SHVkBuffer>& bufHandle : vertexBuffers) 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 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() void SHDebugDrawSystem::Exit()
@ -110,6 +163,11 @@ namespace SHADE
if (vertexBuffer) if (vertexBuffer)
vertexBuffer.Free(); vertexBuffer.Free();
} }
for (auto vertexBuffer : persistentVertexBuffers)
{
if (vertexBuffer)
vertexBuffer.Free();
}
} }
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -117,32 +175,97 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
void SHDebugDrawSystem::DrawLine(const SHVec4& color, const SHVec3& startPt, const SHVec3& endPt) 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."); SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements.");
return; return;
} }
points.emplace_back(PointVertex{ startPt, color }); storage.emplace_back(PointVertex{ startPt, color });
points.emplace_back(PointVertex{ endPt, 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 EXTENTS = SHVec3{ 0.5f, 0.5f, 0.5f };
static const SHVec3 UNIT_BOT_LEFT_FRONT = SHVec3{ pos - EXTENTS }; static const SHVec3 UNIT_BOT_LEFT_FRONT = SHVec3{ pos - EXTENTS };
@ -163,8 +286,9 @@ namespace SHADE
const SHVec3 TOP_LEFT_FRONT = UNIT_TOP_LEFT_FRONT * size; const SHVec3 TOP_LEFT_FRONT = UNIT_TOP_LEFT_FRONT * size;
const SHVec3 TOP_RIGHT_FRONT = UNIT_TOP_RIGHT_FRONT * size; const SHVec3 TOP_RIGHT_FRONT = UNIT_TOP_RIGHT_FRONT * size;
DrawPoly drawLineSet
( (
storage,
color, color,
{ {
// Bottom Square // 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()) if (spherePoints.empty())
{ {
@ -197,6 +321,6 @@ namespace SHADE
spherePoints.emplace_back(SPHERE.VertexPositions[idx]); spherePoints.emplace_back(SPHERE.VertexPositions[idx]);
} }
} }
DrawPoly(color, spherePoints.begin(), spherePoints.end()); drawLineSet(storage, color, spherePoints.begin(), spherePoints.end());
} }
} }

View File

@ -126,6 +126,82 @@ namespace SHADE
/// <param name="size">Size of the rendered sphere.</param> /// <param name="size">Size of the rendered sphere.</param>
void DrawSphere(const SHVec4& color, const SHVec3& pos, double radius); 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: private:
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* Type Definitions */
@ -137,6 +213,7 @@ namespace SHADE
}; };
using TripleBuffer = std::array<Handle<SHVkBuffer>, SHGraphicsConstants::NUM_FRAME_BUFFERS>; 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 */ /* Constants */
@ -148,11 +225,28 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
// CPU Buffers // CPU Buffers
std::vector<PointVertex> points; std::vector<PointVertex> points;
std::vector<PointVertex> persistentPoints;
// GPU Buffers // GPU Buffers
TripleBuffer vertexBuffers; TripleBuffer vertexBuffers;
TripleUInt numPoints; TripleUInt numPoints;
TripleBuffer persistentVertexBuffers;
TripleUInt numPersistentPoints;
TripleBool persistentBuffersCleared;
// Cached Points for polygon drawing // Cached Points for polygon drawing
std::vector<SHVec3> spherePoints; 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);
}; };
} }

View File

@ -20,12 +20,21 @@ namespace SHADE
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
template<typename IterType> template<typename IterType>
void SHDebugDrawSystem::DrawPoly(const SHVec4& color, IterType pointListBegin, IterType pointListEnd) 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 // Ensure dereferenced type is SHVec3
static_assert(std::is_same_v<SHVec3, std::remove_cvref_t<decltype(*pointListBegin)>>, "Parameters to DrawPoly must be 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 // 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."); SHLOG_WARNING("[DebugDraw] Exceeded maximum size of drawable debug elements.");
return; return;
@ -42,7 +51,39 @@ namespace SHADE
const size_t POINTS_ROUNDED_COUNT = POINTS_COUNT / 2 * 2; const size_t POINTS_ROUNDED_COUNT = POINTS_COUNT / 2 * 2;
for (auto pointIter = pointListBegin; pointIter != (pointListBegin + POINTS_ROUNDED_COUNT); ++pointIter) 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 });
}
} }

View File

@ -70,7 +70,17 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
static constexpr uint32_t RENDERGRAPH_RESOURCE = 4; 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; static constexpr uint32_t BATCHED_PER_INST_DATA = 0;
}; };
struct VertexBufferBindings struct VertexBufferBindings

View File

@ -40,6 +40,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Assets/SHAssetManager.h" #include "Assets/SHAssetManager.h"
#include "Resource/SHResourceManager.h" #include "Resource/SHResourceManager.h"
#include "Graphics/SHVkUtil.h" #include "Graphics/SHVkUtil.h"
#include "Graphics/RenderGraph/SHRenderGraphNodeCompute.h"
#include "../Meshes/SHPrimitiveGenerator.h"
namespace SHADE namespace SHADE
{ {
@ -51,7 +53,11 @@ namespace SHADE
/* BACKEND BOILERPLATE */ /* BACKEND BOILERPLATE */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
// Set Up Instance // Set Up Instance
#ifdef _DEBUG
SHVkInstance::Init(true, true, true); SHVkInstance::Init(true, true, true);
#else
SHVkInstance::Init(true, false, true);
#endif
// Get Physical Device and Construct Logical Device // Get Physical Device and Construct Logical Device
physicalDevice = SHVkInstance::CreatePhysicalDevice(SH_PHYSICAL_DEVICE_TYPE::BEST); 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 VS_DEBUG = 48002439; debugVertShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(VS_DEBUG);
static constexpr AssetID FS_DEBUG = 36671027; debugFragShader = SHResourceManager::LoadOrGet<SHVkShaderModule>(FS_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 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 void SHGraphicsSystem::InitSceneRenderGraph(void) noexcept
@ -153,109 +161,117 @@ namespace SHADE
renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0]; renderContextCmdPools[i] = renderContext.GetFrameData(i).cmdPoolHdls[0];
} }
/*-----------------------------------------------------------------------*/
/* SCENE RENDER GRAPH RESOURCES */
/*-----------------------------------------------------------------------*/
// Initialize world render graph // Initialize world render graph
worldRenderGraph->Init(device, swapchain); 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("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("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("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("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("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("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("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", auto gBufferNode = worldRenderGraph->AddNode("G-Buffer",
{ {
"Position", "Position",
"Entity ID", "Entity ID",
"Light Layer Indices", "Light Layer Indices",
"Normals", "Normals",
//"Tangents",
"Albedo", "Albedo",
"Depth Buffer", "Depth Buffer",
"Scene" "Scene",
"SSAO",
"SSAO Blur"
}, },
{}); // no predecessors {}); // no predecessors
/*-----------------------------------------------------------------------*/
/* G-BUFFER SUBPASS INIT */
/*-----------------------------------------------------------------------*/
auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write"); auto gBufferSubpass = gBufferNode->AddSubpass("G-Buffer Write");
gBufferSubpass->AddColorOutput("Position"); gBufferSubpass->AddColorOutput("Position");
gBufferSubpass->AddColorOutput("Entity ID"); gBufferSubpass->AddColorOutput("Entity ID");
gBufferSubpass->AddColorOutput("Light Layer Indices"); gBufferSubpass->AddColorOutput("Light Layer Indices");
gBufferSubpass->AddColorOutput("Normals"); gBufferSubpass->AddColorOutput("Normals");
//gBufferSubpass->AddColorOutput("Tangents");
gBufferSubpass->AddColorOutput("Albedo"); gBufferSubpass->AddColorOutput("Albedo");
gBufferSubpass->AddDepthOutput("Depth Buffer", SH_ATT_DESC_TYPE_FLAGS::DEPTH_STENCIL); 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 ssaoTransferCmdBuffer = graphicsCmdPool->RequestCommandBuffer(SH_CMD_BUFFER_TYPE::PRIMARY);
auto debugDrawNode = worldRenderGraph->AddNode("Debug Draw", { "Scene" }, {"G-Buffer"}); 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"); auto debugDrawSubpass = debugDrawNode->AddSubpass("Debug Draw");
debugDrawSubpass->AddColorOutput("Scene"); 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 // Dummy Node
auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Debug Draw" }); // no predecessors auto dummyNode = worldRenderGraph->AddNode("Dummy Pass", { "Scene" }, { "Debug Draw" }); // no predecessors
auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass"); auto dummySubpass = dummyNode->AddSubpass("Dummy Subpass");
dummySubpass->AddInput("Scene"); dummySubpass->AddInput("Scene");
/*-----------------------------------------------------------------------*/
/* GENERATE RENDER GRAPH */
/*-----------------------------------------------------------------------*/
// Generate world render graph // Generate world render graph
worldRenderGraph->Generate(); worldRenderGraph->Generate();
/*-----------------------------------------------------------------------*/
/* BIND RENDER GRAPH TO RENDERER */
/*-----------------------------------------------------------------------*/
// Add world renderer to default viewport // Add world renderer to default viewport
worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph); worldRenderer = worldViewport->AddRenderer(resourceManager, swapchain->GetNumImages(), renderContextCmdPools, descPool, SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::HIGH_FREQUENCY_GLOBALS], worldRenderGraph);
worldRenderer->SetCamera(worldCamera); worldRenderer->SetCamera(worldCamera);
worldRenderer->SetCameraDirector(cameraSystem->CreateDirector()); worldRenderer->SetCameraDirector(cameraSystem->CreateDirector());
// Create default materials
defaultMaterial = AddMaterial(defaultVertShader, defaultFragShader, gBufferSubpass);
// Create debug draw pipeline // Create debug draw pipeline
auto debugDrawPipelineLayout = resourceManager.Create<SHVkPipelineLayout> debugDrawPipeline = createDebugDrawPipeline(debugDrawNode->GetRenderpass(), debugDrawSubpass);
( debugDrawDepthPipeline = createDebugDrawPipeline(debugDrawNodeDepth->GetRenderpass(), debugDrawDepthSubpass);
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();
} }
void SHGraphicsSystem::InitMiddleEnd(void) noexcept void SHGraphicsSystem::InitMiddleEnd(void) noexcept
@ -296,6 +312,29 @@ namespace SHADE
lightingSubSystem->Init(device, descPool); 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 #ifdef SHEDITOR
void SHGraphicsSystem::InitEditorRenderGraph(void) noexcept void SHGraphicsSystem::InitEditorRenderGraph(void) noexcept
{ {
@ -336,8 +375,7 @@ namespace SHADE
InitBoilerplate(); InitBoilerplate();
InitMiddleEnd(); InitMiddleEnd();
InitSubsystems(); InitSubsystems();
InitBuiltInResources();
} }
void SHGraphicsSystem::Exit(void) void SHGraphicsSystem::Exit(void)
@ -399,6 +437,17 @@ namespace SHADE
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>(); 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 every viewport
for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex) for (int vpIndex = 0; vpIndex < static_cast<int>(viewports.size()); ++vpIndex)
@ -435,8 +484,7 @@ namespace SHADE
currentCmdBuffer->BindIndexBuffer(buffer, 0); currentCmdBuffer->BindIndexBuffer(buffer, 0);
} }
// Bind the descriptor set for lights lightingSubSystem->BindDescSet(currentCmdBuffer, frameIndex);
lightingSubSystem->Run(currentCmdBuffer, frameIndex);
// Bind textures // Bind textures
auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup(); auto textureDescSet = texLibrary.GetTextureDescriptorSetGroup();
@ -460,7 +508,7 @@ namespace SHADE
{ {
auto editorSystem = SHSystemManager::GetSystem<SHEditor>(); auto editorSystem = SHSystemManager::GetSystem<SHEditor>();
if (editorSystem->editorState != SHEditor::State::PLAY) 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 else
renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex); renderers[renIndex]->UpdateDataAndBind(currentCmdBuffer, frameIndex);
} }
@ -685,6 +733,18 @@ namespace SHADE
transferCmdBuffer.Free(); transferCmdBuffer = {}; 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 */ /* Texture Registration Functions */
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -717,6 +777,11 @@ namespace SHADE
graphicsTexCmdBuffer.Free(); graphicsTexCmdBuffer = {}; graphicsTexCmdBuffer.Free(); graphicsTexCmdBuffer = {};
} }
Handle<SHTexture> SHGraphicsSystem::GetTextureHandle(SHTexture::Index textureId) const
{
return texLibrary.GetTextureHandle(textureId);
}
#pragma endregion ADD_REMOVE #pragma endregion ADD_REMOVE
#pragma region ROUTINES #pragma region ROUTINES
@ -729,6 +794,7 @@ namespace SHADE
void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept void SHGraphicsSystem::BeginRoutine::Execute(double) noexcept
{ {
SHResourceManager::FinaliseChanges();
reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender(); reinterpret_cast<SHGraphicsSystem*>(system)->BeginRender();
} }
@ -754,7 +820,6 @@ namespace SHADE
void SHGraphicsSystem::EndRoutine::Execute(double) noexcept void SHGraphicsSystem::EndRoutine::Execute(double) noexcept
{ {
reinterpret_cast<SHGraphicsSystem*>(system)->EndRender(); reinterpret_cast<SHGraphicsSystem*>(system)->EndRender();
SHResourceManager::FinaliseChanges();
} }
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -772,11 +837,6 @@ namespace SHADE
if (!renderable.HasChanged()) if (!renderable.HasChanged())
continue; continue;
if (!renderable.GetMesh())
{
SHLOG_CRITICAL("NULL Mesh provided!");
}
// Remove from the SuperBatch it is previously in (prevMat if mat has changed) // Remove from the SuperBatch it is previously in (prevMat if mat has changed)
Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial(); Handle<SHMaterialInstance> prevMaterial = renderable.HasMaterialChanged() ? renderable.GetPrevMaterial() : renderable.GetMaterial();
if (prevMaterial) 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
// Add to new SuperBatch if there is a material and a mesh to render
Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial(); Handle<SHMaterialInstance> newMatInstance = renderable.GetMaterial();
if (newMatInstance) if (newMatInstance && renderable.GetMesh())
{ {
Handle<SHSuperBatch> newSuperBatch = newMatInstance->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch(); Handle<SHSuperBatch> newSuperBatch = newMatInstance->GetBaseMaterial()->GetPipeline()->GetPipelineState().GetSubpass()->GetSuperBatch();
newSuperBatch->Add(&renderable); newSuperBatch->Add(&renderable);
@ -867,5 +928,57 @@ namespace SHADE
return worldRenderGraph->GetNode(G_BUFFER_RENDER_GRAPH_NODE_NAME.data()); 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 #pragma endregion MISC
} }

View File

@ -31,6 +31,7 @@ of DigiPen Institute of Technology is prohibited.
#include "../Textures/SHVkSamplerCache.h" #include "../Textures/SHVkSamplerCache.h"
#include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h" #include "Graphics/MiddleEnd/Interface/SHPostOffscreenRenderSystem.h"
#include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h" #include "Graphics/MiddleEnd/Lights/SHLightingSubSystem.h"
#include "Graphics/MiddleEnd/PostProcessing/SHSSAO.h"
namespace SHADE namespace SHADE
{ {
@ -57,6 +58,19 @@ namespace SHADE
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Type Definitions */ /* 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 \brief
@ -71,6 +85,7 @@ namespace SHADE
void InitSceneRenderGraph (void) noexcept; void InitSceneRenderGraph (void) noexcept;
void InitMiddleEnd (void) noexcept; void InitMiddleEnd (void) noexcept;
void InitSubsystems (void) noexcept; void InitSubsystems (void) noexcept;
void InitBuiltInResources (void);
#ifdef SHEDITOR #ifdef SHEDITOR
void InitEditorRenderGraph (void) noexcept; void InitEditorRenderGraph (void) noexcept;
@ -206,6 +221,21 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void BuildMeshBuffers(); 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 */ /* Texture Registration Functions */
@ -262,6 +292,33 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void BuildTextures(); 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 PrepareResize(uint32_t newWidth, uint32_t newHeight) noexcept;
void HandleResize(void) noexcept; void HandleResize(void) noexcept;
@ -289,6 +346,7 @@ namespace SHADE
Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;}; Handle<SHPostOffscreenRenderSystem> GetPostOffscreenRenderSystem(void) const noexcept {return postOffscreenRender;};
Handle<SHRenderGraphNode> GetPrimaryRenderpass() const noexcept; Handle<SHRenderGraphNode> GetPrimaryRenderpass() const noexcept;
Handle<SHVkPipeline> GetDebugDrawPipeline(void) const noexcept { return debugDrawPipeline; } 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(); } uint32_t GetCurrentFrameIndex(void) const noexcept { return renderContext.GetCurrentFrame(); }
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -315,6 +373,7 @@ namespace SHADE
Handle<SHVkDescriptorPool> descPool; Handle<SHVkDescriptorPool> descPool;
Handle<SHVkCommandPool> graphicsCmdPool; Handle<SHVkCommandPool> graphicsCmdPool;
Handle<SHVkCommandBuffer> transferCmdBuffer; Handle<SHVkCommandBuffer> transferCmdBuffer;
Handle<SHVkCommandBuffer> ssaoTransferCmdBuffer;
Handle<SHVkCommandBuffer> graphicsTexCmdBuffer; Handle<SHVkCommandBuffer> graphicsTexCmdBuffer;
SHRenderContext renderContext; SHRenderContext renderContext;
std::array<Handle<SHVkSemaphore>, 2> graphSemaphores; std::array<Handle<SHVkSemaphore>, 2> graphSemaphores;
@ -351,21 +410,37 @@ namespace SHADE
Handle<SHVkShaderModule> debugVertShader; Handle<SHVkShaderModule> debugVertShader;
Handle<SHVkShaderModule> debugFragShader; Handle<SHVkShaderModule> debugFragShader;
Handle<SHVkShaderModule> deferredCompositeShader; Handle<SHVkShaderModule> deferredCompositeShader;
Handle<SHVkShaderModule> ssaoShader;
Handle<SHVkShaderModule> ssaoBlurShader;
// Built-In Materials // Built-In Materials
Handle<SHMaterial> defaultMaterial; Handle<SHMaterial> defaultMaterial;
Handle<SHVkPipeline> debugDrawPipeline; 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; Handle<SHRenderGraph> worldRenderGraph;
// Sub systems // Sub systems
Handle<SHMousePickSystem> mousePickSystem; Handle<SHMousePickSystem> mousePickSystem;
Handle<SHPostOffscreenRenderSystem> postOffscreenRender; Handle<SHPostOffscreenRenderSystem> postOffscreenRender;
Handle<SHLightingSubSystem> lightingSubSystem; Handle<SHLightingSubSystem> lightingSubSystem;
Handle<SHSSAO> ssaoStorage;
uint32_t resizeWidth; uint32_t resizeWidth = 1;
uint32_t resizeHeight; uint32_t resizeHeight = 1;
bool restoredFromMinimize = false; bool restoredFromMinimize = false;
/*---------------------------------------------------------------------------------*/
/* Helper Functions */
/*---------------------------------------------------------------------------------*/
Handle<SHVkPipeline> createDebugDrawPipeline(Handle<SHVkRenderpass> renderPass, Handle<SHSubpass> subpass);
}; };
} }

View File

@ -83,13 +83,14 @@ namespace SHADE
{ {
if (camera && cameraDirector) 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(); //cpuCameraData.viewProjectionMatrix = camera->GetViewProjectionMatrix();
cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex); cameraBuffer->WriteToMemory(&cpuCameraData, sizeof(SHShaderCameraData), 0, cameraDataAlignedSize * frameIndex);
@ -97,16 +98,19 @@ namespace SHADE
std::array<uint32_t, 1> dynamicOffsets{ frameIndex * cameraDataAlignedSize }; 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::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::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 = 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 Handle<SHRenderGraph> SHRenderer::GetRenderGraph(void) const noexcept
@ -119,4 +123,9 @@ namespace SHADE
return commandBuffers[frameIndex]; return commandBuffers[frameIndex];
} }
Handle<SHCameraDirector> SHRenderer::GetCameraDirector(void) const noexcept
{
return cameraDirector;
}
} }

View File

@ -46,6 +46,8 @@ namespace SHADE
{ {
SHVec4 cameraPosition; SHVec4 cameraPosition;
SHMatrix viewProjectionMatrix; SHMatrix viewProjectionMatrix;
SHMatrix viewMatrix;
SHMatrix projectionMatrix;
}; };
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
@ -79,15 +81,16 @@ namespace SHADE
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
void Draw(uint32_t frameIndex, Handle<SHVkDescriptorPool> descPool) noexcept; 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) 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 UpdateCameraDataToBuffer (void) noexcept;
void SetViewProjectionMatrix (SHMatrix const& vpMatrix) noexcept; void SetViewProjectionMatrix (SHMatrix const& viewMatrix, SHMatrix const& projMatrix) noexcept;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Setters and Getters */ /* Setters and Getters */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHRenderGraph> GetRenderGraph (void) const noexcept; Handle<SHRenderGraph> GetRenderGraph (void) const noexcept;
Handle<SHVkCommandBuffer> GetCommandBuffer(uint32_t frameIndex) const noexcept; Handle<SHVkCommandBuffer> GetCommandBuffer(uint32_t frameIndex) const noexcept;
Handle<SHCameraDirector> GetCameraDirector (void) const noexcept;
private: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -9,9 +9,9 @@ namespace SHADE
{ {
lightData.Reset(); lightData.Reset();
SetType(SH_LIGHT_TYPE::DIRECTIONAL); SetType(SH_LIGHT_TYPE::DIRECTIONAL);
indexInBuffer = std::numeric_limits<uint32_t>::max(); //indexInBuffer = std::numeric_limits<uint32_t>::max();
isActive = true; isActive = true;
Unbind(); //Unbind();
} }
@ -23,28 +23,28 @@ namespace SHADE
void SHLightComponent::SetPosition(SHVec3 const& position) noexcept void SHLightComponent::SetPosition(SHVec3 const& position) noexcept
{ {
lightData.position = position; lightData.position = position;
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::SetType(SH_LIGHT_TYPE type) noexcept void SHLightComponent::SetType(SH_LIGHT_TYPE type) noexcept
{ {
lightData.type = type; lightData.type = type;
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::SetDirection(SHVec3 const& direction) noexcept void SHLightComponent::SetDirection(SHVec3 const& direction) noexcept
{ {
lightData.direction = direction; lightData.direction = direction;
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::SetColor(SHVec4 const& color) noexcept void SHLightComponent::SetColor(SHVec4 const& color) noexcept
{ {
lightData.color = color; lightData.color = color;
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::ModifyCullingMask(uint8_t layerIndex, bool value) noexcept void SHLightComponent::ModifyCullingMask(uint8_t layerIndex, bool value) noexcept
@ -54,7 +54,7 @@ namespace SHADE
else else
lightData.cullingMask &= ~(1u << layerIndex); lightData.cullingMask &= ~(1u << layerIndex);
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::SetCullingMask(uint32_t const& value) noexcept void SHLightComponent::SetCullingMask(uint32_t const& value) noexcept
@ -65,43 +65,43 @@ namespace SHADE
void SHLightComponent::SetAllLayers(void) noexcept void SHLightComponent::SetAllLayers(void) noexcept
{ {
lightData.cullingMask = std::numeric_limits<uint32_t>::max(); lightData.cullingMask = std::numeric_limits<uint32_t>::max();
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::ClearAllLayers(void) noexcept void SHLightComponent::ClearAllLayers(void) noexcept
{ {
lightData.cullingMask = 0; lightData.cullingMask = 0;
MakeDirty(); //MakeDirty();
} }
void SHLightComponent::MakeDirty(void) noexcept //void SHLightComponent::MakeDirty(void) noexcept
{ //{
dirty = true; // dirty = true;
} //}
void SHLightComponent::ClearDirtyFlag(void) noexcept //void SHLightComponent::ClearDirtyFlag(void) noexcept
{ //{
dirty = false; // dirty = false;
} //}
void SHLightComponent::Unbind(void) noexcept // void SHLightComponent::Unbind(void) noexcept
{ // {
bound = false; // bound = false;
MakeDirty(); // MakeDirty();
} // }
//
void SHLightComponent::SetBound(uint32_t inIndexInBuffer) noexcept // void SHLightComponent::SetBound(uint32_t inIndexInBuffer) noexcept
{ //{
bound = true; // bound = true;
indexInBuffer = inIndexInBuffer; // indexInBuffer = inIndexInBuffer;
} // }
void SHLightComponent::SetStrength(float value) noexcept void SHLightComponent::SetStrength(float value) noexcept
{ {
lightData.strength = value; lightData.strength = value;
MakeDirty(); //MakeDirty();
} }
SHLightData const& SHLightComponent::GetLightData(void) const noexcept SHLightData const& SHLightComponent::GetLightData(void) const noexcept
@ -135,20 +135,20 @@ namespace SHADE
} }
bool SHLightComponent::IsDirty(void) const noexcept //bool SHLightComponent::IsDirty(void) const noexcept
{ //{
return dirty; // return dirty;
} //}
bool SHLightComponent::GetBound(void) const noexcept //bool SHLightComponent::GetBound(void) const noexcept
{ //{
return bound; // return bound;
} //}
uint32_t SHLightComponent::GetIndexInBuffer(void) const noexcept //uint32_t SHLightComponent::GetIndexInBuffer(void) const noexcept
{ //{
return indexInBuffer; // return indexInBuffer;
} //}
float SHLightComponent::GetStrength(void) const noexcept float SHLightComponent::GetStrength(void) const noexcept
{ {

View File

@ -17,13 +17,13 @@ namespace SHADE
//! Since the lighting system is gonna be self contained and light weight, we store this //! 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 //! 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. //! 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. ////! If the light component changed some value we mark this true.
bool dirty; //bool dirty;
//! If the light's data is already in the buffers, this will be set to true. ////! If the light's data is already in the buffers, this will be set to true.
bool bound; //bool bound;
public: public:
@ -44,10 +44,10 @@ namespace SHADE
void SetCullingMask (uint32_t const& value) noexcept; void SetCullingMask (uint32_t const& value) noexcept;
void SetAllLayers (void) noexcept; // serialized void SetAllLayers (void) noexcept; // serialized
void ClearAllLayers (void) noexcept; // serialized void ClearAllLayers (void) noexcept; // serialized
void MakeDirty (void) noexcept; //void MakeDirty (void) noexcept;
void ClearDirtyFlag (void) noexcept; //void ClearDirtyFlag (void) noexcept;
void Unbind (void) noexcept; //void Unbind (void) noexcept;
void SetBound (uint32_t inIndexInBuffer) noexcept; //void SetBound (uint32_t inIndexInBuffer) noexcept;
void SetStrength (float value) noexcept; // serialized void SetStrength (float value) noexcept; // serialized
@ -57,8 +57,8 @@ namespace SHADE
SHVec3 const& GetDirection (void) const noexcept; // serialized SHVec3 const& GetDirection (void) const noexcept; // serialized
SHVec4 const& GetColor (void) const noexcept; // serialized SHVec4 const& GetColor (void) const noexcept; // serialized
uint32_t const& GetCullingMask (void) const noexcept; // serialized uint32_t const& GetCullingMask (void) const noexcept; // serialized
bool IsDirty (void) const noexcept; //bool IsDirty (void) const noexcept;
bool GetBound (void) const noexcept; //bool GetBound (void) const noexcept;
uint32_t GetIndexInBuffer (void) const noexcept; uint32_t GetIndexInBuffer (void) const noexcept;
float GetStrength (void) const noexcept; float GetStrength (void) const noexcept;
RTTR_ENABLE() RTTR_ENABLE()

View File

@ -8,6 +8,8 @@
#include "SHLightComponent.h" #include "SHLightComponent.h"
#include "ECS_Base/Managers/SHComponentManager.h" #include "ECS_Base/Managers/SHComponentManager.h"
#include "SHLightComponent.h" #include "SHLightComponent.h"
#include "Math/Vector/SHVec4.h"
#include "Math/SHMatrix.h"
namespace SHADE 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(); auto const& lightData = lightComp->GetLightData();
switch (lightData.type) switch (lightData.type)
@ -40,8 +42,12 @@ namespace SHADE
{ {
SHDirectionalLightData* lightPtr = reinterpret_cast<SHDirectionalLightData*>(address); 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->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->diffuseColor = lightData.color;
lightPtr->active = lightComp->isActive; lightPtr->active = lightComp->isActive;
break; 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) if (unboundLight)
{ {
@ -259,10 +265,10 @@ namespace SHADE
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * numLights); void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * numLights);
// Write the light data to address // Write the light data to address
WriteLightToAddress(writeLocation, unboundLight); WriteLightToAddress(writeLocation, viewMat, unboundLight);
// Set the light component to be bound to that location // Set the light component to be bound to that location
unboundLight->SetBound(numLights); //unboundLight->SetBound(numLights);
// Increase light count // Increase light count
++numLights; ++numLights;
@ -280,11 +286,11 @@ namespace SHADE
*/ */
/***************************************************************************/ /***************************************************************************/
void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept //void SHLightingSubSystem::PerTypeData::ModifyLight(SHLightComponent* lightComp) noexcept
{ //{
void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * lightComp->GetIndexInBuffer()); // void* writeLocation = reinterpret_cast<uint8_t*>(intermediateData.get()) + (lightDataAlignedSize * lightComp->GetIndexInBuffer());
WriteLightToAddress(writeLocation, lightComp); // WriteLightToAddress(writeLocation, lightComp);
} //}
void SHLightingSubSystem::PerTypeData::WriteToGPU(uint32_t frameIndex) noexcept 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 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); static uint32_t constexpr NUM_LIGHT_TYPES = SHUtilities::ToUnderlying(SH_LIGHT_TYPE::NUM_TYPES);
auto& lightComps = SHComponentManager::GetDense<SHLightComponent>(); auto& lightComps = SHComponentManager::GetDense<SHLightComponent>();
bool expanded = false; bool expanded = false;
bool rewrite = false;
if (numLightComponents > lightComps.size()) // First we reset the number of lights. We do this every frame so that we can count how many lights we have
{
rewrite = true;
ResetNumLights(); ResetNumLights();
}
numLightComponents = lightComps.size(); //bool rewrite = false;
//if (numLightComponents > lightComps.size())
//{
// rewrite = true;
// ResetNumLights();
//}
//numLightComponents = lightComps.size();
for (auto& light : lightComps) 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 // 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. // 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]; //++lightCountsData[enumValue];
} }
// if there was modification to the light data // if there was modification to the light data
if (light.IsDirty()) //if (light.IsDirty())
{ {
// Write the data to the CPU // Write the data to the CPU
perTypeData[enumValue].ModifyLight(&light); //perTypeData[enumValue].ModifyLight(&light);
// Light is now updated in the container // 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. // so we do it anyway. #NoteToSelf: if at any point it affects performance, do a check before computing.
ComputeDynamicOffsets(); 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] });
}
} }

View File

@ -95,15 +95,15 @@ namespace SHADE
//! to the GPU that stores NUM_FRAME_BUFFERS copies. //! to the GPU that stores NUM_FRAME_BUFFERS copies.
std::unique_ptr<uint8_t[]> intermediateData; 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:
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void InitializeData (Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept; void InitializeData (Handle<SHVkLogicalDevice> logicalDevice, SH_LIGHT_TYPE type) noexcept;
void Expand (Handle<SHVkLogicalDevice> logicalDevice) noexcept; void Expand (Handle<SHVkLogicalDevice> logicalDevice) noexcept;
void AddLight (Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, bool expanded) noexcept; void AddLight (Handle<SHVkLogicalDevice> logicalDevice, SHLightComponent* unboundLight, SHMatrix const& viewMat, bool& expanded) noexcept;
void ModifyLight (SHLightComponent* lightComp) noexcept; //void ModifyLight (SHLightComponent* lightComp) noexcept;
void WriteToGPU (uint32_t frameIndex) noexcept; void WriteToGPU (uint32_t frameIndex) noexcept;
void ResetNumLights (void) 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 //! 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, //! set is less than the size recorded, rewrite all light components into the its respective buffers. If its more,
//! don't do anything. //! don't do anything.
uint32_t numLightComponents; //uint32_t numLightComponents;
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
/* PRIVATE MEMBER FUNCTIONS */ /* PRIVATE MEMBER FUNCTIONS */
@ -159,8 +159,10 @@ namespace SHADE
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
void Init (Handle<SHVkLogicalDevice> device, Handle<SHVkDescriptorPool> descPool) noexcept; 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 Exit (void) noexcept;
void BindDescSet (Handle<SHVkCommandBuffer> cmdBuffer, uint32_t frameIndex) noexcept;
}; };
} }

View File

@ -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;
}
}
}

View File

@ -16,9 +16,18 @@ of DigiPen Institute of Technology is prohibited.
#include <utility> #include <utility>
// Project Includes // Project Includes
#include "Assets/SHAssetMacros.h" #include "Assets/SHAssetMacros.h"
#include <yaml-cpp/yaml.h>
namespace SHADE namespace SHADE
{ {
/*-----------------------------------------------------------------------------------*/
/* Forward Declaration */
/*-----------------------------------------------------------------------------------*/
class SHMaterial;
/*-----------------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------------*/
/*************************************************************************************/ /*************************************************************************************/
/*! /*!
\brief \brief
@ -32,5 +41,11 @@ namespace SHADE
AssetID fragShader; AssetID fragShader;
std::string subpassName; std::string subpassName;
YAML::Node properties; YAML::Node properties;
/*---------------------------------------------------------------------------------*/
/* Constructors */
/*---------------------------------------------------------------------------------*/
SHMaterialSpec() = default;
explicit SHMaterialSpec(const SHMaterial& material);
}; };
} }

View File

@ -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;
};
}

View File

@ -13,7 +13,8 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes // Project Includes
#include "Math/SHMath.h" #include "Math/SHMath.h"
#include "SHMeshData.h" #include "Assets/Asset Types/SHModelAsset.h"
#include "Graphics/MiddleEnd/Interface/SHMeshLibrary.h"
#include "SH_API.h" #include "SH_API.h"
namespace SHADE namespace SHADE

View File

@ -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;
}
}

View File

@ -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;
};
}

View File

@ -156,14 +156,15 @@ namespace SHADE
/* Build Descriptor Set with all the Textures only if there are textures */ /* Build Descriptor Set with all the Textures only if there are textures */
if (!texOrder.empty()) if (!texOrder.empty())
{ {
if (!texDescriptors) if (texDescriptors)
{ {
texDescriptors.Free();
}
texDescriptors = descPool->Allocate texDescriptors = descPool->Allocate
( (
{ SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS] }, { SHGraphicsGlobalData::GetDescSetLayouts()[SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS] },
{ static_cast<uint32_t>(texOrder.size()) } { static_cast<uint32_t>(texOrder.size()) }
); );
}
texDescriptors->ModifyWriteDescImage texDescriptors->ModifyWriteDescImage
( (
SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS, SHGraphicsConstants::DescriptorSetIndex::STATIC_GLOBALS,

View File

@ -129,6 +129,21 @@ namespace SHADE
/* Getter Functions */ /* Getter Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
Handle<SHVkDescriptorSetGroup> GetTextureDescriptorSetGroup() const noexcept { return texDescriptors; } 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: private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/

View File

@ -2,8 +2,10 @@
#define SH_PIPELINE_LAYOUT_PARAMS_H #define SH_PIPELINE_LAYOUT_PARAMS_H
#include "Graphics/SHVulkanIncludes.h" #include "Graphics/SHVulkanIncludes.h"
#include "Graphics/SHVulkanDefines.h"
#include "Resource/SHHandle.h" #include "Resource/SHHandle.h"
#include "Graphics/Descriptors/SHVkDescriptorSetLayout.h" #include "Graphics/Descriptors/SHVkDescriptorSetLayout.h"
#include <unordered_set>
namespace SHADE 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 the layout to initialize the pipeline layout but we do not
//! want to use it for allocating descriptor sets. //! want to use it for allocating descriptor sets.
std::vector<Handle<SHVkDescriptorSetLayout>> const& globalDescSetLayouts = {}; 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 struct SHPipelineLayoutParamsDummy

View File

@ -165,6 +165,28 @@ namespace SHADE
newBinding.Stage = shaderModule->GetShaderStageFlagBits(); newBinding.Stage = shaderModule->GetShaderStageFlagBits();
newBinding.Type = descBindingInfo.ConvertFromReflectDescType(reflectedBinding->descriptor_type); 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 // 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 // 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 // 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{} , vkDescriptorSetLayoutsAllocate{}
, descriptorSetLayoutsPipeline{} , descriptorSetLayoutsPipeline{}
, vkDescriptorSetLayoutsPipeline{} , vkDescriptorSetLayoutsPipeline{}
, dynamicBufferBindings{std::move (pipelineLayoutParams.dynamicBufferBindings)}
{ {
for (auto& mod : shaderModules) for (auto& mod : shaderModules)
{ {

View File

@ -29,6 +29,9 @@ namespace SHADE
//! Push constant interface //! Push constant interface
SHPushConstantInterface pushConstantInterface; SHPushConstantInterface pushConstantInterface;
//! See SHPipelineLayoutParams for details
std::unordered_set<BindingAndSetHash> dynamicBufferBindings;
//! Push constant ranges //! Push constant ranges
std::vector<vk::PushConstantRange> vkPcRanges; std::vector<vk::PushConstantRange> vkPcRanges;

View File

@ -129,4 +129,9 @@ namespace SHADE
return vkQueue; return vkQueue;
} }
void SHVkQueue::WaitIdle(void) const noexcept
{
vkQueue.waitIdle();
}
} }

View File

@ -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; 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::Result Present (Handle<SHVkSwapchain> const& swapchain, std::initializer_list<Handle<SHVkSemaphore>> waitSems, uint32_t frameIndex) noexcept;
vk::Queue GetVkQueue() noexcept; vk::Queue GetVkQueue() noexcept;
void WaitIdle (void) const noexcept;
}; };
} }

View File

@ -263,7 +263,7 @@ namespace SHADE
return subpass; 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 // Look for the required resources in the graph
std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{}; std::vector<Handle<SHRenderGraphResource>> nodeComputeResources{};
@ -276,7 +276,7 @@ namespace SHADE
} }
// Create the subpass compute with the resources // 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); nodeComputes.push_back(nodeCompute);
return nodeCompute; return nodeCompute;

View File

@ -100,7 +100,7 @@ namespace SHADE
/* PUBLIC MEMBER FUNCTIONS */ /* PUBLIC MEMBER FUNCTIONS */
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
Handle<SHSubpass> AddSubpass(std::string subpassName) noexcept; 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; void AddDummySubpassIfNeeded (void) noexcept;
// TODO: RemoveSubpass() // TODO: RemoveSubpass()

Some files were not shown because too many files have changed in this diff Show More