Skip to main content
The Witcher: A bard's tale

The Witcher: A bard's tale

·668 words·4 mins

Overview
#

The Witcher: A Bard’s Tale is a cooperative beat-’em-up / hack-and-slash adventure. Players control Geralt of Rivia and Yennefer of Vengerberg as they fight to rescue Ciri.


Play

About the project
#

This is a university group project built with a custom C++ engine and OpenGL. The design focuses on responsive combat, cinematic boss encounters, and polished presentation. My work spans graphics programming, gameplay tooling, and content creation.


My individual contributions
#

  • GPU skinning (vertex shader skinning)
  • Subtitles system (JSON import + typewriter effect)
  • Boss presentation (cinematic camera movement)
  • Dummy enemy for combat testing
  • Dissolve shader effects
  • Main character models and 3D assets
  • Scene lighting
  • HUD design and menu polish

Skinning with shaders
#

To improve runtime performance we moved skinning to the GPU (vertex skinning in the vertex shader). Each vertex stores:

  • an ivec4 of bone indices (maximum 4 bones per vertex), and
  • a vec4 of bone weights (one weight per bone index).

On the CPU we upload an array of bone transformation matrices (one mat4 per bone). The vertex shader reads the bone indices and weights, builds a skinning matrix from the corresponding bone matrices, and transforms the vertex position and normal entirely on the GPU.

I also fixed a bug where some models collapsed toward the origin. The root cause was applying bone transforms relative to the original vertex positions instead of using the mesh origin; the fix was to compute skinned positions relative to the mesh origin and correctly apply bone transformations.

Vertex skinning animation showing character mesh deformation
GPU vertex skinning in action
Animation showing model collapsing to origin before skinning fix
Bug demonstration: model collapsing to origin before the fix

Subtitles system
#

The game includes narrative sequences that require subtitles. We used Subtitle Horse to author subtitles and exported them to JSON in order to easily integrate them into our engine.

I implemented a Subtitles Manager that:

  • Loads subtitle timings and text from JSON files
  • Displays timed lines with a typewriter effect
  • Synchronizes subtitles with cutscene timings
Subtitle display with typewriter effect during a cutscene
Subtitles with a typewriter effect
End-of-cutscene frame showing subtitles
Cutscene end frame with subtitles

Boss presentation (cinematic camera)
#

For boss introductions I created a cinematic camera system. The camera follows a Bezier curve to focus on the boss for a dramatic reveal. It then smoothly returns to the player before gameplay resumes.

This is implemented as a small script that samples a cubic Bezier over normalized time and interpolates both position and orientation.

Cinematic camera movement focusing on boss during intro
Cinematic boss introduction using a Bezier camera path

Dummy enemy
#

I implemented a dummy enemy used for combat training. The dummy lets players exercise attacks and combos and helps the team debug input timing, hit detection, and animation transitions.

Dummy enemy used to test combat system and combos
Dummy enemy for combat testing

Dissolve shader
#

I implemented a dissolve shader for stylized appearance/disappearance transitions. The effect uses a noise texture (or procedural noise) and a parameter that drives a threshold mask—this creates smooth, controllable fade-ins/fade-outs with edge detail.


3D models and assets
#

I produced characters and game assets, and learned the production art pipeline: sculpting, retopology in Maya, texture painting in Substance, and creating low-poly bases for production.

Geralt of Rivia
#

3D concept art of Geralt of Rivia
Geralt concept art
Retopology process for Geralt model
Geralt retopology process

Yennefer of Vengerberg
#

Yennefer concept art and retopology
Yennefer concept and retopology
Yennefer rendered in the engine
Yennefer in-engine render

Ghoul enemy
#

Ghoul concept sculpt in ZBrush
Ghoul concept sculpt
Ghoul size comparison chart
Ghoul size comparison

Other assets
#

I created environmental props such as bushes, rocks and minerals used across scenes.


HUD design
#

I created the HUD layout and icons, iterated on UI prototypes, and implemented polished icons and feedback elements.


Main menu polish #

For the main menu I added particle systems and a global bloom post-process to make the scene feel more dynamic and atmospheric.


Lighting tweaks
#

I iterated on scene lighting to match each arena’s atmosphere, balancing directional lights, ambient contribution and baked elements where appropriate.


Links & downloads #