Yeah that would be great if possible
The question also seems whether there could be some confusing terminology with P3. My Samsung is advertised as having DCI-P3 coverage, but after reading up on wikipedia DCI-P3, my monitor much more resembles Display-P3, Apple’s adoption of DCI-P3 color space for computer monitors.
From the wikipedia article:
DCI-P3 specifications are designed for viewing in a fully darkened theater environment. The projection system uses a simple 2.6 gamma curve, the nominal white luminance is 48 cd/m2 with the white point defined as a correlated color temperature of ~6300 K.
Display P3 is a color space created by Apple Inc.[12][13] It uses the DCI-P3 primaries, but instead of the ~6300 K white point, Display P3 uses the CIE standard illuminant D65 as the white point, which is the most common standard for self-illuminated displays and devices (sRGB and Adobe RGB both use D65). Also, unlike the DCI-P3 projection gamma of 2.6, Display P3 uses the sRGB transfer curve, which is approximately equivalent to a display with a 2.2 gamma.
So DCI-P3 being the movie theater projection standard for a fully dark viewing environment it does explain the very high 2.6 gamma. It also uses the “odd” 6300k white point. Display-P3 on the other hand makes a lot more sense for watching content on computer monitors or TVs in dim lit (not fully dark!) rooms with its sRGB transfer function and D65 white point.
Out of the box my Samsung was set to its native SDR mode with wide color (P3) gamut, but with D65 white and a gamma curve that resembles something between an sRGB curve and a pure power gamma, averaging out between 2.3 and 2.4. Clearly closer to Display-P3 than DCI-P3, even though the marketing is saying DCI-P3.
It would not be surprising if most wide gamut monitors actually use Display-P3 spec and not DCI-P3 spec and there’s just a general misconcepted use of the terminology where everything P3 is just called “DCI-P3”?
Regardless, it could make sense to add Display-P3 to your shader instead of or as a complement to DCI-P3. The latter really only seems suited for use in a fully dark theater environment.
Not to derail the current conversation but has anyone had any luck solving the gray ramp thing on an SDR display? I had to lower CRT gamma to 1.7 to get all the gray bars visible, which results in a washed out picture elsewhere, and it’s still a bit dark. Any suggestions?
No shader
Megatron
shaders = "5"
feedback_pass = "0"
shader0 = "shaders_slang/ntsc/shaders/ntsc-adaptive/ntsc-pass1.slang"
filter_linear0 = "false"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "true"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "4.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "shaders_slang/ntsc/shaders/ntsc-adaptive/ntsc-pass2.slang"
filter_linear1 = "true"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = ""
float_framebuffer1 = "false"
srgb_framebuffer1 = "false"
scale_type_x1 = "source"
scale_x1 = "0.750000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders_slang/hdr/shaders/crt-sony-megatron-source-pass.slang"
filter_linear2 = "false"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = "SourceSDR"
float_framebuffer2 = "false"
srgb_framebuffer2 = "false"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "source"
scale_y2 = "1.000000"
shader3 = "shaders_slang/hdr/shaders/crt-sony-megatron-hdr-pass.slang"
filter_linear3 = "false"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
alias3 = "SourceHDR"
float_framebuffer3 = "false"
srgb_framebuffer3 = "false"
scale_type_x3 = "source"
scale_x3 = "1.000000"
scale_type_y3 = "source"
scale_y3 = "1.000000"
shader4 = "shaders_slang/hdr/shaders/crt-sony-megatron.slang"
filter_linear4 = "false"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = ""
float_framebuffer4 = "false"
srgb_framebuffer4 = "false"
hcrt_hdr = "0.000000"
hcrt_gamma_out = "2.204996"
hcrt_crt_resolution = "3.000000"
hcrt_brightness = "0.250000"
hcrt_gamma_in = "1.700001"
hcrt_red_scanline_min = "0.450000"
hcrt_red_scanline_max = "0.900000"
hcrt_red_scanline_attack = "0.850000"
hcrt_green_scanline_min = "0.450000"
hcrt_green_scanline_max = "0.900000"
hcrt_green_scanline_attack = "0.850000"
hcrt_blue_scanline_min = "0.450000"
hcrt_blue_scanline_max = "0.900000"
hcrt_blue_scanline_attack = "0.850000"
hcrt_blue_horizontal_convergence = "-1.000000"
hcrt_red_beam_sharpness = "1.000000"
hcrt_red_beam_attack = "0.000000"
hcrt_green_beam_sharpness = "1.000000"
hcrt_green_beam_attack = "0.000000"
hcrt_blue_beam_sharpness = "1.000000"
hcrt_blue_beam_attack = "0.000000"
Hey there @Nesguy,
I looked into this recently. It has to do with the way gamma has been setup for the three Colour Spaces under SDR: Display Color Space (r709 | SRGB | DCI-P3).
@MajorPainTheCactus made the choice of having all three color spaces (respectively r709, sRGB and DCI-P3) use power law gamma function on linearizing (gamma_in) but use the respective color space’s gamma function when doing the reverse operation on gamma_out.
This seemingly causes a “mismatch” for the gamma curves used on gamma_in and _out for r709 and sRGB modes, darkening the early ramp quite a bit. DCI-P3 is ok, because it uses power law by specification and that is used both on gamma_in and _out in the shader.
So currently you have for the three SDR colour spaces “gamma_in vs. gamma_out” functions:
r709: pow vs. r709 transfer curve
sRGB: pow vs. sRGB transfer curve
DCI-P3:pow vs. pow transfer curve.
There’s no wrong or right here I think. It’s more a matter of choice. There’s enough literature out there that would describe CRT transfer function as either power law, r709 or sRGB curve. It depends on certain assumptions and from what I understand from the Microsoft and HP article on sRGB also depends on what settings were generally used for the analog “brightness” (black level) and “contrast” settings on CRTs.
My guess is that you’re using either r709 or sRGB for the SDR: Display Color Space setting in the shader?
So as a very quick test you could set the color space in the shader to DCI-P3, it will give washed out colors if your monitor is not wide gamut, but does it solve the gray ramp issue for you?
Or if you’re into some code editing -as a quick test - you could change the gamma transfer functions used for the r709 or sRGB modes on gamma_out to also use power law. The slightly more involved way would be to match the gamma_in to their respective color space transfer curves but since differences may be small, using power law on both is good enough for a test.
To do this if you go to “hdr/shaders/include/gamma_correct.h” you can change the gamma_corrections “LinearTo709” and “LinearTosRGB” to use “LinearToDCIP3”, which actually is the power law conversion:
so change this in gamma_correct.h:
if(HCRT_HDR < 1.0f)
{
if(HCRT_OUTPUT_COLOUR_SPACE == 0.0f)
{
gamma_corrected = LinearTo709(scanline_colour);
}
else if(HCRT_OUTPUT_COLOUR_SPACE == 1.0f)
{
gamma_corrected = LinearTosRGB(scanline_colour);
}
else
{
gamma_corrected = LinearToDCIP3(scanline_colour);
}
to this:
if(HCRT_HDR < 1.0f)
{
if(HCRT_OUTPUT_COLOUR_SPACE == 0.0f)
{
gamma_corrected = LinearToDCIP3(scanline_colour);
}
else if(HCRT_OUTPUT_COLOUR_SPACE == 1.0f)
{
gamma_corrected = LinearToDCIP3(scanline_colour);
}
else
{
gamma_corrected = LinearToDCIP3(scanline_colour);
}
Note this only changes the transfer curve to also use power law on gamma_out for r709 and sRGB modes, nothing else.
Thank you! Yes, this solves the gray ramp issue while resulting in washed out colors on my non-wide gamut display.
I’ll give this a shot later, thanks! Perhaps a power law toggle switch could be added if this proves to be a good solution @MajorPainTheCactus
So this isn’t actually true - it shouldn’t be converting from any of those spaces as this should all be rec. 601 stuff on input i.e what the consoles output of the time adhered to.
Rec. 709, sRGB and rec. 2020 are all on output and are all modern color spaces and gamma curves sRGB for instance being developed for website viewing on the desktop. However what I will say is that rec. 601 transfer function is the same as rec. 709 transfer function.
However there is a bug in that I’m not using my function rec601ToLinear on input and defaulting the CRT gamma to be 2.22. I’ll fix that right away.
You don’t need to mess around with the output transfer functions above but you will need to make sure whatever you choose for those, that your monitor matches them.
Fixed that the right input rec. 601 transfer function is being used and should hopefully fix both @Nesguy and @rafan issues. The pull request is V4.2 Sony Megatron Shader so should get in the build in the next day or two depending on when the pull request is merged. Thanks for pointing this out as it wasn’t obvious in HDR (which is what I always use) as you can compensate for this issue much more easily - its way more obvious in the SDR modes.
Does there seem to be some kind of compression(?) occurring at the low end, now?
#reference "shaders_slang/hdr/crt-sony-megatron-aeg-CTV-4800-VT-hdr.slangp"
hcrt_hdr = "0.000000"
hcrt_gamma_out = "2.200000"
hcrt_lcd_resolution = "0.000000"
hcrt_crt_screen_type = "0.000000"
hcrt_crt_resolution = "1.000000"
hcrt_gamma_in = "2.400000"
hcrt_red_scanline_min = "0.800000"
hcrt_red_scanline_max = "0.900000"
hcrt_green_scanline_min = "0.800000"
hcrt_green_scanline_max = "0.900000"
hcrt_blue_scanline_min = "0.800000"
hcrt_blue_scanline_max = "0.900000"
Definitely make sure all your setting are neutral i.e usually set to 0 or 1 except for maybe the attacks. I’m not sure I can see what you’re talking about though - are you saying the darkest two bars are the same? They should be very slightly different as in black and super super dark grey - I think the dark grey will be near to 1,1,1 (white being 255,255,255) or something once gamma corrected with a ^2.4.
EDIT: Btw I would expect your gamma in and out values to be swapped around. Generally rec. 601 was 2.22 (in) and sRGB is 2.4 (out).
Yep, the 3rd and 4th bars from right are the same, swapping the gamma values back to the default fixed it. Gamma can be a confusing thing due to differing nomenclatures.
Btw, I’m embarrassed to ask, but what exactly does scanline attack do?
You shouldn’t be it’s a pretty specific thing to this shader. So as a rough high level description it’s attack of the various curves I use for various things or to put it another way, how steep or shallow the curves are.
So for example vertical scanline attack says how fast the intensity of the scanline falls off in the vertical direction. The horizontal attack is how fast it falls off in the horizontal axis ie how fast it transitions from a black pixel to a white pixel.
The slightly more technical description is that I use 1D berzier curves for everything which have two anchor points at 0 and 1 and two control points at 0.333 and 0.666 and effectively the attack moves the two control points up and down.
IDK, I think there’s still something odd going on with gamma in SDR mode, but I can’t quite put my finger on it. It’s either bright and washed out or well saturated but dark. Gray ramp looks good, but the colors don’t. I know gamma is affected by just about everything but I’m having a hard time getting a handle on it. Maybe I just need to play with brightness/saturation/contrast. I’m curious to see what others can come up with. @rafan
EDIT: I think I just need to adjust contrast and saturation, actually.
I’d add also check your TV settings. Certainly let me know any tests I can look at that you think are off.
I’m using the worst display for this, it’s like 250 nits max . It’s a good test case to see what Megatron in SDR is really capable of
I think this is looking pretty decent though. Beam shape could use some work, and still trying to figure out “scanline attack.” Does scanline attack 1.00 result in the fastest fall off?
Good to hear! What scanline attack are you talking about and I’ll try and do a detailed description. Generally a higher value means more of an attack and moves the first control point.
Here’s an interactive 1D cubic berzier curve demo:
http://www.demofox.org/bezcubic1d.html
You might need to run this on desktop. Place the first point at 0,0 and the last at 1,1, the third at 0.666,1 and then the attack value will usually straight effect the y coord of the second control point 0.333, y.
At least that’s usually what it’s doing.
How that maps onto the scanline is if you imagine the last point is at the peak of the middle of the scanline and the first is the middle of the black empty space between the scanlines then this graph shows the shape of the scanline in the vertical direction i.e the vertical scanline attack.
Thanks for the description on the scanline attack, it’s really neat to get this in-depth explanation on the inner workings of your shader.
I was triggered by the bezier curve demo of a book that I recently came across that is very detailed on everything related to a CRT display. It’s called Image Performance in CRT Displays by Kenneth Compton and it has a chapter that I thought may interest you. It’s called “Generating the Pixel” and goes into detail on the shape of the pixel, including manufacturing/design targets for pixel shape and factors that influence the idealized pixel shape. I included the part from that chapter below, it’s intriguing stuff.
Based on my experience with the Megatron shader I’m thinking your shader may already be nailing it, also accounting for the factors impacting the idealized pixel shape as described in the book. Nonetheless, looking at the gaussian shape, see the referenced 5.1 image “gaussian profile” below, I was trying to replicate this in the 1D bezier curve demo and noticed it seems to need different values for the control points to achieve the gaussian roll-off in the scanline than the ones you mentioned for B and C. It may even need a positive value for A also. See my snap of the 1D bezier curve below.
Would be great if you could share your thoughts on what’s described in the quoted part of Chapter 5 below and more specifically how that ties in with current Megatron. Do you think scanline modelling is nailing it already or close enough (I think any of the two ) or could maybe some parts be improved based on what is written in this chapter 5?
Here’s the snap of the Cubic Bezier demo with custom control points:
Hi @MajorPainTheCactus, have you ever thought about putting in a switch for a tate mode so that we could switch to vertical scanlines (and rotated mask) for vertical games?
This would be great in the Mega Bezel where we have control over the scanlines normally with other shaders.
I’m currently working on finishing up getting HDR working for Megatron in the Mega Bezel, it’s almost done!
Looking forward to trying it out!
Thanks Rafan great chapter! So what I would say is that although we roughly want to get close to that diagram there’s a number of things our side (as well as on the CRT side) that will always stop us getting that close to that perfect luminance distribution. Not least we’re dealing with individual sub pixels rather than continuous strips of coloured phosphor. As in they will have their own luminance lobes.
Then add on there’s no dimensions to the diagram and youre starting to fight a losing battle. What I will point out is that cubic berzier demo stretches the curve over a square and what I do stretch or squeeze that square onto a rectangle which has an effect on the curve shape. See min max scanline lengths.
The way I tackle it is to get close up images of CRTs and just eye ball what the different characteristics of the beam are and then change the values to as closely match that taking photos of the LCD to match and compare i.e use empirical methods and not so much theoretical (although a bit of both are key)
@Jamirus kindly submitted these close up shots of Soul Calibur 2 on GameCube which is a 480p game (or rather 528 because of GameCubes dreadful upscaler (at least I think it’s the GameCubes and not Dolphins).
So I decided to match it which showed up some quite glaring bugs in the higher resolution. That I’ve now fixed. Anyway here’s a comparison shot of where I got to…