per request: Shader Request: Smooth Glass borders. See pic for example
I’m not going for a particular look exactly, it’s more I’m just trying to imitate a CRT-look without it seeming artificial/sterile.
On the other hand I could pull a PVM set-up out of my *$$ for this chain, but it’s just not my current goal, lol.
So to sum it up, I’m going for a grungy CRT setup. It’s on the blurrier side of things, has a vignette, curvature, bloom, and I’m currently not setting up video modes yet (composite, s-video, etc.)
I updated grade.glsl. Now it is gamma aware and works in a linear workflow, this exponentially improves everything else as all the matrices were using scene referred values already. Because of this I also had to update the white point function (I will update the stand alone shader later on EDIT: Updated). Now it’s based on sRGB primaries and works in linear light, apparently it also improves the curve fitting.
Now I have to check what’s going on with the LUTs and whether they are authored with sRGB gamma embedded or not…
If you have any ideas for improvement just tell.
Well this sound right up my alley.
As for what games you should use for screenshots, I would suggest you pick games you just love the look of. If it was me making a shader chain, I would use one of the Sonic games for the Genesis/Megadrive and Chrono Cross for the PS1, but that’s because I have fond memories of those games and I like the way they look on a CRT.
Added sigmoidal contrast to grade.glsl, the previous contrast was crushing the blacks, and it also duplicated the luminance parameter and maybe black_level (if I allow it to go negative?). Also moved it before the vignette and black_level calls where I think it’s supposed to be.
EDIT: Detached contrast from saturation, and a few more tweaks. Finally opted to use an inverse sRGB gamma for CRT to linear, the pure power curve was killing details in the dark (eg. DK series). You can mimic the pure power curve of 2.4 without killing details by increasing sRGB gamma to 2.55.
I try to make it look like a bvm. I think. Might be too much maybe … this is how they seem to look at least zoomed in on the internet. Never seen one irl …
Example using my current settings for guest-dr-venom. The goal is accuracy and my reference is a consumer-grade Trinitron using RGB.
A well-maintained consumer-grade CRT displaying an RGB signal is much sharper than many people seem to think. The blur is essentially gaussian, but it’s so slight that black borders/edges remain sharp and clean.
There’s no mask emulation here since my Plasma TV doesn’t like masks. The colors might be a bit warm but that’s because I’m changing the color temp using my TV’s controls instead of doing it through software. Scanlines are a bit sharper than what you see on the Trinitron due to the resolution being used (5x vertical scale). At 6x vertical scale you can reduce the width of the black lines and make the scanlines look closer to those seen on the Trinitron. As it is, the scanlines are somewhere between what you see on a consumer-grade Trinitron and a PVM.
and here’s a shot from a consumer-grade Trinitron.
shaders = "11"
shader0 = "shaders_slang/stock.slang"
filter_linear0 = "false"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "false"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "1.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "shaders_slang/stock.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_border"
mipmap_input1 = "false"
alias1 = ""
float_framebuffer1 = "false"
srgb_framebuffer1 = "false"
scale_type_x1 = "source"
scale_x1 = "1.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders_slang/crt/shaders/guest/d65-d50.slang"
filter_linear2 = "false"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = "WhitePointPass"
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/crt/shaders/guest/afterglow.slang"
filter_linear3 = "false"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
alias3 = "AfterglowPass"
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/crt/shaders/guest/avg-lum0.slang"
filter_linear4 = "false"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = ""
float_framebuffer4 = "false"
srgb_framebuffer4 = "false"
scale_type_x4 = "source"
scale_x4 = "1.000000"
scale_type_y4 = "source"
scale_y4 = "1.000000"
shader5 = "shaders_slang/crt/shaders/guest/avg-lum.slang"
filter_linear5 = "false"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "true"
alias5 = "AvgLumPass"
float_framebuffer5 = "false"
srgb_framebuffer5 = "false"
scale_type_x5 = "source"
scale_x5 = "1.000000"
scale_type_y5 = "source"
scale_y5 = "1.000000"
shader6 = "shaders_slang/crt/shaders/guest/linearize.slang"
filter_linear6 = "false"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "false"
alias6 = "LinearizePass"
float_framebuffer6 = "true"
srgb_framebuffer6 = "false"
scale_type_x6 = "source"
scale_x6 = "1.000000"
scale_type_y6 = "source"
scale_y6 = "1.000000"
shader7 = "shaders_slang/crt/shaders/guest/blur_horiz.slang"
filter_linear7 = "false"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
alias7 = ""
float_framebuffer7 = "true"
srgb_framebuffer7 = "false"
scale_type_x7 = "source"
scale_x7 = "1.000000"
scale_type_y7 = "source"
scale_y7 = "1.000000"
shader8 = "shaders_slang/crt/shaders/guest/blur_vert.slang"
filter_linear8 = "false"
wrap_mode8 = "clamp_to_border"
mipmap_input8 = "false"
alias8 = "GlowPass"
float_framebuffer8 = "true"
srgb_framebuffer8 = "false"
scale_type_x8 = "source"
scale_x8 = "1.000000"
scale_type_y8 = "source"
scale_y8 = "1.000000"
shader9 = "shaders_slang/crt/shaders/guest/linearize_scanlines.slang"
filter_linear9 = "true"
wrap_mode9 = "clamp_to_border"
mipmap_input9 = "false"
alias9 = ""
float_framebuffer9 = "true"
srgb_framebuffer9 = "false"
scale_type_x9 = "source"
scale_x9 = "1.000000"
scale_type_y9 = "source"
scale_y9 = "1.000000"
shader10 = "shaders_slang/crt/shaders/guest/crt-guest-dr-venom.slang"
filter_linear10 = "true"
wrap_mode10 = "clamp_to_border"
mipmap_input10 = "false"
alias10 = ""
float_framebuffer10 = "false"
srgb_framebuffer10 = "false"
scale_type_x10 = "viewport"
scale_x10 = "1.000000"
scale_type_y10 = "viewport"
scale_y10 = "1.000000"
parameters = "WP;wp_saturation;SW;AR;PR;AG;PG;AB;PB;sat;STH;GAMMA_INPUT;TAPSH;GLOW_FALLOFF_H;TAPSV;GLOW_FALLOFF_V;TATE;IOS;OS;BLOOM;brightboost;brightboost1;gsl;scanline1;scanline2;beam_min;beam_max;beam_size;h_sharp;s_sharp;csize;bsize;warpX;warpY;glow;shadowMask;masksize;vertmask;slotmask;slotwidth;double_slot;mcut;maskDark;maskLight;CGWG;gamma_out;spike;inter;bloom"
WP = "0.000000"
wp_saturation = "1.000000"
SW = "0.000000"
AR = "0.070000"
PR = "0.050000"
AG = "0.070000"
PG = "0.050000"
AB = "0.070000"
PB = "0.050000"
sat = "0.100000"
STH = "0.700000"
GAMMA_INPUT = "2.400000"
TAPSH = "4.000000"
GLOW_FALLOFF_H = "0.000000"
TAPSV = "4.000000"
GLOW_FALLOFF_V = "0.000000"
TATE = "0.000000"
IOS = "0.000000"
OS = "1.000000"
BLOOM = "0.000000"
brightboost = "1.000000"
brightboost1 = "1.000000"
gsl = "2.000000"
scanline1 = "15.000000"
scanline2 = "23.000000"
beam_min = "1.000000"
beam_max = "1.000000"
beam_size = "0.000000"
h_sharp = "5.000000"
s_sharp = "0.000000"
csize = "0.000000"
bsize = "600.000000"
warpX = "0.000000"
warpY = "0.000000"
glow = "0.000000"
shadowMask = "0.000000"
masksize = "1.000000"
vertmask = "0.000000"
slotmask = "0.000000"
slotwidth = "2.000000"
double_slot = "1.000000"
mcut = "0.200000"
maskDark = "0.500000"
maskLight = "1.500000"
CGWG = "0.000000"
gamma_out = "2.200000"
spike = "2.000000"
inter = "400.000000"
bloom = "0.000000"
textures = "SamplerLUT1;SamplerLUT2;SamplerLUT3"
SamplerLUT1 = "shaders_slang/crt/shaders/guest/lut/sony_trinitron1.png"
SamplerLUT1_linear = "true"
SamplerLUT1_wrap_mode = "clamp_to_border"
SamplerLUT1_mipmap = "false"
SamplerLUT2 = "shaders_slang/crt/shaders/guest/lut/sony_trinitron2.png"
SamplerLUT2_linear = "true"
SamplerLUT2_wrap_mode = "clamp_to_border"
SamplerLUT2_mipmap = "false"
SamplerLUT3 = "shaders_slang/crt/shaders/guest/lut/other1.png"
SamplerLUT3_linear = "true"
SamplerLUT3_wrap_mode = "clamp_to_border"
SamplerLUT3_mipmap = "false"
Looks like you have some misaligned scanlines, there- have you enabled integer scale and set a custom aspect ratio?
It is because I use reshade for the scanlines. It is hard to align them but iam gonna try some more. I use retroarchs shaders for “before filtering”. Hmmm of course I could add some crt shader in the retroarch chain. Gonna try that!
@Nesguy - great results, the blur is spot on. But I can’t see the grill, how come? Did you give up on masks for good? Also, color temperature too warm as usual
@Mickevincent - no shadowmask, high and obviously interpolated resolution, too strong and misaligned scanlines. Not a very natural result honestly. I know too well that getting the lines right with reshade is a major pita. You might want to try matsilagi’s ports of the RA shaders, they work very well. I also suggest you go hunting for screens of actual N64s (since you seem to be very fond of that system) running on crts and try to replicate that. It won’t be easy haha but that’s why we are here is it not?
@c9f5fdda06 - I much prefer a black background, but the image itself looks fantastic. Is it guest?
Here’s your answer for @Nesguy.
And @c9f5fdda06 image is with a modified version of guest-dr-venom you can find in the link he posted.
@Nesguy I do have a question about that post though, is there a reason you’re using an older version of that shader? Also why are you using two stock passes?
I requested this shader because it helps ensure even wear on my display (OLED). You will find a link to my request in my original post that shows I wanted guest + border glass/blur.
@Syh No real reason, I just need to update my shaders. I replaced the first two passes with stock because it was color-related stuff that I wasn’t using anyway.
@Squalo Thanks for the feedback! Since my emulation PC is using a different input on my TV I just set it to a cooler temperature on that input. You’re right that a cooler temp is better for most 240p stuff once your eyes adjust to it.
This plasma TV does some kind of temporal dithering to get bright enough, so masks are out of the question, which is too bad. On the other hand, the plasma uses the same phosphors as a CRT, so the glow and color reproduction are amazing.
N64 is a tough nut to crack, since the hardware did its own antialiasing and filtering.
Speaking of which… has anyone made a shader specifically to replicate whatever the N64 hardware does?
Unles you have access in shaders for the ZBuffer I find it hard to replicate exactly, but I made a proposal at raster level here. It still has to be coded/ported though.
That example looks really nice. What needs to be ported? This?
Yes, seems like only mode 22 which is what I used:
RG_FORCEINLINE Byte rg_mode22_cpp(const Byte* pSrc, int srcPitch) {
LOAD_SQUARE_CPP(pSrc, srcPitch);
Byte l1 = (a1 + a8 + 1) / 2;
Byte l2 = (a2 + a7 + 1) / 2;
Byte l3 = (a3 + a6 + 1) / 2;
Byte l4 = (a4 + a5 + 1) / 2;
auto ma = std::max(std::max(std::max(l1, l2), l3), l4);
auto mi = std::min(std::min(std::min(l1, l2), l3), l4);
return clip(c, mi, ma);
}
EDIT: And to elaborate a little bit, this was my avisynth script. We have nnedi already so it’s feasible.
depoint(width/2,height/2) # to 240p
removegrain(22)
ConvertBits(8)
ConvertToYV24() # 4:4:4
nnedi3_resize16(width*2,height*2,lsb_in=false) # this is a mix for nnedi3 (edge area) and spline64 (flat area)
If you look closely you’ll see that there’s actually still a very faint mask in the shot I posted here, despite setting CGWG mask strength to 0.
Any idea why…?
Yeah, the default mask bright value is a bit higher to compensate for brightness loss. You still get 1.1 and 1.0 combos with setting the strength to 0.0.
I was about to change it twice already, but it’s a nice compensation.
If you want no mask then mask ‘-1’ should be selected.