Skip to content

Examples

Alex Dixon edited this page Apr 10, 2021 · 61 revisions

The example projects slowly introduce engine features and also act as unit tests for specific functionality across all platforms.

You can check out the live WebAssembly/WebGL examples here.

Contents

  1. Empty Project
  2. Clear
  3. Basic Triangle
  4. Basic Texture
  5. Basic Compute
  6. Render Target
  7. Depth Test
  8. Depth Texture
  9. Texture Array
  10. Debug Text
  11. Buffer Multi Update
  12. Input
  13. ImGui
  14. Blend Modes
  15. Texture Formats
  16. Rasterizer State
  17. Geometry Primitives
  18. Stencil Buffer
  19. MSAA Resolve
  20. Render Target Mip Maps
  21. Multiple Render Targets
  22. Single Shadow
  23. Play Sound
  24. Audio Player
  25. Shader Toy
  26. Rigid Body Primitives
  27. Physics Constraints
  28. Complex Rigid Bodies
  29. Shadow Maps
  30. Volume Texture
  31. Cubemap
  32. Instancing
  33. Skinning
  34. Vertex Stream Out
  35. Scriptable Renderer
  36. Scriptable Post Processing
  37. Dynamic Cubemap
  38. Signed Distance Field Shadows
  39. Subsurface Scattering
  40. Entities
  41. Area Lights
  42. Stencil Shadow Volumes
  43. Global Illumination
  44. Compute Demo (work in progress)..
  45. IK (work in progress)..
  46. Dr. Scientist.

Empty Project

source code

The first sample shows how to hook yourself into the pmtech entry point and create an empty window.

Clear

source code

Depth Test

Very basic sample just shows the bare minimum rendering code required to bind the back buffer and clear it.

Basic Triangle

source code

Basic Triangle

This sample introduces the first basic rendering functionality required to a get a single triangle drawing into the backbuffer: clear, shader loading, input layout, raster state, vertex buffer, set render target, viewport, and draw arrays draw call.

All render states and resources are created through create functions which return a handle, so that resources and states can be re-used and passed around easily, typically a creation_params struct is used to initialised values, these structs are based on d3d11 desc structures which follow the same pattern.

Basic Texture

source code

Basic Texture

Builds on top of the features introduced in the previous sample and introduces: texture loading, sampler states, texture binding, index buffer and draw indexed draw call.

Basic Compute

source code

Basic Compute Set's up a basic compute pipeline which takes a read-write texture and converts the RGB input into a greyscale output. Currently compute is only supported on the Metal and D3D11 rendering path because of the lack of compute on OpenGL for MacOS.

Render Target

source code

Render Target

Draws a triangle into a render target and then draws the render target into the backbuffer, introduces the new renderering features: render target creation and binding.

Depth Test

source code

Depth Test

Draws 2 triangles in front to back order and uses the depth test to correctly draw the teal triangle behind the gold one, without a working depth test the gold triangle would not be seen, this sample uses the back buffers depth buffer which is part of the swap chain.

Depth Texture

source code

Depth Test

Using similar code to the render target sample, this sample instead renders the triangle into a depth stencil target which is then rendered to the screen as a texture. This ensures that all rendering back-ends can create depth stencil targets and the perform the associated steps to setup resource views or image views so the depth values can be read in a shader.

Texture Array

source code
zombie/export.jsn

Texture Array

Simple demonstration / test of a texture array, the array texture is generated in the pmbuild pipeline from a container folder with an export.jsn file containing individual images. The images in the folder are sorted by name and packed into a texture array.

Debug Text

source code

Debug Text

Draws debug text to the screen, introduces new rendering functionality of gpu buffer update, constant buffers and constant buffer binding.

Buffer Multi Update

source code

Buffer multi update

This example is to test graphics API backend conformance. If the test passes you will see 4 different coloured quads, if the test fails you will only be able to see 1 quad.

OpenGL and Direct3D11 allow buffers to be updated multiple times per frame, the contents of a buffer when used in a draw call will be the same when the GPU consumes command buffer as it was on the CPU when the draw call was issued.

Metal, Vulkan and other game console graphics API's typically do not support this behaviour, the contents of a buffer during a draw call when the GPU consumes the command buffer will be that of the last buffer update.

To support this behaviour on platforms which do not natively support it a ring buffer can be used to push dynamic draw data and preserve a buffers contents at the time the CPU made the draw call, this behaviour is typically implemented by older graphics API drivers (Direct3D11- and OpenGL3- etc).

Input

source code

Input

Demonstrates how to obtain data from input devices, it displays keyboard, mouse and raw gamepad input data as well as mapped gamepad data for known gamepad devices.

ImGui

source code

Debug Text

Implementation of the legendary dear imgui. This sample also introduces blend states and blending.

Blend Modes

Source

Blend Modes

Provides a test bed for different blend modes. The application is configured using a pmfx config blend_modes.jsn, which is used to supply different blend modes and render passes to render 2 images on top of each other. This test is useful to ensure all rendering backend blend modes are implemented correctly.

Texture Formats

source code

Texture Formats

Loads and renders different texture formats which have been exported using texturec in the build pipeline. Some texture formats differ from platform to platform and are excluded by using the pen::renderer caps of the current platform. This sample also serves as a good starting point for the implementation of new texture format support in lower level graphics api's.

Rasterizer State

source code

Rasterizer State

Renders some cube meshes with different raster states: back-face, front-face and no-face culling plus wireframe fill mode to test rasteriser state across different platforms.

Geometry Primitives

source code

Geometry Primitives

Renders built in primitives, these can also be used as physics collision volumes.

Stencil Buffer

source code stencil_buffer.jsn

Stencil Buffer

Very simple stencil buffer example, clears the stencil buffer to 0x22 and renders a cube with stencil ref as 0x22, render passes are configured in stencil_buffer.jsn.

MSAA Resolve

Source

MSAA Resolve

Demonstrates how pmfx views defined in masa_resolve.jsn can choose to resolve their render targets after rendering is complete. The sample shows that a colour target can be resolve with average, depth buffer with max and an additional render target with a custom shader technique that applies gradient and swaps colours.

Render Target Mip Maps

Source

Render Target Mip Maps

Renders a simple scene into a render target and automatically generates mip maps for the render target. Uses glGenerateMipMap, mtlblitcommandencoder and GenerateMips (D3D11).

Multiple Render targets

Source

Multiple Render targets

Renders a scene to multiple render targets.

Single Shadow

Source

Single Shadow

Sets up a simple single shadow map scene.

Play Sound

source code

Play Sound

Demonstrates very basic sound playback using Fmod.

Audio Player

source code

Audio Player

Shows how the audio API can be used to do advanced audio manipulation such as EQ, pitch, volume and analyse audio spectrum through FFT.

Shader Toy

source code

Shader Toy

Introduces shader hot loading for shader-toy like real time shader editing, it also introduces the need to bind textures and constant buffers to different slots which can be used as a test for the shader compilation pipeline for various shader platforms and uniform buffer bindings on platforms supporting glsl 330 where location attributes cannot be used on uniform buffers.

Rigid Body Primitives

source code

Rigid Body Primitives

Shows how to create and add rigid body primitives through the pmtech entity component system. Press (T) or click the hand icon on the tool bar to enter physics picking mode, you can click to grab physics objects and move them.

Physics Constraints

source code

Physics Constraints

Shows you how to attach point to point, hinge and 6 degrees of freedom constraints to rigid bodies. Press (T) or click the hand icon on the tool bar to enter physics picking mode, you can click to grab physics objects and move them.

Complex Rigid Bodies

source code

Complex Rigid Bodies

This sample introduces more complex rigid bodies:

  • Convex hull rigid body - Generated from triangle list.
  • Concave triangle mesh rigid body - Allowed only for static objects.
  • Compound rigid body - Dynamic concave shapes can be created from a collection of convex bodies.

Press (T) or click the hand icon on the tool bar to enter physics picking mode, you can click to grab physics objects and move them.

Shadow Maps

source code

Shadow Maps

Demonstrates variable number of shadow maps via texture arrays. Orthogonal directional (texture 2d array), perspective spot lights (texture 2d array) and omni directional point lights (texture cube array)

Volume Texture

source code

Volume Texture

Procedurally creates a 3D volume texture and renders it using ray marching.

Cubemap

source code. export.jsn.

Cubemap

Loads and renders a cubemap from a dds file, the dds file is generated through pmbuild using an export.jsn file to specify how to pack individual images into a cubemap.

Instancing

source code

Instancing

Shows how the entities inside the entity component system can be grouped into instances to reduce draw call requirements. The sample can easily run at 60fps on a variety of different hardware showcasing the excellent performance characteristics of the data-oriented entity component system. Even though the cubes in the example are instanced, they still get unique transformation and update per frame:

  • Update 32k nodes modifying their rotation and invalidating their transform.
  • Recalculate 32k local matrices from translation, rotation and scale transform.
  • Transform 32k entities by parent to get world matrix.
  • Recalculate 32k node AABB's from world matrix.
  • Reverse combine all child node AABB's to generate parent containing AABB.

Skinning

source code

Skinning

Loads a skinned mesh and applies an animation, to show how to use animation controller and bind animation to rigs.

Vertex Stream Out

source code

Vertex Stream Out

Uses vertex stream out (d3d) or transform feedback (opengl) to demonstrate how to skin a model once, and render it many times via instancing. This strategy could be used to skin a model once and then render multiple times into shadow maps or other buffers without having to pay the overhead of skinning during each pass.

Scriptable Renderer

Source

Renderer

The sample can render entities in the component entity system with 100 lights in forward, deferred or z-prepass render mode (I plan to add fwd+, clustered and other methods here too). The entity component scene is rendered via a scene view renderer and all render state is defined in config files, configs can include one another and views can be inherited making the system very powerful to create different rendering strategies with minimal amounts of code duplication.

Scriptable Post Processing

Source

Post Processing

The post processing sample builds upon the systems explained in the data driven renderer example using pmfx. It renders some repeated Menger sponges and gradient background in a pixel shader through ray marching. Post process layers of bloom depth of field, colour correction and CRT effect create the final image.

Dynamic Cubemap

Source

Dynamic Cubemap

Uses pmfx to quickly setup multiple render passes of a scene into the faces of a 2 Cubemap textures. The dynamic Cubemap textures are then applied to spheres which move around the scene, the camera for the Cubemap rendering is positioned at the centre of each sphere.

Signed Distance Field Shadows

Source

This sample uses a pre-calculated 3D signed distance field (level-set) which was generated from triangular meshes that are placed in the scene. The volume texture was generated in pmtech editor. The 3D texture is stored and loaded in DDS format and then ray marched during forward rendering for each point light. It demonstrates how static scenes can be dynamicaly lit by point lights with complex shadows due to the benefits of ray marching.

Subsurface Scattering

Source

Demonstrates and implementation of the seperable sub surface scattering technique, once again pmfx is used to configure the scene simply and easily. A pass is used to generate a shadow map for the head, the head is then rendered with forward lighting and light transmittance is performed on the mesh using the shadow map to detect thickness. Finally a post process pass is used for light reflectance which uses a wide Gaussian distribution.

Entities

Source

The entities demo demonstrates how the entity component system can handle large number of entity updates and renders them multiple times into 4 shadow maps with a main pass using forward lighting. Similar to the instancing demo the tourus is made of 64k cubes which all individually rotate but are rendered as instances.

Area Lights

Source

This is an implementation of area lights with linearly transformed cosines. It adds the ability in pmtech to apply quad area lights with textures or animated shaders. Area lights are textured by using texture arrays which have mip maps that can be updated on the fly. This sample makes good use of render target mip map generation in d3d, opengl and via blit command encoder in metal and can be used as a unit test for that functionality.

Stencil Shadow Volumes

Source

This demo shows how pmfx can be used to configure complex rendering strategies by implementing stencil shadow volumes. The scene is rendered multiple times per light with a 2 sided stencil test to generate shadow volumes and additive blending to add lighting.

Shadow volume extrusion is done in a vertex shader with a pre-computed edge mesh, where every edge from a polygon mesh has a degenerate quad which can be extruded in the light direction if it is on the silhouette of the mesh from the lights direction.

pmfx introduces "template" and "abstract" view types where the abstract view can be used to render template views multiple times.

This sample also acts a good unit test for the rendering backends and a workout for the stencil buffer which I often find to be an overlooked hardware feature these days.

Global Illumination / Temporal AA

Realtime global illumination achieved by rendering shadow maps with colour information and then projecting the shadow map into voxels stored in a 3D texture using a compute shader, mip maps are generated for the the 3D texture and then 3D texture is cone traced in real time to evaluate incoming irradiance. Stochastic sampling is used for the rays that are cone traced which results in a noisy image, temporal AA is used to smooth this out and allow for wider GI distributions.

Dr. Scientist

A small game I was working on that is unfinished. It is located in a different repository because the assets make it larger to clone and download. It showcases some pmtech features not in any of the other examples and adds new extension functionality including:

  • setup of character animations
  • character controller
  • root motion animation system
  • collectable physics items
  • physics ray casts and sphere casts for kinematic character controller