mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-30 17:02:19 +00:00
120 lines
3.0 KiB
Plaintext
120 lines
3.0 KiB
Plaintext
|
// Spline36 upscaling shader.
|
||
|
// See issue #3921
|
||
|
|
||
|
#ifdef GL_ES
|
||
|
precision mediump float;
|
||
|
precision mediump int;
|
||
|
#endif
|
||
|
|
||
|
uniform sampler2D sampler0;
|
||
|
varying vec2 v_position;
|
||
|
|
||
|
uniform vec2 u_texelDelta;
|
||
|
uniform vec2 u_pixelDelta;
|
||
|
|
||
|
const vec2 HALF_PIXEL = vec2(0.5, 0.5);
|
||
|
|
||
|
float spline36_0_1(float x) {
|
||
|
return ((13.0 / 11.0 * x - 453.0 / 209.0) * x - 3.0 / 209.0) * x + 1.0;
|
||
|
}
|
||
|
|
||
|
float spline36_1_2(float x) {
|
||
|
return ((-6.0 / 11.0 * x + 612.0 / 209.0) * x - 1038.0 / 209.0) * x + 540.0 / 209.0;
|
||
|
}
|
||
|
|
||
|
float spline36_2_3(float x) {
|
||
|
return ((1.0 / 11.0 * x - 159.0 / 209.0) * x + 434.0 / 209.0) * x - 384.0 / 209.0;
|
||
|
}
|
||
|
|
||
|
vec4 rgb(int inputX, int inputY) {
|
||
|
return texture2D(sampler0, (vec2(inputX, inputY) + HALF_PIXEL) * u_texelDelta);
|
||
|
}
|
||
|
|
||
|
vec4 interpolateHorizontally(vec2 inputPos, ivec2 inputPosFloor, int dy) {
|
||
|
float sumOfWeights = 0.0;
|
||
|
vec4 sumOfWeightedPixel = vec4(0.0);
|
||
|
|
||
|
float x;
|
||
|
float weight;
|
||
|
|
||
|
x = inputPos.x - float(inputPosFloor.x - 2);
|
||
|
weight = spline36_2_3(x);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * rgb(inputPosFloor.x - 2, inputPosFloor.y + dy);
|
||
|
|
||
|
--x;
|
||
|
weight = spline36_1_2(x);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * rgb(inputPosFloor.x - 1, inputPosFloor.y + dy);
|
||
|
|
||
|
--x;
|
||
|
weight = spline36_0_1(x);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * rgb(inputPosFloor.x + 0, inputPosFloor.y + dy);
|
||
|
|
||
|
x = 1.0 - x;
|
||
|
weight = spline36_0_1(x);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * rgb(inputPosFloor.x + 1, inputPosFloor.y + dy);
|
||
|
|
||
|
++x;
|
||
|
weight = spline36_1_2(x);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * rgb(inputPosFloor.x + 2, inputPosFloor.y + dy);
|
||
|
|
||
|
++x;
|
||
|
weight = spline36_2_3(x);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * rgb(inputPosFloor.x + 3, inputPosFloor.y + dy);
|
||
|
|
||
|
return sumOfWeightedPixel / sumOfWeights;
|
||
|
}
|
||
|
|
||
|
vec4 process(vec2 outputPos) {
|
||
|
vec2 inputPos = outputPos / u_texelDelta;
|
||
|
ivec2 inputPosFloor = ivec2(inputPos);
|
||
|
|
||
|
// Vertical interporation
|
||
|
float sumOfWeights = 0.0;
|
||
|
vec4 sumOfWeightedPixel = vec4(0.0);
|
||
|
|
||
|
float weight;
|
||
|
float y;
|
||
|
|
||
|
y = inputPos.y - float(inputPosFloor.y - 2);
|
||
|
weight = spline36_2_3(y);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * interpolateHorizontally(inputPos, inputPosFloor, -2);
|
||
|
|
||
|
--y;
|
||
|
weight = spline36_1_2(y);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * interpolateHorizontally(inputPos, inputPosFloor, -1);
|
||
|
|
||
|
--y;
|
||
|
weight = spline36_0_1(y);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * interpolateHorizontally(inputPos, inputPosFloor, +0);
|
||
|
|
||
|
y = 1.0 - y;
|
||
|
weight = spline36_0_1(y);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * interpolateHorizontally(inputPos, inputPosFloor, +1);
|
||
|
|
||
|
++y;
|
||
|
weight = spline36_1_2(y);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * interpolateHorizontally(inputPos, inputPosFloor, +2);
|
||
|
|
||
|
++y;
|
||
|
weight = spline36_2_3(y);
|
||
|
sumOfWeights += weight;
|
||
|
sumOfWeightedPixel += weight * interpolateHorizontally(inputPos, inputPosFloor, +3);
|
||
|
|
||
|
return vec4((sumOfWeightedPixel / sumOfWeights).xyz, 1.0);
|
||
|
}
|
||
|
|
||
|
void main()
|
||
|
{
|
||
|
gl_FragColor.rgba = process(v_position);
|
||
|
}
|