Order of the Roses

SPITE: Order of the Roses was made in C++ using our own engine called Dream Engine. Dream Engine uses DX11 and was made by myself and my team. Dream Engine is based on the engine The Game Engine. The Game Engine was created by the teachers of The Game Assembly.
Details
- Genre: Top down APRG
- Engine: Dream Engine
- Duration: 10 weeks at 50%
- Team: 6 programmers, 4 artists, 2 level design, 2 procedural artists
My contributions for this project:
- VFX
- Post processing
- Multi-threaded model loading
- Particle system
- Model culling
VFX
The majority of this project I worked on VFX. I started by creating a tool for myself and for the other programmers to be able to import pixel shaders from the Visual Studio tool "Shader Designer". This was in cooperation with our procedural artists as they wanted to have a visual graph system to create pixel shaders for our VFX.
To be able to import the pixel shaders without creating too much more work for the programmers I had to create a tool that sent the correct data to the shaders without the need to modify the shader itself.
To read more about the shader importer click the link below.
Shader Importer
Post processing
I created a few post processing effects but the one I want to highlight is the vignette effect. It was a requirement for our project and an easy effect to create. Despite it being easy to create it has a big impact on the feeling of the game.
I also gave the option to modify the amount of vignette to our artists.

Multi-threaded model loading
To achieve a faster loading of our levels I parallelized the model loading over multiple threads. I set the amount of threads to four and wrote code to split the work evenly across the threads.
void RunThreadsForModelLoading(LevelData& aLevelData,
std::vector<std::shared_ptr<Setdressing>>* someSetdressingObjects,
std::vector<int> someTaggedID, int aSplitAmount, std::string aTagName)
{
if(aSplitAmount == 0)
{
LoadModels(aLevelData, someSetdressingObjects, someTaggedID, 0, static_cast<int>(someTaggedID.size()-1), aTagName);
}
else
{
std::thread modelLoadingThread1(&LoadModels, aLevelData, someSetdressingObjects, someTaggedID, 0, aSplitAmount, aTagName);
std::thread modelLoadingThread2(&LoadModels, aLevelData, someSetdressingObjects, someTaggedID, aSplitAmount + 1, aSplitAmount * 2, aTagName);
std::thread modelLoadingThread3(&LoadModels, aLevelData, someSetdressingObjects, someTaggedID, (aSplitAmount * 2) + 1, aSplitAmount * 3, aTagName);
std::thread modelLoadingThread4(&LoadModels, aLevelData, someSetdressingObjects, someTaggedID, (aSplitAmount * 3) + 1, static_cast<int>(someTaggedID.size() - 1), aTagName);
while(!modelLoadingThread1.joinable()) {}
modelLoadingThread1.join();
while(!modelLoadingThread2.joinable()) {}
modelLoadingThread2.join();
while(!modelLoadingThread3.joinable()) {}
modelLoadingThread3.join();
while(!modelLoadingThread4.joinable()) {}
modelLoadingThread4.join();
}
}
Particle system

The particle system used is the same particle system I have worked on and used during the last few game projects in our school.
Model culling
The model culling was created as a way to increase our performance. We had quite large levels and our group always strive to be able to play the full experience in 60 fps with all of our debugging tools.
The code below is the code used for the culling. The code is not perfect but was enough for our cause and did not need more iterations.
bool ObjectLoader::Culling(DE::Vector3f aModelPos)
{
float modelLength;
DE::Vector3f cullingOffset = { -850.0f , 0, -942.0f };
DE::Vector3f playerPos = myPlayer->GetTransform()->GetPosition();
playerPos.y = aModelPos.y;
playerPos += cullingOffset;
modelLength = (aModelPos - playerPos).LengthSqr();
if (modelLength <= myCullingRange * myCullingRange)
{
return true;
}
return false;
}