Nathan Reed

Blog Stuff I’ve Made Talks About Me
All Posts

Texture Gathers and Coordinate Precision

January 15, 2022 · Graphics, GPU · Comments

A few years ago I came across an interesting problem. I was trying to implement some custom texture filtering logic in a pixel shader. It was for a shadow map, and I wanted to experiment with filters beyond the usual hardware bilinear.

I went about it by using texture gathers to retrieve a neighborhood of texels, then performing my own filtering math in the shader. I used frac on the scaled texture coordinates to figure out where in the texel I was, emulating the logic the GPU texture unit would have used to calculate weights for bilinear filtering.

To my surprise, I noticed a strange artifact in the resulting image when I got the camera close to a surface. A grid of flickery, stipply lines appeared, delineating the texels in the soft edges of the shadows—but not in areas that were fully shadowed or fully lit. What was going on?

Read more


git-partial-submodule

September 4, 2021 · Comments

View on GitHub

Have you ever thought about adding a submodule to your git project, but you didn’t want to bear the burden of downloading and storing the submodule’s entire history, or you only need a handful of files out of the submodule?

Git provides partial clone and sparse checkout features that can make this happen for top-level repositories, but so far they aren’t available for submodules. That’s a hole I aimed to fill with this project. git-partial-submodule is a tool for setting up submodules with blobless clones. It can also save sparse-checkout patterns in your .gitmodules file, allowing them to be managed by version control, and automatically applied when the submodules are cloned.

Read more


Slope Space in BRDF Theory

July 16, 2021 · Graphics, Math · Comments

When you read BRDF theory papers, you’ll often see mention of slope space. Sometimes, components of the BRDF such as NDFs or masking-shadowing functions are defined in slope space, or operations are done in slope space before being converted back to ordinary vectors or polar coordinates. However, the meaning and intuition of slope space is rarely explained. Since it may not be obvious exactly what slope space is, why it is useful, or how to transform things to and from it, I thought I would write down a gentler introduction to it.

Read more


Hash Functions for GPU Rendering

May 21, 2021 · Coding, GPU, Graphics · Comments

Back in 2013, I wrote a somewhat popular article about pseudorandom number generation on the GPU. In the eight years since, a number of new PRNGs and hash functions have been developed; and a few months ago, an excellent paper on the topic appeared in JCGT: Hash Functions for GPU Rendering, by Mark Jarzynski and Marc Olano. I thought it was time to update my former post in light of this paper’s findings.

Read more


Making Your Own Container Compatible With C++20 Ranges

March 20, 2021 · Coding · Comments

With some of my spare time lately, I’ve been enjoying learning about some of the new features in C++20. Concepts and the closely-related requires clauses are two great extensions to template syntax that remove the necessity for all the SFINAE junk we used to have to do, making our code both more readable and more precise, and providing much better error messages (although MSVC has sadly been lagging in the error messages department, at the time of this writing).

Another interesting C++20 feature is the addition of the ranges library (also ranges algorithms), which provides a nicer, more composable abstraction for operating on containers and sequences of objects. At the most basic level, a range wraps an iterator begin/end pair, but there’s much more to it than that. This article isn’t going to be a tutorial on ranges, but here’s a talk to watch if you want to see more of what it’s all about.

What I’m going to discuss today is the process of adding “ranges compatibility” to your own container class. Many of the C++ codebases we work in have their own set of container classes beyond the STL ones, for a variety of reasons—better performance, more control over memory layouts, more customized interfaces, and so on. With a little work, it’s possible to make your custom containers also function as ranges and interoperate with the C++20 ranges library. Here’s how to do it.

Read more


Python-Like enumerate() In C++17

November 24, 2018 · Coding · Comments

Python has a handy built-in function called enumerate(), which lets you iterate over an object (e.g. a list) and have access to both the index and the item in each iteration. You use it in a for loop, like this:

for i, thing in enumerate(listOfThings):
    print("The %dth thing is %s" % (i, thing))

Iterating over listOfThings directly would give you thing, but not i, and there are plenty of situations where you’d want both (looking up the index in another data structure, progress reports, error messages, generating output filenames, etc).

C++ range-based for loops work a lot like Python’s for loops. Can we implement an analogue of Python’s enumerate() in C++? We can!

Read more


Using A Custom Toolchain In Visual Studio With MSBuild

November 20, 2018 · Coding · Comments

Like many of you, when I work on a graphics project I sometimes have a need to compile some shaders. Usually, I’m writing in C++ using Visual Studio, and I’d like to get my shaders built using the same workflow as the rest of my code. Visual Studio these days has built-in support for HLSL via fxc, but what if we want to use the next-gen dxc compiler?

This post is a how-to for adding support for a custom toolchain—such as dxc, or any other command-line-invokable tool—to a Visual Studio project, by scripting MSBuild (the underlying build system Visual Studio uses). We won’t quite make it to parity with a natively integrated language, but we’re going to get as close as we can.

Read more


Mesh Shader Possibilities

September 29, 2018 · Coding, GPU, Graphics · Comments

NVIDIA recently announced their latest GPU architecture, called Turing. Although its headlining feature is hardware-accelerated ray tracing, Turing also includes several other developments that look quite intriguing in their own right.

One of these is the new concept of mesh shaders, details of which dropped a couple weeks ago—and the graphics programming community was agog, with many enthusiastic discussions taking place on Twitter and elsewhere. So what are mesh shaders (and their counterparts, task shaders), why are graphics programmers so excited about them, and what might we be able to do with them?

Read more


Normals and the Inverse Transpose, Part 3: Grassmann On Duals

July 22, 2018 · Graphics, Math · Comments

Welcome back! In the last couple of articles, we learned about different ways to understand normal vectors in 3D space—either as bivectors (part 1), or as dual vectors (part 2). Both can be valid interpretations, but they carry different units, and react differently to transformations.

In this third and final installment, we’re going leave behind the focus on normal vectors, and explore a couple of other unitful vector quantities. We’ve seen how Grassmann bivectors and trivectors act as oriented areas and volumes, respectively; and we saw how dual vectors act as oriented line densities, with units of inverse length. Now, we’re going to put these two geometric concepts together, and find out what they can accomplish with their combined powers. (Get it? Powers? Like powers of a scale factor? Uh, you know what, never mind.)

Read more


Normals and the Inverse Transpose, Part 2: Dual Spaces

May 19, 2018 · Graphics, Math · Comments

In the first part of this series, we learned about Grassmann algebra, and concluded that normal vectors in 3D can be interpreted as bivectors. To transform bivectors, we need to use a different matrix (in general) than the one that transforms ordinary vectors. Using a canonical basis for bivectors, we found that the matrix required is the cofactor matrix, which is proportional to the inverse transpose. This provides at least a partial explanation of why the inverse transpose is used to transform normal vectors.

However, we also left a few loose ends untied. We found out about the cofactor matrix, but we didn’t really see how that connects to the algebraic derivation that transforming a plane equation $N \cdot x + d = 0$ involves the inverse transpose. I just sort of handwaved the proportionality between the two.

Read more

All Posts

Subscribe

  • Follow in Feedly Feedly
  • RSS RSS

Recent Posts

  • Texture Gathers and Coordinate Precision
  • git-partial-submodule
  • Slope Space in BRDF Theory
  • Hash Functions for GPU Rendering
  • Making Your Own Container Compatible With C++20 Ranges
  • Python-Like enumerate() In C++17
  • All Posts

Categories

  • Graphics(30)
  • Coding(23)
  • Math(19)
  • GPU(15)
  • Physics(6)
  • Eye Candy(4)
© 2007–2022 by Nathan Reed. Licensed CC-BY-4.0.