NTSC Shaders with curvature (Without Scanlines)

So, I’ve been trying to get the ntsc-256px-svideo.glslp (NES-SNES-N64) and ntsc-320px-svideo.glslp (SG-PSX) to work with curvature, but without any other gamma control or scanline, could someone share a preset of those configured just with a Geom’s like curvature (if possible with the configurable curvature parameters).

try adding antialiasing/shaders/ewa-curvature after it.

Hi! I tried, the whole picture became as it wasn’t any shaders (pixellated).

Works fine here using this preset (place it into your glsl shaders’ ‘presets’ directory):

shaders = 4
shader0 = ../ntsc/shaders/ntsc-pass1-composite-3phase.glsl
shader1 = ../ntsc/shaders/ntsc-pass2-3phase.glsl
shader2 = ../stock.glsl
shader3 = ../anti-aliasing/shaders/ewa_curvature.glsl

filter_linear0 = false
filter_linear1 = false
filter_linear2 = false

scale_type0 = source
scale_x0 = 4.0
scale_y0 = 1.0
frame_count_mod0 = 2
float_framebuffer0 = true

scale_type1 = source
scale_x1 = 0.5
scale_y1 = 1.0

scale_type_x2 = source
scale_type_y2 = viewport
scale2 = 1.0

Thank you for your help, I must be dumb, I put it in the “presets” (glsl shaders directory), but it doesn’t load at all, I do have the glsl shaders updated, and I did check if all the shaders are in the respective folders, I tried to add the directories manually like shader0 = “D:\Retro\shaders\shaders_glsl\ntsc\shaders\ntsc-pass1-composite-3phase.glsl”, same way doesn’t load, I tried then to add ewa_curvature alone, without any other shader, and it doesn’t add curvature to the image (tried linear, nearest and other scales, “don’t care” as well)…

1080ti latest Nvidia Driver just for knowledge.

Do you have the ewa_curvature shader?

Yep, just checked, same code. https://i.imgur.com/XkFgXDpl.png It’s applied, but it doesn’t change the curvature.

Go to Shader Parameters.

I did, there’s none.

Ok, if there’s no parameters, that means the shader isn’t compiling. Must be some driver/compiler-specific nitpick. I’ll try to test it on my Shield later and see. In the meantime, would you mind posting a log of you trying to apply the shader?

If tell me how I do it, no problem.

https://docs.libretro.com/guides/generating-retroarch-logs/

Here we go https://ufile.io/zc3v6

Can you try replacing the contents of ewa_curvature with this:

#version 130

/**
* Practical Elliptical Texture Filtering on the GPU
* Copyright 2010-2011 Pavlos Mavridis, All rights reserved.
*
* Version: 0.6 - 12 / 7 / 2011 (DD/MM/YY)
*/

#pragma parameter distortion "EWA Curvature" 0.2 0.0 1.0 0.05

#define USE_LOD

#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 distortion;
#else
#define distortion 0.2
#endif

//{========= TEXTURE FILTERING (EWA) PARAMETERS =========
#define MAX_ECCENTRICITY 1
#define NUM_PROBES 1
#define FILTER_WIDTH 0.8
#define FILTER_SHARPNESS 1.0
#define TEXELS_PER_PIXEL 1.0
#define TEXEL_LIMIT 32
#define FILTER_FUNC triFilter
//}======================================================

#define M_PI 3.14159265358979323846

#define SourceImage Source

//{========================= FILTER FUNCTIONS =======================
// We only use the Gaussian filter function. The other filters give
// very similar results.
 
float boxFilter(float r2){
    return 1.0;
}
 
float gaussFilter(float r2){
    float alpha = FILTER_SHARPNESS;
    return exp(-alpha * r2);
}
 
float triFilter(float r2){
    float alpha = FILTER_SHARPNESS;
    float r= sqrt(r2);
    return max(0., 1.-r);///alpha);
}
 
float sinc(float x){
    return sin(M_PI*x)/(M_PI*x);
}
 
float lanczosFilter(float r2){
    if (r2==0.)
        return 1.;
    float r= sqrt(r2);
    return sinc(r)*sinc(r/1.3);
}
 
//catmull-rom filter
float crFilter(float r2){
    float r = sqrt(r2);
    return (r>=2.)? 0. :(r<1.)?(3.*r*r2-5.*r2+2.):(-r*r2+5.*r2-8.*r+4.);
}
 
float quadraticFilter(float r2){
    float a = FILTER_SHARPNESS;
    return 1.0 - r2/(a*a);
}
 
float cubicFilter(float r2){
    float a = FILTER_SHARPNESS;
    float r = sqrt(r2);
    return 1.0 - 3.*r2/(a*a) + 2.*r*r2/(a*a*a);
}
//}

//==================== EWA ( reference / 2-tex / 4-tex) ====================
 
/**
*   EWA filter
*   Adapted from an ANSI C implementation from Matt Pharr
*/

vec4 ewaFilter(sampler2D Source, vec2 p0, vec2 du, vec2 dv, float lod, int psize){
#ifdef USE_LOD 
    int scale = psize >> int(lod);
#else
	int scale = psize;
#endif
    vec4 foo = COMPAT_TEXTURE(Source,p0);
   
    //don't bother with elliptical filtering if the scale is very small
    if(scale<2)
        return foo;
	vec2 temp0 = p0;
    temp0 -=vec2(0.5,0.5)/float(scale);
    vec2 p = float(scale) * temp0;
 
    float ux = FILTER_WIDTH * du.s * float(scale);
    float vx = FILTER_WIDTH * du.t * float(scale);
    float uy = FILTER_WIDTH * dv.s * float(scale);
    float vy = FILTER_WIDTH * dv.t * float(scale);
 
    // compute ellipse coefficients
    // A*x*x + B*x*y + C*y*y = F.
    float A = vx*vx+vy*vy+1.;
    float B = -2.*(ux*vx+uy*vy);
    float C = ux*ux+uy*uy+1.;
    float F = A*C-B*B/4.;
 
    // Compute the ellipse's (u,v) bounding box in texture space
    float bbox_du = 2. / (-B*B+4.0*C*A) * sqrt((-B*B+4.0*C*A)*C*F);
    float bbox_dv = 2. / (-B*B+4.0*C*A) * sqrt(A*(-B*B+4.0*C*A)*F);
 
    //the ellipse bbox             
    int u0 = int(floor(p.s - bbox_du));
    int u1 = int(ceil (p.s + bbox_du));
    int v0 = int(floor(p.t - bbox_dv));
    int v1 = int(ceil (p.t + bbox_dv));
 
    // Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
    // and incrementally update the value of Ax^2+Bxy*Cy^2; when this
    // value, q, is less than F, we're inside the ellipse so we filter
    // away..
    vec4 num= vec4(0., 0., 0., 1.);
    float den = 0.;
    float ddq = 2. * A;
    float U = float(u0) - p.s;
   
    for (int v = v0; v <= v1; ++v) {
        float V = float(v) - p.t;
        float dq = A*(2.*U+1.) + B*V;
        float q = (C*V + B*U)*V + A*U*U;

        for (int u = u0; u <= u1; ++u) {
            if (q < F)
            {
                float r2 = q / F;
                float weight = FILTER_FUNC(r2);
#ifdef USE_LOD
                num += weight* textureLod(Source, vec2(u+0.5,v+0.5)/scale , int(lod));
#else
                num += weight* COMPAT_TEXTURE(Source, vec2(float(u)+0.5,float(v)+0.5)/float(scale));
#endif
                den += weight;
            }
            q += dq;
            dq += ddq;
        }

    }

    vec4 color = num*(1./den);
    return color;
}

#ifdef USE_LOD
//Function for mip-map lod selection
vec2 textureQueryLODEWA(sampler2D tex, vec2 du, vec2 dv, int psize){
    int scale = psize;
 
    float ux = du.s * scale;
    float vx = du.t * scale;
    float uy = dv.s * scale;
    float vy = dv.t * scale;
 
    // compute ellipse coefficients
    // A*x*x + B*x*y + C*y*y = F.
    float A = vx*vx+vy*vy;
    float B = -2*(ux*vx+uy*vy);
    float C = ux*ux+uy*uy;
    float F = A*C-B*B/4.;
       
    A = A/F;
    B = B/F;
    C = C/F;
   
    float root=sqrt((A-C)*(A-C)+B*B);
    float majorRadius = sqrt(2./(A+C-root));
    float minorRadius = sqrt(2./(A+C+root));
 
    float majorLength = majorRadius;
    float minorLength = minorRadius;
 
    if (minorLength<0.01) minorLength=0.01;
 
    const float maxEccentricity = MAX_ECCENTRICITY;
 
    float e = majorLength / minorLength;
 
    if (e > maxEccentricity) {
        minorLength *= (e / maxEccentricity);
    }
   
    float lod = log2(minorLength / TEXELS_PER_PIXEL);  
    lod = clamp (lod, 0.0, log2(float(psize)));
 
    return vec2(lod, e);
}
#endif

vec4 texture2DEWA(sampler2D tex, vec2 coords){
 
    vec2 du = dFdx(coords);
    vec2 dv = dFdy(coords);
   
    int psize = int(TextureSize.x);//textureSize(tex, 0).x;
    float lod = 0.;
#ifdef USE_LOD
    lod = textureQueryLODEWA(tex, du, dv, psize).x;
#endif

    return ewaFilter(tex, coords, du, dv, lod, psize );
}

vec2 radialDistortion(vec2 coord) {
    vec2 cc = coord - vec2(0.5);
    float dist = dot(cc, cc) * distortion;
    return coord + cc * (1.0 - dist) * dist;
}

void main()
{
    FragColor = texture2DEWA(SourceImage,radialDistortion(vTexCoord * TextureSize / InputSize) * InputSize / TextureSize);
} 
#endif

Done, it’s working now your genius :smiley: (Even your previously preset.)

1 Like