Dual Quaternions for Mere Mortals

This article is written for people seeking intuition on dual quaternions (and perhaps even complex numbers and quaternions) beyond what is offered by traditional texts. The standard way a dual quaternion is defined is by introducing a dual unit which satisfies and slapping a quaternion and a dual-scaled quaternion together. A whole ton of algebra follows and mechanically at least, everything checks out, as if by magic. At some point, the writer will point out how dual quaternions are isomorphic to Clifford algebras (or somesuch mumbo-jumbo pertaining to Lie algebras). If you’ve taken a course in abstract algebra and are intimately comfortable with the notion of homogeneous coordinate systems already, maybe such a treatise was more than adequate. Chances are though, the concept of dual quaternions (and likely quaternions as well) feels somewhat hollow, and you are left with a lingering suspicion that there is a better way of grasping matters. Geometric algebra is there (and I recommend you take a look), but personally, having an appreciation of both is still useful, and I don’t actually find quaternions or dual quaternions to be unduly difficult or an inferior formulation in any way. I can’t lay claim to having a perfect understanding of the subject, but I am documenting my understanding here in the hopes that it may point you, fellow mathematician (graphics programmer, AI researcher, masochist, or what have you), in the right direction.

Render Graph Optimization Scribbles

When I implemented my own render graph, I needed to make a number of decisions for proceeding and wanted to record the various considerations for authoring such a library. By way of background, a render graph is an acyclic directed graph of nodes, each of which may consume a set of resources and produce a set of resources. Edges in the graph denote an execution dependency (the child node should happen after the parent), with the caveat that the dependency need not be a full pipeline barrier. For example, a parent node may produce results A and B, but a child node may only depend on A. Another caveat is that the dependencies may be relaxed to allow some overlapping. For example, a parent node may produce some result in its fragment stage which is consumed in the fragment stage of a child node. In such a case, the child node can execute its vertex stage while the parent node is also executing its vertex stage.

Optimizing C++ by Avoiding Moves

This is a quick post, but I wanted to document an evolution in how my thinking with respect to move operators and move construction. Back when C++11 was released and we were getting used to the concepts, C++ moves were groundbreaking in their ability to greatly accelerate STL containers, which were often forced to invoke copy constructors wholesale due to reallocation (e.g. a std::vector grows in size and copies N elements as a result). A move constructor allowed the programmer to create a “shallow copy” so to speak which is much faster than the default (presumably) deep copy. Ergo, to think that avoiding moves entirely might be a performance win is somewhat paradoxical. Of course, it isn’t without it’s caveats, but for me, it’s been well worth it to go all in on possibly never writing a move constructor again.

Vulkan Synchronization Primer - Part II

This is part II (and possibly the final part) on this series titled the Vulkan Synchronization Primer. For the first part, click here.