Please show off what crt shaders can do!

@aorin1 - Nice comparison shots, Quick question if I may? The original/older version of crt-guest-dr-venom.glslp definitely had the Saturation parameter, however the latest release seems to no longer include this (or I’m going blind), are you adding another colour adjustment shader to the chain to control saturation?

@lfan - I found I had to replace the afterglow.glsl, avg-lum0.glsl and avg-lum.glsl with stock for it to play nice with the N64 cores. I also add a first pass with stock.glsl and force the resolution to 240 on the y axis for scanlines to look proper.

@hunterk, @guest.r, Dr .Venom, Hyllian, EasyMode, @torridgristle (forum won’t let me tag more users!), all those shader coding geeks which my futile brain can’t remember the names of - I wish I had your skills! ALL contributers/devs involved, we the community, thank you for your efforts, it’s nice to have all these choices.

Keep the screens coming y’all!

5 Likes

Ah, that’s my bad. I mplemented it in a test version, but it got overwritten or something. :frowning:

@hunterk, could you please update the d65-d50 shader with this code? It includes saturation…

// Parameter lines go here:
#pragma parameter WP "Color Temperature %" 0.0 -100.0 100.0 5.0 
#pragma parameter saturation "Saturation Adjustment" 1.0 0.0 2.0 0.05 

#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;

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;

void main()
{
    gl_Position = MVPMatrix * VertexCoord;
    COL0 = COLOR;
    TEX0.xy = TexCoord.xy;
}

#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;
// in variables go here as COMPAT_VARYING whatever

// 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 WP;
uniform COMPAT_PRECISION float saturation;
#else
#define WP  0.0
#define saturation  1.0
#endif 
 
const mat3 D65_to_XYZ = mat3 (
           0.4306190,  0.2220379,  0.0201853,
           0.3415419,  0.7066384,  0.1295504,
           0.1783091,  0.0713236,  0.9390944);

const mat3 XYZ_to_D65 = mat3 (
           3.0628971, -0.9692660,  0.0678775,
          -1.3931791,  1.8760108, -0.2288548,
          -0.4757517,  0.0415560,  1.0693490);
		   
const mat3 D50_to_XYZ = mat3 (
           0.4552773,  0.2323025,  0.0145457,
           0.3675500,  0.7077956,  0.1049154,
           0.1413926,  0.0599019,  0.7057489);
		   
const mat3 XYZ_to_D50 = mat3 (
           2.9603944, -0.9787684,  0.0844874,
          -1.4678519,  1.9161415, -0.2545973,
          -0.4685105,  0.0334540,  1.4216174);		   

void main()
{
	
	vec3 color = COMPAT_TEXTURE(Source, TEX0.xy).rgb;
	
	color = normalize(pow(color + 1e-4, vec3(saturation)))*length(color);
	
	float p = 2.4;
	
	color = pow(color, vec3(p));
	
	vec3 warmer = D50_to_XYZ*color;
	warmer = XYZ_to_D65*warmer;
	
	vec3 cooler = D65_to_XYZ*color;
	cooler = XYZ_to_D50*cooler;
	
	float m = abs(WP)/100.0;
	
	vec3 comp = (WP < 0.0) ? cooler : warmer;
	
	color = mix(color, comp, m);

	color = pow(color, vec3(1.0/p));	
	
	FragColor = vec4(color,1.0);
} 
#endif
1 Like

I’m using the Vulkan driver, it doesn’t work with glsl shaders.

There’s a slang one, too:

1 Like

I changed the color saturation parameter inspired by the Cadillacs screenshots you guys were comparing here, but I wonder why some colors become more inclined to purple instead of blue, the CRT photo looks more blueish while the emulation is purple. What would be the correct approach to solve this? In my post above, you can also see the Sonic 1 for Genesis also becomes a little more purple when I tone down the saturation a bit.

PS: The same adjustment doesn’t make Super Mario World blues purple, so maybe people with real hardware and TVs could confirm if they’re looking as they should?

@hunterk I downloaded the crt-guest-dr-venom-ntsc-composite.slangp preset and tried loading it but it made no difference whatsoever, like no shader was loaded at all.

A method I’m using to make purples look more bluish is the LUT Colors parameter in the new crt-guest-dr-venom shader. However, I’m using a @torridgristle LUT png from this thread CRT Color Correction 3DLUTs (Sony, Mitsubishi, CTX, NEC, Hyundai) to replace the the other1.png in @guest.r shader folder.

In the first post there is a link to zip file with a host of PNG’s, from this I extract the “CTX D-Group - 32px.png” and replace the “other1.png” in the crt/guest/lut folder with this png. Now load up a game, select the crt-guest-dr-venom shader and set the “LUT Colors” parameter to 3. It’s a subtle change but I feel for me anyway, the blues looks better - more natural blue. Try it, might work or might not, it’s best to do a screen capture of both to compare for yourself.

2 Likes

@guest.r @shenglong

I don’t know how use the stock. Could you explain?

I always use the native internal resolution.

1 Like

@lfan

You will have to re-build the CRT shader chain but for the first pass (shader 0) add a stock pass then set the scale type to absolute and scale y to 240.

I normally re-build the shader chain within the Retroarch GUI by adding each pass as per the desired shader preset, but start off with stock.glsl or sharp-bilinear-simple.glsl as the first pass, once all the passes have been added save the preset. Now open the preset in a text editor add/edit the shader 0 type and y0 values as per below:

scale_type_y0 = "absolute"
scale_y0 = 240

For 3D content (N64/PSX) I also set

filter_linear0 = "true"

This is covered earlier in the thread:

https://forums.libretro.com/t/please-show-off-what-crt-shaders-can-do/19193/141

https://forums.libretro.com/t/please-show-off-what-crt-shaders-can-do/19193/265

And here:

https://forums.libretro.com/t/reicast-240p-and-mame-roms-support/16665/13

All this does is downscale the video output resolution to 240 pixels forced height. I find this works better for CRT shaders and scanlines which look better with 240p, 224p etc… content. This method works especially well for the PSX core, PSX games had different resolutions within a game, making scanlines look inconsistent, this fixes that for me.

1 Like

@shenglong

I edited the crt-guest-dr-venom-ntsc-composite to add the stock (shader0) as first pass. The black screen continue. What I doing wrong?

Thanks!

shaders = 12

shader0 = ../stock.glsl
filter_linear0 = false
scale_type_x0 = source
scale_type_y0 = absolute
scale_y0 = 240

shader1 = ../ntsc/shaders/ntsc-pass1-composite-2phase.glsl
shader2 = ../ntsc/shaders/ntsc-pass2-2phase-gamma.glsl

filter_linear1 = false
filter_linear2 = false

scale_type_x1 = source
scale_type_y1 = source
scale_x1 = 4.0
scale_y1 = 1.0
frame_count_mod1 = 2
float_framebuffer1 = true

scale_type2 = source
scale_x2 = 0.5
scale_y2 = 1.0 

shader3 = ../crt/shaders/guest/lut/lut.glsl
filter_linear3 = false
scale_type3 = source
scale3 = 1.0

textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3"
SamplerLUT1 = ../crt/shaders/guest/lut/sony_trinitron1.png
SamplerLUT1_linear = true 
SamplerLUT2 = ../crt/shaders/guest/lut/sony_trinitron2.png
SamplerLUT2_linear = true 
SamplerLUT3 = ../crt/shaders/guest/lut/other1.png
SamplerLUT3_linear = true 

shader4 = ../crt/shaders/guest/d65-d50.glsl
filter_linear4 = false
scale_type4 = source
scale4 = 1.0

shader5 = ../crt/shaders/guest/afterglow.glsl
filter_linear5 = false
scale_type5 = source
scale5 = 1.0

shader6 = ../crt/shaders/guest/avg-lum0.glsl
filter_linear6 = false
scale_type6 = source
scale6 = 1.0

shader7 = ../crt/shaders/guest/avg-lum.glsl
filter_linear7 = false
scale_type7 = source
scale7 = 1.0
mipmap_input7 = true

shader8 = ../crt/shaders/guest/linearize.glsl
filter_linear8 = false
scale_type8 = source
scale8 = 1.0
float_framebuffer8 = true

shader9 = ../crt/shaders/guest/blur_horiz.glsl
filter_linear9 = false
scale_type9 = source
scale9 = 1.0
float_framebuffer9 = true

shader10 = ../crt/shaders/guest/blur_vert.glsl
filter_linear10 = false
scale_type10 = source
scale10 = 1.0
float_framebuffer10 = true

shader11 = ../crt/shaders/guest/crt-guest-dr-venom.glsl
filter_linear11 = true
scale_type11 = viewport
scale_x11 = 1.0
scale_y11 = 1.0
1 Like

replace afterglow, avglum and avglum0 with stock, as well. The framebuffer history used in those passes apparently isn’t jiving with the N64 cores.

2 Likes

Now the screen is flickering…

:confused:

shader5 = ../crt/shaders/guest/afterglow.glsl
filter_linear5 = false
scale_type_y5 = absolute
scale_y5 = 240

shader6 = ../crt/shaders/guest/avg-lum0.glsl
filter_linear6 = false
scale_type_y6 = absolute
scale_y6 = 240

shader7 = ../crt/shaders/guest/avg-lum.glsl
filter_linear7 = false
scale_type_y7 = absolute
scale_y7 = 240
mipmap_input7 = true

no, I can see how the instructions were confusing. Like this:

shaders = 12

shader0 = ../stock.glsl
filter_linear0 = false
scale_type_x0 = source
scale_type_y0 = absolute
scale_y0 = 240

shader1 = ../ntsc/shaders/ntsc-pass1-composite-2phase.glsl
shader2 = ../ntsc/shaders/ntsc-pass2-2phase-gamma.glsl

filter_linear1 = false
filter_linear2 = false

scale_type_x1 = source
scale_type_y1 = source
scale_x1 = 4.0
scale_y1 = 1.0
frame_count_mod1 = 2
float_framebuffer1 = true

scale_type2 = source
scale_x2 = 0.5
scale_y2 = 1.0 

shader3 = ../crt/shaders/guest/lut/lut.glsl
filter_linear3 = false
scale_type3 = source
scale3 = 1.0

textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3"
SamplerLUT1 = ../crt/shaders/guest/lut/sony_trinitron1.png
SamplerLUT1_linear = true 
SamplerLUT2 = ../crt/shaders/guest/lut/sony_trinitron2.png
SamplerLUT2_linear = true 
SamplerLUT3 = ../crt/shaders/guest/lut/other1.png
SamplerLUT3_linear = true 

shader4 = ../crt/shaders/guest/d65-d50.glsl
filter_linear4 = false
scale_type4 = source
scale4 = 1.0

shader5 = ../stock.glsl
filter_linear5 = false
scale_type5 = source
scale5 = 1.0

shader6 = ../stock.glsl
filter_linear6 = false
scale_type6 = source
scale6 = 1.0

shader7 = ../stock.glsl
filter_linear7 = false
scale_type7 = source
scale7 = 1.0

shader8 = ../crt/shaders/guest/linearize.glsl
filter_linear8 = false
scale_type8 = source
scale8 = 1.0
float_framebuffer8 = true

shader9 = ../crt/shaders/guest/blur_horiz.glsl
filter_linear9 = false
scale_type9 = source
scale9 = 1.0
float_framebuffer9 = true

shader10 = ../crt/shaders/guest/blur_vert.glsl
filter_linear10 = false
scale_type10 = source
scale10 = 1.0
float_framebuffer10 = true

shader11 = ../crt/shaders/guest/crt-guest-dr-venom.glsl
filter_linear11 = true
scale_type11 = viewport
scale_x11 = 1.0
scale_y11 = 1.0
4 Likes

Thanks, @hunterk!

@shenglong, what is the perceptive difference?

Adds a subtle blur making the graphics a bit smoother, like anti aliasing.

2 Likes

The latest slang version is also missing the saturation adjustment.

17 posts were split to a new topic: BFI/Strobing/Motionblur thread reorganized

@guest.r, could you add an ON/OFF option to enable or disable the composite video flicker or to reduce?

Just for curiosity: why your ntsc composite shader doesn’t have option for 256px and 320px?

Thanks.

1 Like

Hi there,

the NTSC composite passes are using original files, so adding an option to remove flickering is very unlikely, but you can modify the preset and change:

frame_count_mod0 = 1

Imo it doesn’t look that nice though.

Shader doesn’t have the 256px and 320px option, because preset values can’t be accessed by shader menu. So i used a hybrid approach, where 256x content behaves like 256px, 320x like 320px etc. It’s a very good compromise i think.

3 Likes

This post has good info on taking photographs of CRTs, which can probably be applied to photos of LCDs running CRT shaders, as well: https://int10h.org/blog/2018/06/taking-decent-photos-of-your-crt-tv-screen/

It also contains an interesting bit about white balance:

White balance: In theory 6500K is the standard white point for TV, and decent/newer sets can be adjusted to this (it’d even be somewhat accurate). In practice, older CRT TV color temperatures are all over the place: it was found that an electric blue tint had more of a sensory impact on consumers, so manufacturers used to race each other to the higher end of the scale (not unlike the music industry’s Loudness War). So again, it’s up to experimentation. My TV appeared too blueish even with the camera’s highest WB preset of 7000K, and I had to manually add a white balance shift factor of A4 (towards amber/away from blue) + G3 (towards green/away from magenta). Adobe Camera Raw interprets this as a WB of 8200K with a tint value of -8; not sure how correct those values are, but the result looks correct indeed.

Emphasis added.

3 Likes

6 posts were merged into an existing topic: The BFI/strobing/motion blur thread