Dogway's grading shader (slang)

@hunterk I’m having difficulties converting grade.glsl to slang, only the vignette and both LUT blocks are failing could you take a look when you can? It’s driving me insane since I have little experience with slang despite having both shaders working separately on their own.

EDIT: Check settings descriptions at this later post.

3 Likes

I moved this to its own topic for you :slight_smile:

This one works for me:

#version 450

layout(push_constant) uniform Push
{
    float gamma_in;
    float vignette;
    float str;
    float power;
    float LUT_Size1;
    float LUT1_toggle;
    float LUT_Size2;
    float LUT2_toggle;
    float temperature;
    float luma_preserve;
    float sat;
    float lum;
    float size;
    float cntrst;
    float mid;
    float black_level;
    float blr;
    float blg;
    float blb;
    float r;
    float g;
    float b;
    float rg;
    float rb;
    float gr;
    float gb;
    float br;
    float bg;
} params;

/*
   Grade
   > Ubershader grouping some color related monolithic shaders like color-mangler, vignette, lut,
   > white_point, and the addition of black level, sigmoidal contrast and proper gamma transforms.

   Author: hunterk, Guest, Dr. Venom, Dogway
   License: Public domain
*/

#pragma parameter gamma_in "CRT Gamma" 2.55 0.0 3.0 0.05
#pragma parameter vignette "Vignette Toggle" 1.0 0.0 1.0 1.0
#pragma parameter power "Power" 0.07 0.0 0.5 0.01
#pragma parameter str "Strength" 15.0 10.0 40.0 1.0
#pragma parameter LUT_Size1 "LUT Size 1" 16.0 0.0 64.0 16.0
#pragma parameter LUT1_toggle "LUT 1 Toggle" 0.0 0.0 1.0 1.0
#pragma parameter LUT_Size2 "LUT Size 2" 64.0 0.0 64.0 16.0
#pragma parameter LUT2_toggle "LUT 2 Toggle" 0.0 0.0 1.0 1.0
#pragma parameter temperature "White Point" 6504.0 1000.0 12000.0 100.0
#pragma parameter luma_preserve "WP Preserve Luminance" 1.0 0.0 1.0 1.0
#pragma parameter sat "Saturation" 1.0 0.0 3.0 0.01
#pragma parameter lum "Brightness" 1.0 0.0 2.0 0.01
#pragma parameter cntrst "Contrast" 0.0 -1.5 1.5 0.05
#pragma parameter mid "Contrast Pivot" 0.5 0.0 1.0 0.01
#pragma parameter black_level "Black Level" 0.0 -0.5 1.0 0.01
#pragma parameter blr "Black-Red Tint" 0.0 0.0 1.0 0.005
#pragma parameter blg "Black-Green Tint" 0.0 0.0 1.0 0.005
#pragma parameter blb "Black-Blue Tint" 0.0 0.0 1.0 0.005
#pragma parameter r "White-Red Tint" 1.0 0.0 2.0 0.01
#pragma parameter g "White-Green Tint" 1.0 0.0 2.0 0.01
#pragma parameter b "White-Blue Tint" 1.0 0.0 2.0 0.01
#pragma parameter rg "Red-Green Tint" 0.0 -1.0 1.0 0.005
#pragma parameter rb "Red-Blue Tint" 0.0 -1.0 1.0 0.005
#pragma parameter gr "Green-Red Tint" 0.0 -1.0 1.0 0.005
#pragma parameter gb "Green-Blue Tint" 0.0 -1.0 1.0 0.005
#pragma parameter br "Blue-Red Tint" 0.0 -1.0 1.0 0.005
#pragma parameter bg "Blue-Green Tint" 0.0 -1.0 1.0 0.005

layout(std140, set = 0, binding = 0) uniform UBO
{
    mat4 MVP;
    vec4 SourceSize;
    vec4 OriginalSize;
    vec4 OutputSize;
} global;

#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;

void main()
{
    gl_Position = global.MVP * Position;
    vTexCoord = TexCoord;
}

#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;
layout(set = 0, binding = 3) uniform sampler2D SamplerLUT1;
layout(set = 0, binding = 4) uniform sampler2D SamplerLUT2;

// White Point Mapping function
//
// From the first comment post (sRGB and linear light compensated)
//      http://www.zombieprototypes.com/?p=210#comment-4695029660
// Based on the Neil Bartlett's blog update
//      http://www.zombieprototypes.com/?p=210
// Inspired itself by Tanner Helland's work
//      http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/

vec3 wp_adjust(vec3 color){

    float temp = params.temperature / 100.;
    float k = params.temperature / 10000.;
    float lk = log(k);

    vec3 wp = vec3(1.);

    // calculate RED
    wp.r = (temp <= 65.) ? 1. : 0.32068362618584273 + (0.19668730877673762 * pow(k - 0.21298613432655075, - 1.5139012907556737)) + (- 0.013883432789258415 * lk);

    // calculate GREEN
    float mg = 1.226916242502167 + (- 1.3109482654223614 * pow(k - 0.44267061967913873, 3.) * exp(- 5.089297600846147 * (k - 0.44267061967913873))) + (0.6453936305542096 * lk);
    float pg = 0.4860175851734596 + (0.1802139719519286 * pow(k - 0.14573069517701578, - 1.397716496795082)) + (- 0.00803698899233844 * lk);
    wp.g = (temp <= 65.5) ? ((temp <= 8.) ? 0. : mg) : pg;

    // calculate BLUE
    wp.b = (temp <= 19.) ? 0. : (temp >= 66.) ? 1. : 1.677499032830161 + (- 0.02313594016938082 * pow(k - 1.1367244820333684, 3.) * exp(- 4.221279555918655 * (k - 1.1367244820333684))) + (1.6550275798913296 * lk);

    // clamp
    wp.rgb = clamp(wp.rgb, vec3(0.), vec3(1.));

    // Linear color input
    return color * wp;
}

vec3 sRGB_to_XYZ(vec3 RGB){

const mat3x3 m = mat3x3(
0.4124564, 0.3575761, 0.1804375,
0.2126729, 0.7151522, 0.0721750,
0.0193339, 0.1191920, 0.9503041);
return RGB * m;
}


vec3 XYZtoYxy(vec3 XYZ){

    float XYZrgb = XYZ.r+XYZ.g+XYZ.b;
    float Yxyg = (XYZrgb <= 0.0) ? 0.3805 : XYZ.r / XYZrgb;
    float Yxyb = (XYZrgb <= 0.0) ? 0.3769 : XYZ.g / XYZrgb;
    return vec3(XYZ.g, Yxyg, Yxyb);
}


vec3 XYZ_to_sRGB(vec3 XYZ){

const mat3x3 m = mat3x3(
3.2404542, -1.5371385, -0.4985314,
-0.9692660, 1.8760108, 0.0415560,
0.0556434, -0.2040259, 1.0572252);
return XYZ * m;
}


vec3 YxytoXYZ(vec3 Yxy){

    float Xs = Yxy.r * (Yxy.g/Yxy.b);
    float Xsz = (Yxy.r <= 0.0) ? 0.0 : 1.0;
    vec3 XYZ = vec3(Xsz,Xsz,Xsz) * vec3(Xs, Yxy.r, (Xs/Yxy.g)-Xs-Yxy.r);
    return XYZ;
}

// This shouldn't be necessary but it seems some undefined values can
// creep in and each GPU vendor handles that differently. This keeps
// all values within a safe range
vec3 mixfix(vec3 a, vec3 b, float c)
{
    return (a.z < 1.0) ? mix(a, b, c) : a;
}


vec3 linear_to_sRGB(vec3 color, float gamma){

color = clamp(color, 0.0, 1.0);
color.r = (color.r <= 0.00313066844250063) ?
 color.r * 12.92 : 1.055 * pow(color.r, 1.0 / gamma) - 0.055;
color.g = (color.g <= 0.00313066844250063) ?
 color.g * 12.92 : 1.055 * pow(color.g, 1.0 / gamma) - 0.055;
color.b = (color.b <= 0.00313066844250063) ?
 color.b * 12.92 : 1.055 * pow(color.b, 1.0 / gamma) - 0.055;

    return color.rgb;
}


vec3 sRGB_to_linear(vec3 color, float gamma){

color = clamp(color, 0.0, 1.0);
color.r = (color.r <= 0.04045) ?
 color.r / 12.92 : pow((color.r + 0.055) / (1.055), gamma);
color.g = (color.g <= 0.04045) ?
 color.g / 12.92 : pow((color.g + 0.055) / (1.055), gamma);
color.b = (color.b <= 0.04045) ?
 color.b / 12.92 : pow((color.b + 0.055) / (1.055), gamma);

    return color.rgb;
}


//  Performs better in gamma encoded space
vec3 contrast_sigmoid(vec3 color, float cont, float piv){

    cont = pow(cont + 1., 3.);

    float knee = 1. / (1. + exp(cont * piv));
    float shldr = 1. / (1. + exp(cont * (piv - 1.)));

    color.r = (1. / (1. + exp(cont * (piv - color.r))) - knee) / (shldr - knee);
    color.g = (1. / (1. + exp(cont * (piv - color.g))) - knee) / (shldr - knee);
    color.b = (1. / (1. + exp(cont * (piv - color.b))) - knee) / (shldr - knee);

    return color.rgb;
}


//  Performs better in gamma encoded space
vec3 contrast_sigmoid_inv(vec3 color, float cont, float piv){

    cont = pow(cont - 1., 3.);

    float knee = 1. / (1. + exp (cont * piv));
    float shldr = 1. / (1. + exp (cont * (piv - 1.)));

    color.r = piv - log(1. / (color.r * (shldr - knee) + knee) - 1.) / cont;
    color.g = piv - log(1. / (color.g * (shldr - knee) + knee) - 1.) / cont;
    color.b = piv - log(1. / (color.b * (shldr - knee) + knee) - 1.) / cont;

    return color.rgb;
}


void main()
{
//  Pure power was crushing blacks (eg. DKC2). You can mimic pow(c, 2.4) by raising the gamma_in value to 2.55
    vec3 imgColor = sRGB_to_linear(texture(Source, vTexCoord.xy).rgb, params.gamma_in);

//  Look LUT
    float red = (imgColor.r * (params.LUT_Size1 - 1.0) + 0.4999) / (params.LUT_Size1 * params.LUT_Size1);
    float green = (imgColor.g * (params.LUT_Size1 - 1.0) + 0.4999) / params.LUT_Size1;
    float blue1 = (floor(imgColor.b * (params.LUT_Size1 - 1.0)) / params.LUT_Size1) + red;
    float blue2 = (ceil(imgColor.b * (params.LUT_Size1 - 1.0)) / params.LUT_Size1) + red;
    float mixer = clamp(max((imgColor.b - blue1) / (blue2 - blue1), 0.0), 0.0, 32.0);
    vec3 color1 = texture(SamplerLUT1, vec2(blue1, green)).rgb;
    vec3 color2 = texture(SamplerLUT1, vec2(blue2, green)).rgb;
    vec3 vcolor = (params.LUT1_toggle < 1.0) ? imgColor : mixfix(color1, color2, mixer);

//  Saturation agnostic sigmoidal contrast
    vec3 Yxy = XYZtoYxy(sRGB_to_XYZ(vcolor));
    vec3 toLinear = linear_to_sRGB(vec3(Yxy.r, 0.0, 0.0), 2.4);
    vec3 contrast = (params.cntrst > 0.0) ? contrast_sigmoid(toLinear, params.cntrst, params.mid) : contrast_sigmoid_inv(toLinear, params.cntrst, params.mid);
    contrast.rgb = vec3(sRGB_to_linear(contrast, 2.4).r, Yxy.g, Yxy.b);
    vec3 XYZsrgb = clamp(XYZ_to_sRGB(YxytoXYZ(contrast)), 0.0, 1.0);
    contrast = (params.cntrst == 0.0) ? vcolor : XYZsrgb;

//  Vignetting & Black Level
    vec2 vpos = vTexCoord*(global.OriginalSize.xy/global.SourceSize.xy);

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

    contrast += (params.black_level / 5.0) * (1.0 - contrast);


//  RGB related transforms
    vec4 screen = vec4(max(contrast, 0.0), 1.0);

    mat4 color = mat4(params.r, params.rg, params.rb, 0.0,
 params.gr, params.g, params.gb, 0.0,
 params.br, params.bg, params.b, 0.0,
 params.blr, params.blg, params.blb, 0.0);

    mat4 adjust = mat4((1.0 - params.sat) * 0.2126 + params.sat, (1.0 - params.sat) * 0.2126, (1.0 - params.sat) * 0.2126, 1.0,
 (1.0 - params.sat) * 0.7152, (1.0 - params.sat) * 0.7152 + params.sat, (1.0 - params.sat) * 0.7152, 1.0,
 (1.0 - params.sat) * 0.0722, (1.0 - params.sat) * 0.0722, (1.0 - params.sat) * 0.0722 + params.sat, 1.0,
 0.0, 0.0, 0.0, 1.0);


    color *= adjust;
    screen = clamp(screen * ((params.lum - 1.0) * 2.0 + 1.0), 0.0, 1.0);
    screen = color * screen;

//  Color Temperature
    vec3 adjusted = wp_adjust(screen.rgb);
    vec3 base_luma = XYZtoYxy(sRGB_to_XYZ(screen.rgb));
    vec3 adjusted_luma = XYZtoYxy(sRGB_to_XYZ(adjusted));
    adjusted = (params.luma_preserve > 0.5) ? adjusted_luma + (vec3(base_luma.r, 0.0, 0.0) - vec3(adjusted_luma.r, 0.0, 0.0)) : adjusted_luma;
    adjusted = clamp(XYZ_to_sRGB(YxytoXYZ(adjusted)), 0.0, 1.0);

//  Technical LUT
    float red_2 = (adjusted.r * (params.LUT_Size2 - 1.0) + 0.4999) / (params.LUT_Size2 * params.LUT_Size2);
    float green_2 = (adjusted.g * (params.LUT_Size2 - 1.0) + 0.4999) / params.LUT_Size2;
    float blue1_2 = (floor(adjusted.b * (params.LUT_Size2 - 1.0)) / params.LUT_Size2) + red_2;
    float blue2_2 = (ceil(adjusted.b * (params.LUT_Size2 - 1.0)) / params.LUT_Size2) + red_2;
    float mixer_2 = clamp(max((adjusted.b - blue1_2) / (blue2_2 - blue1_2), 0.0), 0.0, 32.0);
    vec3 color1_2 = texture(SamplerLUT2, vec2(blue1_2, green_2)).rgb;
    vec3 color2_2 = texture(SamplerLUT2, vec2(blue2_2, green_2)).rgb;
    vec3 LUT2_output = mixfix(color1_2, color2_2, mixer_2);

    FragColor = (params.LUT2_toggle < 1.0) ? vec4(linear_to_sRGB(adjusted, 2.4), 1.0) : vec4(linear_to_sRGB(LUT2_output, 2.4), 1.0);
} 

The thing it was choking on was the implicit casts from vec4 to vec3 whenever it sampled the LUTs. By default, texture(sampler2D, vec2) produces a vec4, so if you only want a vec3 out of it (which is pretty common), you need to explicitly cast it down to a vec3 by adding ‘.rgb’ (or ‘.xyz’) at the end.

3 Likes

Thanks I checked and still refuses to work even without the vignette block, was that right already? Oh, I’m on 1.7.7 still, don’t know if that makes a difference.

hmm, shouldn’t matter which version. I didn’t get any problems out of the vignette block on my end.

Can you post your errors? Could be GPU/compiler-specific.

I’m on GTX 1070, (441.66). Win7

By the way, I tested without the LUT code and vignette worked go figure. So it’s only the LUT part what 's failing on me.

[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enterta
inment System\RetroArch 1.7.7 x64\shaders\shaders_slang\misc\grade-good.slang"
.
[INFO] [slang]: Using render target format R8G8B8A8_UNORM for pass output #0.
[INFO] [slang]: Building pass #0 (N/A)
[INFO] [Vulkan filter chain]: Creating framebuffer 1024 x 1024 (max 1 level(s)).

[ERROR] [slang]: Non-semantic textures not supported yet.
[ERROR] [slang]: Failed to reflect SPIR-V. Resource usage is inconsistent with e
xpectations.
[ERROR] [Vulkan]: Failed to create preset: "Y:\HyperSpin\Emulators\Super Nintendo
Entertainment System\RetroArch 1.7.7 x64\shaders\Nintendo 64.slangp".
[ERROR] [Vulkan]: Failed to create filter chain: "Y:\HyperSpin\Emulators\Super Ni
ntendo Entertainment System\RetroArch 1.7.7 x64\shaders\Nintendo 64.slangp".
 Falling back to stock.
[INFO] [slang]: Building pass #0 (N/A)
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: no):
[INFO] [slang]:   Push Constants (Vertex: no, Fragment: no):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [Vulkan filter chain]: Not using frame history.
[INFO] [Vulkan filter chain]: Not using framebuffer feedback.

Ah, that means your preset doesn’t have the right references for the textures (usually).

EDIT: here’s the preset I made. It’s running from the ‘reshade’ directory and uses 2 of the generic passthru LUTs:

shaders = 1

shader0 = shaders/LUT/dogway.slang

textures = "SamplerLUT1;SamplerLUT2"

SamplerLUT1 = shaders/LUT/16.png
SamplerLUT1_linear = true
SamplerLUT2 = shaders/LUT/32.png
SamplerLUT2_linear = true
2 Likes

Thanks! I wasn’t debugging correctly - loading the single shader through GUI. And when loading the shader preset I forgot to disable crt-royale geometry mode (doesn’t work in vulkan yet).

Added a few fixes and uploaded; grade.glsl, grade.slang and ported white_point to slang too.

EDIT: Updated with new gamma function to fix the in/out gamma difference in the piece-wise function.

I noticed ntsc-adaptive is not in glsl, so I took a stab at porting it (pass1, pass2), it’s not possible right (runtime variables)?

1 Like

royale geometry should work with vulkan. What’s it doing on your end?

NTSC-adaptive should be port-able, I think, i just hadn’t gotten around to it, as I wasn’t sure if some lurking problem with the shader design was going to derail the whole endeavor. I’ll try to look it over soon.

2 Likes

It’s just rendering black for any mode (audio plays), and when changed to 0 it comes back.

I share the log but it looks like it doesn’t report any errors:

[INFO] [Vulkan]: Queue family 0 supports 16 sub-queues.
[INFO] [Vulkan]: Swapchain supports present mode: 2.
[INFO] [Vulkan]: Swapchain supports present mode: 3.
[INFO] [Vulkan]: Swapchain supports present mode: 1.
[INFO] [Vulkan]: Swapchain supports present mode: 0.
[INFO] [Vulkan]: Creating swapchain with present mode: 2
[INFO] [Vulkan]: Using swapchain size 2560 x 1440.
[INFO] [Vulkan]: Got 2 swapchain images.
[INFO] [Vulkan]: Using resolution 2560x1440
[INFO] [Vulkan]: Using BGRA8888 format.
[INFO] [Vulkan]: GPU supports linear images as textures, but not DEVICE_LOCAL. F
alling back to copy path.
[INFO] [Vulkan]: GPU supports linear images as textures, but not DEVICE_LOCAL. F
alling back to copy path.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\misc\grade.slang".
[INFO] [slang]: Using render target format R16G16B16A16_SFLOAT for pass output #
0.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\ntsc\shaders\ntsc-adaptive\ntsc-pass1.slang".
[INFO] [slang]: Using render target format R16G16B16A16_SFLOAT for pass output #
1.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\ntsc\shaders\ntsc-adaptive\ntsc-pass2.slang".
[INFO] [slang]: Using render target format R8G8B8A8_UNORM for pass output #2.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\crt\shaders\crt-royale\src\crt-royale-first-pass-linearize-crt-gamma-bob-fi
elds.slang".
[INFO] [slang]: Using render target format R8G8B8A8_SRGB for pass output #3.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\crt\shaders\crt-royale\src\crt-royale-scanlines-vertical-interlacing.slang"
.
[INFO] [slang]: Using render target format R8G8B8A8_SRGB for pass output #4.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\crt\shaders\crt-royale\src\crt-royale-bloom-approx.slang".
[INFO] [slang]: Using render target format R8G8B8A8_SRGB for pass output #5.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\blurs\blur9fast-vertical.slang".
[INFO] [slang]: Using render target format R8G8B8A8_SRGB for pass output #6.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\blurs\blur9fast-horizontal.slang".
[INFO] [slang]: Using render target format R8G8B8A8_SRGB for pass output #7.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\crt\shaders\crt-royale\src\crt-royale-mask-resize-vertical.slang".
[INFO] [slang]: Using render target format R8G8B8A8_UNORM for pass output #8.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\crt\shaders\crt-royale\src\crt-royale-mask-resize-horizontal.slang".
[INFO] [slang]: Using render target format R8G8B8A8_UNORM for pass output #9.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\crt\shaders\crt-royale\src\crt-royale-scanlines-horizontal-apply-mask.slang
".
[INFO] [slang]: Using render target format R8G8B8A8_SRGB for pass output #10.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\crt\shaders\crt-royale\src\crt-royale-brightpass.slang".
[INFO] [slang]: Using render target format R8G8B8A8_SRGB for pass output #11.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\crt\shaders\crt-royale\src\crt-royale-bloom-vertical.slang".
[INFO] [slang]: Using render target format R8G8B8A8_SRGB for pass output #12.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\crt\shaders\crt-royale\src\crt-royale-bloom-horizontal-reconstitute.slang".

[INFO] [slang]: Using render target format R8G8B8A8_SRGB for pass output #13.
[INFO] [slang]: Compiling shader "Y:\HyperSpin\Emulators\Super Nintendo Enter
tainment System\RetroArch 1.7.7 x64\shaders\presets\ParaLLEl N64\..\..\shaders_s
lang\crt\shaders\crt-royale\src\crt-royale-geometry-aa-last-pass.slang".
[INFO] [slang]: Using render target format R8G8B8A8_UNORM for pass output #14.
[INFO] [slang]: Building pass #0 (N/A)
[INFO] [Vulkan filter chain]: Creating framebuffer 1024 x 1024 (max 1 level(s)).

[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:      User (#0)
[INFO] [slang]:      User (#1)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OriginalSize (#0) (Offset: 80)
[INFO] [slang]:      SourceSize (#0) (Offset: 64)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #0 (PushOffset: 0)
[INFO] [slang]:     #1 (PushOffset: 4)
[INFO] [slang]:     #2 (PushOffset: 8)
[INFO] [slang]:     #3 (PushOffset: 12)
[INFO] [slang]:     #4 (PushOffset: 16)
[INFO] [slang]:     #5 (PushOffset: 20)
[INFO] [slang]:     #6 (PushOffset: 24)
[INFO] [slang]:     #7 (PushOffset: 28)
[INFO] [slang]:     #8 (PushOffset: 32)
[INFO] [slang]:     #9 (PushOffset: 36)
[INFO] [slang]:     #10 (PushOffset: 40)
[INFO] [slang]:     #11 (PushOffset: 44)
[INFO] [slang]:     #12 (PushOffset: 48)
[INFO] [slang]:     #13 (PushOffset: 56)
[INFO] [slang]:     #14 (PushOffset: 60)
[INFO] [slang]:     #15 (PushOffset: 64)
[INFO] [slang]:     #16 (PushOffset: 68)
[INFO] [slang]:     #17 (PushOffset: 72)
[INFO] [slang]:     #18 (PushOffset: 76)
[INFO] [slang]:     #19 (PushOffset: 80)
[INFO] [slang]:     #20 (PushOffset: 84)
[INFO] [slang]:     #21 (PushOffset: 88)
[INFO] [slang]:     #22 (PushOffset: 92)
[INFO] [slang]:     #23 (PushOffset: 96)
[INFO] [slang]:     #24 (PushOffset: 100)
[INFO] [slang]:     #25 (PushOffset: 104)
[INFO] [slang]:     #26 (PushOffset: 108)
[INFO] [slang]:     #27 (PushOffset: 112)
[INFO] [Vulkan]: Push Constant Block: 116 bytes.
[INFO] [slang]: Building pass #1 (N/A)
[INFO] [Vulkan filter chain]: Creating framebuffer 1536 x 1024 (max 1 level(s)).

[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: no, Fragment: no):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (Offset: 64)
[INFO] [slang]:      FrameCount (Offset: 112)
[INFO] [slang]:      OriginalSize (#0) (Offset: 80)
[INFO] [slang]:      SourceSize (#0) (Offset: 96)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #0 (Offset: 116)
[INFO] [slang]:     #1 (Offset: 120)
[INFO] [slang]: Building pass #2 (N/A)
[INFO] [Vulkan filter chain]: Creating framebuffer 768 x 1024 (max 1 level(s)).
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: no, Fragment: no):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OriginalSize (#0) (Offset: 80)
[INFO] [slang]:      SourceSize (#0) (Offset: 96)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #0 (Offset: 112)
[INFO] [slang]: Building pass #3 (ORIG_LINEARIZED)
[INFO] [Vulkan filter chain]: Creating framebuffer 768 x 1024 (max 1 level(s)).
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      FrameCount (PushOffset: 48)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #0 (Offset: 64)
[INFO] [slang]:     #43 (Offset: 244)
[INFO] [slang]:     #44 (Offset: 236)
[INFO] [slang]:     #45 (Offset: 240)
[INFO] [Vulkan]: Push Constant Block: 52 bytes.
[INFO] [slang]: Building pass #4 (VERTICAL_SCANLINES)
[INFO] [Vulkan filter chain]: Creating framebuffer 768 x 1440 (max 1 level(s)).
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      FrameCount (PushOffset: 48)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #7 (Offset: 92)
[INFO] [slang]:     #8 (Offset: 96)
[INFO] [slang]:     #9 (Offset: 100)
[INFO] [slang]:     #10 (Offset: 104)
[INFO] [slang]:     #11 (Offset: 108)
[INFO] [slang]:     #12 (Offset: 112)
[INFO] [slang]:     #19 (Offset: 140)
[INFO] [slang]:     #20 (Offset: 144)
[INFO] [slang]:     #21 (Offset: 148)
[INFO] [slang]:     #43 (Offset: 244)
[INFO] [slang]:     #44 (Offset: 236)
[INFO] [slang]:     #45 (Offset: 240)
[INFO] [Vulkan]: Push Constant Block: 52 bytes.
[INFO] [slang]: Building pass #5 (BLOOM_APPROX)
[INFO] [Vulkan filter chain]: Creating framebuffer 320 x 240 (max 1 level(s)).
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Original (#0)
[INFO] [slang]:      Source (#0)
[INFO] [slang]:      PassOutput (#3)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #8 (Offset: 96)
[INFO] [slang]:     #16 (Offset: 128)
[INFO] [slang]:     #17 (Offset: 132)
[INFO] [slang]:     #18 (Offset: 136)
[INFO] [slang]:     #19 (Offset: 140)
[INFO] [slang]:     #20 (Offset: 144)
[INFO] [slang]:     #21 (Offset: 148)
[INFO] [slang]:     #24 (Offset: 168)
[INFO] [slang]:     #25 (Offset: 164)
[INFO] [slang]:     #26 (Offset: 160)
[INFO] [slang]:     #36 (Offset: 208)
[INFO] [slang]:     #37 (Offset: 212)
[INFO] [slang]:     #43 (Offset: 244)
[INFO] [slang]:     #45 (Offset: 240)
[INFO] [Vulkan]: Push Constant Block: 80 bytes.
[INFO] [slang]: Building pass #6 (N/A)
[INFO] [Vulkan filter chain]: Creating framebuffer 320 x 240 (max 1 level(s)).
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [Vulkan]: Push Constant Block: 52 bytes.
[INFO] [slang]: Building pass #7 (HALATION_BLUR)
[INFO] [Vulkan filter chain]: Creating framebuffer 320 x 240 (max 1 level(s)).
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [Vulkan]: Push Constant Block: 52 bytes.
[INFO] [slang]: Building pass #8 (N/A)
[INFO] [Vulkan filter chain]: Creating framebuffer 64 x 90 (max 1 level(s)).
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:      User (#2)
[INFO] [slang]:      User (#4)
[INFO] [slang]:      User (#6)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #22 (Offset: 152)
[INFO] [slang]:     #23 (Offset: 156)
[INFO] [slang]:     #24 (Offset: 168)
[INFO] [slang]:     #25 (Offset: 164)
[INFO] [slang]:     #26 (Offset: 160)
[INFO] [slang]:     #36 (Offset: 208)
[INFO] [slang]:     #37 (Offset: 212)
[INFO] [slang]:     #43 (Offset: 244)
[INFO] [Vulkan]: Push Constant Block: 52 bytes.
[INFO] [slang]: Building pass #9 (MASK_RESIZE)
[INFO] [Vulkan filter chain]: Creating framebuffer 120 x 90 (max 1 level(s)).
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #23 (Offset: 156)
[INFO] [slang]:     #24 (Offset: 168)
[INFO] [slang]:     #25 (Offset: 164)
[INFO] [slang]:     #26 (Offset: 160)
[INFO] [slang]:     #43 (Offset: 244)
[INFO] [Vulkan]: Push Constant Block: 52 bytes.
[INFO] [slang]: Building pass #10 (MASKED_SCANLINES)
[INFO] [Vulkan filter chain]: Creating framebuffer 1920 x 1440 (max 1 level(s)).

[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:      PassOutput (#4)
[INFO] [slang]:      PassOutput (#5)
[INFO] [slang]:      PassOutput (#7)
[INFO] [slang]:      PassOutput (#9)
[INFO] [slang]:      User (#3)
[INFO] [slang]:      User (#5)
[INFO] [slang]:      User (#7)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:      PassOutputSize (#4) (PushOffset: 48)
[INFO] [slang]:      PassOutputSize (#5) (PushOffset: 64)
[INFO] [slang]:      PassOutputSize (#7) (PushOffset: 80)
[INFO] [slang]:      PassOutputSize (#9) (PushOffset: 96)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #3 (Offset: 76)
[INFO] [slang]:     #13 (Offset: 116)
[INFO] [slang]:     #14 (Offset: 120)
[INFO] [slang]:     #15 (Offset: 124)
[INFO] [slang]:     #16 (Offset: 128)
[INFO] [slang]:     #17 (Offset: 132)
[INFO] [slang]:     #18 (Offset: 136)
[INFO] [slang]:     #22 (Offset: 152)
[INFO] [slang]:     #23 (Offset: 156)
[INFO] [slang]:     #24 (Offset: 168)
[INFO] [slang]:     #25 (Offset: 164)
[INFO] [slang]:     #26 (Offset: 160)
[INFO] [slang]:     #43 (Offset: 244)
[INFO] [Vulkan]: Push Constant Block: 112 bytes.
[INFO] [slang]: Building pass #11 (BRIGHTPASS)
[INFO] [Vulkan filter chain]: Creating framebuffer 1920 x 1440 (max 1 level(s)).

[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      PassOutput (#5)
[INFO] [slang]:      PassOutput (#10)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:      PassOutputSize (#5) (PushOffset: 80)
[INFO] [slang]:      PassOutputSize (#10) (PushOffset: 64)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #2 (Offset: 72)
[INFO] [slang]:     #5 (Offset: 84)
[INFO] [slang]:     #6 (Offset: 88)
[INFO] [slang]:     #22 (Offset: 152)
[INFO] [slang]:     #23 (Offset: 156)
[INFO] [slang]:     #24 (Offset: 168)
[INFO] [slang]:     #25 (Offset: 164)
[INFO] [slang]:     #26 (Offset: 160)
[INFO] [slang]:     #43 (Offset: 244)
[INFO] [Vulkan]: Push Constant Block: 96 bytes.
[INFO] [slang]: Building pass #12 (N/A)
[INFO] [Vulkan filter chain]: Creating framebuffer 1920 x 1440 (max 1 level(s)).

[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #23 (Offset: 156)
[INFO] [slang]:     #24 (Offset: 168)
[INFO] [slang]:     #25 (Offset: 164)
[INFO] [slang]:     #26 (Offset: 160)
[INFO] [slang]:     #43 (Offset: 244)
[INFO] [Vulkan]: Push Constant Block: 96 bytes.
[INFO] [slang]: Building pass #13 (N/A)
[INFO] [Vulkan filter chain]: Creating framebuffer 1920 x 1440 (max 4294967295 l
evel(s)).
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:      PassOutput (#7)
[INFO] [slang]:      PassOutput (#10)
[INFO] [slang]:      PassOutput (#11)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:      PassOutputSize (#7) (PushOffset: 64)
[INFO] [slang]:      PassOutputSize (#10) (PushOffset: 48)
[INFO] [slang]:      PassOutputSize (#11) (PushOffset: 80)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #2 (Offset: 72)
[INFO] [slang]:     #4 (Offset: 80)
[INFO] [slang]:     #22 (Offset: 152)
[INFO] [slang]:     #23 (Offset: 156)
[INFO] [slang]:     #24 (Offset: 168)
[INFO] [slang]:     #25 (Offset: 164)
[INFO] [slang]:     #26 (Offset: 160)
[INFO] [slang]:     #43 (Offset: 244)
[INFO] [Vulkan]: Push Constant Block: 96 bytes.
[INFO] [slang]: Building pass #14 (N/A)
[INFO] [Vulkan filter chain]: Creating framebuffer 1920 x 1440 (max 1 level(s)).

[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: yes):
[INFO] [slang]:   Push Constants (Vertex: yes, Fragment: yes):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:      OutputSize (PushOffset: 32)
[INFO] [slang]:      FrameCount (PushOffset: 48)
[INFO] [slang]:      SourceSize (#0) (PushOffset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [slang]:     #1 (Offset: 68)
[INFO] [slang]:     #29 (Offset: 180)
[INFO] [slang]:     #30 (Offset: 184)
[INFO] [slang]:     #31 (Offset: 188)
[INFO] [slang]:     #32 (Offset: 192)
[INFO] [slang]:     #33 (Offset: 196)
[INFO] [slang]:     #34 (Offset: 200)
[INFO] [slang]:     #35 (Offset: 204)
[INFO] [slang]:     #38 (Offset: 216)
[INFO] [slang]:     #39 (Offset: 220)
[INFO] [slang]:     #40 (Offset: 224)
[INFO] [slang]:     #41 (Offset: 228)
[INFO] [slang]:     #42 (Offset: 232)
[INFO] [slang]:     #43 (Offset: 244)
[INFO] [Vulkan]: Push Constant Block: 112 bytes.
[INFO] [slang]: Building pass #15 (N/A)
[INFO] [slang]: Reflection
[INFO] [slang]:   Textures:
[INFO] [slang]:      Source (#0)
[INFO] [slang]:
[INFO] [slang]:   Uniforms (Vertex: yes, Fragment: no):
[INFO] [slang]:   Push Constants (Vertex: no, Fragment: no):
[INFO] [slang]:      MVP (Offset: 0)
[INFO] [slang]:
[INFO] [slang]:   Parameters:
[INFO] [Vulkan filter chain]: Not using frame history.
[INFO] [Vulkan filter chain]: Not using framebuffer feedback.

any chance you’re using an old version? It should be fixed as of several months ago. Does it treat you any differently via GLCore?

1 Like

I updated the slang crt royale a month ago. With GL it’s fine. I share a preset I use just in case I missed something and whether it works on your end.

shaders = "15"
shader0 = "..\..\shaders_slang\misc\grade.slang"
filter_linear0 = "false"
wrap_mode0 = "clamp_to_border"
mipmap_input0 = "false"
alias0 = ""
float_framebuffer0 = "true"
srgb_framebuffer0 = "false"
scale_type_x0 = "source"
scale_x0 = "1.000000"
scale_type_y0 = "source"
scale_y0 = "1.000000"
shader1 = "..\..\shaders_slang\ntsc\shaders\ntsc-adaptive\ntsc-pass1.slang"
filter_linear1 = "false"
wrap_mode1 = "clamp_to_border"
frame_count_mod1 = "2"
mipmap_input1 = "false"
alias1 = ""
float_framebuffer1 = "true"
srgb_framebuffer1 = "false"
scale_type_x1 = "source"
scale_x1 = "5.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "..\..\shaders_slang\ntsc\shaders\ntsc-adaptive\ntsc-pass2.slang"
filter_linear2 = "false"
wrap_mode2 = "clamp_to_border"
mipmap_input2 = "false"
alias2 = ""
float_framebuffer2 = "false"
srgb_framebuffer2 = "false"
scale_type_x2 = "source"
scale_x2 = "0.500000"
scale_type_y2 = "source"
scale_y2 = "1.000000"
shader3 = "..\..\shaders_slang\crt\shaders\crt-royale\src\crt-royale-first-pass-linearize-crt-gamma-bob-fields.slang"
filter_linear3 = "false"
wrap_mode3 = "clamp_to_border"
mipmap_input3 = "false"
alias3 = "ORIG_LINEARIZED"
float_framebuffer3 = "false"
srgb_framebuffer3 = "true"
scale_type_x3 = "source"
scale_x3 = "1.000000"
scale_type_y3 = "source"
scale_y3 = "1.000000"
shader4 = "..\..\shaders_slang\crt\shaders\crt-royale\src\crt-royale-scanlines-vertical-interlacing.slang"
filter_linear4 = "true"
wrap_mode4 = "clamp_to_border"
mipmap_input4 = "false"
alias4 = "VERTICAL_SCANLINES"
float_framebuffer4 = "false"
srgb_framebuffer4 = "true"
scale_type_x4 = "source"
scale_x4 = "1.000000"
scale_type_y4 = "viewport"
scale_y4 = "1.000000"
shader5 = "..\..\shaders_slang\crt\shaders\crt-royale\src\crt-royale-bloom-approx.slang"
filter_linear5 = "true"
wrap_mode5 = "clamp_to_border"
mipmap_input5 = "false"
alias5 = "BLOOM_APPROX"
float_framebuffer5 = "false"
srgb_framebuffer5 = "true"
scale_type_x5 = "absolute"
scale_x5 = "320"
scale_type_y5 = "absolute"
scale_y5 = "240"
shader6 = "..\..\shaders_slang\blurs\blur9fast-vertical.slang"
filter_linear6 = "true"
wrap_mode6 = "clamp_to_border"
mipmap_input6 = "false"
alias6 = ""
float_framebuffer6 = "false"
srgb_framebuffer6 = "true"
scale_type_x6 = "source"
scale_x6 = "1.000000"
scale_type_y6 = "source"
scale_y6 = "1.000000"
shader7 = "..\..\shaders_slang\blurs\blur9fast-horizontal.slang"
filter_linear7 = "true"
wrap_mode7 = "clamp_to_border"
mipmap_input7 = "false"
alias7 = "HALATION_BLUR"
float_framebuffer7 = "false"
srgb_framebuffer7 = "true"
scale_type_x7 = "source"
scale_x7 = "1.000000"
scale_type_y7 = "source"
scale_y7 = "1.000000"
shader8 = "..\..\shaders_slang\crt\shaders\crt-royale\src\crt-royale-mask-resize-vertical.slang"
filter_linear8 = "true"
wrap_mode8 = "clamp_to_border"
mipmap_input8 = "false"
alias8 = ""
float_framebuffer8 = "false"
srgb_framebuffer8 = "false"
scale_type_x8 = "absolute"
scale_x8 = "64"
scale_type_y8 = "viewport"
scale_y8 = "0.062500"
shader9 = "..\..\shaders_slang\crt\shaders\crt-royale\src\crt-royale-mask-resize-horizontal.slang"
filter_linear9 = "false"
wrap_mode9 = "clamp_to_border"
mipmap_input9 = "false"
alias9 = "MASK_RESIZE"
float_framebuffer9 = "false"
srgb_framebuffer9 = "false"
scale_type_x9 = "viewport"
scale_x9 = "0.062500"
scale_type_y9 = "source"
scale_y9 = "1.000000"
shader10 = "..\..\shaders_slang\crt\shaders\crt-royale\src\crt-royale-scanlines-horizontal-apply-mask.slang"
filter_linear10 = "true"
wrap_mode10 = "clamp_to_border"
mipmap_input10 = "false"
alias10 = "MASKED_SCANLINES"
float_framebuffer10 = "false"
srgb_framebuffer10 = "true"
scale_type_x10 = "viewport"
scale_x10 = "1.000000"
scale_type_y10 = "viewport"
scale_y10 = "1.000000"
shader11 = "..\..\shaders_slang\crt\shaders\crt-royale\src\crt-royale-brightpass.slang"
filter_linear11 = "true"
wrap_mode11 = "clamp_to_border"
mipmap_input11 = "false"
alias11 = "BRIGHTPASS"
float_framebuffer11 = "false"
srgb_framebuffer11 = "true"
scale_type_x11 = "viewport"
scale_x11 = "1.000000"
scale_type_y11 = "viewport"
scale_y11 = "1.000000"
shader12 = "..\..\shaders_slang\crt\shaders\crt-royale\src\crt-royale-bloom-vertical.slang"
filter_linear12 = "true"
wrap_mode12 = "clamp_to_border"
mipmap_input12 = "false"
alias12 = ""
float_framebuffer12 = "false"
srgb_framebuffer12 = "true"
scale_type_x12 = "source"
scale_x12 = "1.000000"
scale_type_y12 = "source"
scale_y12 = "1.000000"
shader13 = "..\..\shaders_slang\crt\shaders\crt-royale\src\crt-royale-bloom-horizontal-reconstitute.slang"
filter_linear13 = "true"
wrap_mode13 = "clamp_to_border"
mipmap_input13 = "false"
alias13 = ""
float_framebuffer13 = "false"
srgb_framebuffer13 = "true"
scale_type_x13 = "source"
scale_x13 = "1.000000"
scale_type_y13 = "source"
scale_y13 = "1.000000"
shader14 = "..\..\shaders_slang\crt\shaders\crt-royale\src\crt-royale-geometry-aa-last-pass.slang"
filter_linear14 = "true"
wrap_mode14 = "clamp_to_border"
mipmap_input14 = "true"
alias14 = ""
float_framebuffer14 = "false"
srgb_framebuffer14 = "false"
scale_type_x14 = "viewport"
scale_x14 = "1.000000"
scale_type_y14 = "viewport"
scale_y14 = "1.000000"
parameters = "quality;bw;linearize;gamma_type;gamma_in;vignette;str;power;LUT_Size1;LUT1_toggle;LUT_Size2;LUT2_toggle;temperature;luma_preserve;sat;lum;cntrst;black_level;blr;blg;blb;r;g;b;rg;rb;gr;gb;br;bg;crt_gamma;lcd_gamma;levels_contrast;halation_weight;diffusion_weight;bloom_underestimate_levels;bloom_excess;beam_min_sigma;beam_max_sigma;beam_spot_power;beam_min_shape;beam_max_shape;beam_shape_power;beam_horiz_filter;beam_horiz_sigma;beam_horiz_linear_rgb_weight;convergence_offset_x_r;convergence_offset_x_g;convergence_offset_x_b;convergence_offset_y_r;convergence_offset_y_g;convergence_offset_y_b;mask_type;mask_sample_mode_desired;mask_specify_num_triads;mask_triad_size_desired;mask_num_triads_desired;aa_subpixel_r_offset_x_runtime;aa_subpixel_r_offset_y_runtime;aa_cubic_c;aa_gauss_sigma;geom_mode_runtime;geom_radius;geom_view_dist;geom_tilt_angle_x;geom_tilt_angle_y;geom_aspect_ratio_x;geom_aspect_ratio_y;geom_overscan_x;geom_overscan_y;border_size;border_darkness;border_compress;interlace_detect_toggle;interlace_bff;interlace_1080i"
quality = "1.000000"
bw = "0.000000"
linearize = "0.000000"
gamma_in = "2.400000"
gamma_type = "1.000000"
vignette = "1.000000"
str = "40.000000"
power = "0.250000"
LUT_Size1 = "32.000000"
LUT1_toggle = "0.000000"
LUT_Size2 = "64.000000"
LUT2_toggle = "0.000000"
temperature = "9311.000000"
luma_preserve = "1.000000"
sat = "0.950000"
lum = "1.050000"
cntrst = "0.000000"
mid = "0.500000"
black_level = "0.040000"
blr = "0.000000"
blg = "0.000000"
blb = "0.000000"
r = "1.000000"
g = "1.000000"
b = "1.000000"
rg = "0.000000"
rb = "0.000000"
gr = "0.000000"
gb = "0.000000"
br = "0.000000"
bg = "0.050000"
crt_gamma = "2.200000"
lcd_gamma = "2.200000"
levels_contrast = "1.000000"
halation_weight = "0.000000"
diffusion_weight = "0.075000"
bloom_underestimate_levels = "0.800000"
bloom_excess = "0.000000"
beam_min_sigma = "0.020000"
beam_max_sigma = "0.300000"
beam_spot_power = "0.330000"
beam_min_shape = "2.000000"
beam_max_shape = "4.000000"
beam_shape_power = "0.250000"
beam_horiz_filter = "0.000000"
beam_horiz_sigma = "0.350000"
beam_horiz_linear_rgb_weight = "1.000000"
convergence_offset_x_r = "0.000000"
convergence_offset_x_g = "0.000000"
convergence_offset_x_b = "0.000000"
convergence_offset_y_r = "0.000000"
convergence_offset_y_g = "0.000000"
convergence_offset_y_b = "0.000000"
mask_type = "1.000000"
mask_sample_mode_desired = "0.000000"
mask_specify_num_triads = "0.000000"
mask_triad_size_desired = "3.000000"
mask_num_triads_desired = "480.000000"
aa_subpixel_r_offset_x_runtime = "-0.333333"
aa_subpixel_r_offset_y_runtime = "0.000000"
aa_cubic_c = "0.500000"
aa_gauss_sigma = "0.500000"
geom_mode_runtime = "1.000000"
geom_radius = "1.800000"
geom_view_dist = "2.000000"
geom_tilt_angle_x = "0.000000"
geom_tilt_angle_y = "0.000000"
geom_aspect_ratio_x = "432.000000"
geom_aspect_ratio_y = "329.000000"
geom_overscan_x = "1.000000"
geom_overscan_y = "1.000000"
border_size = "0.015000"
border_darkness = "2.000000"
border_compress = "2.500000"
interlace_detect_toggle = "0.000000"
interlace_bff = "0.000000"
interlace_1080i = "0.000000"
textures = "SamplerLUT1;SamplerLUT2;mask_grille_texture_small;mask_grille_texture_large;mask_slot_texture_small;mask_slot_texture_large;mask_shadow_texture_small;mask_shadow_texture_large"
SamplerLUT1 = "..\..\shaders_slang\reshade\shaders\LUT\Sony Trinitron Std D50 - Edit 1 - Gamma Unadjusted -32px.png"
SamplerLUT1_linear = "true"
SamplerLUT1_wrap_mode = "clamp_to_border"
SamplerLUT1_mipmap = "false"
SamplerLUT2 = "..\..\shaders_slang\reshade\shaders\LUT\SamsungH6640-2020-03-02XYZLUT+MTX.Rec709_2.4.png"
SamplerLUT2_linear = "true"
SamplerLUT2_wrap_mode = "clamp_to_border"
SamplerLUT2_mipmap = "false"
mask_grille_texture_small = "..\..\shaders_slang\crt\shaders\crt-royale\SamsungTileableLinearApertureGrille15Wide8And5d5SpacingResizeTo64.png"
mask_grille_texture_small_linear = "true"
mask_grille_texture_small_wrap_mode = "repeat"
mask_grille_texture_small_mipmap = "false"
mask_grille_texture_large = "..\..\shaders_slang\crt\shaders\crt-royale\SamsungTileableLinearApertureGrille15Wide8And5d5Spacing.png"
mask_grille_texture_large_linear = "true"
mask_grille_texture_large_wrap_mode = "repeat"
mask_grille_texture_large_mipmap = "true"
mask_slot_texture_small = "..\..\shaders_slang\crt\shaders\crt-royale\SamsungTileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacingResizeTo64.png"
mask_slot_texture_small_linear = "true"
mask_slot_texture_small_wrap_mode = "repeat"
mask_slot_texture_small_mipmap = "false"
mask_slot_texture_large = "..\..\shaders_slang\crt\shaders\crt-royale\SamsungTileableLinearSlotMaskTall15Wide9And4d5Horizontal9d14VerticalSpacing.png"
mask_slot_texture_large_linear = "true"
mask_slot_texture_large_wrap_mode = "repeat"
mask_slot_texture_large_mipmap = "true"
mask_shadow_texture_small = "..\..\shaders_slang\crt\shaders\crt-royale\SamsungTileableLinearShadowMaskEDPResizeTo64.png"
mask_shadow_texture_small_linear = "true"
mask_shadow_texture_small_wrap_mode = "repeat"
mask_shadow_texture_small_mipmap = "false"
mask_shadow_texture_large = "..\..\shaders_slang\crt\shaders\crt-royale\SamsungTileableLinearShadowMaskEDP.png"
mask_shadow_texture_large_linear = "true"
mask_shadow_texture_large_wrap_mode = "repeat"
mask_shadow_texture_large_mipmap = "true"
1 Like

By the way, I updated grade again to include Dullness/Vibrance and a few cosmetic changes. For now this is it for me on this shader.

As a side note I included a discriminatory POW vs sRGB gamma setting because I noticed that Medievil was using a pure power compensated gamma. I don’t know if this is by system or by game but I default it to sRGB because on most titles it improves the dynamic range in the low range.

Also I’m concerned on overshooting values, so I might consider in the future a soft roll-off to bring those back to range.

Here all updated shaders for reference: GitHub Dogway RetroArch Shaders

5 Likes

I know this a big ask, but could you possibly do a version of the grade shader without the vignette and LUTs?

I’m asking because I don’t personally know enough about color management and I’m afraid I’d end up messing things up (color-wise) by just removing them outright, without knowing how to compensate for the removal.

If you’re not interested in doing it, it’s cool, I just figured I’d ask.

Either way this is some quality work, I’m glad that you go it where you wanted!

1 Like

Can’t you toggle off those ones? I know that for the slang version you either point to an existing LUT file or it renders black, and that’s an annoyance. If that’s what you mean I can post a version here without that.

1 Like

Yeah, that’ll work for me, my main concern was removing the LUTs without breaking things in a color sense.

Thanks!

You can just change the LUTs in the preset to point to the existing passthru LUTs. You’ll have the (minor) performance impact, but the image won’t change.

1 Like

That’s why I was asking about removing them (not from his main branch, just a personal version), I mean if I don’t have to do anything complicated I could just remove them myself. (I probably could have worded everything better.)

So really the main questions are do I have to do anything special to remove them as compensation and how would I do the fragColor at the end with them removed for correct gamma?

If I know this I can probably just do it myself, lol.

Sorry, I entertained myself debugging a possible chroma banding issue, anyways here it is:

grade_(noLUT).slang

#version 450

layout(push_constant) uniform Push
{
    float gamma_out;
    float gamma_in;
    float gamma_type;
    float vignette;
    float str;
    float power;
    float temperature;
    float luma_preserve;
    float sat;
    float dulvibr;
    float lum;
    float size;
    float cntrst;
    float mid;
    float black_level;
    float blr;
    float blg;
    float blb;
    float r;
    float g;
    float b;
    float rg;
    float rb;
    float gr;
    float gb;
    float br;
    float bg;
} params;

/*
   Grade
   > Ubershader grouping some color related monolithic shaders like color-mangler, vignette, white_point,
   > and the addition of vibrance, black level, sigmoidal contrast and proper gamma transforms.

   Author: hunterk, Guest, Dr. Venom, Dogway
   License: Public domain
*/

#pragma parameter gamma_out "Display Gamma" 2.20 0.0 3.0 0.05
#pragma parameter gamma_in "CRT Gamma" 2.40 0.0 3.0 0.05
#pragma parameter gamma_type "CRT Gamma (POW = 0, sRGB = 1)" 1.0 0.0 1.0 1.0
#pragma parameter vignette "Vignette Toggle" 1.0 0.0 1.0 1.0
#pragma parameter str "Vignette Strength" 40.0 10.0 40.0 1.0
#pragma parameter power "Vignette Power" 0.20 0.0 0.5 0.01
#pragma parameter temperature "White Point" 9311.0 1031.0 12047.0 72.0
#pragma parameter luma_preserve "WP Preserve Luminance" 1.0 0.0 1.0 1.0
#pragma parameter sat "Saturation" 0.0 -1.0 2.0 0.02
#pragma parameter dulvibr "Dullness/Vibrance" 0.0 -1.0 1.0 0.05
#pragma parameter lum "Brightness" 1.0 0.0 2.0 0.01
#pragma parameter cntrst "Contrast" 0.0 -1.0 1.0 0.05
#pragma parameter mid "Contrast Pivot" 0.5 0.0 1.0 0.01
#pragma parameter black_level "Black Level" 0.0 -0.5 0.5 0.01
#pragma parameter blr "Black-Red Tint" 0.0 0.0 1.0 0.005
#pragma parameter blg "Black-Green Tint" 0.0 0.0 1.0 0.005
#pragma parameter blb "Black-Blue Tint" 0.0 0.0 1.0 0.005
#pragma parameter r "White-Red Tint" 1.0 0.0 2.0 0.01
#pragma parameter g "White-Green Tint" 1.0 0.0 2.0 0.01
#pragma parameter b "White-Blue Tint" 1.0 0.0 2.0 0.01
#pragma parameter rg "Red-Green Tint" 0.0 -1.0 1.0 0.005
#pragma parameter rb "Red-Blue Tint" 0.0 -1.0 1.0 0.005
#pragma parameter gr "Green-Red Tint" 0.0 -1.0 1.0 0.005
#pragma parameter gb "Green-Blue Tint" 0.0 -1.0 1.0 0.005
#pragma parameter br "Blue-Red Tint" 0.0 -1.0 1.0 0.005
#pragma parameter bg "Blue-Green Tint" 0.0 -1.0 1.0 0.005

layout(std140, set = 0, binding = 0) uniform UBO
{
    mat4 MVP;
    vec4 SourceSize;
    vec4 OriginalSize;
    vec4 OutputSize;
} global;

#pragma stage vertex
layout(location = 0) in vec4 Position;
layout(location = 1) in vec2 TexCoord;
layout(location = 0) out vec2 vTexCoord;

void main()
{
    gl_Position = global.MVP * Position;
    vTexCoord = TexCoord;
}

#pragma stage fragment
layout(location = 0) in vec2 vTexCoord;
layout(location = 0) out vec4 FragColor;
layout(set = 0, binding = 2) uniform sampler2D Source;


// White Point Mapping function
//
// From the first comment post (sRGB primaries and linear light compensated)
//      http://www.zombieprototypes.com/?p=210#comment-4695029660
// Based on the Neil Bartlett's blog update
//      http://www.zombieprototypes.com/?p=210
// Inspired itself by Tanner Helland's work
//      http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/

vec3 wp_adjust(vec3 color){

    float temp = params.temperature / 100.;
    float k = params.temperature / 10000.;
    float lk = log(k);

    vec3 wp = vec3(1.);

    // calculate RED
    wp.r = (temp <= 65.) ? 1. : 0.32068362618584273 + (0.19668730877673762 * pow(k - 0.21298613432655075, - 1.5139012907556737)) + (- 0.013883432789258415 * lk);

    // calculate GREEN
    float mg = 1.226916242502167 + (- 1.3109482654223614 * pow(k - 0.44267061967913873, 3.) * exp(- 5.089297600846147 * (k - 0.44267061967913873))) + (0.6453936305542096 * lk);
    float pg = 0.4860175851734596 + (0.1802139719519286 * pow(k - 0.14573069517701578, - 1.397716496795082)) + (- 0.00803698899233844 * lk);
    wp.g = (temp <= 65.5) ? ((temp <= 8.) ? 0. : mg) : pg;

    // calculate BLUE
    wp.b = (temp <= 19.) ? 0. : (temp >= 66.) ? 1. : 1.677499032830161 + (- 0.02313594016938082 * pow(k - 1.1367244820333684, 3.) * exp(- 4.221279555918655 * (k - 1.1367244820333684))) + (1.6550275798913296 * lk);

    // clamp
    wp.rgb = clamp(wp.rgb, vec3(0.), vec3(1.));

    // Linear color input
    return color * wp;
}

vec3 sRGB_to_XYZ(vec3 RGB){

    const mat3x3 m = mat3x3(
    0.4124564, 0.3575761, 0.1804375,
    0.2126729, 0.7151522, 0.0721750,
    0.0193339, 0.1191920, 0.9503041);
    return RGB * m;
}


vec3 XYZtoYxy(vec3 XYZ){

    float XYZrgb = XYZ.r+XYZ.g+XYZ.b;
    float Yxyg = (XYZrgb <= 0.0) ? 0.3805 : XYZ.r / XYZrgb;
    float Yxyb = (XYZrgb <= 0.0) ? 0.3769 : XYZ.g / XYZrgb;
    return vec3(XYZ.g, Yxyg, Yxyb);
}


vec3 XYZ_to_sRGB(vec3 XYZ){

    const mat3x3 m = mat3x3(
    3.2404542, -1.5371385, -0.4985314,
   -0.9692660,  1.8760108,  0.0415560,
    0.0556434, -0.2040259,  1.0572252);
    return XYZ * m;
}


vec3 YxytoXYZ(vec3 Yxy){

    float Xs = Yxy.r * (Yxy.g/Yxy.b);
    float Xsz = (Yxy.r <= 0.0) ? 0.0 : 1.0;
    vec3 XYZ = vec3(Xsz,Xsz,Xsz) * vec3(Xs, Yxy.r, (Xs/Yxy.g)-Xs-Yxy.r);
    return XYZ;
}

// This shouldn't be necessary but it seems some undefined values can
// creep in and each GPU vendor handles that differently. This keeps
// all values within a safe range
vec3 mixfix(vec3 a, vec3 b, float c)
{
    return (a.z < 1.0) ? mix(a, b, c) : a;
}


vec4 mixfix_v4(vec4 a, vec4 b, float c)
{
    return (a.z < 1.0) ? mix(a, b, c) : a;
}


float SatMask(float color_r, float color_g, float color_b)
{
    float max_rgb = max(color_r, max(color_g, color_b));
    float min_rgb = min(color_r, min(color_g, color_b));
    float msk = clamp((max_rgb - min_rgb) / (max_rgb + min_rgb), 0.0, 1.0);
    return msk;
}


float moncurve_r( float color, float gamma, float offs)
{
    // Reverse monitor curve
    color = clamp(color, 0.0, 1.0);
    float yb = pow( offs * gamma / ( ( gamma - 1.0) * ( 1.0 + offs)), gamma);
    float rs = pow( ( gamma - 1.0) / offs, gamma - 1.0) * pow( ( 1.0 + offs) / gamma, gamma);

    color = ( color > yb) ? ( 1.0 + offs) * pow( color, 1.0 / gamma) - offs : color * rs;
    return color;
}


vec3 moncurve_r_f3( vec3 color, float gamma, float offs)
{
    color.r = moncurve_r( color.r, gamma, offs);
    color.g = moncurve_r( color.g, gamma, offs);
    color.b = moncurve_r( color.b, gamma, offs);
    return color.rgb;
}


float moncurve_f( float color, float gamma, float offs)
{
    // Forward monitor curve
    color = clamp(color, 0.0, 1.0);
    float fs = (( gamma - 1.0) / offs) * pow( offs * gamma / ( ( gamma - 1.0) * ( 1.0 + offs)), gamma);
    float xb = offs / ( gamma - 1.0);

    color = ( color > xb) ? pow( ( color + offs) / ( 1.0 + offs), gamma) : color * fs;
    return color;
}

vec3 moncurve_f_f3( vec3 color, float gamma, float offs)
{
    color.r = moncurve_f( color.r, gamma, offs);
    color.g = moncurve_f( color.g, gamma, offs);
    color.b = moncurve_f( color.b, gamma, offs);
    return color.rgb;
}


//  Performs better in gamma encoded space
float contrast_sigmoid(float color, float cont, float pivot){

    cont = pow(cont + 1., 3.);

    float knee = 1. / (1. + exp(cont * pivot));
    float shldr = 1. / (1. + exp(cont * (pivot - 1.)));

    color = (1. / (1. + exp(cont * (pivot - color))) - knee) / (shldr - knee);

    return color;
}


//  Performs better in gamma encoded space
float contrast_sigmoid_inv(float color, float cont, float pivot){

    cont = pow(cont - 1., 3.);

    float knee = 1. / (1. + exp (cont * pivot));
    float shldr = 1. / (1. + exp (cont * (pivot - 1.)));

    color = pivot - log(1. / (color * (shldr - knee) + knee) - 1.) / cont;

    return color;
}



void main()
{

//  Pure power was crushing blacks (eg. DKC2). You can mimic pow(c, 2.4) by raising the gamma_in value to 2.55
    vec3 imgColor = texture(Source, vTexCoord.xy).rgb;
    imgColor = (params.gamma_type == 1.0) ? moncurve_f_f3(imgColor, params.gamma_in + 0.15, 0.055) : pow(imgColor, vec3(params.gamma_in));


//  Saturation agnostic sigmoidal contrast
    vec3 Yxy = XYZtoYxy(sRGB_to_XYZ(imgColor));
    float toLinear = moncurve_r(Yxy.r, 2.40, 0.055);
    float sigmoid = (params.cntrst > 0.0) ? contrast_sigmoid(toLinear, params.cntrst, params.mid) : contrast_sigmoid_inv(toLinear, params.cntrst, params.mid);
    vec3 contrast = vec3(moncurve_f(sigmoid, 2.40, 0.055), Yxy.g, Yxy.b);
    vec3 XYZsrgb = clamp(XYZ_to_sRGB(YxytoXYZ(contrast)), 0.0, 1.0);
    contrast = (params.cntrst == 0.0) ? imgColor : XYZsrgb;


//  Vignetting & Black Level
    vec2 vpos = vTexCoord*(global.OriginalSize.xy/global.SourceSize.xy);

    vpos *= 1.0 - vpos.xy;
    float vig = vpos.x*vpos.y * params.str;
    vig = min(pow(vig, params.power), 1.0);
    contrast *= (params.vignette == 1.0) ? vig : 1.0;

    contrast += (params.black_level / 20.0) * (1.0 - contrast);


//  RGB related transforms
    vec4 screen = vec4(max(contrast, 0.0), 1.0);
    float sat = params.sat + 1.0;

                   //  r               g           b  alpha ; alpha does nothing for our purposes
    mat4 color = mat4(params.r, params.rg,  params.rb,  0.0,  //red tint
                     params.gr,  params.g,  params.gb,  0.0,  //green tint
                     params.br, params.bg,   params.b,  0.0,  //blue tint
                    params.blr, params.blg, params.blb, 0.0); //black tint

    mat4 adjust = mat4((1.0 - sat) * 0.2126 + sat, (1.0 - sat) * 0.2126, (1.0 - sat) * 0.2126, 1.0,
                       (1.0 - sat) * 0.7152, (1.0 - sat) * 0.7152 + sat, (1.0 - sat) * 0.7152, 1.0,
                       (1.0 - sat) * 0.0722, (1.0 - sat) * 0.0722, (1.0 - sat) * 0.0722 + sat, 1.0,
                        0.0, 0.0, 0.0, 1.0);

    screen = clamp(screen * ((params.lum - 1.0) * 2.0 + 1.0), 0.0, 1.0);
    screen = color * screen;
    float sat_msk = (params.dulvibr > 0.0) ? clamp(1.0 - (SatMask(screen.r, screen.g, screen.b) * params.dulvibr), 0.0, 1.0) : clamp(1.0 - abs(SatMask(screen.r, screen.g, screen.b) - 1.0) * abs(params.dulvibr), 0.0, 1.0);
    screen = mixfix_v4(screen, adjust * screen, sat_msk);


//  Color Temperature
    vec3 adjusted = wp_adjust(screen.rgb);
    vec3 base_luma = XYZtoYxy(sRGB_to_XYZ(screen.rgb));
    vec3 adjusted_luma = XYZtoYxy(sRGB_to_XYZ(adjusted));
    adjusted = (params.luma_preserve == 1.0) ? adjusted_luma + (vec3(base_luma.r, 0.0, 0.0) - vec3(adjusted_luma.r, 0.0, 0.0)) : adjusted_luma;
    adjusted = clamp(XYZ_to_sRGB(YxytoXYZ(adjusted)), 0.0, 1.0);


    FragColor = vec4(moncurve_r_f3(adjusted, params.gamma_out + 0.20, 0.055), 1.0);
}
2 Likes

Your good man, you weren’t obligated to do anything anyway.

At least I don’t have to do it now, lol.

Really appreciate this!

1 Like

Thanks again for the shader, looks great from my testing so far. Black level management is much better than in you’re earlier version (less drastic.)

The only thing I was having issues with was the dull/vibrance setting. I wasn’t really noticing any changes… (Maybe I need to take some screenshots for myself to compare it at -1 and 1?)

Looks good though, everything else was working great for me.

EDIT: Does the shader need to be ran with srgb_framebuffer set to true?

1 Like