Live Long and Render (I)

320x240

Fun fact: I created a draft for this article in early 2016, while I was rounding up Metal support and shortly after Vulkan was announced. It took me three years, but here it is:

YES.

I’m finally working on a Vulkan-based rendering backend for Crimild.

This time it’s going to be much more than just making a Renderer class with Vulkan code inside as I did with Metal some time ago. This time, thought, I’m willing to go as far as I have to and make a modern rendering architecture.

It’s BIG refactor time!

Why now?

I started this year (2019, I think) talking about how render graphs and shader graphs and other rendering improvements were critical for the next major version of Crimild. But as time has passed, I come to realize that they were not enough.

Despite their benefits, I was headed towards a mixed solution. Neither old school nor modern. Using state of the art techniques, but bounded by OpenGL limitations. And, while it was indeed a step forward towards newer paradigms and APIs (Vulkan, Metal, etc), if I followed that road I was going to have to change most of it again in the near future. After all, there’s no gain in making Vulkan work like OpenGL.

Therefore, I started from scratch and decided to do it the right way from the beginning. I’m going to implement a whole new rendering system on top of Vulkan and it’s major concepts (render devices, swapchains, pipelines, render passes, etc).

What about OpenGL? Well, as much as I love it, I would like to get rid of it. The only environment in which I see OpenGL as still relevant is on web (as in WebGL). Being able to publish apps on browsers (throught Emscripten) is still a goal for Crimild, so I guess OpenGL is not going anywhere for now. But, it’s going to change based on whatever architecture I come up with after this refactor.

What about Metal? I am getting rid of the Metal renderer. Plain and simple. There’s no point in supporting both Vulkan and Metal (at least for the moment). And the current implementation is quite limited. The good size of this is that after having a Vulkan-based rendering system, implementing on in Metal should be straightforward. Provided I needed, of course.

What have I done so far?

I have read articles, books, even tweets. I have watched videos. I have completed the excellent Vulkan Tutorial and looked into several examples.

I recently started working on (that is, actually coding) the new rendering architecture on my spare time (I have other priorities at the moment). This is what I achieved so far:

Yeap, that’s just a window.

Well, it’s a bit more than that.

At the moment, I can create a Vulkan Instance and a Surface, which is not a small feat for Vulkan. I’m working on a Mac (using MoltenVK) with GLFW for window management, but the new implementation is supposed to work on multiple platforms.

I made changes to other parts of Crimild too, like simulations and systems. Nothing too big, just a few tools to better prioritize systems. I am planning to change them a lot once go full ECS in the not-so-distant future. But, one refactor at a time.

That’s it for now. I try and write more posts as I make progress. But I won’t make any promises 🙂

Bye!

Your wish, my command (console)

A couple of weeks ago, when I was working on a secret project of mine , the following situation occurred:

Each level in the game is composed of several sections. Some of them are interactive, requiring the player to do something (like traversing a path or killing enemies). Cut-scenes are played in-between those sections, triggered by some event happening in the game world (for example, when the player reaches a predefined point in the map).

As you might have guessed, it’s very frustrating to play entire sections of the level just to reach the last cut-scene and realizing that some actors were misplaced. Despite the fact that everything is based on Lua scripts and that reloading them is very fast, we still need to replay at least a couple of sections just to verify that our changes worked. It would be great to have a tool to trigger those animations and any other events as soon as the level loads, right?

Of course.

And what better tool for such a situation than an interactive console?… Actually, a scene editor would be much better. Maybe one embedding a script editor. Oh, oh! Visual scripting will be great too… and also… Ok, fine, it’s not the best solution, but bear with me.

Anyway, the interactive console is very simple to use. You press the tile (~) character in your keyboard and a prompt appears waiting for you to input commands. Yes, it’s pretty similar to UNIX terminals and it even has a command history and scrollable text, although there is no support for autocompletion at the moment.

Implementing new commands is as simple as registering a name and a callback that will be triggered whenever the user inputs such text into the prompt. For example:

Console::getInstance()->registerCommand( crimild::alloc< SimpleConsoleCommand>( "foo", []( Console *console, ConsoleCommand::ConsoleCommandArgs const &args ) {
   console->printLine( "Bar" );
}));

Here is the console in action:

Screen Shot 2017-05-10 at 1.09.08 AM

Probably the most useful command at the moment is the set one, which lets you change settings values while the game is running. For example, you can enable the profiler change the value of the profiler.enable variable like this:

set profiler.enabled=1

Screen Shot 2017-05-10 at 1.12.06 AM.png

The best part is that the console is already included into the Simulation framework and will be available as part of the next release (any time now). The only requirements is that you, the application developer, are responsible for providing a System Font to be used during the rendering phase. The same is true for the Profiler, btw.

See you next time!

Progress Update – November 2016

This post summarizes all the things I’m currently working on, without any specific priority order (as usual).

Job System

Probably the biggest feature to be included in the next release (whenever that happens) is the new Job System.

Last year I implemented a Task Scheduler for asynchronous work and while it is (was?) useful, it does lack the mechanisms required for programs to properly work concurrently. In particular, there’s no way to wait for tasks to complete or group them together as one unit of work.

Enters the new Job System, in which we’re going to be able to schedule jobs (obviously), that may or may not be linked with other jobs (as in parent/child jobs) and wait for them to complete before continuing. A “work stealing” approach is being used internally and we can spawn as many worker threads as we need.

The new Job System will allow us to move to a more parallel architecture by implementing things like parallel visitors, multi-threaded render queues and more.

Surprisingly, the current state of this feature is quite advanced and looking good. I just pushed the main classes to the development branch and I expect to refactor the Simulation flow pretty soon.

Ray Tracer Improvements

I needed a way to test the new Job System before having to refactor the entire Simulation flow and the Ray Tracer seemed to be the perfect candidate.

Initial tests are promising, showing that the rendering time has been reduced by 60% (depending on the number of worker threads, of course). The image below took “only” 80 minutes to render in my Macbook using 8 worker threads.

output_800_600_100

I’ve included several fixes in the latest code and I’m going to move to phase two (actual geometry, lighting, textures, etc) probably before the end of the year.

Scripting

As it is right now, the scripting system is mostly used for scene building, specifying objects and components in script files using Lua. But I want more. I need more. I want to be able to create components from Lua files and interact between them and first class ones written in C++. I want to be able to create a whole new simulation or game without enforcing the developer to write and compile C++ code.

The improved scripting tools are still in a design phase and even when I would like to include them in the next release, I know they might not make it.

Improving Audio Support

This is something that I had in my list for a while and I’m giving it a try as a side project. At the moment, Crimild supports audio clips using OpenAL (including positional audio, of course) only in WAV format and there’s no way to play background music.

My initial goal is to work with OGG files. By the end of phase one I should be able not only to play music files but also to support some simple mixing mechanisms.

I don’t expect this feature to be included in the next release, but it should be done early next year because it’s something that I need for a different, super secret, project.

Scene Streaming

Yes, this is back. You know, that super useful thing let you save and load entire scenes to disk, using a binary file format (which was there five years ago but then disappeared one day without reason).

A working implementation for scene streaming was included in the last version (I’m not kidding, it’s there). I’m constantly revisiting it by adding support for more components and entities. The new binary file format has proven quite good, and loading times have been reduced in a great amount.

That’s it. Well, not really. There might be one or two more things in my TODO list right now, but the ones above are the most important ones. I’m planning on having a new release before the year’s done, including most of these features. So, stay tuned.