Modern Vulkan-based 3D engine featuring procedural shape generation, scene management, and ImGui integration
Find a file
2016-07-06 21:13:24 +02:00
android Updated android build file for deferred shading example 2016-07-04 20:54:00 +02:00
base Reverted change for inverted normal y 2016-07-04 19:28:19 +02:00
bin Added missing assimp dll 2016-02-16 21:12:25 +01:00
bloom Sample directly from framebuffer color attachment, removed texture targets 2016-06-05 18:20:02 +02:00
cmake cmake: Add FindASSIMP.cmake 2016-03-16 15:10:02 -07:00
computeparticles Use Vulkan result check macro, removed unused functionality from tools and base class 2016-05-30 20:57:38 +02:00
computeshader Use Vulkan result check macro, code cleanup, added text overlay 2016-05-23 21:22:00 +02:00
data Use gl_FrontFacing to determine mirrored surface side, enable clipping (Refs #190) 2016-07-06 21:13:24 +02:00
debugmarker Use undefined initial image layout (fixes #187), added missing layout transition for compute texture target in ray tracing example 2016-06-22 20:30:14 +02:00
deferred Normal orientation, don't pause by default 2016-07-04 19:28:43 +02:00
displacement Updated displacement example 2016-06-06 14:28:13 +02:00
distancefieldfonts Refactoring, use Vulkan result check macro 2016-06-06 11:21:07 +02:00
documentation Added my Khronos Meetup Munich Presentation 2016-04-09 12:53:39 +02:00
external Partial merge branch 'add-debug-marker-use' of https://github.com/baldurk/Vulkan into baldurk-add-debug-marker-use (Refs #146) 2016-05-22 12:44:29 +02:00
gears Refactoring, use Vulkan result check macro, staging 2016-06-06 10:38:03 +02:00
geometryshader Refactored geometry shader example, added normal map toggle, updated shaders, etc. 2016-06-05 19:57:35 +02:00
images Rephrased paragraph on building the examples for the supported platforms 2016-03-26 13:46:49 +01:00
instancing Text overlay, updated draw function, Vulkan result check macro 2016-06-05 19:27:35 +02:00
libs Updated headers to SDK 1.0.11.1 2016-05-19 19:50:09 +02:00
mesh Refactoring, added text overlay 2016-06-05 20:28:39 +02:00
models Added Vulkan examples sources! 2016-02-16 15:07:25 +01:00
multisampling Refactoring, removed device wait idles 2016-06-05 20:21:00 +02:00
multithreading Reuse fence, use Vulkan result check macro, enabled text overlay 2016-05-29 13:15:16 +02:00
occlusionquery Display occlusion query stats on text overlay 2016-05-18 19:44:24 +02:00
offscreen Use gl_FrontFacing to determine mirrored surface side, enable clipping (Refs #190) 2016-07-06 21:13:24 +02:00
parallaxmapping Refactoring, added text overlay, removed device wait idles 2016-06-05 20:58:58 +02:00
particlefire Refactored particle fire example 2016-06-05 20:14:04 +02:00
pipelines Add dynamic line width state, enable wide line feature (Fixes #165) 2016-07-03 17:07:23 +02:00
pushconstants Refactoring, added text overlay, removed device wait idles 2016-06-05 20:35:39 +02:00
radialblur Use undefined initial image layout (fixes #187), added missing layout transition for compute texture target in ray tracing example 2016-06-22 20:30:14 +02:00
raytracing Use undefined initial image layout (fixes #187), added missing layout transition for compute texture target in ray tracing example 2016-06-22 20:30:14 +02:00
scenerendering Text overlay 2016-06-20 22:06:36 +02:00
screenshots Visually upgraded deferred rendering example with moving lights, multiple meshes and normal mapping 2016-07-03 21:32:35 +02:00
shadowmapping Removed offscreen texture target, sample directly from framebuffer color attachment 2016-06-05 17:35:21 +02:00
shadowmappingomni Use undefined initial image layout (fixes #187), added missing layout transition for compute texture target in ray tracing example 2016-06-22 20:30:14 +02:00
skeletalanimation Initialize skinned mesh with nullptr 2016-06-14 18:12:47 +02:00
sphericalenvmapping Use example base prepare and submit frame function, added ext overlay 2016-05-20 21:30:17 +02:00
terraintessellation Android asset loading for height map 2016-06-25 22:49:22 +02:00
tessellation Updated PN-Triangles tessellation shader demo 2016-05-21 16:01:48 +02:00
textoverlay Use undefined initial image layout (fixes #187), added missing layout transition for compute texture target in ray tracing example 2016-06-22 20:30:14 +02:00
texture Cleaned up image layouts, pass subresourcerange, use undefined image layout for optimal tiled images (refs #187) 2016-06-21 20:36:54 +02:00
texturearray Use undefined initial image layout (fixes #187), added missing layout transition for compute texture target in ray tracing example 2016-06-22 20:30:14 +02:00
texturecubemap Use undefined initial image layout (fixes #187), added missing layout transition for compute texture target in ray tracing example 2016-06-22 20:30:14 +02:00
triangle Build command buffers for pre and post present barriers only once (instead of every frame) 2016-06-21 23:07:16 +02:00
vulkanscene Use Vulkan result check macro, code cleanup, text overlay 2016-06-02 23:02:39 +02:00
.gitattributes gitattributes 2016-02-18 12:03:13 +01:00
.gitignore Added Vulkan examples sources! 2016-02-16 15:07:25 +01:00
cleanup.bat Added Vulkan examples sources! 2016-02-16 15:07:25 +01:00
CMakeLists.txt Added text overlay example to cmake and android build 2016-05-07 15:59:08 +02:00
LICENSE.md Added Vulkan examples sources! 2016-02-16 15:07:25 +01:00
README.md Visually upgraded deferred rendering example with moving lights, multiple meshes and normal mapping 2016-07-03 21:32:35 +02:00
vulkanExamples.sln Keys for tessellation and wireframe 2016-06-20 20:04:28 +02:00
vulkanExamples.vcxproj Added Vulkan examples sources! 2016-02-16 15:07:25 +01:00
vulkanExamples.vcxproj.filters Added Vulkan examples sources! 2016-02-16 15:07:25 +01:00

Vulkan examples and demos

Vulkan demo scene

Assorted C++ examples for Vulkan(tm), the new graphics and compute API from Khronos.

Building

The repository contains everything required to compile and build the examples on Windows, Linux and Android using a C++ compiler that supports C++11. All required dependencies are included.

Windows

A Visual Studio solution file for compiling all examples is included with the repository, examples will compile with VS2015 out of the box.

If you're using a different IDE or compiler you can use the provided CMakeLists.txt for use with CMake to generate a build configuration for your toolchain.

Linux

Use the provided the provided CMakeLists.txt for use with CMake to generate a build configuration for your favorite IDE or compiler.

Note that you need assimp in order to compile the examples for Linux. Either compile and install from the repository, or install libassimp-dev. The examples require at least version 3.2.

Android

Building on Android is done using the Android NDK and requires a device that supports Vulkan. Please see the Android readme on how to build and deploy the examples.

Binaries

Precompiled binaries for Windows (x64), Linux (x64) and Android can be found here. I'll try keep them up-to-date with the repository.

Note that these only contain the binaries, you still need the repository for the data (shaders, models, textures) and put the binaries into to bin subfolder. Except for Android, where all required assets are stored inside of the apk.

Additional documentation

Additional documentation for several base classes and some Presentations can be found in this directory.

Presentations

Examples

Triangle

Most basic example. Renders a colored triangle using an indexed vertex buffer. Vertex and index data are uploaded to device local memory using so-called "staging buffers". Uses a single pipeline with basic shaders loaded from SPIR-V and and single uniform block for passing matrices that is updated on changing the view.

This example is far more explicit than the other examples and is meant to be a starting point for learning Vulkan from the ground up. Much of the code is boilerplate that you'd usually encapsulate in helper functions and classes (which is what the other examples do).

Texture mapping

Shows how to upload a 2D texture to video memory for sampling in a shader. Loads a compressed texture into a host visible staging buffer and copies all mip levels to a device local optimal tiled image for best performance.

Also demonstrates the use of (combined) image samplers. Samplers are detached from the actual texture image and only contain information on how a image is sampled in the shader.

Cubemap texture

Building on the basic texture loading example, a cubemap texture is loaded into a staging buffer and is copied over to a device local optimal image using buffer to image copies for all of it's faces and mip maps.

The demo then uses two different pipelines (and shader sets) to display the cubemap as a skybox (background) and as a source for reflections.

Texture array

Texture arrays allow storing of multiple images in different layers without any interpolation between the layers. This example demonstrates the use of a 2D texture array with instanced rendering. Each instance samples from a different layer of the texture array.

Text overlay (Multi pass)

Renders a 2D text overlay on top of an existing 3D scene. The example implements a text overlay class with separate descriptor sets, layouts, pipelines and render pass to detach it from the rendering of the scene. The font is generated by loading glyph data from a stb font file into a buffer that's copied to the font image.

After rendering the scene, the second render pass of the text overlay class loads the contents of the first render pass and displays text on top of it using blending.

Distance field fonts

Instead of just sampling a bitmap font texture, a texture with per-character signed distance fields is used to generate high quality glyphs in the fragment shader. This results in a much higher quality than common bitmap fonts, even if heavily zoomed.

Distance field font textures can be generated with tools like Hiero.

Pipelines

Pipeline state objects replace the biggest part of the dynamic state machine from OpenGL, baking state information for culling, blending, rasterization, etc. and shaders into a fixed stat that can be optimized much easier by the implementation.

This example uses three different PSOs for rendering the same scene with different visuals and shaders and also demonstrates the use pipeline derivatives.

Gears

Vulkan interpretation of glxgears. Procedurally generates separate meshes for each gear, with every mesh having it's own uniform buffer object for animation. Also demonstrates how to use different descriptor sets.

Mesh loading and rendering

Uses assimp to load a mesh from a common 3D format including a color map. The mesh data is then converted to a fixed vertex layout matching the shader vertex attribute bindings.

Scene rendering

This example demonstrates a way to render a scene consisting of multiple meshes with different materials and textures. It makes use of separate per-material descriptor sets for passing texturing information and uses push constants to pass material properties to the shaders.

Also shows how to use multiple descriptor sets simultaneously with the new GLSL "set" layout qualifier introduced with GL_KHR_vulkan_glsl.

Mesh instancing

Shows the use of instancing for rendering many copies of the same mesh using different attributes and textures. A secondary vertex buffer containing instanced data, stored in device local memory, is used to pass instance data to the shader via vertex attributes with a per-instance step rate. The instance data also contains a texture layer index for having different textures for the instanced meshes.

Multi sampling

Demonstrates the use of resolve attachments for doing multisampling. Instead of doing an explicit resolve from a multisampled image this example creates multisampled attachments for the color and depth buffer and sets up the render pass to use these as resolve attachments that will get resolved to the visible frame buffer at the end of this render pass. To highlight MSAA the example renders a mesh with fine details against a bright background. Here is a screenshot without MSAA to compare.

Multi threaded command buffer generation

This example demonstrates multi threaded command buffer generation. All available hardware threads are used to generated n secondary command buffers concurrent, with each thread also checking object visibility against the current viewing frustum. Command buffers are rebuilt on each frame.

Once all threads have finished (and all secondary command buffers have been constructed), the secondary command buffers are executed inside the primary command buffer and submitted to the queue.

Particle system

Point sprite based particle system simulating a fire. Particles and their attributes are stored in a host visible vertex buffer that's updated on the CPU on each frame. Also makes use of pre-multiplied alpha for rendering particles with different blending modes (smoke and fire) in one single pass.

Push constants

Demonstrates the use of push constants for updating small blocks of shader data with high speed (and without having to use a uniform buffer). Displays several light sources with position updates through a push constant block in a separate command buffer.

Occlusion queries

Shows how to use occlusion queries to determine object visibility depending on the number of passed samples for a given object. Does an occlusion pass first, drawing all objects (and the occluder) with basic shaders, then reads the query results to conditionally color the objects during the final pass depending on their visibility.

Offscreen rendering

Shows how to do basic offscreen rendering. Uses a separate framebuffer with color and depth attachments (that is not part of the swap chain) to render the mirrored scene off screen in the first pass.

The second pass then samples from the color attachment of that framebuffer for rendering a mirror surface.

Radial blur

Demonstrates basic usage of fullscreen shader effects. The scene is rendered into a low resolution offscreen framebuffer first.

After rendering the object the second pass then blends a full screen quad on top of the scene, sampling from the color attachment of the offscreen framebuffer ti implement a radial blur.

Bloom

Implements a bloom effect to simulate glowing parts of a 3D mesh. A two pass gaussian blur (horizontal and then vertical) is used to generate a blurred low res version of the scene only containing the glowing parts of the 3D mesh. This then gets blended onto the scene to add the blur effect.

Deferred shading

Demonstrates the use of multiple render targets to fill a G-Buffer for a deferred shading setup with multiple dynamic lights and normal mapped surfaces.

Deferred shading collects all values (color, normal, position) into different render targets in one pass thanks to multiple render targets, and then does all shading and lighting calculations based on these in screen space, thus allowing for much more light sources than traditional forward renderers.

Shadow mapping

Shows how to implement dynamic shadows from a directional light source in two passes. The first pass renders the scene depth from the light's point-of-view into a separate framebuffer attachment with a different (higher) resolution.

The second pass renders the scene from the camera's point-of-view and compares the depth value of the texels with the one stored in the offscreen depth attachment (which the shader directly samples from) to determine whether a texel is shadowed or not and then applies a PCF filter to smooth out shadow borders

To avoid shadow artifacts the dynamic depth bias state (vkCmdSetDepthBias) is used to apply a constant and slope dept bias factor.

Omnidirectional shadow mapping

Shows how to implement dynamic shadows from a point light source. Uses a dynamic 32 bit floating point cube map for a point light source that casts shadows in all directions (unlike projective shadow mapping).

The cube map faces contain the distances from the light sources, which are then used in the final scene rendering pass to determine if the fragment is shadowed or not.

Spherical environment mapping

Uses a (spherical) material capture texture containing environment lighting and reflection information to fake complex lighting. The example also uses a texture array to store (and select) several material caps that can be toggled at runtime.

The technique is based on this article.

Parallax mapping

Like normal mapping, parallax mapping simulates geometry on a flat surface. In addition to normal mapping a heightmap is used to offset texture coordinates depending on the viewing angle giving the illusion of added depth.

Skeletal animation

Based on the mesh loading example, this example loads and displays a rigged COLLADA model including animations. Bone weights are extracted for each vertex and are passed to the vertex shader together with the final bone transformation matrices for vertex position calculations.

(Tessellation shader) Displacement mapping

Uses tessellation shaders to generate additional details and displace geometry based on a heightmap.

(Tessellation shader) Dynamic terrain tessellation

Renders a terrain with dynamic tessellation based on screen space triangle size, resulting in closer parts of the terrain getting more details than distant parts. The terrain geometry is also generated by the tessellation shader using a 16 bit height map for displacement. To improve performance the example also does frustum culling in the tessellation shader.

(Tessellation shader) PN-Triangles

Generating curved PN-Triangles on the GPU using tessellation shaders to add details to low-polygon meshes, based on this paper, with shaders from this tutorial.

(Compute shader) Particle system

Attraction based particle system. A shader storage buffer is used to store particle on which the compute shader does some physics calculations. The buffer is then used by the graphics pipeline for rendering with a gradient texture for. Demonstrates the use of memory barriers for synchronizing vertex buffer access between a compute and graphics pipeline

(Compute shader) Ray tracing

Implements a simple ray tracer using a compute shader. No primitives are rendered by the traditional pipeline except for a fullscreen quad that displays the ray traced results of the scene rendered by the compute shaders. Also implements shadows and basic reflections.

(Compute shader) Image processing

Demonstrates the use of a separate compute queue (and command buffer) to apply different convolution kernels on an input image in realtime.

(Geometry shader) Normal debugging

Uses a geometry shader to generate per-vertex normals that could be used for debugging. The first pass displays the solid mesh using basic phong shading and then does a second pass with the geometry shader that generates normals for each vertex of the mesh.

(Extension) VK_EXT_debug_marker

Example application to be used along with this tutorial for demonstrating the use of the new VK_EXT_debug_marker extension. Introduced with Vulkan 1.0.12, it adds functionality to set debug markers, regions and name objects for advanced debugging in an offline graphics debugger like RenderDoc.

Vulkan demo scene

More of a playground than an actual example. Renders multiple meshes with different shaders (and pipelines) including a background.


Credits

Thanks to the authors of these libraries :

And a huge thanks to the Vulkan Working Group, Vulkan Advisory Panel, the fine people at LunarG, Baldur Karlsson (RenderDoc) and everyone from the different IHVs that helped me get the examples up and working on their hardware!

Attributions / Licenses

Please note that (some) models and textures use separate licenses. Please comply to these when redistributing or using them in your own projects :

External resources