Universal Shader

AI is what social media was when they first came out. As social media gave the delusion that everyone is famous and important, AI too gives the delusion that everyone can be an assisted doctor, a physiotherapist, a pilot or whatever. It’s success is due to fulfilling people’s secret desires or at least make them feeling it did so.

istockphoto-962352142-170667a

Your attitude isn’t exactly what I’d call constructive. I don’t understand exactly what you’re trying to say with these posts. Criticism for its own sake has also gone out of fashion on forums. What do you want to prove? That Royale or Guest Advanced is better than zfast or mine? I can put my name to that, I assure you. Instead, show us some of your work.

I also remember the dawn of social media and the internet, forums… In the early days, people enjoyed offending and making fun of others, but fortunately today in many forums people work constructively, driven by passion, without annoying people… not in all of them… You remind me a lot of the early days, it seems to me that you haven’t made the leap.

1 Like

I wonder what kind of shader support an AI assisted human could give to a non AI assisted human when the AI assisted human has no clue what’s going on under the hood.

I honestly imagine him just like an echo/repeater who forwards support requests to the LLM and back without even being able to verify the correctness of the answers.

I am not stating this is what it is happening in this particular case, but I’ve the impression it is. At least to a certain extent.

Wouldn’t it be better to use LLMs to learn how to code and gain the knowledge to create something really new?

Coding shaders by scratch is fun and immediately rewarding, try it!

2 Likes

I don’t have a “programmer’s card,” I don’t have an MIT degree. I think you’re asking far more questions about me as a person than about what I do. Am I not worthy of being here? Don’t I have the right? What are your concerns?

Don’t get me wrong.

I’m expressing my subjective opinion and personal doubts, not trying to enforce it/them to you nor anyone else.

Everybody can learn how to code a glsl shader, I did without a MIT degree and it was a fun process when LLM weren’t even a thing. Now it would be even easier; hence my suggestion to just try.

If not for anything else, it would gain you the ability to give the shader a proper support.

2 Likes

Your point is correct and I agree. It would be really interesting, but I imagine it would take a long time to learn most of the features. Mine is a shortcut. To be honest, I didn’t think relying on the AI ​​would be a problem, really. I thought they’d be more interested in my shader preset than in what’s around it. That said, it’s good advice; I’ll keep it in mind and try it.

1 Like

You can rest assured i have spend so many thousands of hours into code i see lines passing in front of me like damn Neo in Matrix Revolutions. I probably spend 1.000 hours studying NTSC alone before writing a single line.

2 Likes

This is what I mean…and I love it…

It is time to address the misconception that utilizing modern development tools equates to a lack of understanding or creativity.

In truth, much of software development—including shader design—involves iterating on established concepts. Innovation is often subjective, and the core principles of technologies like CRT emulation remain constant, regardless of the writing method.

AI functions not as a creator, but as a high-speed engine for handling the technical implementation and syntax. The vision, intent, and creative direction remain firmly in human hands. Utilizing AI is no more ‘random’ than utilizing a specialized library, compiler, or IDE; it is simply a more efficient way to translate conceptual ideas into functional code.

Labeling users of these tools as ‘parrots’ or ‘repeaters’ is not only inaccurate but also overlooks the professional shift happening across the industry. The tech world is moving toward an era where major game studios and professional developers integrate AI to accelerate complex workflows. When an articulated vision can be executed efficiently, spending hours on manual syntax often becomes an inefficiency rather than a mark of quality.

Ultimately, contribution and innovation are defined by results. Whether code is written manually or realized through acceleration, the priority remains the quality of the end product and the user experience. The focus belongs on the efficacy of the shader itself, rather than the methodology of its creation.

1 Like

True, the input on what to do always comes from humans. Unfortunately, I’m not a natural programmer… But I get ideas on how to represent them. I even thought about and tried a lockUP table to manage the size of the phosphors… I managed to get it to work, but in the end it wasn’t the best… I tried many and rejected even more…

True, the input on what to do always comes from humans. Unfortunately, I’m not a natural programmer… But I get ideas on how to represent them. I even thought about and tried a lockUP table to manage the size of the phosphors… I managed to get it to work, but in the end it wasn’t the best… I tried many and rejected even more… Even if I wouldn’t beatify it for certain things, the use I make of it in the retro game sector, and not just on shaders, has certainly changed and speeded up the way I work. Certainly, I never even dreamed of doing certain things before… I understand and respect real programmers who write code, of course… I don’t even want to put myself on their level. They’re professionals, I just enjoy it.

1 Like

I’m glad you mentioned that because I’m in the exact same boat. It’s been a total game-changer for me as well.

Honestly, the most rewarding part isn’t just the final output; it’s the learning curve. I’ve reached a point where I can now successfully port logic and techniques from one shader to another, which is something I couldn’t have dreamed of doing before.

The ironic part is that the AI has actually been a better tutor than people. It’s taught me concepts that I had asked human ‘experts’ about in the past—only to be ignored or dismissed. Having an accessible way to learn while building has allowed me to speed up my workflow significantly. I’m right there with you; it’s an incredible accelerator that’s allowed me to translate my ideas into reality much faster than ever before

Hand-coded developers certainly deserve our full respect and appreciation, and in fact, we are learning from them. Even if some of them attack me, I still hold them in high regard

First error, apply saturation at the end of image-adjustment.glsl.

Before/After the correction, max value 2.0. Before was altering hue

// Shader per regolazione gamma, luminosita, contrasto e saturazione
// Compatibile con RetroArch OpenGL - Parametri integrati

#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

uniform mat4 MVPMatrix;
COMPAT_ATTRIBUTE vec4 VertexCoord;
COMPAT_ATTRIBUTE vec4 TexCoord;
COMPAT_VARYING vec4 TEX0;

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;
    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 sampler2D Texture;
COMPAT_VARYING vec4 TEX0;

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;

// Parametri regolabili con #pragma
#pragma parameter BOGUS_IMG_ADJUST "---------------IMAGE ADJUSTMENT---------------" 0.0 0.0 0.0 0.0
#pragma parameter GAMMA "Gamma Correction" 1.0 0.5 2.5 0.10
#pragma parameter BRIGHTNESS "Brightness" 0.0 -1.0 1.0 0.025
#pragma parameter CONTRAST "Contrast" 1.0 0.5 2.0 0.10
#pragma parameter SATURATION "Saturation" 1.0 0.0 2.0 0.10

// Dichiarazione delle variabili uniform basate sui pragma
uniform COMPAT_PRECISION float GAMMA;
uniform COMPAT_PRECISION float BRIGHTNESS;
uniform COMPAT_PRECISION float CONTRAST;
uniform COMPAT_PRECISION float SATURATION;

// Funzione per regolare il contrasto
vec3 adjustContrast(vec3 color, float value) {
    return clamp(((color - 0.5) * max(value, 0.0)) + 0.5, 0.0, 1.0);
}

// Funzione per regolare la saturazione
vec3 adjustSaturation(vec3 color, float value) {
    // Calcola l'intensita luminosa (formula standard per la luminosita)
    float luminance = dot(color, vec3(0.299, 0.587, 0.114));
    
    // Interpola tra il colore in scala di grigi e il colore originale
    return mix(vec3(luminance), color, value);
}

void main()
{
    // Campiona il colore originale dalla texture
    vec4 originalColor = COMPAT_TEXTURE(Texture, TEX0.xy);
    vec3 color = originalColor.rgb;
    
    // Applica la luminosita (aggiunge/sottrae valore a tutti i canali)
    color += BRIGHTNESS;
    
    // Applica il contrasto
    color = adjustContrast(color, CONTRAST);
    

    // Applica la correzione gamma
    color = pow(color, vec3(1.0 / GAMMA));
    
    // Assicura che i valori rimangano nell'intervallo [0, 1]
    color = clamp(color, 0.0, 1.0);
    
    // Applica la saturazione
    color = adjustSaturation(color, SATURATION);

    FragColor = vec4(color, originalColor.a);
}
#endif
2 Likes

Thank’s a lot @DariusG. It’s not a small oversight. I respect programmers. The human eye sees beyond. The colors are noticeably more vivid.

2nd error, a massive one. In Candy-bloom.glsl

That divide by MaxRGB will boost all dark colors massively as a dark color will divide by e.g. 0.1 and skyrocket it’s value. MinRGB isn’t used at all. Absolute mess, better erase and replace with a simple boost dark / boost bright. PassPrev3Texture is declared as “candy_ref” texture, but there is no 3rd previous texture at all.

void main()
{
	vec3 Picture = COMPAT_TEXTURE(Source, vTexCoord).xyz;

    float MaxRGB       = max(Picture.x, max(Picture.y, Picture.z));
    float MinRGB       = min(Picture.x, min(Picture.y, Picture.z));

    float YIQLuminance = ((0.299*Picture.x) + (0.587*Picture.y) + (0.114*Picture.z));
    
    
    Picture /= MaxRGB;
    Picture = clamp(Picture,0.0,1.0);
    
    
    FragColor = vec4(mix(COMPAT_TEXTURE(candy_ref, vTexCoord).xyz, Picture, mix(1.-pow(1.-YIQLuminance,2.0),YIQLuminance*YIQLuminance,GlowTightness)*GlowLevel),1.0);
}

More Proper code

// CRT-torridgristle - Candy Bloom
// license: public domain

#pragma parameter BOGUS_CANDY_BLOOM "------------------CANDY BLOOM------------------" 0.0 0.0 0.0 0.0
#pragma parameter GlowLevel "Glow Level" 1.15 1.0 1.5 0.05
#pragma parameter GlowTightness "Glow Tightness" 0.75 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;

vec4 _oPosition1; 
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;

// compatibility #defines
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

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

#elif defined(FRAGMENT)

#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

#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out COMPAT_PRECISION vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#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;
uniform sampler2D PassPrev3Texture;
COMPAT_VARYING vec4 TEX0;

// 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
uniform COMPAT_PRECISION float GlowLevel, GlowTightness;
#else
#define GlowLevel 1.25
#define GlowTightness 0.75
#endif

void main()
{
	vec3 Picture = COMPAT_TEXTURE(Source, vTexCoord).xyz;

    float MaxRGB       = max(Picture.x, max(Picture.y, Picture.z));
    float MinRGB       = min(Picture.x, min(Picture.y, Picture.z));

    float YIQLuminance = dot(vec3(0.3,0.6,0.1),Picture);
        
    FragColor = vec4(mix(Picture*GlowTightness, Picture*GlowLevel,YIQLuminance),1.0);
} 
#endif
1 Like

I’ve not stated that “utilizing modern development tools equates to a lack of understanding or creativity”, so it is not clear why you are answering that to me.

Wasn’t this clear enough?

“I am not stating this is what it is happening in this particular case, but I’ve the impression it is. At least to a certain extent.”

In “this particular case” I was right, since aurunmilla effectively lacks programming skills, so we were discussing further from given facts about some concerns on the shader support a “vibe coder” could ever give to users.

I agree that iterating on established concepts is the common way of developing software; but this does not imply it is the best way to handle it; reinventing the wheel from scratch rather than reiterating the common way of rounding squares to make them circles may produce unexpected results, may produce a rounder wheel never seen before.

That’s the innovation I personally pursue, try see the world with the eye of a child and try make wonderful new things out of nowhere, but It is a skill reserved to blank minds not yet tainted by “established common ways of doing things” => An inexperienced coder is the perfect candidate, so I’d take the chance!

Final note, let’s stop calling LLM AIs; they are not. It is important to distinguish between them, because it highlights what kind of answers you can expect out of them; LLMs will extrapolate knowledge out of documents they were trained on; it can never be innovative, by design.

It’s a tool which is too much often misused.

I totally agree with that instead, using LLM to learn looks like a genuine use to me,but the learning should start from the basic, to avoid risking learning “AI allucinations” due to the lack of knowledge.

3rd amendment, film_grain.glsl, in reality a Deconvergence with Film Grain. Reduced previously massive values of deconvergence and film grain to a more pleasant end result. Moving on to next pass

#version 130
// film noise
// by hunterk
// license: public domain

// Parameter lines go here:
#pragma parameter BOGUS_FILM_NOISE "-------------------CONVERG./FILM NOISE-------------------" 0.0 0.0 0.0 0.0
#pragma parameter x_off_r "Conv. X Offset Red" 0.05 -1.0 1.0 0.01
#pragma parameter y_off_r "Conv. Y Offset Red" 0.0 -1.0 1.0 0.01
#pragma parameter x_off_g "Conv. X Offset Green" -0.0 -1.0 1.0 0.01
#pragma parameter y_off_g "Conv. Y Offset Green" -0.05 -1.0 1.0 0.01
#pragma parameter x_off_b "Conv. X Offset Blue" -0.05 -1.0 1.0 0.01
#pragma parameter y_off_b "Conv. Y Offset Blue" 0.0 -1.0 1.0 0.01
#pragma parameter grain_str "Grain Strength" 2.0 0.0 16.0 0.5

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

vec4 _oPosition1; 
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;

// compatibility #defines
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

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

#elif defined(FRAGMENT)

#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

#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out COMPAT_PRECISION vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#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;

// 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
uniform COMPAT_PRECISION float x_off_r;
uniform COMPAT_PRECISION float y_off_r;
uniform COMPAT_PRECISION float x_off_g;
uniform COMPAT_PRECISION float y_off_g;
uniform COMPAT_PRECISION float x_off_b;
uniform COMPAT_PRECISION float y_off_b;
uniform COMPAT_PRECISION float grain_str;
#else
#define x_off_r 0.05
#define y_off_r 0.05
#define x_off_g -0.05
#define y_off_g -0.05
#define x_off_b -0.05
#define y_off_b 0.05
#define grain_str 12.0
#endif

//https://www.shadertoy.com/view/4sXSWs strength= 16.0
float filmGrain(vec2 uv, float strength, float timer ){       
    float x = (uv.x + 4.0 ) * (uv.y + 4.0 ) * ((mod(timer, 800.0) + 10.0) * 10.0);
	return  (mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01)-0.005) * strength;
}

float hash( float n ){
    return fract(sin(n)*43758.5453123);
}

void main()
{

	vec2 red_coord = vTexCoord + 0.01 * vec2(x_off_r, y_off_r);
	vec3 red_light = COMPAT_TEXTURE(Source, red_coord).rgb;
	vec2 green_coord = vTexCoord + 0.01 * vec2(x_off_g, y_off_g);
	vec3 green_light = COMPAT_TEXTURE(Source, green_coord).rgb;
	vec2 blue_coord = vTexCoord + 0.01 * vec2(x_off_b, y_off_b);
	vec3 blue_light = COMPAT_TEXTURE(Source, blue_coord).rgb;

	vec3 film = vec3(red_light.r, green_light.g, blue_light.b);
	film += filmGrain(vTexCoord.xy, grain_str, float(FrameCount)); // Film grain

	FragColor = vec4(film, 1.0);
} 
#endif
1 Like

here there was a simplification of the shader, evidently gone badly… unfortunately, not having the basics of programming, I was unable to criticize the result. thank’You for the fixes

1 Like

Overlay glsl defaults

/*
   Frame Overlay - Curved Sides with Adaptive Rounded Corners
   Author: ChatGPT
   License: MIT
*/

#pragma parameter BOGUS_OVERLAY "-----------------FRAME OVERLAY-----------------" 0.0 0.0 0.0 0.0
#pragma parameter OVERLAY_ENABLE "Enable Frame" 1.0 0.0 1.0 1.0
#pragma parameter FRAME_SIZE "Frame Size %" 2.0 0.0 10.0 0.25
#pragma parameter CURVE_AMOUNT "Curve Amount" 0.5 0.0 1.0 0.05
#pragma parameter CORNER_RADIUS "Corner Radius %" 50.0 0.0 25.0 5.0
#pragma parameter FADE_WIDTH "Fade Width %" 40.0 0.0 100.0 5.0
#pragma parameter FADE_CURVE "Fade Curve" 2.0 0.0 15.0 1.0

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

#define Source Texture
#define vTexCoord TEX0.xy
#define texture(c, d) COMPAT_TEXTURE(c, d)

#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float OVERLAY_ENABLE;
uniform COMPAT_PRECISION float FRAME_SIZE;
uniform COMPAT_PRECISION float CURVE_AMOUNT;
uniform COMPAT_PRECISION float CORNER_RADIUS;
uniform COMPAT_PRECISION float FADE_WIDTH;
uniform COMPAT_PRECISION float FADE_CURVE;
#else
#define OVERLAY_ENABLE 1.0
#define FRAME_SIZE 2.0
#define CURVE_AMOUNT 0.5
#define CORNER_RADIUS 50.0
#define FADE_WIDTH 0.0
#define FADE_CURVE 2.0
#endif

// Funzione di curva potenziata
float apply_fade_curve(float t, float curve_power) {
    t = clamp(t, 0.0, 1.0);
    
    if (curve_power <= 0.0) {
        return t; // Lineare
    } else if (curve_power <= 1.0) {
        // Da lineare a quadratico
        return mix(t, t * t, curve_power);
    } else if (curve_power <= 2.0) {
        // Da quadratico a cubico
        return mix(t * t, t * t * t, curve_power - 1.0);
    } else if (curve_power <= 3.0) {
        // Da cubico a quartico
        float cubic = t * t * t;
        float quartic = t * t * t * t;
        return mix(cubic, quartic, curve_power - 2.0);
    } else {
        // Potenza elevata per curve molto pronunciate
        float power = 1.0 + (curve_power - 3.0) * 2.0; // Da 1 a 5
        return pow(t, power);
    }
}

void main()
{
    vec4 color = texture(Source, vTexCoord);
    
    if (OVERLAY_ENABLE > 0.5) {
        vec2 pixel_pos = gl_FragCoord.xy;
        
        // 1. CALCOLA LA FORMA BASE DELLA CORNICE
        
        // Spessore cornice in pixel
        float frame_thickness = (FRAME_SIZE / 100.0) * min(OutputSize.x, OutputSize.y);
        
        // Raggio angoli in pixel
        float min_dimension = min(OutputSize.x, OutputSize.y);
        float corner_radius = (CORNER_RADIUS / 100.0) * min_dimension * 0.1;
        
        // Limita il raggio massimo
        float max_possible_radius = min(OutputSize.x, OutputSize.y) * 0.25;
        corner_radius = min(corner_radius, max_possible_radius);
        corner_radius = max(corner_radius, 1.0);
        
        // Definisci l'area base dell'immagine (rettangolo interno)
        float base_left = frame_thickness;
        float base_right = OutputSize.x - frame_thickness;
        float base_top = frame_thickness;
        float base_bottom = OutputSize.y - frame_thickness;
        
        // 2. CALCOLA LA FORMA CON CURVATURA
        
        // Inizializza i bordi curvi come quelli base
        float curved_left = base_left;
        float curved_right = base_right;
        float curved_top = base_top;
        float curved_bottom = base_bottom;
        
        // Applica la curvatura ai lati
        if (CURVE_AMOUNT > 0.0) {
            float curve_strength = CURVE_AMOUNT * frame_thickness;
            
            // Calcola la posizione normalizzata lungo i bordi
            float norm_x = (pixel_pos.x - base_left) / (base_right - base_left);
            float norm_y = (pixel_pos.y - base_top) / (base_bottom - base_top);
            norm_x = clamp(norm_x, 0.0, 1.0);
            norm_y = clamp(norm_y, 0.0, 1.0);
            
            // Curva parabolica (massimo al centro, zero agli estremi)
            float curve_x = 4.0 * norm_x * (1.0 - norm_x);
            float curve_y = 4.0 * norm_y * (1.0 - norm_y);
            
            // Applica curvatura ai bordi
            curved_left = base_left - curve_y * curve_strength;
            curved_right = base_right + curve_y * curve_strength;
            curved_top = base_top - curve_x * curve_strength;
            curved_bottom = base_bottom + curve_x * curve_strength;
        }
        
        // 3. DETERMINA LA DISTANZA DAL BORDO
        
        float distance_to_edge = 0.0;
        
        // Prima controlla gli angoli arrotondati
        bool in_corner_area = false;
        
        // Angolo alto-sinistra
        if (pixel_pos.x < base_left + corner_radius && pixel_pos.y < base_top + corner_radius) {
            in_corner_area = true;
            vec2 corner_center = vec2(base_left + corner_radius, base_top + corner_radius);
            float corner_distance = distance(pixel_pos, corner_center);
            distance_to_edge = corner_radius - corner_distance;
        }
        // Angolo alto-destra
        else if (pixel_pos.x > base_right - corner_radius && pixel_pos.y < base_top + corner_radius) {
            in_corner_area = true;
            vec2 corner_center = vec2(base_right - corner_radius, base_top + corner_radius);
            float corner_distance = distance(pixel_pos, corner_center);
            distance_to_edge = corner_radius - corner_distance;
        }
        // Angolo basso-sinistra
        else if (pixel_pos.x < base_left + corner_radius && pixel_pos.y > base_bottom - corner_radius) {
            in_corner_area = true;
            vec2 corner_center = vec2(base_left + corner_radius, base_bottom - corner_radius);
            float corner_distance = distance(pixel_pos, corner_center);
            distance_to_edge = corner_radius - corner_distance;
        }
        // Angolo basso-destra
        else if (pixel_pos.x > base_right - corner_radius && pixel_pos.y > base_bottom - corner_radius) {
            in_corner_area = true;
            vec2 corner_center = vec2(base_right - corner_radius, base_bottom - corner_radius);
            float corner_distance = distance(pixel_pos, corner_center);
            distance_to_edge = corner_radius - corner_distance;
        }
        
        // Se non siamo in un angolo, calcola distanza dai lati curvi
        if (!in_corner_area) {
            float dist_left = pixel_pos.x - curved_left;
            float dist_right = curved_right - pixel_pos.x;
            float dist_top = pixel_pos.y - curved_top;
            float dist_bottom = curved_bottom - pixel_pos.y;
            
            distance_to_edge = min(min(dist_left, dist_right), min(dist_top, dist_bottom));
        }
        
        // 4. APPLICA LA SFUMATURA CON CENTRO SPOSTATO VERSO L'INTERNO
        
        if (FADE_WIDTH > 0.0) {
            // Calcola la larghezza totale della sfumatura
            float total_fade_width = (FADE_WIDTH / 100.0) * frame_thickness;
            
            // Calcola quanto il nero penetra nell'immagine
            // Con FADE_WIDTH = 100%, il nero penetra quanto e spessa la cornice
            // Con FADE_WIDTH = 200%, il nero penetra il doppio
            float black_penetration = total_fade_width * 0.7; // 70% della larghezza e nero che penetra
            
            // La zona di transizione completa (nero che sfuma a immagine)
            float full_transition = total_fade_width;
            
            // Se siamo completamente nella cornice (nero pieno)
            if (distance_to_edge <= -black_penetration) {
                color.rgb = vec3(0.0);
            }
            // Se siamo nella zona di transizione
            else if (distance_to_edge < (full_transition - black_penetration)) {
                // Calcola la posizione nella transizione
                // 0.0 = inizio transizione (bordo esterno del nero)
                // 1.0 = fine transizione (immagine piena)
                float transition_pos = 0.0;
                
                // Sposta il centro del fade verso l'interno
                float adjusted_distance = distance_to_edge + black_penetration;
                
                if (adjusted_distance < 0.0) {
                    // Nella parte di nero che penetra
                    transition_pos = (adjusted_distance + black_penetration) / (black_penetration * 2.0);
                } else {
                    // Nella parte di sfumatura verso l'immagine
                    transition_pos = 0.5 + (adjusted_distance / (full_transition * 2.0));
                }
                
                transition_pos = clamp(transition_pos, 0.0, 1.0);
                
                // APPLICA LA CURVA DEL FADE - ORA MOLTO PIU EVIDENTE!
                float curve_value = apply_fade_curve(transition_pos, FADE_CURVE);
                
                // Calcola l'intensita del nero
                // Inverti: piu alta la curva, meno nero nell'immagine
                float black_intensity = 1.0 - curve_value;
                
                // Aggiusta per un fade piu naturale
                black_intensity = clamp(black_intensity, 0.0, 1.0);
                
                // Se siamo nella cornice, assicurati che ci sia almeno un po' di nero
                if (distance_to_edge < 0.0) {
                    black_intensity = max(black_intensity, 0.3);
                }
                
                // Applica la sfumatura con effetto piu pronunciato
                color.rgb = mix(color.rgb, vec3(0.0), black_intensity);
            }
            // Altrimenti: siamo completamente nell'immagine
        } else {
            // Senza sfumatura: transizione netta alla cornice base
            if (distance_to_edge < 0.0) {
                color.rgb = vec3(0.0);
            }
        }
    }
    
    FragColor = color;
}
#endif

final film_grain.glsl (raising Y will blur hell of a lot)

#version 130
// film noise
// by hunterk
// license: public domain

// Parameter lines go here:
#pragma parameter BOGUS_FILM_NOISE "-------------------CONVERG./FILM NOISE-------------------" 0.0 0.0 0.0 0.0
#pragma parameter x_off_r "Conv. X Offset Red" 0.05 -1.0 1.0 0.01
#pragma parameter y_off_r "Conv. Y Offset Red" 0.0 -1.0 1.0 0.01
#pragma parameter x_off_g "Conv. X Offset Green" -0.0 -1.0 1.0 0.01
#pragma parameter y_off_g "Conv. Y Offset Green" -0.0 -1.0 1.0 0.01
#pragma parameter x_off_b "Conv. X Offset Blue" -0.05 -1.0 1.0 0.01
#pragma parameter y_off_b "Conv. Y Offset Blue" 0.0 -1.0 1.0 0.01
#pragma parameter grain_str "Grain Strength" 2.0 0.0 16.0 0.5

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

vec4 _oPosition1; 
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;

// compatibility #defines
#define vTexCoord TEX0.xy
#define SourceSize vec4(TextureSize, 1.0 / TextureSize) //either TextureSize or InputSize
#define OutSize vec4(OutputSize, 1.0 / OutputSize)

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

#elif defined(FRAGMENT)

#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

#if __VERSION__ >= 130
#define COMPAT_VARYING in
#define COMPAT_TEXTURE texture
out COMPAT_PRECISION vec4 FragColor;
#else
#define COMPAT_VARYING varying
#define FragColor gl_FragColor
#define COMPAT_TEXTURE texture2D
#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;

// 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
uniform COMPAT_PRECISION float x_off_r;
uniform COMPAT_PRECISION float y_off_r;
uniform COMPAT_PRECISION float x_off_g;
uniform COMPAT_PRECISION float y_off_g;
uniform COMPAT_PRECISION float x_off_b;
uniform COMPAT_PRECISION float y_off_b;
uniform COMPAT_PRECISION float grain_str;
#else
#define x_off_r 0.05
#define y_off_r 0.05
#define x_off_g -0.05
#define y_off_g -0.05
#define x_off_b -0.05
#define y_off_b 0.05
#define grain_str 12.0
#endif

//https://www.shadertoy.com/view/4sXSWs strength= 16.0
float filmGrain(vec2 uv, float strength, float timer ){       
    float x = (uv.x + 4.0 ) * (uv.y + 4.0 ) * ((mod(timer, 800.0) + 10.0) * 10.0);
	return  (mod((mod(x, 13.0) + 1.0) * (mod(x, 123.0) + 1.0), 0.01)-0.005) * strength;
}

float hash( float n ){
    return fract(sin(n)*43758.5453123);
}

void main()
{

	vec2 red_coord = vTexCoord + 0.01 * vec2(x_off_r, y_off_r);
	vec3 red_light = COMPAT_TEXTURE(Source, red_coord).rgb;
	vec2 green_coord = vTexCoord + 0.01 * vec2(x_off_g, y_off_g);
	vec3 green_light = COMPAT_TEXTURE(Source, green_coord).rgb;
	vec2 blue_coord = vTexCoord + 0.01 * vec2(x_off_b, y_off_b);
	vec3 blue_light = COMPAT_TEXTURE(Source, blue_coord).rgb;

	vec3 film = vec3(red_light.r, green_light.g, blue_light.b);
	film += filmGrain(vTexCoord.xy, grain_str, float(FrameCount)); // Film grain

	FragColor = vec4(film, 1.0);
} 
#endif

final dotmask.glsl with true scanlines and adjustable mask

/*
   CRT - Clean Subpixel RGB/BGR Mask with Arcade Scanlines
*/
#pragma parameter BOGUS_DOTMASK "--------- CRT SCANLINES & SUBPIXEL MASK ---------" 0.0 0.0 0.0 0.0

// SCANLINE CONTROLS
#pragma parameter SCAN_LOW "Scanline Intensity (Dark Scenes)" 0.8 0.0 1.0 0.05
#pragma parameter SCAN_HIGH "Scanline Intensity (Bright Scenes)" 0.3 0.0 1.0 0.05

// MASK CONTROLS
#pragma parameter DOTMASK_STRENGTH "Mask Strength" 0.3 0.0 1.0 0.05
#pragma parameter MASK_LIGHT "Mask Light" 1.50 0.0 3.0 0.05
#pragma parameter MASK_DARK  "Mask Dark"  0.50 0.0 3.0 0.05
#pragma parameter SUBPIXEL_LAYOUT "Subpixel Layout (0=RGB, 1=BGR)" 0.0 0.0 1.0 1.0

#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;
COMPAT_VARYING vec2 ogl2pos;

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;
    ogl2pos = TEX0.xy*TextureSize.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;
COMPAT_VARYING vec2 ogl2pos;

#define Source Texture
#define vTexCoord TEX0.xy
#define texture(c, d) COMPAT_TEXTURE(c, d)

#define tau 6.283185307179586

#ifdef PARAMETER_UNIFORM
uniform COMPAT_PRECISION float SCAN_LOW;
uniform COMPAT_PRECISION float SCAN_HIGH;
uniform COMPAT_PRECISION float DOTMASK_STRENGTH;
uniform COMPAT_PRECISION float MASK_LIGHT;
uniform COMPAT_PRECISION float MASK_DARK;
uniform COMPAT_PRECISION float SUBPIXEL_LAYOUT;
#else
#define SCAN_LOW 0.8
#define SCAN_HIGH 0.3
#define MASK_LIGHT 1.5
#define MASK_DARK 0.5
#define DOTMASK_STRENGTH 0.3
#define SUBPIXEL_LAYOUT 0.0
#endif

vec3 SimpleSubpixelMask(vec2 fragCoord) {
    vec3 mask = vec3(MASK_DARK);
    
    // Cycle every 3 screen pixels horizontally
    float pos_x = fract(fragCoord.x * 0.333333333);

    if (SUBPIXEL_LAYOUT > 0.5) {
        // BGR Layout
        if      (pos_x < 0.3333) mask.b = MASK_LIGHT;
        else if (pos_x < 0.6666) mask.g = MASK_LIGHT;
        else                     mask.r = MASK_LIGHT;
    } else {
        // RGB Layout
        if      (pos_x < 0.3333) mask.r = MASK_LIGHT;
        else if (pos_x < 0.6666) mask.g = MASK_LIGHT;
        else                     mask.b = MASK_LIGHT;
    }
    
    return mask;
}

void main()
{
    float near = floor(ogl2pos.y)+0.5;
    float f = ogl2pos.y - near;
    float y = (near + 4.0*f*f*f)/TextureSize.y;
    vec2 pos = vec2(vTexCoord.x, y);
    vec3 pixelColor = texture(Source, pos).rgb;
    float lum = dot(vec3(0.3),pixelColor);
    // --- ARCADE SCANLINE CALCULATION ---
    float l = max(max(pixelColor.r, pixelColor.g), pixelColor.b);
    float infl = mix(SCAN_LOW, SCAN_HIGH, l);
    float scan = infl * sin((vTexCoord.y * TextureSize.y-0.25) * tau);
    vec3 scanlineColor = pixelColor + (pixelColor * scan);
    
    // --- CLEAN SUBPIXEL RGB/BGR MASK ---
    vec3 maskStructure = SimpleSubpixelMask(gl_FragCoord.xy);
    vec3 finalMask = mix(vec3(1.0), maskStructure, mix(DOTMASK_STRENGTH*2.0, DOTMASK_STRENGTH, lum));
    
    // Combine scanlines and mask
    vec3 finalColor = scanlineColor * finalMask;
    
    FragColor = vec4(finalColor, 1.0);
}
#endif

final universal.glslp should be in “shaders”

shaders = "5"
shader0 = "shaders_glsl/Universal/shaders/image-adjustment.glsl"

shader1 = "shaders_glsl/Universal/shaders/Candy-Bloom.glsl"
filter_linear1 = "true"
scale_type_x1 = "source"
scale_x1 = "1.000000"
scale_type_y1 = "source"
scale_y1 = "1.000000"
shader2 = "shaders_glsl/Universal/shaders/film_noise.glsl"
filter_linear2 = "true"
scale_type_x2 = "source"
scale_x2 = "1.000000"
scale_type_y2 = "source"
scale_y2 = "1.000000"
shader3 = "shaders_glsl/Universal/shaders/overlay.glsl"
filter_linear3 = "true"
scale_type_x3 = "source"
scale_x3 = "1.000000"
scale_type_y3 = "source"
scale_y3 = "1.000000"
shader4 = "shaders_glsl/Universal/shaders/dotmask.glsl"
filter_linear4 = "true"

end result, still on 27-28% on HD630, less than before (35%)

1 Like

Let’s analyze this objectively, free from emotion. What distinguishes a great shader from a ‘stupid’ one? Isn’t it about the absence of errors, precision, and speed? If we produce a shader that fulfills the requirements, delivers satisfying visual quality, and runs at lightning speed—isn’t that a success?

Secondly, why should I burden myself with learning everything from scratch when it is sufficient for me to observe my Toshiba TV or my Dell CRT monitor to understand the physics, the image, and the CRT overlay, and then translate that into functional equations for the emulator? Isn’t that also a success?

The point I am making is that there are multiple paths to reach a goal. It is not a matter of whether a method is ‘right’ or ‘wrong’; what truly matters is: am I satisfied with my work? Have I successfully brought what was in my mind to life?

I have never infringed upon the work of manual shader programmers. On the contrary, I constantly face unjustified attacks literally just for mentioning AI. If I were seeking fame, I would have erased all mention of AI and claimed all the credit for myself, but I do not want fame.

For context, I created a hack, ‘New Super Mario World by Elsayed,’ which has been downloaded 40,000 times on https://www.romhacking.net/hacks/5540/ and viewed millions of times.

Let me understand… on the dotmask.glsl you replaced the dynamic bars that a subpixel masker… basically it was almost completely rewritten. I also noticed in the preset that you put the bloom before the noise… why? This way the shader noise has much less effect?