Please show off what crt shaders can do!

After seeing you guys putting so much effort in these shaders, for the first time I tried adjusting a shader and I’m using the latest crt-guest-dr-venom, the only adjustment I changed is the saturation from 1.00 down to 0.65, they are looking good, but unfortunately I don’t have any CRT TV around to match them together, making the emulation more accurately displayed in a LCD HDTV.

Saturation 1.00

Saturation 0.65

1.00

0.65

1.00

0.65

1.00

0.65

1.00

0.65

The raw output is much more vivid, but with a lower saturation it looks more accurate if I remember the 90’s correctly. I’m using vulkan with the slang shaders, the gl results are the same, I have tried it with FB Alpha before switching to Vulkan.

2 Likes

The dulling of the colors that you’re remembering may be related to the way it was connected to your TV. Have you tried the crt-guest-dr-venom-ntsc preset that’s in the ‘presets’ directory?

3 Likes

@guest.r

Your shader is really the best! It’s my preference for arcade and now for consoles (ntsc composite).

I setup the shader for Mesen, Genesis Plus GX and FB Alpha, but when I apply on Mupen64plus and Dolphin, stays a black screen. What could be?

Thanks.

2 Likes

I just looked for it, but there’s no shader there, I mean, only some other folders with manually created presets, should I update all shaders again?

dunno. it’s this one:

1 Like

The full version of the shader (NTSC version included) is a bit sensitive to original resolution used. I managed to get it working with Dolphin at 1x internal resolution, while 4x crashed RA. You could replace the avg-lum pass with stock shader to try anything higher than 640x480 for example.

1 Like

Many thanks for your efforts. Extra thanks for the readme, stuff that’s being done get’s way to rarely documented!

2 Likes

@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?