AWS for Games Blog
Splitting the Atom: Introducing Lumberyard’s New Photorealistic Renderer
Authored by Chanelle Mosquera and Doug Erickson of the Amazon Lumberyard team.
For over 5 years, Amazon Lumberyard‘s graphics engine has served our customers in fine stead. As we looked to our future, we recognized that its fixed approach to rendering and its established feature set would limit our customers’ ability to innovate and take advantage of new graphics techniques and hardware. With the developments around modern 3D engines that showcase physically based rendering and ray tracing in gaming, as well as current demands from other industries with rendering needs — like detailed simulations for automotive and industrial applications, and high-tech special effects for motion pictures — we determined that our customers would benefit from a different kind of renderer. One that is far more modular and customizable. One that supports the feature sets of modern GPUs. And one that is more performant across a wide variety of scenarios, including and beyond gaming.
So, we built an all-new graphics engine to provide the backbone for the future of Lumberyard visuals: the Atom renderer!
At the highest level, the Atom renderer is a high-performance, physically based renderer capable of delivering all the latest and greatest graphics features that games and multimedia customers want to see in 2021 and beyond. There’s global illumination for structural engineers and designers to incorporate into multifaceted lighting environments. Ray tracing for manufacturers to accurately model their new products in realistically lit scenes. Interfaces for modern hardware-based effects to make next-generation, immersive video game environments. Several SIGGRAPH technical papers’ worth of post-processing effects for movie- and game-industries to really “wow” their audiences. Support for Forward+ rendering right out of the box, and the infrastructure to readily add deferred rendering in the future. Support for DirectX 12, Vulkan, and Metal. Support for multiple platforms, including Windows, Linux, Mac, Android, iOS — with even more to come.
The Atom renderer is designed to accelerate your creativity and innovation. It’s an Atom you can easily split: we built it to be modular with a data-driven design that facilitates customization and expansion to suit tomorrow’s rendering demands. To back that statement up, let’s take a peek into Atom’s forward-thinking approach and high-level details.
Modular and customizable for adaptive rendering
The Atom renderer is designed from the ground up to be modular and easily customized. Likewise, it is fully multi-threaded to support multiple parallelized workloads. It’s entirely data-driven, with almost every feature and configuration defined and managed through JSON files, reducing time spent in recompilation. If a developer wants to customize Atom even further, they can update the modularized C++ code and APIs and recompile just the components they’ve changed — not the entire renderer.
What does that mean? It means that the Atom renderer isn’t a monolith. It’s a collection of different components that you can easily assemble, integrate with, and extend without all the messy glue and asserts and hours spent raging at the API documentation. You can work directly in JSON, or automate with your own scripts and code. You can isolate and optimize without wondering about what the fixed code paths in the engine are doing to drive your frame rates into the gutter. You can easily create, integrate, and optimize shaders and shader stages. You can use the replaceable hardware interfaces to take full advantage of future platforms as they are released. Working with Computer-Aided Design (CAD) data? Focus on fidelity over frame rate. Creating visuals for a next-gen photorealistic game? Find the right balance between accuracy and performance, tailored to your game’s scenes. Looking into XR? Customize the pipeline to add the features you need for the best virtual experience, rather than hacking around a fixed rendering model.
This snippet of a JSON file is actually the Atom renderer’s main pipeline. It defines the root pass that initiates all subsequent render passes through a series of PassRequests. As you can see, the properties of the render pipeline are easy to read and allow for straightforward configuration.
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "PassAsset",
"ClassData": {
"PassTemplate": {
"Name": "MainPipeline",
"PassClass": "ParentPass",
"Slots": [
{
"Name": "SwapChainOutput",
"SlotType": "InputOutput",
"ScopeAttachmentUsage": "RenderTarget"
}
],
"PassRequests": [
{
"Name": "SkinningPass",
"TemplateName": "SkinningPassTemplate"
},
{
"Name": "RayTracingAccelerationStructurePass",
"TemplateName": "RayTracingAccelerationStructurePassTemplate"
},
{
"Name": "DiffuseProbeGridUpdatePass",
"TemplateName": "DiffuseProbeGridUpdatePassTemplate",
"ExecuteAfter": [
"RayTracingAccelerationStructurePass"
]
},
...
]
}
}
}
How’s this all work? Well, let’s take a look at Atom’s high-level architecture and its core systems that make it such a modular and flexible rendering engine.
At the lowest level of the pipeline is the Rendering Hardware Interface (RHI), which is the layer that communicates with all the graphics APIs and hardware abstractions. On top of the RHI is the Rendering Pipeline Interface (RPI), which is the platform-independent layer that render engineers will interact with most. The benefit of this design is that engineers don’t need to be concerned with platform details as they build out new features. Instead, they can just focus on making great graphics, regardless of platform.
Within the RPI is the new Pass System that handles the many render passes throughout the render pipeline. Using JSON serialization, such as in the snippet displayed above, passes can be authored and configured in data. This allows you to modify the graphics pipeline without rebuilding the entire rendering engine. We’ll go more into how this data-driven process simplifies workflows across many aspects of the rendering workflow in a bit.
This diagram shows how Atom is structured at the top level:
On the shader side of things, we’ve created the Amazon Shading Language, or AZSL. AZSL is an extension of Microsoft’s DirectX 12’s HLSL language, with some extra tweaks to support Atom’s inherent flexibility. We know you prefer the familiar in your day-to-day work, and likewise saw no need to dramatically reinvent shading language grammars.
Here are a couple of key benefits that AZSL brings:
- Write your shader once, in a unified language — which Atom uses to create native shaders for all the platforms it supports. No need to write different shaders for different platforms!
- Shader Resource Groups (effectively containers of shader resources) are exposed in a way that’s convenient and easier to work with across multiple shaders.
- The new shader permutation management system allows for more efficiency when processing shaders.
Now, whether it’s implementing new render techniques, switching render passes, or creating eye-catching shaders, Atom is designed to streamline all these workflows so that you can focus on what you came here for: creating and rendering beautiful environments and characters to immerse your players, improve the visual fidelity of your simulations, and take your CG media to a new level.
The systems underpinning Atom are specifically organized and encapsulated with a friendly API so that you can configure a specific aspect of the render pipeline, or turn 180 degrees and switch to a completely different render pipeline. With the variety of cutting-edge render projects, this flexibility is essential. Developers can activate only the graphics features that they need, and they can develop additional graphics features across all platforms without touching any graphics APIs. Just fire up your JSON parser or text editor and go!
As part of Atom’s modular efforts, graphics features have a clean communication workflow between Lumberyard and Atom. Developers can take advantage of this to extend or create new features. To give you an example, the Bloom and Depth of Field effects are features that are both managed by the “Post Process Feature Processor” in Atom. These features provide data to the same feature processor, which then handles post processing calculations and pushes them through the rendering engine. Essentially, feature processors are interfaces in Atom that allow graphics features to be integrated into Lumberyard or other tools. In the same way, you can create your own feature processors and easily integrate new features.
We’ll go more in-depth into how this works in a future blog post, but the takeaway is that modular design makes for far cleaner and more manageable code, and encourages you to play with configurations and customizations without all the recompilation overhead or potential regressions. Additionally, this modular approach allows for faster iterative development and simpler maintenance since there’s less code tangle across the features.
Performant physically based rendering for realistic and highly detailed environments
While realism isn’t always asked for, it’s a good place to start, and provides a credible set of features and effects to build more visually dynamic and hyper-realistic scenes as you’d like.
To this end, the Atom renderer uses physically based rendering (PBR, not be confused with the classic American beverage) techniques to simulate realistic interaction between materials and light. Atom supports artist-friendly PBR material types that can be designed using Atom’s Material Editor, or converted from popular content creation tools like Blender and Maya. Using the Atom tools or your own (or both), you can create a StandardPBR material that features a fully-equipped, metallic/roughness workflow and has minimal performance limitations. Or you can create an EnhancedPBR material that’s a bit heavier on performance, but has additional features such as rendering with subsurface scattering and anisotropy (and more). We will invest in expanding the library of materials starting with multi-layer PBR materials.
However, the complexity of your materials is not limited to the existing collection of material types. You can take the simplified MinimalPBR material type and extend it to support a customized set of material properties. Did we mention the bulk of this work uses Atom’s intuitive data-driven methods?
For all the technical artists, we know you’ve got your own set of tools and content creation workflows, and Atom intends to complement your creative pursuits. You’ll be able to integrate our physically based shading models seamlessly into your workflow with our image and asset builders and DCC (digital content creation) scripting integrations.
Data-driven for iterative workflows
The complexity of scenes, shaders, and materials in modern games and multimedia is a far cry [Ed: what a horrible pun] from those developed in the days of DirectX 9 and OpenGL 2.0. As we developed the Atom renderer, your ability to manage and work with all these complex components was in the forefront of our minds and our planning. If anything can be represented as data, why shouldn’t we do just that, instead of hiding the configuration and management behind confusing APIs, arbitrary schemas, and opaque code paths?
Atom’s data-driven design untangles the complexity of code from our creative process. Let’s take a quick peek at what advantages Atom’s data-driven philosophy gives us:
- A data-driven material system.
Materials are created from a material type, such as our “standard” and “enhanced” PBR material types mentioned above. Both materials and material types can be created and edited in JSON files. While the new Material Editor we’re working on is one way to create materials, you also have the option to create scripts to automate any material creation — or just make a simple change straight into the material file. Creating your own material types must be handled outside of the Material Editor, so this data-driven method is highly effective. Nonetheless, our developers are hard at work designing a node-based graph tool to further leverage artists’ workflow and creativity with material types. CPU-side marshalling of material data is handled through Lua scripts, but can also be handled through custom C++ where needed for performance. - A data-driven pass system.
As with all renderers, a chain of render passes helps 3D objects go from plain vertex data and assorted materials data to beautiful, lush environments awash in ephemeral lights and enhanced with post-processing effects. Render passes can be configured and authored in a data-driven way using JSON. You can customize the pipeline by enabling and disabling different render passes, tweaking a property here and there, or authoring a completely new render pass. For those who want to customize passes with more complex logic, or for those who are simply more comfortable working in code, you can create passes in C++ as well. - Rapid iteration with hot reloading.
Atom’s shaders, materials, passes, and even entire rendering pipelines automatically reload as you make changes, so you can quickly tweak and adjust your math and configuration without recompiling or restarting the application. Spend your time getting a scene looking just right, without watching a compiler grind away on your dev rig. And don’t worry about introducing pipeline errors and crashing your application! Edits to passes and pipelines will trigger a validation step that, if it fails, will report the errors while running the pipeline minus the recent unsuccessful changes.
And this is just the beginning. The Atom renderer is a foundational investment in graphics rendering technology and specifically designed to NOT lock you into one or a few approaches, but instead to provide a flexible, modular, and massively extensible platform for graphics development. The greatest visuals and effects won’t come from us. They will come from our customers as they build atop this framework and extend it to bring in scenes and effects unencumbered by stale APIs, fixed implementations, and closed pipelines. It’s been a long road over the past 3+ years to create Atom, and involved many engineers and key industry partners, but what’ll make it truly great is YOU. A graphics engine doesn’t create great experiences by itself. That’s up to the developers and content creators who build the games, movie visuals, and simulations. We’re extremely excited to see what they can do with Atom once we release it.
“Yay,” you say. “Awesome! Can’t wait to hear more! Can’t wait to play with it and see what it can do! Gimme some benchmarks, Lumberyard! Gimme some bits to download!”
You’ll have to wait a little longer. But it’ll be soon. Very soon.
We have a lot of amazing new features to announce around Lumberyard’s future, and we’ll be diving deeper into Atom in our coming blogs. When we’re ready this year, you’ll have a chance to try it for yourself. And we will definitely want your feedback on what you — the development community — want in a new renderer. Share your ideas and thoughts in the comments below, or on the Lumberyard forums.
Watch this space!
—
Chanelle Mosquera is a programmer writer for Amazon Lumberyard, and specifically Atom. She can’t even begin to render her excitement for the next cinematic stampede of real-time dinosaurs.
Doug Erickson is the documentation manager for AWS Game Tech services. He has been obsessed with graphics programming since the days of the Commodore Amiga. For some reason, AWS lets him write about games.