Please show off what crt shaders can do!

All except the LUTs were done last year so the novelty for me was the LUTs integration. My goal was to color manage retroarch, so colors can be reproduced correctly on a calibrated display, that’s the main goal of LUT2, I guess not everybody would calibrate the display or use 2 LUTs so it can be disabled. LUT1 is for using some CRT colors emulation luts or in this case a GenesisPlusGX color fix.

Black level I did a few days ago (I posted about it a few days ago), I wanted to wash out the blacks a bit without realising that the color mangler had already a Lift parameter (in R/G/B though).

Vignette, was last year, I think I only copied a chunk from another shader and copied it over. For slang I had to be more creative since I didn’t have any reference whatsoever.

1 Like

Excuse my ignorance, but how exactly do I use this? It doesn’t seem like other shader presets. I don’t think I can just copy and paste that, rename it to .glslp, etc. If I’m supposed to put it in manually, that’s fine, but as far as I can tell, “gdapt-pass0-stripes.glsl” simply doesn’t exist. I’m just going to assume I’m doing something wrong here. Shader looks amazing in the screenshot, though.

1 Like

I’m pretty sure that version of gdapt isn’t part of the shader repo, you may try searching it on the forum… I know the shader exists somewhere as I remember seeing it somewhere in the shader threads, lol.

If you gather all of the shaders together, and place them in the correct places, you can copy and paste that glslp (loading it as a regular preset, meaning you don’t have to load each shader in order one at a time.

Tried searching on the forum. Got this and nothing else. I tried googling it. Same result. If anybody’s got a link or something, that would be great, but I don’t want to derail anything.

Yea, I completely understand color managing retroarch. That’s why I personally use color-mangler.

I remember you posting the color-mangler+vignette shader forever ago… I’m pretty sure I asked for a copy, lol.

Personally I prefer having a black level only setting over having to do it via the RGB Lift, so thanks so much for that.

I have a pretty decent vignette code that has a hotspot function which can be used in slang and glsl if you’re interested.

I’ll have to check out your double LUT thing for sure though.

1 Like

Try this.

https://pastebin.com/dKMneLZ8

I think that’s it, I was posted by @Dogway here;

Seems this was @Sp00kyfox work…

If you need anymore help send me a PM.

1 Like

Yes, share please, I’m not happy at all with my slang vignette.

I asked for the inclusion of the shader in that thread so I guessed it was already included. The original discussion was here. Admitedly I was a bit of a douche back then, but hey wasn’t it for me pushing forward we wouldn’t have the shader.

On the color management part what I did was calibrate the HDTV with DisplayCAL on the Reshade preset and use the generated LUT with guest.r shader. I really would like to port it to PCSX2 so if I have time I will give it a stab, at first glance the code looks simple.

I uploaded lut_x2 for anyone interested only on the double LUT part of the shader and toggling.

1 Like

Ehh everyone can seem a little like that sometimes, lol. Could be worse.

I’ll send you the code when I wake up, bout to die. It works for both glsl and slang, haven’t ever messed with cg so idk if it’ll work for that.

1 Like

…are you OK, Syh?

Here’s a video of a moon-walking bird:

2 Likes

@c9f5fdda06 You coming on to me, lol? Nah I’m good just ended up sleeping like 14 hours…

@Dogway Here ya go! Originally from https://www.shadertoy.com/view/lsKSWR

Here’s the setting parameters:

#pragma parameter XFX_VIGNETTE "[Effect] Vignette:" 0.10 0.0 0.5 0.01
#pragma parameter XFX_HOTSPOT "[Effect] Hotspot:" 15.0 10.0 40.0 1.0

The Actual Vignette Code:

vec2 vpos = pos*(TextureSize.xy/InputSize.xy);
vpos *= 1.0 - vpos.yx;
float vig = vpos.x*vpos.y * XFX_HOTSPOT;
vig = pow(vig, XFX_VIGNETTE);
color *= vig; 

If you need any refrence for pos/color tags, this was pulled out of my copy of guest-dr-venom. The hotspot works differently from the yours that I tried forever ago, mainly how it interacts with a solid black screen.

Optional Shorter Version of the Vignette Code: (I have tested it on shadertoy and it worked fine so I’m assuming it works until I test it or someone else says something, was pulled from the comments on that shadertoys comment section)

vec2 vpos = pos*(TextureSize.xy/InputSize.xy);
vpos *= 1.0 - vpos;
vig = vec4(pow(vpos.x*vpos.y * XFX_HOTSPOT, XFX_VIGNETTE);
color *= vig; 

The parameters values are just some guessing on my part for sane values based on the source material ie. from the shadertoy implementation.

EDIT: Formatting… Also for context about the coming on to me thing, the video link @c9f5fdda06 posted is a bird courting video (mating, lol). Also sorry @c9f5fdda06 about the joke. Sorry about the crappy joke guys…

3 Likes

Just had a look and it was missing a few things like the “params.” prefix for variables. I don’t like the hotspot feature so I removed it. So much better than my previous vignette. Thanks!

vec2 vpos = vTexCoord*(params.OriginalSize.xy/params.SourceSize.xy);

vpos *= 1.0 - vpos.yx;
float vig = vpos.x*vpos.y * params.str;
vig = min(pow(vig, params.pow), 1.0);
color *= (params.vignette > 0.5) ? vig : 1.0;
1 Like

That’s my bad, my slang setup defines all of the “params.setting” to just “setting”.

I didn’t think about as I’m used to glsl, and just started with slang in the last couple of months.

Glad you like vignette, spent a couple of days deep-diving shadertoy and testing vignettes before I decided on it.

EDIT: @hunterk or anyone really, quick question which is faster (uses less resources)?

Option 1;

vec2 vpos = vTexCoord*(params.OriginalSize.xy/params.SourceSize.xy);

vpos *= 1.0 - vpos.yx;
float vig = vpos.x*vpos.y * params.str;
vig = min(pow(vig, params.pow), 1.0);
color *= (params.vignette > 0.5) ? vig : 1.0;

Or this (Option 2);

if (params.vignette > 0.5)
{
vec2 vpos = vTexCoord*(params.OriginalSize.xy/params.SourceSize.xy);

vpos *= 1.0 - vpos.yx;
float vig = vpos.x*vpos.y * params.str;
vig = min(pow(vig, params.pow), 1.0);
color *= vig;
}

I’m super curious about this as I’ve just been using if statements as toggles, lol…

Branches are considered a big no-no in shaders, but that sort of toggle really doesn’t have that much impact. I use them often.

Another way to handle it is do mix(1.0, vig, params.vignette). This gets rid of the branch while keeping the toggle functionality, but it still has a performance impact that’s probably a little faster in some situations (but not really in normal circumstances).

1 Like

I’ve only ever used it toggle, never really thought of using it to branch things off. (NVM, I think I’ve used it to technically branch in a sense. Like in a pick a mask situation but with other things… Hmm.)

I’ve attempted to use the mix function this way but have never had any luck with it personally. (Only thing I’ve ever tried it with is a vignette, the mix.) Most likely it was me not doing things right as if I didn’t use the mix and just applied it like normal everything was fine but if I tried to mix I’d invert the vignette and other nonsense, lol.

Well thanks for info!

Edit: @HyperspaceMadness come back, lol. Please add to the conversation, it’s great to hear from others. (As we all explain things in a different manner, me I personally explain things in a stupid cluster-f**ked manner.)

EDIT2: Figured out my issues with the mix function, its because I’m stupid rofl.

I was wondering about this sort of thing, do you know how this works in terms of execution? If it is testing something dynamic does it execute both branches? If it’s testing a constant (E.G. a ui parameter from the params block) does it only execute one branch?

Also do you know if there’s any difference between doing this :

if (x == y) 
{my_var = some expression;}
else 
{my_var = some other expression;} 

And this:

my_var = (x == y) ? some expression : some other expression;

I’ve seen the latter in a bunch of places and I’m wondering if there is any execution speed difference between them

1 Like

There seems to be some disagreement about it all around. Some sources say if/else and ternary expressions are identical, with the ternary being “syntactic sugar”, others say the ternary expression compiles down to a single selection instruction while if/else or mix/clamp/whatever compile down to multiple instructions. Some of the folks at the stackoverflow link suggest that it comes down to the individual GPU/compiler (probably at least somewhat true) and you’d have to spend some time poring over various shader assemblies to know for sure.

In my experience, it’s not a big deal in either direction. I have definitely hidden some serious shit behind conditional parameter checks, and it makes a big impact when a specific branch hits (see the subpixel_mask.h function, where some masks have a huge perf impact and others are quite fast), so it’s definitely not executing both/all branches all the time. Sometimes, I think it can help to add an early return on the first branch, just in case (you might see some of that in a few shaders I’ve worked on, like the super-xbr3d shaders).

I believe parameters that are in the push constants struct are considered more … stable(?) than some random derived value, so I think they’re probably the best ones to use for that sort of thing when possible. I also suspect basing the conditional on a value that’s calculated in and passed from the vertex is lighter than using one that’s calculated it in the fragment (i.e., since the fragment value would be calculated once for each pixel, vs just 4x for the vertex).

OTOH, I think most of that stuff is splitting hairs for our purposes. :man_shrugging:

2 Likes

Ok thanks! That gives me some good background, I’m definitely happier when I don’t have to split hairs!

You also pointed out something that I didn’t know which was that the fragment shader was run 4 times more than the vertex, I wasn’t sure what the ratio between these two were and how much stuff I should be trying to stuff into the vertex shader to optimize :slight_smile: .

oh it’s waaaaay more than that. Fragments run once for every pixel (that is, >2 million times for a 1080p screen and >8 million for 4K), vertex runs once for each vertex (i.e., 4 times for the fullscreen quad).

It’s important to note that there’s a lot of stuff that just can’t be done properly in the vertex, like mask and curvature effects (basically anything that involves the current texture coordinate, which makes sense, of course), as they need to actually run on each pixel, but you could potentially calculate a value that it needs to multiply by that’s based on SourceSize or whatever.

2 Likes

@hunterk Sorry to continue my derailing and bothering you but one last question.

Something else I’m curious about does the amount of characters used change speed any?

Like lets say for example I used 160 characters for some code, but if I changed my (tags?) for things it could whittle down to 80 characters, would this make any difference to speed?

Or is just one of those things that it would take a ridiculously large amount characters to make a difference to the point of it being negligible?

Doesn’t matter at all, AFAIK. However, it’s pretty common to see 1-character variables or dropped trailing zeros on floats (or even implicit casts from int to float) in shaders from people who participate in demoscene and other coding competitions that use character limits as if they were weight classes (e.g., must fit in a tweet, etc.).

1 Like