Please show off what crt shaders can do!

@Squalo I may be wrong but I think he was trying to mimic the actual CRT capture you found, so the 3rd image.

1 Like

yeah, i took the default FBA settings screenshot and adjusted it to match the capture video screenshot.

2 Likes

I see, my bad! Thing is, this morning I posted another image that was too similar to the youtube video, and at first I thought you had used that one. Yes, the video is too blue (as it’s often the case when photographing crts as you said), and the default emulator output is too yellow. My goal lies in the golden spot in between.

This is what that screen looks like with my settings for the Mega Drive by the way. I think it’s quite nice : )

Uncorrected so you can compare

(no massive differences since there’s no greens in there, but still noticeable)

3 Likes

That looks really good, yeah. Very similar to what I see on my CRTs.

2 Likes

Oh yeah, noticed something similar a few days ago. Something from footage I took with my phone:

Sky seems clear blue by this, but it wasn’t at all what I saw on the TV. Raw emulator shots are really closer, or something like this:

5 Likes

How is that a contradiction? Objective brightness/luminance and color are are two different things.

An LCD emulating a CRT should aim to be as bright as a CRT (ie a max of around 100-120 Nits). It isn’t nearly as simple to pin down what the “correct” colors should be, given the lack of universal standards and practices at the time. It makes some sense that consoles would use 9300k since that was the standard for NTSC-J, but given that a huge share of their market used NTSC, it seems plausible that artists would choose colors that looked good on both (“oops, that color makes the sky purple with NTSC, let’s not use that color again”)

Furthermore, I’m never going to be convinced that cooler colors are going to look good on an LCD monitor, at least the one I’m using. My eyes have gotten used to warm colors and cooler colors just look too bright and washed out in comparison. Yes, going to warm colors after looking at cool colors will make things look too yellow and possibly over-saturated, but it works in reverse as well; going to cool colors from warm colors makes everything look too obviously blue and washed out.

I also don’t think cool colors on an LCD look the same as they do on a CRT; at least they don’t in any of the side by side comparisons I’ve done with my CRT monitor. Hunter already mentioned this, but CRTs look very different in person compared to a photograph.

The phosphors used by the display matter a lot, too. The same colors will look different on two different displays using different phosphors, which is why individual calibration is necessary. Even calibrated to the same standard, they’re not going to look exactly the same.

Then there’s the fact that everyone has a different distribution of rods/cones in their eyes and people perceive colors differently. Warmer colors might just look better to some people as a result of this.

So, color is largely a matter of personal preference and it’s quite a bit harder to pin down “correct” color vs correct brightness.

FWIW, I think the corrected colors in your most recent comparison look pretty good, even though I prefer warmer colors. I’ve definitely taken this discussion regarding color into consideration and I do think that just slightly boosting the blue channel on my monitor through the OSD is an improvement, but I’ve yet to find any color mangler settings that are significantly better than this. In any case, getting the colors “perfect” is a headache I’d rather avoid.

Regarding the scanlines, why are you using 720p? Is it to get shaders to run full speed? Even at non-integer scales, scanlines shouldn’t be cutting through pixels like that; they should just vary slightly in width, afaik.

2 Likes

Glad you like it. :slight_smile: I’m using the same preset in the Cadillacs & Dinosaurs screen. These settings should look good on both 1080p and 2160p. The main difference is that the mask will look much higher-res at 2160p (720 TVL vs. 360 TVL).

Here’s the preset. You’ll need to edit the file paths (where it says “shader0, shader1, shader2…”) so that they’re correct for your system.

alias0 = ""
alias1 = ""
alias2 = ""
amp = "1.000000"
AUTO_PRESCALE = "1.000000"
CRT_GAMMA = "2.400000"
DOTMASK_STRENGTH = "0.300000"
float_framebuffer0 = "true"
float_framebuffer1 = "false"
float_framebuffer2 = "false"
lines_black = "0.000000"
lines_white = "1.000000"
maskDark = "0.000000"
maskLight = "1.500000"
mipmap_input0 = "false"
mipmap_input1 = "false"
mipmap_input2 = "false"
parameters = "TVOUT_COMPOSITE_CONNECTION;TVOUT_TV_COLOR_LEVELS;CRT_GAMMA;TVOUT_RESOLUTION;TVOUT_RESOLUTION_Y;TVOUT_RESOLUTION_I;TVOUT_RESOLUTION_Q;SHARP_BILINEAR_PRE_SCALE;AUTO_PRESCALE;amp;phase;lines_black;lines_white;shadowMask;DOTMASK_STRENGTH;maskDark;maskLight"
phase = "0.000000"
scale_type_x0 = "source"
scale_type_x1 = "viewport"
scale_type_y0 = "source"
scale_type_y1 = "source"
scale_x0 = "1.000000"
scale_x1 = "1.000000"
scale_y0 = "1.000000"
scale_y1 = "1.000000"
shader0 = "D:\retroarch\shaders\shaders_glsl\crt\shaders\tvout-tweaks-multipass\tvout-tweaks-pass-0.glsl"
shader1 = "D:\retroarch\shaders\shaders_glsl\crt\shaders\tvout-tweaks-multipass\tvout-tweaks-pass-1.glsl"
shader2 = "D:\retroarch\shaders\shaders_glsl\crt\shaders\sharp-bilinear-scanlines+dotmask.glsl"
shaders = "3"
shadowMask = "2.000000"
SHARP_BILINEAR_PRE_SCALE = "4.000000"
srgb_framebuffer0 = "true"
srgb_framebuffer1 = "false"
srgb_framebuffer2 = "false"
TVOUT_COMPOSITE_CONNECTION = "0.000000"
TVOUT_RESOLUTION = "480.000000"
TVOUT_RESOLUTION_I = "83.199997"
TVOUT_RESOLUTION_Q = "25.600000"
TVOUT_RESOLUTION_Y = "256.000000"
TVOUT_TV_COLOR_LEVELS = "0.000000"
wrap_mode0 = "clamp_to_border"
wrap_mode1 = "clamp_to_border"
wrap_mode2 = "clamp_to_border"

TV-out-tweaks-multipass should already be in the repo, but I don’t think sharp-bilinear-scanlines+dotmask has been added, so here it is:

/*
 * sharp-bilinear
 * Author: Themaister
 * License: Public domain
 * 
 * Does a bilinear stretch, with a preapplied Nx nearest-neighbor scale, giving a
 * sharper image than plain bilinear.
 */

// Parameter lines go here:
#pragma parameter SHARP_BILINEAR_PRE_SCALE "Sharp Bilinear Prescale" 4.0 1.0 10.0 1.0
#pragma parameter AUTO_PRESCALE "Automatic Prescale" 1.0 0.0 1.0 1.0
#pragma parameter amp          "Amplitude"      1.2500  0.000 2.000 0.05
#pragma parameter phase        "Phase"          0.5000  0.000 2.000 0.05
#pragma parameter lines_black  "Lines Blacks"   0.0000  0.000 1.000 0.05
#pragma parameter lines_white  "Lines Whites"   1.0000  0.000 2.000 0.05
#pragma parameter shadowMask "Mask Style" 3.0 0.0 4.0 1.0
#pragma parameter DOTMASK_STRENGTH "CGWG Dot Mask Strength" 0.3 0.0 1.0 0.01
#pragma parameter maskDark "Lottes maskDark" 0.5 0.0 2.0 0.1
#pragma parameter maskLight "Lottes maskLight" 1.5 0.0 2.0 0.1
 
#define freq             0.500000
#define offset           0.000000
#define pi               3.141592654

#ifndef PARAMETER_UNIFORM
#define amp              1.250000
#define phase            0.500000
#define lines_black      0.000000
#define lines_white      1.000000
#endif

#if defined(VERTEX)

#if __VERSION__ >= 130
#define COMPAT_VARYING out
#define COMPAT_ATTRIBUTE in
#define COMPAT_TEXTURE texture
#else
#define COMPAT_VARYING varying 
#define COMPAT_ATTRIBUTE attribute 
#define COMPAT_TEXTURE texture2D
#endif

#ifdef GL_ES
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif

COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 COLOR;
COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 COL0;
COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING float angle;

uniform mat4 MVPMatrix;
uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;

// vertex compatibility #defines
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define outsize vec4(OutputSize, 1.0 / OutputSize)

#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float amp;
uniform COMPAT_PRECISION float phase;
uniform COMPAT_PRECISION float lines_black;
uniform COMPAT_PRECISION float lines_white;
#endif

void main()
{
    gl_Position = MVPMatrix * VertexCoord;
    COL0 = COLOR;
    TEX0.xy = TexCoord.xy;
    float omega = 2.0 * pi * freq;              // Angular frequency
    angle = TEX0.y * omega * TextureSize.y + phase;
}

#elif defined(FRAGMENT)

#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#endif

#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#define COMPAT_PRECISION mediump
#else
#define COMPAT_PRECISION
#endif

uniform COMPAT_PRECISION int FrameDirection;
uniform COMPAT_PRECISION int FrameCount;
uniform COMPAT_PRECISION vec2 OutputSize;
uniform COMPAT_PRECISION vec2 TextureSize;
uniform COMPAT_PRECISION vec2 InputSize;
uniform sampler2D Texture;
COMPAT_VARYING vec4 TEX0;
COMPAT_VARYING float angle;

// fragment compatibility #defines
#define Source Texture
#define vTexCoord TEX0.xy

#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define outsize vec4(OutputSize, 1.0 / OutputSize)

#ifdef PARAMETER_UNIFORM
// All parameter floats need to have COMPAT_PRECISION in front of them
uniform COMPAT_PRECISION float SHARP_BILINEAR_PRE_SCALE;
uniform COMPAT_PRECISION float AUTO_PRESCALE;
uniform COMPAT_PRECISION float amp;
uniform COMPAT_PRECISION float phase;
uniform COMPAT_PRECISION float lines_black;
uniform COMPAT_PRECISION float lines_white;
uniform COMPAT_PRECISION float shadowMask;
uniform COMPAT_PRECISION float DOTMASK_STRENGTH;
uniform COMPAT_PRECISION float maskDark;
uniform COMPAT_PRECISION float maskLight;
#else
#define SHARP_BILINEAR_PRE_SCALE 4.0
#define AUTO_PRESCALE 1.0
#define shadowMask 3.0
#define DOTMASK_STRENGTH 0.3
#define maskDark 0.5
#define maskLight 1.5
#endif

#define mod_factor vTexCoord.x * SourceSize.x * outsize.x / SourceSize.x

// Shadow mask.
vec3 Mask(vec2 pos)
{
   vec3 mask = vec3(maskDark, maskDark, maskDark);
   
   // Very compressed TV style shadow mask.
   if (shadowMask == 1.0)
   {
      float line = maskLight;
      float odd  = 0.0;

      if (fract(pos.x/6.0) < 0.5)
         odd = 1.0;
      if (fract((pos.y + odd)/2.0) < 0.5)
         line = maskDark;

      pos.x = fract(pos.x/3.0);
    
      if      (pos.x < 0.333) mask.r = maskLight;
      else if (pos.x < 0.666) mask.g = maskLight;
      else                    mask.b = maskLight;
      mask*=line;  
   } 

   // Aperture-grille.
   else if (shadowMask == 2.0)
   {
      pos.x = fract(pos.x/3.0);

      if      (pos.x < 0.333) mask.r = maskLight;
      else if (pos.x < 0.666) mask.g = maskLight;
      else                    mask.b = maskLight;
   } 

   // Stretched VGA style shadow mask (same as prior shaders).
   else if (shadowMask == 3.0)
   {
      pos.x += pos.y*3.0;
      pos.x  = fract(pos.x/6.0);

      if      (pos.x < 0.333) mask.r = maskLight;
      else if (pos.x < 0.666) mask.g = maskLight;
      else                    mask.b = maskLight;
   }

   // VGA style shadow mask.
   else if (shadowMask == 4.0)
   {
      pos.xy = floor(pos.xy*vec2(1.0, 0.5));
      pos.x += pos.y*3.0;
      pos.x  = fract(pos.x/6.0);

      if      (pos.x < 0.333) mask.r = maskLight;
      else if (pos.x < 0.666) mask.g = maskLight;
      else                    mask.b = maskLight;
   }

   return mask;
}

void main()
{
   vec2 texel = vTexCoord * SourceSize.xy;
   vec2 texel_floored = floor(texel);
   vec2 s = fract(texel);
   float scale = (AUTO_PRESCALE > 0.5) ? floor(outsize.y / InputSize.y + 0.01) : SHARP_BILINEAR_PRE_SCALE;
   float region_range = 0.5 - 0.5 / scale;

   // Figure out where in the texel to sample to get correct pre-scaled bilinear.
   // Uses the hardware bilinear interpolator to avoid having to sample 4 times manually.

   vec2 center_dist = s - 0.5;
   vec2 f = (center_dist - clamp(center_dist, -region_range, region_range)) * scale + 0.5;

   vec2 mod_texel = texel_floored + f;

   vec3 color = COMPAT_TEXTURE(Source, mod_texel / SourceSize.xy).rgb;
   
    float grid;
 
    float lines;
 
    lines = sin(angle);
    lines *= amp;
    lines += offset;
    lines = abs(lines);
    lines *= lines_white - lines_black;
    lines += lines_black;
    color *= lines;
    
   color = pow(color, vec3(2.2));
   
   float mask = 1.0 - DOTMASK_STRENGTH;

   //cgwg's dotmask emulation:
   //Output pixels are alternately tinted green and magenta
   vec3 dotMaskWeights = mix(vec3(1.0, mask, 1.0),
                             vec3(mask, 1.0, mask),
                             floor(mod(mod_factor, 2.0)));
   if (shadowMask == 0.) 
   {
      color *= dotMaskWeights;
   }
   else 
   {
      color *= Mask(floor(1.000001 * gl_FragCoord.xy + vec2(0.5,0.5)));
   }
   
   FragColor = vec4(pow(color, vec3(1.0/2.2, 1.0/2.2, 1.0/2.2)), 1.0);
} 
#endif
2 Likes

Looks pretty good! The mask looks like a 600 or 700 line PVM or a high-end TV from the 2000s. I don’t personally care for that glow(?) since it washes out the mask, but that’s one way to get acceptable brightness at a normal backlight level. At least the phosphors are still red, blue and green instead of the yellow-magenta-cyan you sometimes see with shaders. Colors and brightness look nice. Good job overall! :+1:

1 Like

@Nesguy Thank you :stuck_out_tongue: yes I think it takes a screen 8k for this emulator for it to be correct, and compared to all others is based with the bloom unfortunately.But I just spend hours to do 12 different presets with the glow off in using another shader! And I changed it with stock.glsl to make it lighter. If someone has free time and has no internet download quota, please have fun with these links haha and i will paste the presets if someone ask a specific one. Only for 4k users and using paint in windows

  1. https://ibb.co/PZdGLhx
  2. https://ibb.co/x5Tbb8t
  3. https://ibb.co/Hnf1nbd
  4. https://ibb.co/THtztqw
  5. https://ibb.co/GxbVHr9
  6. https://ibb.co/ngp47cv
  7. https://ibb.co/GR41W69
  8. https://ibb.co/YX0VvPb
  9. https://ibb.co/P4c6Jpb
  10. https://ibb.co/JmxJZvD
  11. https://ibb.co/mHGz4X6
  12. https://ibb.co/n6XQkgJ

And this time for everyone,here’s a message from (Dr.Venom)

" 1 The color gamut / RGB primaries for many CRT monitors and TVs are different from sRGB (used by most LCDs). Generally speaking they will be slightly more saturated, mainly for green and red, which means a small part of the CRT color spectrum cannot be displayed correctly with sRGB gamut. IMO this gamut “clipping” gets “worse” when moving away from high-end / newer CRT specs (like Sony BVM), which are closer to sRGB actually, to lower end and older TV’s and monitors.

2 At least a gamut of DCI-P3 or wider is needed for these CRT color profiles to be displayed properly.

3 Trying to match CRT colors on a non-wide color gamut / sRGB monitor is a futile mission, it will not work. I’ve been there. Especially when talking about older Trinitron monitors, they use a very deep saturated green, which gets heavily clipped on the sRGB gamut as are colors involving a mix with those saturated greens.

So the good news is that we’ve got “CRT colors” largely covered now with the correct specs and two “quite accurate” calibrated profiles. The bad news is that with a default sRGB monitor the profiles will be more or less clipped and look wrong, depending on the content. Then we have some good news, as it seems that DCI-P3 or some other wide color gamut will be part of the HDR-500+ spec (see here. ) So within a few years wide color gamut should become mainstream in monitors. " Conclusion, when we will have wrinkles we will play in better conditions on our modern screens :older_man:

6 Likes

Very interesting stuff from Dr. Venom! Thanks for sharing!

1 Like

@Nesguy good answer :+1:t3:

This is very true, and also in line with the contradiction I believe you fell into. See, I remember you said a few times that a lot of the screens I post are too bright, that your brightness levels were more natural and objectively ‘better’, that one can get used to a too bright image and then properly balanced gammas will be perceived as too dark and dull.

Well, the same principles can be applied to colour. The roles are reversed now, this time it’s me telling you that over the years one can get used to the too warm, oversaturated look of emulators on lcds, and then a proper white balance will be perceived as unsaturated, dull and lifeless. I was surprised that someone as meticulous as you are declared that colour is not a critical factor in retrogaming.

This might be the case, maybe modern displays can’t match crt tones and now we have Dr Venom’s opinion on the matter, which might explain why that happens. But think about it: it’s the same with scanlines, masks, contrast, motion resolution etc. We are slowly but steadily approximating to an accurate simulation of crt technology, and the way I see it, colour is a crucial ingredient in the recipe and can’t be overlooked, or merely regarded as a subjective factor whose quality depends solely on personal taste.

Please revisit post #372. Aside from being much closer to the trinitron tones, isn’t the corrected image much more pleasing, with actually white clouds and green greens?

Regarding 720p, it’s a combination of performance and preference. First, I simply like the ‘720p look’ a lot, it seems more natural to me (at least compared to 1080p). Second, when dealing with heavy-duty shaders and increased internal resolutions on 3d games, there’s a massive performance improvement, and that allows me to run things smooth as silk at ok temperatures, which my laptop really appreciates. And in all honesty, I look at the 240p test screen that I just posted, and I see good evenness and homogeneity in the scanlines, even up close. In fact, taking into account that it’s 720p/non integer, I see a borderline miracle! Easymode-halation is extraordinary in that regard.

@ProfessorBraun interesting stuff indeed, thx mate. And btw, no need to post the heavy pngs. A well compressed jpeg will look exactly the same and be way more manageable.

2 Likes

Unfortunately I have already tried and there is a loss of visible quality, it may be less visible with a lower resolution, which led me to take things in hand and tested my images in 720p and 1080p ( so that less the native resolution of picture). And what a disappointment :frowning: I know you said it looks good and I thank you for that but they are all horrible, no relation to the original image whether colors, brightness, aspect ratio, the shape of the mask, variation of scanlines I know that an image taken in low resolution will normally be displayed in high resolution, but not the other way around, same as for the trick with paint.Noone has seen what my images really look like, I assure you that my preset posted even in old posts have not been seen yet on google images with such care and resolutions.Apart for users 4k but no one showed up unfortunately, I’m a little disgusted that I can not show you what I’ve done with these presets . Why I have not tested by myself before posting? haha Sad mood :sob:

I understand that these images require very careful compression, due to the amount of fine detail. This is one of your GnG images, compressed. By disabling color subsampling I get something virtually indistinguishable (what a word that is haha) from the original png, even at 400% (or whatever) magnification. Check it out (click twice to see it at 100%).

And by the way, I love how it looks. Your work is appreciated here, rest assured : )

3 Likes

And yet there is a loss of quality in my resolution, images side by side, the brightness of the mask and its alignment, it is faded mask level too, on the other hand it resembles my native image overall, however my basic image on a lower resolution is horribly worse, 2 completely different images :face_vomiting:. Thank you for your words :v:

Edit : to see only when you have a screen 4k to see the difference even with good compression, this post will be dig up in few years hehe https://ibb.co/9qDZcZr

Man we are all picky here. Look. Side by side, even at 1000% they are perceptually identical.

And by the way, could you please post the settings from the GnG capture? Not practical for me since I don’t have an UHD monitor but it really looks marvelous, and I’m curious about it.

yes on you resolution,not on my native. And that’s logic, and i cannot demonstrate you without buying you a 4k screen, what you see on your screen is already a loos of details, so on your picture you see the same. logic Edit:2 if i told you right on my screen that there are not the same side by side ,it’s not for trolling or else ??

A pixel is a pixel, regardless of the screen on which it is displayed, Mathematically, the png and jpg files are indeed different. Perceptually, they are the same.

my english is probably bad, but the way I can express myself without misleading terms is that if one day you have a screen 4k, test the image with paint and you’ll see, my eyes do not make me a trick of illusions that I know. Take a USB key with the image I posted from my desktop and go to a nearest TV store and ask to be able to open it with paint on a screen 4k and you’ll see. In addition it’s like saying that I was a liar, the pictures are not the same edit1 your request https://ibb.co/Z85CQML edit2 you can post too,the site don’t need inscription guys to upload edit3 what did you asked me ahah ? sorry for my english use a simple term ,what settings you mean lol edit4 better idea i will try myself in a lower resolution with another screen,comeback in a few minutes,i’m sure they will look the same on the lower

This is getting off topic, so I will not insist anymore. I posted a side by side at 1000% magnification and it’s clear that the differences even at pixel level are minuscule, take that as you will.

Back to topic, I meant if you could post the shader chain that resulted in that lovely image.

1 Like

Unless you have a calibrated monitor is futile to do color work on anything. LCD displays variate a lot, and they are specially cool on temperature from stock.

Then there’s the issue that RetroArch if I’m not wrong is not color managed so it won’t show colors accurately. If you don’t have a calibrated (and profiled) monitor all the photos you see on the display will have wrong color mappings and tones because they are not adjusted to the gamut of the LCD display (the delta with an sRGB color space normally).

It could be possible on paper to do accurate color and tone work. You profile an arcade or CRT monitor (without calibration assuming it’s the intended look), assign the profile to the core and RetroArch (if color managed) on booting the core will tag the output with the profile so color remapping can be done to your display profile in an accurate manner be it sRGB or WideGamut. You can test which “intention” is best for the remap, for games “Saturation” intent makes sense.

In any case very VERY few people care for color, Linux is not color managed, Windows is partially, and 99% of photo viewers are not color managed. No one cares if the blacks are crushed or not, or if the red is not vivid enough.

2 Likes