Dogway's grading shader (slang)

Well, if you aim for a PVM with RGB interface sure, set signal type to RGB, phosphor to SMPTE or anything that suits you and temperature to 9200K. I simply like a consumer CRT look with red phosphor decay.

And the games were highly saturated in my opinion for the same reasons than for GBA games, because saturation is lost through the signal. Yeah, miss @Nesguy and @Syh, they were highly active back then.

The output color space is straight forward, I use 709 because my display is calibrated to 709 primaries and an EOTF of 2.4. If yours is calibrated to sRGB (EOTF of roughly a power function of 2.222) then set that to sRGB. But sRGB was never meant to be used at home, but offices and well lit rooms.


I updated Grade with some ideas on my repo and while at it noticed some people would get confused with the plethora of settings so I made a brief guide below.

The changelog:

  • Fix signal_type not being parsed
  • Fix a typo on SLANG no-LUT
  • Fix GLSL fallback defaults
  • Add headers for parameters and move up White Point on the stack
  • Remap CRT Brightness and CRT Contrast values to more CRT-like (also go negative)
  • Add CRT flare given a CRT reflection percentage and a Surround Luminance in nits (at simulated 2700K)
  • Quantize model conversion to 8-bits to replicate CRT (and console) circuit arithmetics (not sure about this one so please test)
Signal Type (0:RGB 1:Composite)                           = 0:RGB disables CRT color controls (Hue, U and V)
Phosphor (-2:CRT-95s -1:P22-80s 1:P22-90s 2:NTSC-J 3:PAL) = Emulated CRT phosphor gamut
Diplay Color Space (-1:709 0:sRGB 1:DCI 2:2020 3:Adobe)   = Host display calibrated color space
Dark to Dim adaptation                                    = Dark to Dim OOTF fpr 709 and 2020 color spaces

// ANALOG CONTROLS //    = This block is for CRT related controls so they behave like a CRT would do
White Point              = Emulated CRT white point temperature. Typically blue voltage was increased to increase the perceptual brightness of the image also as typically red phosphors would decay quick
CRT Hue                  = HUE drift
CRT U Shift              = Color drift in the U channel
CRT V Shift              = Color drift in the V channel
CRT U Multiplier         = Color burst to control saturation in U channel
CRT V Multiplier         = Color burst to control saturation in V channel
CRT Gamma                = CRT output gamma (EOTF)
CRT Brightness           = CRT brightness control (misnomer for Offset)
CRT Contrast             = CRT contrast   control (misnomer for Gain)
CRT Beam Red             = Controls the summed average of beam voltage current and phosphor decay for red
CRT Beam Green           = Controls the summed average of beam voltage current and phosphor decay for green 
CRT Beam Blue            = Controls the summed average of beam voltage current and phosphor decay for blue 
CRT Lambert Refl. in %   = Percetange of flare/glare lambertian reflectance (F0) of CRT display
Surround Luminance -nits-= Surround luminance in nits (cd/m2) for emulated room viewing environment at 2700K surround illuminant
Vignette Toggle          = Toggles vignetting effect around the borders
Vignette Strength        = Controls the vignette strength of the effect
Vignette Power           = Controls the decay rate for the vignette

// DIGITAL CONTROLS //   = Digital color grading controls for artistic purposes
Sega Luma Fix            = Fix white level for Retro Sega Systems; Genesis, 32x, CD and Saturn 2D had color palettes designed in TV levels to save on transformations
Brightness               = Increases brightness (read "Gain") in a roll-off fashion (aka no clipping)
Contrast                 = Applies a sigmoidal (aka no clipping) contrast
Contrast Pivot           = Sets the pivot for the sigmoidal contrast, therefore allowing going from an S shaped curve to a more power like (think gamma) curve
Saturation               = Increase or lower the global saturation
Dullness/Vibrance        = Interacts with "Saturation" to bias its weight over most saturated areas vs least saturated areas
Hue vs Sat Red           = Increase or lower saturation in reds
Hue vs Sat Green         = Increase or lower saturation in greens
Hue vs Sat Blue          = Increase or lower saturation in blues
Black Level              = Raise the black level in a "Lift" fashion
Black-Red Tint           = Red   tint for the black floor (noop if blacks are not raised)
Black-Green Tint         = Green tint for the black floor (noop if blacks are not raised)
Black-Blue Tint          = Blue  tint for the black floor (noop if blacks are not raised)
White-Red Tint           = Red   tint for the whites (similar to CRT Beam Red but keeping brightness)
White-Green Tint         = Green tint for the whites (similar to CRT Beam Red but keeping brightness)
White-Blue Tint          = Blue  tint for the whites (similar to CRT Beam Red but keeping brightness)
Red-Green Tint           = Green contribution to Reds
Red-Blue Tint            = Blue  contribution to Reds
Green-Red Tint           = Red   contribution to Greens
Green-Blue Tint          = Blue  contribution to Greens
Blue-Red Tint            = Red   contribution to Blues
Blue-Green Tint          = Green contribution to Blues
LUT 1 Toggle             = Enable LUT 1 (look LUT)
LUT Size 1               = Size of LUT 1 (8, 16, 32, 48, 64)
LUT 2 Toggle             = Enable LUT 2 (technical LUT)
LUT Size 2               = Size of LUT 2 (8, 16, 32, 48, 64)

Very interesting. Did the old implementation also do this with no clipping?

1 Like

Yes, the function rolled_gain() hasn’t changed in my updates.

Overall I think the shader could be squeeze-optimized a little bit further, but I don’t know how to profile the shader or whether it’s slow or fast.

1 Like

I didn’t know this and I used to be very concerned about clipping when trying to get back lost brightness due to strong mask and scanline settings in my presets.

Perhaps you can benchmark the same games using different versions to see if there are any differences.

There seems to be an issue with the new grade which is causing some blurring for some users.


With ‘new grade’ you mean my last update from yesterday?

If that’s so my first thought could be the quantization to 8-bit, that’s why it works when the new grade is placed first in the stack as it should, otherwise it will mess with float pipelines. You can also try if setting signal type to RGB which bypasses quantization fixes the blurriness to confirm that’s the issue.


I’ll give this a try later when I get home. Also wasn’t aware you updated grade one more time. My shader presets are set up in a way where grade is placed about 3 passes down in the guest shader chain. I’m not sure if having it first will cause some other issue with the other passes in the guest shader, I’ll report back after testing though.

1 Like

Yes, updated yesterday in this post. Didn’t commit to libretro yet because I wanted you to test whether quantization wasn’t creating unwanted posterization. Also I’m researching on gamut compression and wanted to see if I can implement that before.

Grade should always be the first in the stack, it’s output shouldn’t conflict with anything down below because I don’t do any geometric distortion nor texture scaling.


So I likely need to stick this in the middle of my chain where I may have the passes in float format, will this work if I have Grade in Float format? Or will this cause problems?


I set the pass to float to reduce rounding errors but internally I do a quantization to 8-bit when using ‘composite’ signal type. Later float pipeline is restored for the digital grade controls.


Isn’t this accurate? Main difference is that it uses 9300k instead of 6500k, and blank/black are the same but I guess you know that already.

1 Like

Those are different topics, the paper simply defines the conversion from the RGB model to the YUV model while at the same time saturating the whole video range. I do the normalization separately and my model conversion is full->full. And here you find the range definitions for each region.

The temperatures also varies from spec to real world units as current TVs do. None were 6500K but more towards 7100K, and 9300K was only for master monitors in Japan, consumer units were more in the ~8000K, typically 8600K.


@Dogway seem to have done quite a bit of research into NTSC-J color temperatures. I was amazed.
Older CRTs don’t know the exact Kelvin, so for example Panasonic 4K LCD VIERA is 8830K as standard. Therefore, I think that 8600K on a cathode ray tube is almost close. kk32
6500K is often used as a cinema mode in Japan.

It’s wonderful that the white text doesn’t turn blue even though the sky blue of Super Mario Bros. (FC/NES) is light blue.


I decided that I should post solid source information, so I will post two articles.
The Panasonic 4K LCD VIERA and the SONY projector.
This is an article written by a Japan AV-related writer. Of course, it’s in Japanese, so if you’re interested, I recommend translating it into English.
Both references to color temperature are in the middle or bottom of the page.

Sony projector is 8000K, but since the projector projects without directly emitting light, it is probably slightly darker, so I personally think it will be higher than 8000K.

1 Like

Thanks for the sources. It’s always interesting to see other POVs, but as far I could read (still can read some Japanese), it adheres too much on standards.

For instance the recommendation of D65 on a black box, where D60 would make more sense. Or the misconception to match white point with room luminary. There’s an optical effect called “Simultaneous Color Assimilation”, and it’s a non-linear surround visual leak into our perception of temperature. You can see a graph about it here. In other words, if you can’t control your surround illuminance and you’re stuck to 2700K or 3200K surround, the ideal white point for the display to be perceived white at standard 100nits is around 4100K. Given that eyes can’t white adapt to such temperature, it’s ok to set to D50, or simply turn off the lights and use D60. Translating that to a display with fixed D65 white point, surround illuminant should be around 6700K and 100nits.


yes. That’s right.
But I think it’s been proven that Japanese consumer CRT arent 9300K.
I remember that Professional CRT and PVM were 9300K.

In Japan, it is standard to adjust the color temperature according to the lighting and ambient light.
I think this is wrong internationally. But I don’t know if this is unique to Japan.

1 Like

Thanks for the info, yes they aren’t despite what’s reported everywhere on the net. It was 9300K+27MPCD which translates to 8945K CCT for consumer units, that’s the standard while the practice is more spread on the 8000s. I read accounts of as low as 8200K and as high as 8800K.

I forgot what the typical lamp temperatures were in Japan, but in the cool mode it was quite cool, around D65 or maybe higher.

To expand a little on the Simultaneous Color effects:

  1. Simultaneous Color Assimilation: A color effect where color appearance is induced from the surround towards a central area when luminance contrast is high.
  2. Simultaneous Color Contrast: An color effect where color appearance of the complementary color is induced from the surround towards a central area when luminance contrast is low.
  • –Helson-Judd effect: Same as 2 but when additionally central luminance level is low.
  • –Kirschmann’s Third Law: Same as 2 but when additionally central luminance level is equivalent.
  • –Kirschmann’s Fourth Law: Same as 2 but when additionally surround saturation is high

It would be the case that Kirschmann’s Fourth Law counters a bit Simultaneous Color Assimilation, but to what degree I don’t know as the linked source already uses 3200K surround tests, I want to believe in typical bulb saturation values.

EDIT: Reading your second link I found it very interesting how they use as an alternative (custom) temperature tweaking by lowering the Blue channel output, that’s wrong of course because color temperature needs chromatic adaptation but good coincidence that that’s exactly what I chose to do in Grade with the CRT Beam Blue setting. Another thing is how they choose D60 as cinema mode, just as I posted above.


Since you seem to be proficient in the Japanese language or Japan affairs, I think you can decide based on your knowledge, judgment, or research.
I appreciate the results of your research. thank you! :star_struck:


Having first hand access to Japanese displays at this point is more useful than reading Japanese haha.

A good experiment to buy a bunch of old consumer CRTs and measure factory temperature and primaries. Not much info around, at least that I could find. People who buy CRTs for retro gaming in the west typically don’t have colorimeters or don’t care enough for color science.