glsl-shaders/anti-aliasing/shaders/ewa_curvature.glsl
hizzlekizzle 0a951b97eb
fix ewa_curvature on nvidia
Nvidia's compiler was the picky one for once.
2018-12-30 14:21:58 -06:00

313 lines
7.6 KiB
GLSL

#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