Do everything in linear light, and convert to the proper gamma curve afterwards. It's almost the only way to be sure.
If you want to be really sure you're correct do everything in the XYZ colour space and then finally convert to the correct RGB space. Which is pretty much unknown for most displays by the way, if you're lucky it's something similar to sRGB.
What gets super confusing is that you have a bunch of different stuff flying around. You have textures in different formats and render targets in different formats (some are in sRGB, some are in HDR 16-bit floating-point, some are other random formats somewhere in-between). You need to set up your shader state to do the right thing for both the input texture and the render target, and the nuances of how to do this are going to change from system to system. Sometimes if you make a mistake it is easily spotted; other times it isn't.
And then there are issues of vertex color, etc. Do you put your vertex colors in sRGB or linear space? Well, there are good reasons for either choice in different contexts. So maybe your engine provides both options. Well, now that's another thing for a programmer to accidentally get wrong sometimes. Maybe you want to introduce typechecked units to your floating-point colors to try and error-proof this, but we have not tried that and it might be annoying.
All that said, everyone is about to rejigger their engines somewhat in order to be able to output to HDR TVs (we are in the process of doing this, and whereas it is not too terrible, it does involve throwing away some old stuff that doesn't make sense any more, and replace it by stuff that works a new way).
Off topic but curious to know your thoughts on Unreal Engine 4 and if you feel you could be as expressive in it as you would in your own proprietary engine?
I'd love to hear a direct response, but here's[1] a quote from a few years ago (specifically mentioned Unity, not UE4, but I assume the sentiment is the same).
I can't find it, but I was also reading an article a few days ago about why that person would choose to write their own engine over a third-party one. In that article (maybe it was the comments), they specifically called out the game mechanics of the The Witness and Braid as example of things traditional engines don't do very well.
That article is actually why I chose to use the word 'expressive' in my question!
"..when I'm making these games, they're not just commercial products. They're expressive works that we're working very hard to make, and we want them to have as long of a lifetime as possible. So I would like this game to be relevant 20 years from now, 40 years from now. How do you do that? Well, you don't necessarily do that by building it on top of a very complicated system, that you don't own, that somebody else will cease to support at some point in the future."
Given that UE4 is open source I wonder if he still has the same sentiment.
As someone that has been working on a game in UE4 for 2.5 years the idea of rolling and supporting my own engine/tools is dizzying.
After seeing the correct version the problem is really obvious.
The particular problem here is that at some point in the pipeline the colour of the particles were stored linearly instead of in sRGB. That results in the colour banding.
A programmer who was working on the engine managed to accidentally break this, and the thing that really sucks about it is that the issue is really subtle and nobody noticed it for quite some time. Thankfully it didn't get to production before I noticed it, but that was complete chance. It could easily have gone out like that.