portfolio



homehearth

description

CO-OP online survival game for up to 4 players. The goal is to defend the small village from scary monsters that appear at night. Build ​​defences and protect the cute llamas. A custom-made game engine was built using C++ and DirectX11 for this project by 10 students.

contribution

- Advanced animation system:
     * Skeletal animation
     * Blending 2 animations
     * Partial blending
- Model loading (submeshes supported)
- Resource manager
- Mipmapping
- Larger defences and hover effect

learned

- Data Oriented Design with ECS (EnTT)
- Agile methodology (scrum)
- Animation system
- Smart pointers (memory management)
- HacknPlan (planning)
- Hybrid work (some home, others at work)

Download game Source code

TRAILER

features

animator scripting

The goal with this feature was to save time when tuning the animation behaviour for the characters. This made it possible to change values without recompiling the whole game.

It was ​heavily inspired by the animation blend tree that is used in the Unreal Engine which can be seen in the second image in the slideshow.

This implementation featured a bunch of options: 

  1. Skel - Loading in a skeleton for the model.
  2. Anim - Loading in an animation and connecting it to an enum. 
  3. Loopable - Set animation looping on or off.
  4. Tickspeed - Change speed of animation.
  5. Partialanim - Using this animation on top of a idle or running animation. Sets a startbone and optionally an endbone.
  6. State - Blend time between two animations in seconds.

This system was pretty flexible but had some limits. With many blendstate it could get a bit confusing and hard to read. As for future projects it would be better to make a visual blend tree instead of a text based parser. This could make it more clear and easier for a designer to work with.

blending animations

This video show my implementation of linear blending between two animation. It makes the movement feel smooth but still very responsive.

partial blending animations

This technique makes it possible to play two different animations at the same time on different parts of the body. One animation controls the lower body such as an idle or running animation while another is played on the upper body like an attack animation.

vertex skinning optimization

Vertex skinning is a method of making the vertices of a model follow the movement of the bones of the skeleton. This is fastest to do on the GPU. The movement of the bones is calculated on the CPU every frame and saved in transformation matrices (image), one matrix for each bone. All of these is sent to the GPU using a buffer. 

A vertex can be affected by 4 weights where the sum of these weights should always be 1.0f. If a bone has the weight 1.0f it means that bone has 100% control of the vertex position. The weight are calculated on the CPU on start and is being saved in the vertex information together with the bone ids.

So what can we optimized in vertex skinning?

  • Matrix size.
  • Different buffer types.
  • Order of the matrix multiplication.

I did some research and found out that there is a method called dual quaternions which only require 8 floats. 3 floats for translation, 4 for rotation and 1 for the uniformed scale. This method was very interesting but ​unfortunately I did not have enough time to test it.

Implementation GPU time (microseconds) ~GPU instructions
No skinning 33,62 21
Regular 4x4 62,30 80
Optimized 4x4 54,49 69
3x4 matrices 52,06 64
4x3 matrices 50,67 52
3x4 matrices (Constant buffers) 44,36 58
4x3 matrices (Constant buffers) 43,92 56

To meassure the time it took to render an animated model I used RenderDoc. The tests was made on my laptop with a GTX 1060 (6GB VRAM).

The experiment was made using 4 different animated models from the game that had different specifications:

  • Vertices:         11k - 30k
  • Triangles:       4k - 10k
  • Bones:             21 - 23
  • Submeshes:    2 - 8

The final results here are the average of the different models​ rendering times. In this experiment I simplified the pixelshader to be as basic as possible as only the vertex shader was interesting.

The approximate number of GPU instructions was outputted by Visual Studio when viewing the compiled HLSL shaders.

lua scripting

description

A small 2D game that was inspired by "The Binding of Isaac". The project includes a level editor that can be used to change the map. The game logic was made in Lua while all the engine technology was made in C++ together with Irrlicht Engine. This project was made by 3 students.

contribution

- Scene creation and multiple scenes in Lua
- Sprite class
- Creation of UI in scripts
- Basic AABB and circle collision between sprites
- Gridsystem for level editor
- Ortographic camera with zoom

learned

- Communication between Lua and C++.
- ​Capabilities of Irrlicht game engine
- Lua language
- How much time scripting saves

Download game Source code

level editor

This tool makes it possible to change the game level. The buttons in the top left corner can be used create, load or save a state of a level.

On the upper right corner it is possible to change between different layers so it is possible to place objects on top of tiles. Three layers was enough for this project.

At the bottom it is possible pick which type of tile/object you want to place.

scene creation

Creating a new scene for the game is very easy. All it needs is two functions. Start() is ​initializing the scene and creating everything that we want to use. While Update(dt) keeps looping every frame. The deltatime is sent in from C++ for every scene and can be used for example in movement calculations.

To make it possible to start in this scene or change to it we have to add a key and the name of the script to a list with all the scenes available.

gameplay

Player move around with "WASD" and aim with the mouse. Left click can be used to throw a weapon. 

The goal of the game is to collect as much gold as possible and escape the dungeon while avoiding all the dangerous monsters.

Different weapons can be picked up from monsters and chests gives different perks to the player.

prodigium

description

Third-person atmospheric survival horror game. The game takes place in a nightmare where the character has to collect all the memories to wake up. But watch out, there is a ghost floating around in the level that makes you lose your sanity which affects both the visuals and the audio of the game.  Made in a custom engine with C++ and DirectX11 by 6 students.

contribution

- Skeletal animation
- Skybox
- Model loading with Assimp
- Gaussian blur (computeshader)
- Recorded features and edited video

learned

- Working together on distance
- GitHub (commit and multiple branches)
- RenderDoc (debug rendering)
- Assimp library
- Unordered_map
- Trello (organizing of who did what)

Download game Source code

trailer

gameplay

Almost like slender man but we collect memories and run away from a ghost!

features

skeletal animation

My main focus in this project was to make the player character feel alive by animating it in real-time. The implementation took very long time as I did not know anything about the topic and needed to do quite a lot of research. 

The implementation used the asset import library Assimp for loading in the skeleton and animations. This tool saved me from a lot of headaches and could be used to get information such as the offset matrices for the bones.

There was quite a lot of bugs when trying to figure out this technique. One of them was that the exporting settings from the 3D modeling software Maya played a big part. When I got the skeleton and animations from one of our Technical Artists I had to rotate some of them in Blender to make it right which was annoying.

In the first video we can see the final look at how the skeletal animation system worked. Different animations get played depending on direction and action.

In the second video linear interpolation is shown between poses to make animations smoother. Most of the animations already had one pose per frame and therefore it was not utilized to the fullest in this project unfortunately. Interpolation is very useful with having very few keyframes and can save a lot of memory at the cost of some performance.

gaussian blur - sanity effect

cubic skybox

To make the game more ​immersive I created a skybox pass. It was made using a texture cube map with 6 separate images, one for each side of the cube. 

The final textures of the skybox used some very flat colours to fit with the fog. But it made the sky a bit boring to look at. 

If I could remake this today I would have implemented a skydome instead. This would reduce the cubic and perspective look that can be seen on the moon in this video when moving around.

behind the scenes

animations going good?

directX11 pROJECT

description

This was from a project where we learned 3D rendering and how we could utilize the GPU with shaders. In this project, me, myself and I created a smaller game engine with multiple different techniques using DirectX11 as the graphics API.

contribution

- Deffered rendering
- OBJ parser
- Displacement mapping (tessellation hardware)
- Normal mapping
- Shadow mapping
- Back face culling (geometry shader)
- Gaussian & Bilateral filter (compute shader)
- Running water effect (CPU based)

learned

- DirectX11 graphics API
- HLSL
- Different techniques.
- To use "m_" for member variables in classes.

Download game Source code

project demo

features

deferred rendering

water-effect

The goal of this technique was to get a scrolling texture that looked like water. This could be made on the CPU or the GPU. It had to be based on vertex manipulation or texture animation.

I was in a bit of a hurry when coding this so my best solution at this moment was to change the texture coordinates on the CPU.

The ideal and more optimized solution would probably be to make it on the GPU. Sending up a constant buffer with how much to move.

post processing

shadow mapping

This technique was about making real-time shadows. It was casted from a red spotlight on multiple objects in the scene. 

When I coded this ​technique I bumped into the two common shadow problems: shadow acne and peter panning. Both of these was solved with a small bias value.

The resolution of the shadowmap was 2048x2048 pixels high and very aliased. If I would have remade it I would have sampled multiple times and calculated an average to get a smoother and anti-aliased shadow. 

displacement mapping