Author Topic: [FF7PC] The Big Bad Bug Database - post bug reports here  (Read 6314 times)

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #50 on: 2017-05-16 22:22:45 »
I've enhanced the gamma and levels and saturation using shader, but that's not what's making the biggest difference.  It's probably just how the PC and PSX are being rendered.  PC isn't applying any sort of filtering to the background - you're getting sharp pixellation. The PSX doesn't have the pixellation as much so you get blurring instead.

This is also why I refuse to add any of the background packs around here... because when you lose pixellation, you lose clarity. The human brain is good at imagining/adding detail when it sees a pixellated image... it can't do that if you've blended all the pixels together and made it either blurred or plastic.
« Last Edit: 2017-05-16 22:25:23 by DLPB »

obesebear

  • Administrator
  • No life
  • *
  • Posts: 3204
  • Karma: 109
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #51 on: 2017-05-16 23:38:10 »
So it's the exact same image?  The PSX gold framed image looks like it might say POKER, whereas the PC version is just a blob of pixels

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #52 on: 2017-05-16 23:46:58 »
I prefer the PC version tbh haha.  I think PSX suffers with blurriness and washed out colours because of it. I don't mind the pixellation.  Well, OK writing suffers a lot, as you just noted.

But yeah, they are the same image... both 320 * 224,

Kaldarasha

  • No life
  • *
  • Posts: 2138
  • Karma: 129
  • Prince of Model Editing
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #53 on: 2017-05-17 12:54:26 »
A bit off topic, but why is the background such better quality on the psx?

As Luksy has posted the PSX calculates and renders the colors differently. And now I understand what Sunwalkers shader port does:
no shaderwith shader
Look how much better the shadow area at the firs G-Bike gaming machine does blend.

The shader:
Code: [Select]
/*===============================================================================*\
|#######################   [FINAL FANTASY 7 SHADER FX]    ########################|
|#########################   By Sunwalker 21/Jan/2017   ##########################|
||                                Version 1.05                                   ||
||                                                                               ||
||          This program is free software; you can redistribute it and/or        ||
||          modify it under the terms of the GNU General Public License          ||
||          as published by the Free Software Foundation; either version 2       ||
||          of the License, or (at your option) any later version.               ||
||                                                                               ||
||          This program is distributed in the hope that it will be useful,      ||
||          but WITHOUT ANY WARRANTY; without even the implied warranty of       ||
||          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        ||
||          GNU General Public License for more details. (c)2016                 ||
||                                                                               ||
|#################################################################################|
\*===============================================================================*/
#version 120

#extension GL_NV_gpu_shader5 : enable
#extension GL_ARB_gpu_shader5 : enable
#extension GL_ARB_shader_precision : enable
#extension GL_ARB_sample_shading : enable
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_shader_storage_buffer_object : enable
#extension GL_ARB_shader_image_load_store : enable
#extension GL_ARB_bindless_texture : enable
#extension GL_ARB_shading_language_420pack : enable


/*------------------------------------------------------------------------------
[DEFINITIONS & ON/OFF OPTIONS]
------------------------------------------------------------------------------*/
//--------------------------#[CHOOSE EFFECTS]#--------------------------------\\
//#[ANTIALIASING TECHNIQUES]   [1=ON|0=OFF]  # NOTE:
#define USE_FXAA                  0      //# [0 or 1] FXAA Fast Anti-aliasing

//#[LIGHTING & COLOUR]         [1=ON|0=OFF]  # NOTE: This one can enable all
#define GAMMA_CORRECTION            0      //# RGB Gamma Correction. Fixed expansion to variable compression gamma correction curve.
#define BLENDED_BLOOM               0      //# High Quality SP Bloom. Soft lighting with blending techniques, for a natural looking bloom.
#define SCENE_TONEMAPPING           0      //# HDR Scene Tonemapping. Layered component conversion, and applies scene tone mapping.
#define COLOR_CORRECTION            0      //# Component Color Correction. Colorspace conversion, with correction curves, and multiple palette types.
#define CROSS_PROCESSING            0      //# Filmic Cross Processing. Alters the tone of the scene, crossing the game's color set, with another.
#define PIXEL_VIBRANCE              0      //# Pixel Vibrance. Intelligently adjusts pixel vibrance depending on original color saturation.
#define COLOR_GRADING               0      //# Post-Complement Colour Grading. Alters individual colour components on a scene, to enhance selected colour tones.
#define USE_CURVES            0    //# [0 or 1] Curves : Contrast adjustments using S-curves.


//#[MISC]                      [1=ON|0=OFF]  # NOTE: Enable one only
#define NTSC_TV_EMULATION           1      //# SimoneT's TV Colors Emulation Shader. Use to emulate the original PSX color space tone, and vibrancy.
/*------------------------------------------------------------------------------
[EFFECT CONFIG OPTIONS]
------------------------------------------------------------------------------*/

//##[GAMMA_CORRECTION]
#define Gamma 2.40                            //[1.5 to 4.0] Gamma correction. Decrease for lower gamma(darker). Increase for higher gamma(brighter). (Default: 2.2)

//##[BLENDED_BLOOM]
#define BloomType BlendScreen                   //[BlendGlow, BlendAddGlow, BlendAddLight, BlendScreen, BlendLuma, BlendOverlay] The type of blended bloom. Light<->Dark.
#define BloomStrength 0.200                   //[0.000 to 1.000] Overall strength of the bloom. You may want to readjust for each blend type.
#define BlendStrength 1.000                   //[0.000 to 1.000] Strength of the blending. This is a modifier based on bloom. 1.0 equates to 100% strength.
#define BloomDefocus 2.000                    //[1.000 to 4.000] The initial bloom defocus value. Increases the softness of light, bright objects, etc.
#define BloomWidth 3.200                      //[1.000 to 8.000] Width of the bloom. Adjusts the width of the spread and soft glow. Scales with BloomStrength.
#define BloomReds 0.040                       //[0.000 to 1.000] Red channel correction of the bloom. Raising will increase the bloom of reds.
#define BloomGreens 0.030                     //[0.000 to 1.000] Green channel correction of the bloom. Raising will increase the bloom of greens.
#define BloomBlues 0.020                      //[0.000 to 1.000] Blue channel correction of the bloom. Raising will increase the bloom of blues.

//##[SCENE_TONEMAPPING]
#define TonemapType 2                         //[0|1|2|3] The base tone mapping operator. 0 is LDR, 1 is HDR(original), 2 & 3 are Filmic HDR(slight grading).
#define TonemapMask 1                         //[0 or 1] Enables an ALU tone masking curve. Produces a nice cinematic look. Suits some games more than others.
#define MaskStrength 0.10                     //[0.000 to 1.000] Strength of the tone masking. Higher for a stronger effect. This is a dependency of TonemapMask.
#define ToneAmount 0.360                      //[0.050 to 1.000] Tonemap strength (tone correction). Higher for stronger tone mapping, lower for lighter.
#define BlackLevels 0.060                     //[0.000 to 1.000] Black level balance (shadow correction). Increase to deepen blacks, lower to lighten them.
#define Exposure 1.000                        //[0.100 to 2.000] White correction (brightness). Higher values for more scene exposure, lower for less.
#define Luminance 1.000                       //[0.100 to 2.000] Luminance average (luminance correction). Higher values will lower scene luminance average.
#define WhitePoint 1.075                      //[0.100 to 2.000] Whitepoint average (wp lum correction). Higher values will lower the maximum scene white point.

//##[COLOR_CORRECTION]
#define CorrectionPalette 1                   //[1|2|3|4|5] The colorspace palette type. 1: RGB, 2: YXY, 3: XYZ, 4: HSV, 5: YUV. Each one will produce a different combination of shades & hues.
#define ChannelR 1.40                         //[0.00 to 8.00] R(1), Y(2), X(3), H(4), Y(5) component channel varies with the colorspace used. Higher values increase correction strength.
#define ChannelG 1.60                         //[0.00 to 8.00] G(1), X(2), Y(3), S(4), U(5) component channel varies with the colorspace used. Higher values increase correction strength.
#define ChannelB 1.80                         //[0.00 to 8.00] B(1), Y(2), Z(3), V(4), V(5) component channel varies with the colorspace used. Higher values increase correction strength.
#define PaletteStrength 2.00                  //[0.00 to 4.00] The interpolated strength ratio between the base color, and the corrected color. Raise to increase saturation.

//##[PIXEL_VIBRANCE]
#define Vibrance 0.15                          //[-1.00 to 1.00] Overall vibrance strength. Locally adjusts the vibrance of pixels depending on their original saturation.
#define RedVibrance 1.00                       //[-8.00 to 8.00] Red channel coefficient of the vibrance strength. Adjusting the vibrance of the red channel independently.
#define GreenVibrance 1.00                     //[-8.00 to 8.00] Green channel coefficient of the vibrance strength. Adjusting the vibrance of the green channel independently.
#define BlueVibrance 1.00                      //[-8.00 to 8.00] Blue channel coefficient of the vibrance strength. Adjusting the vibrance of the blue channel independently.

//##[CROSS_PROCESSING]
#define FilmicProcess 1                         //[1|2|3] The color conversion type for the cross process. 1: cool, 2: warm, 3: dusk. You can achieve different results with each.
#define RedShift 0.65                           //[0.10 to 1.00] Red color component shift of the filmic processing. Alters the red balance of the shift.
#define GreenShift 0.50                         //[0.10 to 1.00] Green color component shift of the filmic processing. Alters the green balance of the shift.
#define BlueShift 0.50                          //[0.10 to 1.00] Blue color component shift of the filmic processing. Alters the blue balance of the shift.
#define ShiftRatio 0.50                         //[0.10 to 2.00] The blending ratio for the base color and the color shift. Higher for a stronger effect.

//##[COLOR_GRADING]
#define RedGrading 1.20                         //[0.00 to 3.00] Red colour grading coefficient. Adjust to influence the red channel coefficients of the grading, and highlight tones.
#define GreenGrading 1.10                       //[0.00 to 3.00] Green colour grading coefficient. Adjust to influence the Green channel coefficients of the grading, and highlight tones.
#define BlueGrading 1.10                        //[0.00 to 3.00] Blue colour grading coefficient. Adjust to influence the Blue channel coefficients of the grading, and highlight tones.
#define GradingStrength 0.35                    //[0.00 to 1.00] The overall max strength of the colour grading effect. Raise to increase, lower to decrease the amount.
#define Correlation 1.00                        //[0.10 to 1.00] Correlation between the base colour, and the grading influence. Lower = more of the scene is graded, Higher = less of the scene is graded.

//##[USE_CURVES]
#define Curves_mode        2             //[0|1|2] Choose what to apply contrast to. 0 = Luma, 1 = Chroma, 2 = both Luma and Chroma. Default is 0 (Luma)
#define Curves_contrast 0.30         //[-1.00 to 1.00] The amount of contrast you want

//##[Advanced curve settings]
#define Curves_formula      3             //[1|2|3|4|5|6|7|8|9|10] The contrast s-curve you want to use.
                                      //1 = Sine, 2 = Abs split, 3 = Smoothstep, 4 = Exp formula, 5 = Simplified Catmull-Rom (0,0,1,1), 6 = Perlins Smootherstep
                                      //7 = Abs add, 8 = Techicolor Cinestyle, 9 = Parabola, 10 = Half-circles.
                                      //Note that Technicolor Cinestyle is practically identical to Sine, but runs slower. In fact I think the difference might only be due to rounding errors.
                                      //I prefer 2 myself, but 3 is a nice alternative with a little more effect (but harsher on the highlight and shadows) and it's the fastest formula


//[END OF USER OPTIONS]

/*------------------------------------------------------------------------------
[GLOBALS|FUNCTIONS]
------------------------------------------------------------------------------*/

//Global variables
#define saturate(x) clamp(x, 0.0, 1.0)
#define lerp mix
#define frac fract
#define fmod mod
#define mul(x, y) (y * x)
#define float4x3 mat4x3
#define float3x3 mat3
#define float4x4 mat4
#define lumCoeff vec3(0.212656, 0.715158, 0.072186)
#define PI 3.1415972

//OGL Uniforms
uniform sampler2D OGLTexture;
uniform sampler2D OGLTexture0;

//varying
uniform vec2 texcoord;

float Epsilon = 1e-10;

#define texture_width   1024.0
#define texture_height  1024.0

#define texel_size_x  (1.0 / texture_width)
#define texel_size_y  (1.0 / texture_height)

#define OGLSize     vec2(texture_width, texture_height)
#define OGLInvSize  vec2(texel_size_x, texel_size_y)

//Average Relative Luminance (HSP Color Model)
float AvgLuminance(vec3 color)
{
return sqrt(dot(color * color, lumCoeff));
}

//Smoothstep alt
float smootherstep(float a, float b, float x)
{
x = saturate((x - a) / (b - a));
return x*x*x*(x*(x * 6 - 15) + 10);
}

//Conversion matrices
vec3 RGBtoXYZ(vec3 RGB)
{
const mat3 RGBtoXYZ = mat3(
0.6068909, 0.1735011, 0.2003480,
0.2989164, 0.5865990, 0.1144845,
0.0000000, 0.0660957, 1.1162243);

return RGBtoXYZ*RGB;
}

vec3 XYZtoRGB(vec3 XYZ)
{
const mat3 XYZtoRGB = mat3(
1.9099961, -0.5324542, -0.2882091,
-0.9846663, 1.9991710, -0.0283082,
0.0583056, -0.1183781, 0.8975535);

return XYZtoRGB*XYZ;
}

vec3 XYZtoSRGB(vec3 XYZ)
{
const mat3 XYZtoSRGB = mat3(
3.2404542, -1.5371385, -0.4985314,
-0.9692660, 1.8760108, 0.0415560,
0.0556434, -0.2040259, 1.0572252);

return XYZtoSRGB*XYZ;
}

vec3 RGBtoYUV(vec3 RGB)
{
const mat3 RGBtoYUV = mat3(
0.2126, 0.7152, 0.0722,
-0.09991, -0.33609, 0.436,
0.615, -0.55861, -0.05639);

return RGBtoYUV*RGB;
}

vec3 YUVtoRGB(vec3 YUV)
{
const mat3 YUVtoRGB = mat3(
1.000, 0.000, 1.28033,
1.000, -0.21482, -0.38059,
1.000, 2.12798, 0.000);

return YUVtoRGB*YUV;
}

vec3 XYZtoYxy(vec3 XYZ)
{
float w = (XYZ.r + XYZ.g + XYZ.b);
vec3 Yxy;

Yxy.r = XYZ.g;
Yxy.g = XYZ.r / w;
Yxy.b = XYZ.g / w;

return Yxy;
}

vec3 YxytoXYZ(vec3 Yxy)
{
vec3 XYZ;
XYZ.g = Yxy.r;
XYZ.r = Yxy.r * Yxy.g / Yxy.b;
XYZ.b = Yxy.r * (1.0 - Yxy.g - Yxy.b) / Yxy.b;

return XYZ;
}

/*------------------------------------------------------------------------------
[FXAA CODE SECTION]
Code from http://www.geeks3d.com/20110405/fxaa-fast-approximate-anti-aliasing-demo-glsl-opengl-test-radeon-geforce/3/
Credit to original Author
------------------------------------------------------------------------------*/
#if USE_FXAA == 1
float xbrthreshold = 0.020;
vec2 rcpFrame = OGLInvSize;
vec3 FXAA(sampler2D OGLTexture, vec2 texcoord)
{
float FXAA_SPAN_MAX = 8.0;                     //[4.0 t0 8.0]             
float FXAA_REDUCE_MUL = (1.0 / FXAA_SPAN_MAX); //[Default]
float FXAA_REDUCE_MIN = (1.0 / 128.0);         //[Default]
float FXAA_SUBPIX_SHIFT = (1.0 / 4.0);         //[Default]

vec4 posPos = vec4(texcoord.xy, texcoord.xy - (rcpFrame * (0.5 + FXAA_SUBPIX_SHIFT)));

/*---------------------------------------------------------*/
vec3 rgbNW = texture2D(OGLTexture, posPos.zw, 0.0).rgb;
vec3 rgbNE = texture2D(OGLTexture, posPos.zw + vec2(1., 0.)*rcpFrame.xy, 0.0).rgb;
vec3 rgbSW = texture2D(OGLTexture, posPos.zw + vec2(0., 1.)*rcpFrame.xy, 0.0).rgb;
vec3 rgbSE = texture2D(OGLTexture, posPos.zw + vec2(1., 1.)*rcpFrame.xy, 0.0).rgb;
vec3 rgbM = texture2D(OGLTexture, texcoord.xy, 0.0).rgb;
/*---------------------------------------------------------*/
//vec3 luma = vec3(0.299, 0.587, 0.114);
float lumaNW = AvgLuminance(rgbNW);
float lumaNE = AvgLuminance(rgbNE);
float lumaSW = AvgLuminance(rgbSW);
float lumaSE = AvgLuminance(rgbSE);
float lumaM = AvgLuminance(rgbM);
/*---------------------------------------------------------*/
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));

float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
/*---------------------------------------------------------*/
vec2 dir;

dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));

dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
/*---------------------------------------------------------*/
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);

float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);

dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) * rcpFrame.xy;
/*--------------------------------------------------------*/

vec3 rgbA = (1.0 / 2.0) * (texture2D(OGLTexture, texcoord.xy + dir * (1.0 / 3.0 - 0.5)).rgb + texture2D(OGLTexture, texcoord.xy + dir * (2.0 / 3.0 - 0.5)).rgb);
vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * (texture2D(OGLTexture, texcoord.xy + dir * (0.0 / 3.0 - 0.5)).rgb + texture2D(OGLTexture, texcoord.xy + dir * (3.0 / 3.0 - 0.5)).rgb);

float lumaB = AvgLuminance(rgbB);

return ((lumaB < lumaMin) || (lumaB > lumaMax)) ? rgbA.rgb : rgbB.rgb;
}

//Hyllian's xBR Level 2 shader
//Copyright(C) 2011 / 2014 Hyllian / Jararaca - [email protected]
//Credit to Hyllian
float x_Width = texture_width;
float y_Height = texture_height;

float x_coef = texel_size_x;
float y_coef = texel_size_y;

float coef = 2.0;
vec3 rgbw = vec3(14.352, 28.176, 5.472);

float x = 0.5 * (1.0 / x_Width);
float y = 0.5 * (1.0 / y_Height);

//vec2 dx = vec2(x, 0.0);
//vec2 dy = vec2(0.0, y);
vec2 dx = vec2(0.0009765625, 0.0);//vec2(x, 0.0);//
vec2 dy = vec2(0.0, 0.001953125);//vec2(0.0, y);//
vec2 x2 = vec2(0.001953125, 0.0);//vec2(y, 0);//
vec2 y2 = vec2(0.0, 0.00390625);//vec2( 0.0 , y*2.0 );//
vec4 xy = vec4(0.0009765625, 0.001953125, -0.0009765625, -0.001953125);//vec4( x, y,-x,-y);//
vec4 zw = vec4(0.001953125, 0.001953125, -0.001953125, -0.00390625);//vec4( y , y,-y ,-(y*2.0));//
vec4 wz = vec4(0.0009765625, 0.00390625, -0.0009765625, -0.00390625);  //vec4( x, y*2.0 ,-x,-(y*2.0));//

vec4 df(vec4 A, vec4 B)
{
return abs(A - B);
}

vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h)
{
return (df(a, b) + df(a, c) + df(d, e) + df(d, f) + 4.0*df(g, h));
}


vec3 xBR(sampler2D OGLTexture, vec2 texcoord)
{
vec4 edr, edr_left, edr_up; bvec4 px; // px = pixel, edr = edge detection rule
vec4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up;
bvec4 nc; // new_color
vec4 fx, fx_left, fx_up; // inequations of straight lines.

vec2 fp = fract(texcoord.xy*vec2(x_Width, y_Height));
vec2 vTex = texcoord.xy - fp*vec2(0.0009765625*x_coef, 0.001953125*y_coef);//vec2(x, y);

vec3 A = texture2D(OGLTexture, vTex + xy.zw).rgb;
vec3 B = texture2D(OGLTexture, vTex - dy).rgb;
vec3 C = texture2D(OGLTexture, vTex + xy.xw).rgb;
vec3 D = texture2D(OGLTexture, vTex - dx).rgb;
vec3 E = texture2D(OGLTexture, vTex).rgb;
vec3 F = texture2D(OGLTexture, vTex + dx).rgb;
vec3 G = texture2D(OGLTexture, vTex + xy.zy).rgb;
vec3 H = texture2D(OGLTexture, vTex + dy).rgb;
vec3 I = texture2D(OGLTexture, vTex + xy.xy).rgb;
vec3 A1 = texture2D(OGLTexture, vTex + wz.zw).rgb;
vec3 C1 = texture2D(OGLTexture, vTex + wz.xw).rgb;
vec3 A0 = texture2D(OGLTexture, vTex + zw.zw).rgb;
vec3 G0 = texture2D(OGLTexture, vTex + zw.zy).rgb;
vec3 C4 = texture2D(OGLTexture, vTex + zw.xw).rgb;
vec3 I4 = texture2D(OGLTexture, vTex + zw.xy).rgb;
vec3 G5 = texture2D(OGLTexture, vTex + wz.zy).rgb;
vec3 I5 = texture2D(OGLTexture, vTex + wz.xy).rgb;
vec3 B1 = texture2D(OGLTexture, vTex - y2).rgb;
vec3 D0 = texture2D(OGLTexture, vTex - x2).rgb;
vec3 H5 = texture2D(OGLTexture, vTex + y2).rgb;
vec3 F4 = texture2D(OGLTexture, vTex + x2).rgb;

vec4 b = vec4(dot(B, rgbw), dot(D, rgbw), dot(H, rgbw), dot(F, rgbw));
vec4 c = vec4(dot(C, rgbw), dot(A, rgbw), dot(G, rgbw), dot(I, rgbw));
vec4 d = b.yzwx;
vec4 e = vec4(dot(E, rgbw));
vec4 f = b.wxyz;
vec4 g = c.zwxy;
vec4 h = b.zwxy;
vec4 i = c.wxyz;
vec4 i4 = vec4(dot(I4, rgbw), dot(C1, rgbw), dot(A0, rgbw), dot(G5, rgbw));
vec4 i5 = vec4(dot(I5, rgbw), dot(C4, rgbw), dot(A1, rgbw), dot(G0, rgbw));
vec4 h5 = vec4(dot(H5, rgbw), dot(F4, rgbw), dot(B1, rgbw), dot(D0, rgbw));
vec4 f4 = h5.yzwx;

vec4 Ao = vec4(1.0, -1.0, -1.0, 1.0);
vec4 Bo = vec4(1.0, 1.0, -1.0, -1.0);
vec4 Co = vec4(1.5, 0.5, -0.5, 0.5);
vec4 Ax = vec4(1.0, -1.0, -1.0, 1.0);
vec4 Bx = vec4(0.5, 2.0, -0.5, -2.0);
vec4 Cx = vec4(1.0, 1.0, -0.5, 0.0);
vec4 Ay = vec4(1.0, -1.0, -1.0, 1.0);
vec4 By = vec4(2.0, 0.5, -2.0, -0.5);
vec4 Cy = vec4(2.0, 0.0, -1.0, 0.5);
vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25);

// These inequations define the line below which interpolation occurs.
fx = vec4(greaterThan(Ao*fp.y + Bo*fp.x, Co));
fx_left = vec4(greaterThan(Ax*fp.y + Bx*fp.x, Cx));
fx_up = vec4(greaterThan(Ay*fp.y + By*fp.x, Cy));

interp_restriction_lv1 = vec4(notEqual(e, f))*vec4(notEqual(e, h));
interp_restriction_lv2_left = vec4(notEqual(e, g))*vec4(notEqual(d, g));
interp_restriction_lv2_up = vec4(notEqual(e, c))*vec4(notEqual(b, c));

edr = vec4(lessThan(weighted_distance(e, c, g, i, h5, f4, h, f), weighted_distance(h, d, i5, f, i4, b, e, i)))*interp_restriction_lv1;
edr_left = vec4(lessThanEqual(coef*df(f, g), df(h, c)))*interp_restriction_lv2_left;
edr_up = vec4(greaterThanEqual(df(f, g), coef*df(h, c)))*interp_restriction_lv2_up;

nc = bvec4(edr*(max(max(fx, edr_left*fx_left), edr_up*fx_up)));

px = lessThanEqual(df(e, f), df(e, h));

vec3 res = nc.x ? px.x ? F : H : nc.y ? px.y ? B : F : nc.z ? px.z ? D : B : nc.w ? px.w ? H : D : E;

return res;
}

float diff2D(vec2 coord)
{
vec3 dt = vec3(1.0, 1.0, 1.0);

vec3 c00 = texture2D(OGLTexture, coord + 0.25*(-dx - dy)).xyz;
vec3 c20 = texture2D(OGLTexture, coord + 0.25*(dx - dy)).xyz;
vec3 c02 = texture2D(OGLTexture, coord + 0.25*(-dx + dy)).xyz;
vec3 c22 = texture2D(OGLTexture, coord + 0.25*(dx + dy)).xyz;

vec3 mn = min(min(c00, c20), min(c02, c22));
vec3 mx = max(max(c00, c20), max(c02, c22));

return dot(mx - mn, dt);
}

vec4 FXAAPass(vec4 color, vec2 texcoord)
{
vec2 fp = fract(texcoord * OGLSize);
vec2 vTex = texcoord - fp * OGLInvSize + 0.5 * OGLInvSize;
vec2 locator = sign(fp - vec2(0.5000000001, 0.5000000001));

float maxdiff = max(max(diff2D(vTex + locator*dx), diff2D(vTex + locator*dy)), diff2D(vTex));

if (maxdiff <= xbrthreshold) { color.rgb = xBR(OGLTexture, texcoord); }
else { color.rgb = FXAA(OGLTexture, texcoord); }

color.a = AvgLuminance(color.rgb);

return color;
}
#endif

/*------------------------------------------------------------------------------
[GAMMA CORRECTION CODE SECTION]
------------------------------------------------------------------------------*/

vec3 EncodeGamma(vec3 color, float gamma)
{
color = saturate(color);
color.r = (color.r <= 0.0404482362771082) ? color.r / 12.92 : pow((color.r + 0.055) / 1.055, gamma);
color.g = (color.g <= 0.0404482362771082) ? color.g / 12.92 : pow((color.g + 0.055) / 1.055, gamma);
color.b = (color.b <= 0.0404482362771082) ? color.b / 12.92 : pow((color.b + 0.055) / 1.055, gamma);

return color;
}

vec3 DecodeGamma(vec3 color, float gamma)
{
color = saturate(color);
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;
}

#if GAMMA_CORRECTION == 1
vec4 GammaPass(vec4 color, vec2 texcoord)
{
const float GammaConst = 2.233333;
color.rgb = EncodeGamma(color.rgb, GammaConst);
color.rgb = DecodeGamma(color.rgb, float(Gamma));
color.a = AvgLuminance(color.rgb);

return color;
}
#endif

/*------------------------------------------------------------------------------
[PIXEL VIBRANCE CODE SECTION]
------------------------------------------------------------------------------*/

#if PIXEL_VIBRANCE == 1
vec4 VibrancePass(vec4 color, vec2 texcoord)
{
float vib = Vibrance;

float lum = AvgLuminance(color.rgb);
vec3 luma = vec3(lum, lum, lum);

float colorMax = max(color.r, max(color.g, color.b));
float colorMin = min(color.r, min(color.g, color.b));

float colorSaturation = colorMax - colorMin;
vec3 colorCoeff = vec3(RedVibrance * vib, GreenVibrance * vib, BlueVibrance * vib);

color.rgb = lerp(luma, color.rgb, (1.0 + (colorCoeff * (1.0 - (sign(colorCoeff) * colorSaturation)))));
color.a = AvgLuminance(color.rgb);

return saturate(color); //Debug: return colorSaturation.xxxx;
}
#endif

/*------------------------------------------------------------------------------
[BLENDED BLOOM CODE SECTION]
------------------------------------------------------------------------------*/

#if BLENDED_BLOOM == 1
vec3 BlendAddLight(vec3 bloom, vec3 blend)
{
return saturate(bloom + blend);
}

vec3 BlendScreen(vec3 bloom, vec3 blend)
{
return (bloom + blend) - (bloom * blend);
}

vec3 BlendGlow(vec3 bloom, vec3 blend)
{
float glow = AvgLuminance(bloom);
return lerp((bloom + blend) - (bloom * blend), (blend + blend) - (blend * blend), glow);
}

vec3 BlendAddGlow(vec3 bloom, vec3 blend)
{
float addglow = smootherstep(0.0, 1.0, AvgLuminance(bloom));
return lerp(saturate(bloom + blend), (blend + blend) - (blend * blend), addglow);
}

vec3 BlendLuma(vec3 bloom, vec3 blend)
{
float lumavg = smootherstep(0.0, 1.0, AvgLuminance(bloom + blend));
return lerp((bloom * blend), (1.0 - ((1.0 - bloom) * (1.0 - blend))), lumavg);
}

vec3 BlendOverlay(vec3 bloom, vec3 blend)
{
vec3 overlay = step(0.5, bloom);
return lerp((bloom * blend * 2.0), (1.0 - (2.0 *(1.0 - bloom) * (1.0 - blend))), overlay);
}

vec3 BloomCorrection(vec3 color)
{
vec3 bloom = color;

bloom.r = 2.0 / 3.0 * (1.0 - (bloom.r * bloom.r));
bloom.g = 2.0 / 3.0 * (1.0 - (bloom.g * bloom.g));
bloom.b = 2.0 / 3.0 * (1.0 - (bloom.b * bloom.b));

bloom.r = saturate(color.r + float(BloomReds) * bloom.r);
bloom.g = saturate(color.g + float(BloomGreens) * bloom.g);
bloom.b = saturate(color.b + float(BloomBlues) * bloom.b);
color = bloom;
return color;
}

vec4 DefocusFilter(sampler2D OGLTexture, vec2 texcoord, vec2 defocus)
{
defocus = clamp(defocus, 1.0, 1.5);
vec2 texel = vec2(texel_size_x, texel_size_y) * defocus;

vec4 sampleA = texture2D(OGLTexture, texcoord + vec2(0.5, 0.5) * texel);
vec4 sampleB = texture2D(OGLTexture, texcoord + vec2(-0.5, 0.5) * texel);
vec4 sampleC = texture2D(OGLTexture, texcoord + vec2(0.5, -0.5) * texel);
vec4 sampleD = texture2D(OGLTexture, texcoord + vec2(-0.5, -0.5) * texel);

float fx = frac(texcoord.x * texture_width);
float fy = frac(texcoord.y * texture_height);

vec4 interpolateA = lerp(sampleA, sampleB, fx);
vec4 interpolateB = lerp(sampleC, sampleD, fx);
return lerp(interpolateA, interpolateB, fy);
}

vec4 BloomPass(vec4 color, vec2 texcoord)
{
float anflare = 4.0;
float width = BloomWidth;

vec2 defocus = vec2(BloomDefocus, BloomDefocus);
vec4 bloom = DefocusFilter(OGLTexture, texcoord, defocus);

vec2 dx = vec2(texel_size_x * width, 0.0);
vec2 dy = vec2(0.0, texel_size_y * width);

vec2 mdx = vec2(dx.x * defocus.x, 0.0);
vec2 mdy = vec2(0.0, dy.y * defocus.y);

vec4 blend = bloom * 0.22520613262190495;

blend += 0.002589001911021066 * texture2D(OGLTexture, texcoord - mdx + mdy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord - dx + mdy);
blend += 0.024146616900339800 * texture2D(OGLTexture, texcoord + mdy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord + dx + mdy);
blend += 0.002589001911021066 * texture2D(OGLTexture, texcoord + mdx + mdy);

blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord - mdx + dy);
blend += 0.044875475183061630 * texture2D(OGLTexture, texcoord - dx + dy);
blend += 0.100529757860782610 * texture2D(OGLTexture, texcoord + dy);
blend += 0.044875475183061630 * texture2D(OGLTexture, texcoord + dx + dy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord + mdx + dy);

blend += 0.024146616900339800 * texture2D(OGLTexture, texcoord - mdx);
blend += 0.100529757860782610 * texture2D(OGLTexture, texcoord - dx);
blend += 0.100529757860782610 * texture2D(OGLTexture, texcoord + dx);
blend += 0.024146616900339800 * texture2D(OGLTexture, texcoord + mdx);

blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord - mdx - dy);
blend += 0.044875475183061630 * texture2D(OGLTexture, texcoord - dx - dy);
blend += 0.100529757860782610 * texture2D(OGLTexture, texcoord - dy);
blend += 0.044875475183061630 * texture2D(OGLTexture, texcoord + dx - dy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord + mdx - dy);

blend += 0.002589001911021066 * texture2D(OGLTexture, texcoord - mdx - mdy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord - dx - mdy);
blend += 0.024146616900339800 * texture2D(OGLTexture, texcoord - mdy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord + dx - mdy);
blend += 0.002589001911021066 * texture2D(OGLTexture, texcoord + mdx - mdy);
blend = lerp(color, blend, float(BlendStrength));

bloom.xyz = BloomType(bloom.xyz, blend.xyz);
bloom.xyz = BloomCorrection(bloom.xyz);

color.w = AvgLuminance(color.xyz);
bloom.w = AvgLuminance(bloom.xyz);
bloom.w *= anflare;

color = lerp(color, bloom, float(BloomStrength));

return color;
}
#endif

/*------------------------------------------------------------------------------
[SCENE TONE MAPPING CODE SECTION]
------------------------------------------------------------------------------*/

#if SCENE_TONEMAPPING == 1

vec3 ScaleLuminance(vec3 x)
{
float W = 1.02; // WhitePoint Scale
float L = 0.16; // Luminance Scale
float C = 1.02; // Compression Scale

float N = clamp(0.82 + ToneAmount, 1.0, 2.0);
float K = (N - L * C) / C;

vec3 tone = L * C + (1.0 - L * C) * (1.0 + K * (x - L) / ((W - L) * (W - L))) * (x - L) / (x - L + K);

vec3 color;
color.r = (x.r > L) ? tone.r : C * x.r;
color.g = (x.g > L) ? tone.g : C * x.g;
color.b = (x.b > L) ? tone.b : C * x.b;

return color;
}

vec3 TmMask(vec3 color)
{
vec3 tone = color;

float highTone = 6.2;
float greyTone = 0.4;
float midTone = 1.62;
float lowTone = 0.06;

tone.r = (tone.r * (highTone * tone.r + greyTone)) / (tone.r * (highTone * tone.r + midTone) + lowTone);
tone.g = (tone.g * (highTone * tone.g + greyTone)) / (tone.g * (highTone * tone.g + midTone) + lowTone);
tone.b = (tone.b * (highTone * tone.b + greyTone)) / (tone.b * (highTone * tone.b + midTone) + lowTone);

const float gamma = 2.42;
tone = EncodeGamma(tone, gamma);

color = lerp(color, tone, float(MaskStrength));

return color;
}

vec3 TmCurve(vec3 color)
{
vec3 T = color;

float tnamn = ToneAmount;
float blevel = length(T);
float bmask = pow(blevel, 0.02);

float A = 0.100; float B = 0.300;
float C = 0.100; float D = tnamn;
float E = 0.020; float F = 0.300;

float W = 1.000;

T.r = ((T.r*(A*T.r + C*B) + D*E) / (T.r*(A*T.r + B) + D*F)) - E / F;
T.g = ((T.g*(A*T.g + C*B) + D*E) / (T.g*(A*T.g + B) + D*F)) - E / F;
T.b = ((T.b*(A*T.b + C*B) + D*E) / (T.b*(A*T.b + B) + D*F)) - E / F;

float denom = ((W*(A*W + C*B) + D*E) / (W*(A*W + B) + D*F)) - E / F;

vec3 black = vec3(bmask, bmask, bmask);
vec3 white = vec3(denom, denom, denom);

T = T / white;
T = T * black;

color = saturate(T);

return color;
}

vec4 TonemapPass(vec4 color, vec2 texcoord)
{
float L = Luminance;

vec3 tonemap = color.rgb;
vec3 luma = vec3(L, L, L);

float blackLevel = length(tonemap);
tonemap = ScaleLuminance(tonemap);

float luminanceAverage = AvgLuminance(luma);

if (TonemapMask == 1) { tonemap = TmMask(tonemap); }
if (TonemapType == 1) { tonemap = TmCurve(tonemap); }

// RGB -> XYZ conversion
vec3 XYZ = RGBtoXYZ(tonemap);

// XYZ -> Yxy conversion
vec3 Yxy;

Yxy.r = XYZ.g;                                  // copy luminance Y
Yxy.g = XYZ.r / (XYZ.r + XYZ.g + XYZ.b);        // x = X / (X + Y + Z)
Yxy.b = XYZ.g / (XYZ.r + XYZ.g + XYZ.b);        // y = Y / (X + Y + Z)

// (Wt) Tone mapped scaling of the initial wp before input modifiers
float Wt = saturate(Yxy.r / AvgLuminance(XYZ));

if (TonemapType == 2) { Yxy.r = TmCurve(Yxy).r; }

// (Lp) Map average luminance to the middlegrey zone by scaling pixel luminance
float Lp = Yxy.r * float(Exposure) / (luminanceAverage + Epsilon);

// (Wp) White point calculated, based on the toned white, and input modifier
float Wp = dot(abs(Wt), float(WhitePoint));

// (Ld) Scale all luminance within a displayable range of 0 to 1
Yxy.r = (Lp * (1.0 + Lp / (Wp * Wp))) / (1.0 + Lp);

// Yxy -> XYZ conversion
XYZ.r = Yxy.r * Yxy.g / Yxy.b;                  // X = Y * x / y
XYZ.g = Yxy.r;                                  // copy luminance Y
XYZ.b = Yxy.r * (1.0 - Yxy.g - Yxy.b) / Yxy.b;  // Z = Y * (1-x-y) / y

if (TonemapType == 3) { XYZ = TmCurve(XYZ); }

// XYZ -> RGB conversion
tonemap = XYZtoRGB(XYZ);

float shadowmask = pow(saturate(blackLevel), float(BlackLevels));
tonemap = tonemap * vec3(shadowmask, shadowmask, shadowmask);

color.rgb = tonemap;

color.a = AvgLuminance(color.rgb);

return color;
}
#endif

/*------------------------------------------------------------------------------
[COLOR CORRECTION CODE SECTION]
------------------------------------------------------------------------------*/

// Converting pure hue to RGB
vec3 HUEtoRGB(float H)
{
float R = abs(H * 6.0 - 3.0) - 1.0;
float G = 2.0 - abs(H * 6.0 - 2.0);
float B = 2.0 - abs(H * 6.0 - 4.0);

return saturate(vec3(R, G, B));
}

// Converting RGB to hue/chroma/value
vec3 RGBtoHCV(vec3 RGB)
{
vec4 BG = vec4(RGB.bg, -1.0, 2.0 / 3.0);
vec4 GB = vec4(RGB.gb, 0.0, -1.0 / 3.0);

vec4 P = (RGB.g < RGB.b) ? BG : GB;

vec4 XY = vec4(P.xyw, RGB.r);
vec4 YZ = vec4(RGB.r, P.yzx);

vec4 Q = (RGB.r < P.x) ? XY : YZ;

float C = Q.x - min(Q.w, Q.y);
float H = abs((Q.w - Q.y) / (6.0 * C + Epsilon) + Q.z);

return vec3(H, C, Q.x);
}

// Converting RGB to HSV
vec3 RGBtoHSV(vec3 RGB)
{
vec3 HCV = RGBtoHCV(RGB);
float S = HCV.y / (HCV.z + Epsilon);

return vec3(HCV.x, S, HCV.z);
}

// Converting HSV to RGB
vec3 HSVtoRGB(vec3 HSV)
{
vec3 RGB = HUEtoRGB(HSV.x);
return ((RGB - 1.0) * HSV.y + 1.0) * HSV.z;
}

#if COLOR_CORRECTION == 1
// Pre correction color mask
vec3 PreCorrection(vec3 color)
{
vec3 RGB = color;

RGB.r = 2.0 / 3.0 * (1.0 - (RGB.r * RGB.r));
RGB.g = 2.0 / 3.0 * (1.0 - (RGB.g * RGB.g));
RGB.b = 2.0 / 3.0 * (1.0 - (RGB.b * RGB.b));

RGB.r = saturate(color.r + (float(ChannelR) / 200.0) * RGB.r);
RGB.g = saturate(color.g + (float(ChannelG) / 200.0) * RGB.g);
RGB.b = saturate(color.b + (float(ChannelB) / 200.0) * RGB.b);

color = saturate(RGB);

return color;
}

vec3 ColorCorrection(vec3 color)
{
float X = 1.0 / (1.0 + exp(float(ChannelR) / 2.0));
float Y = 1.0 / (1.0 + exp(float(ChannelG) / 2.0));
float Z = 1.0 / (1.0 + exp(float(ChannelB) / 2.0));

color.r = (1.0 / (1.0 + exp(float(-ChannelR) * (color.r - 0.5))) - X) / (1.0 - 2.0 * X);
color.g = (1.0 / (1.0 + exp(float(-ChannelG) * (color.g - 0.5))) - Y) / (1.0 - 2.0 * Y);
color.b = (1.0 / (1.0 + exp(float(-ChannelB) * (color.b - 0.5))) - Z) / (1.0 - 2.0 * Z);

return saturate(color);
}

vec4 CorrectionPass(vec4 color, vec2 texcoord)
{
vec3 colorspace = PreCorrection(color.rgb);

#if CorrectionPalette == 1
colorspace = ColorCorrection(colorspace);

#elif CorrectionPalette == 2
vec3 XYZ = RGBtoXYZ(colorspace);
vec3 Yxy = XYZtoYxy(XYZ);

Yxy = ColorCorrection(Yxy);
XYZ = YxytoXYZ(Yxy);
colorspace = XYZtoRGB(XYZ);

#elif CorrectionPalette == 3
vec3 XYZ = RGBtoXYZ(colorspace);
vec3 Yxy = XYZtoYxy(XYZ);
XYZ = YxytoXYZ(Yxy);
XYZ = ColorCorrection(XYZ);
colorspace = XYZtoRGB(XYZ);

#elif CorrectionPalette == 4
vec3 hsv = RGBtoHSV(colorspace);
hsv = ColorCorrection(hsv);
colorspace = HSVtoRGB(hsv);

#elif CorrectionPalette == 5
vec3 yuv = RGBtoYUV(colorspace);
yuv = ColorCorrection(yuv);
colorspace = YUVtoRGB(yuv);
#endif

color.rgb = lerp(color.rgb, colorspace, float(PaletteStrength));

color.a = AvgLuminance(color.rgb);

return color;
}
#endif

/*------------------------------------------------------------------------------
[S-CURVE CONTRAST CODE SECTION]
------------------------------------------------------------------------------*/

#if USE_CURVES == 1

vec4 CurvesPass(vec4 color, vec2 texcoord)
{
float Curves_contrast_blend = Curves_contrast;


/*-----------------------------------------------------------.
/               Separation of Luma and Chroma                 /
'-----------------------------------------------------------*/

// -- Calculate Luma and Chroma if needed --
#if Curves_mode != 2

//calculate luma (grey)
float luma = dot(lumCoeff, color.rgb);

//calculate chroma
vec3 chroma = color.rgb - luma;
#endif

// -- Which value to put through the contrast formula? --
// I name it x because makes it easier to copy-paste to Graphtoy or Wolfram Alpha or another graphing program
#if Curves_mode == 2
vec3 x = color.rgb; //if the curve should be applied to both Luma and Chroma
#elif Curves_mode == 1
vec3 x = chroma; //if the curve should be applied to Chroma
x = x * 0.5 + 0.5; //adjust range of Chroma from -1 -> 1 to 0 -> 1
#else // Curves_mode == 0
float x = luma; //if the curve should be applied to Luma
#endif

    // Contrast formulas
// -- Curve 1 --
#if Curves_formula == 1
x = sin(PI * 0.5 * x); // Sin - 721 amd fps, +vign 536 nv
x *= x;

//x = 0.5 - 0.5*cos(PI*x);
//x = 0.5 * -sin(PI * -x + (PI*0.5)) + 0.5;
#endif

// -- Curve 2 --
#if Curves_formula == 2
x = x - 0.5;
x = (x / (0.5 + abs(x))) + 0.5;

//x = ( (x - 0.5) / (0.5 + abs(x-0.5)) ) + 0.5;
#endif

// -- Curve 3 --
#if Curves_formula == 3
//x = smoothstep(0.0,1.0,x); //smoothstep
x = x*x*(3.0 - 2.0*x); //faster smoothstep alternative - 776 amd fps, +vign 536 nv
//x = x - 2.0 * (x - 1.0) * x* (x- 0.5);  //2.0 is contrast. Range is 0.0 to 2.0
#endif

// -- Curve 4 --
#if Curves_formula == 4
x = (1.0524 * exp(6.0 * x) - 1.05248) / (20.0855 + exp(6.0 * x)); //exp formula
#endif

// -- Curve 5 --
#if Curves_formula == 5
//x = 0.5 * (x + 3.0 * x * x - 2.0 * x * x * x); //a simplified catmull-rom (0,0,1,1) - btw smoothstep can also be expressed as a simplified catmull-rom using (1,0,1,0)
//x = (0.5 * x) + (1.5 -x) * x*x; //estrin form - faster version
x = x * (x * (1.5 - x) + 0.5); //horner form - fastest version

Curves_contrast_blend = Curves_contrast * 2.0; //I multiply by two to give it a strength closer to the other curves.
#endif

// -- Curve 6 --
#if Curves_formula == 6
x = x*x*x*(x*(x*6.0 - 15.0) + 10.0); //Perlins smootherstep
#endif

// -- Curve 7 --
#if Curves_formula == 7
//x = ((x-0.5) / ((0.5/(4.0/3.0)) + abs((x-0.5)*1.25))) + 0.5;
x = x - 0.5;
x = x / ((abs(x)*1.25) + 0.375) + 0.5;
//x = ( (x-0.5) / ((abs(x-0.5)*1.25) + (0.5/(4.0/3.0))) ) + 0.5;
#endif

// -- Curve 8 --
#if Curves_formula == 8
x = (x * (x * (x * (x * (x * (x * (1.6 * x - 7.2) + 10.8) - 4.2) - 3.6) + 2.7) - 1.8) + 2.7) * x * x; //Techicolor Cinestyle - almost identical to curve 1
#endif

// -- Curve 9 --
#if Curves_formula == 9
x = -0.5 * (x*2.0 - 1.0) * (abs(x*2.0 - 1.0) - 2.0) + 0.5; //parabola
#endif

// -- Curve 10 --
#if Curves_formula == 10 //Half-circles

#if Curves_mode == 0
float xstep = step(x, 0.5);
float xstep_shift = (xstep - 0.5);
float shifted_x = x + xstep_shift;
#else
vec3 xstep = step(x, 0.5);
vec3 xstep_shift = (xstep - 0.5);
vec3 shifted_x = x + xstep_shift;

#endif

x = abs(xstep - sqrt(-shifted_x * shifted_x + shifted_x)) - xstep_shift;

//x = abs(step(x,0.5)-sqrt(-(x+step(x,0.5)-0.5)*(x+step(x,0.5)-0.5)+(x+step(x,0.5)-0.5)))-(step(x,0.5)-0.5); //single line version of the above

//x = 0.5 + (sign(x-0.5)) * sqrt(0.25-(x-trunc(x*2))*(x-trunc(x*2))); //worse

/* // if/else - even worse
if (x-0.5)
x = 0.5-sqrt(0.25-x*x);
else
x = 0.5+sqrt(0.25-(x-1)*(x-1));
*/

//x = (abs(step(0.5,x)-clamp( 1-sqrt(1-abs(step(0.5,x)- frac(x*2%1)) * abs(step(0.5,x)- frac(x*2%1))),0 ,1))+ step(0.5,x) )*0.5; //worst so far

//TODO: Check if I could use an abs split instead of step. It might be more efficient

Curves_contrast_blend = Curves_contrast * 0.5; //I divide by two to give it a strength closer to the other curves.
#endif

// -- Curve 11 --
#if Curves_formula == 11 //Cubic catmull
float a = 1.00; //control point 1
float b = 0.00; //start point
float c = 1.00; //endpoint
float d = 0.20; //control point 2
x = 0.5 * ((-a + 3 * b - 3 * c + d)*x*x*x + (2 * a - 5 * b + 4 * c - d)*x*x + (-a + c)*x + 2 * b); //A customizable cubic catmull-rom spline
#endif

// -- Curve 12 --
#if Curves_formula == 12 //Cubic Bezier spline
float a = 0.00; //start point
float b = 0.00; //control point 1
float c = 1.00; //control point 2
float d = 1.00; //endpoint

float r = (1 - x);
float r2 = r*r;
float r3 = r2 * r;
float x2 = x*x;
float x3 = x2*x;
//x = dot(float4(a,b,c,d),float4(r3,3*r2*x,3*r*x2,x3));

//x = a * r*r*r + r * (3 * b * r * x + 3 * c * x*x) + d * x*x*x;
//x = a*(1-x)*(1-x)*(1-x) +(1-x) * (3*b * (1-x) * x + 3 * c * x*x) + d * x*x*x;
x = a*(1 - x)*(1 - x)*(1 - x) + 3 * b*(1 - x)*(1 - x)*x + 3 * c*(1 - x)*x*x + d*x*x*x;
#endif

// -- Curve 13 --
#if Curves_formula == 13 //Cubic Bezier spline - alternative implementation.
vec3 a = vec3(0.00, 0.00, 0.00); //start point
vec3 b = vec3(0.25, 0.15, 0.85); //control point 1
vec3 c = vec3(0.75, 0.85, 0.15); //control point 2
vec3 d = vec3(1.00, 1.00, 1.00); //endpoint

vec3 ab = lerp(a, b, x);           // point between a and b
vec3 bc = lerp(b, c, x);           // point between b and c
vec3 cd = lerp(c, d, x);           // point between c and d
vec3 abbc = lerp(ab, bc, x);       // point between ab and bc
vec3 bccd = lerp(bc, cd, x);       // point between bc and cd
vec3 dest = lerp(abbc, bccd, x);   // point on the bezier-curve
x = dest;
#endif

// -- Curve 14 --
#if Curves_formula == 14
x = 1.0 / (1.0 + exp(-(x * 10.0 - 5.0))); //alternative exp formula
#endif

   //Joining of Luma and Chroma                 
#if Curves_mode == 2 //Both Luma and Chroma
vec3 col = x;  //if the curve should be applied to both Luma and Chroma
color.rgb = lerp(color.rgb, col, Curves_contrast_blend); //Blend by Curves_contrast

#elif Curves_mode == 1 //Only Chroma
x = x * 2.0 - 1.0; //adjust the Chroma range back to -1 -> 1
vec3 col = luma + x; //Luma + Chroma
color.rgb = lerp(color.rgb, col, Curves_contrast_blend); //Blend by Curves_contrast

#else // Curves_mode == 0 //Only Luma
x = lerp(luma, x, Curves_contrast_blend); //Blend by Curves_contrast
color.rgb = x + chroma; //Luma + Chroma
#endif
//Return the result
color.a = AvgLuminance(color.rgb);

return saturate(color);
}
#endif

/*------------------------------------------------------------------------------
[CROSS PROCESSING CODE SECTION]
------------------------------------------------------------------------------*/
#if CROSS_PROCESSING == 1

vec3 CrossShift(vec3 color)
{
vec3 cross;

vec2 CrossMatrix[3] = vec2[](
vec2(0.960, 0.040 * color.x),
vec2(0.980, 0.020 * color.y),
vec2(0.970, 0.030 * color.z));

cross.x = float(RedShift) * CrossMatrix[0].x + CrossMatrix[0].y;
cross.y = float(GreenShift) * CrossMatrix[1].x + CrossMatrix[1].y;
cross.z = float(BlueShift) * CrossMatrix[2].x + CrossMatrix[2].y;

float lum = AvgLuminance(color);
vec3 black = vec3(0.0, 0.0, 0.0);
vec3 white = vec3(1.0, 1.0, 1.0);

cross = lerp(black, cross, saturate(lum * 2.0));
cross = lerp(cross, white, saturate(lum - 0.5) * 2.0);
color = lerp(color, cross, saturate(lum * float(ShiftRatio)));

return color;
}

vec4 CrossPass(vec4 color, vec2 texcoord)
{
#if FilmicProcess == 1
color.rgb = CrossShift(color.rgb);

#elif FilmicProcess == 2
vec3 XYZ = RGBtoXYZ(color.rgb);
vec3 Yxy = XYZtoYxy(XYZ);

Yxy = CrossShift(Yxy);
XYZ = YxytoXYZ(Yxy);

color.rgb = XYZtoRGB(XYZ);

#elif FilmicProcess == 3
vec3 XYZ = RGBtoXYZ(color.rgb);
vec3 Yxy = XYZtoYxy(XYZ);

XYZ = YxytoXYZ(Yxy);
XYZ = CrossShift(XYZ);

color.rgb = XYZtoRGB(XYZ);
#endif

color.a = AvgLuminance(color.rgb);

return saturate(color);
}
#endif

/*------------------------------------------------------------------------------
[COLOR GRADING CODE SECTION]
------------------------------------------------------------------------------*/

#if COLOR_GRADING == 1
float RGBCVtoHUE(vec3 RGB, float C, float V)
{
vec3 Delta = (V - RGB) / C;

Delta.rgb -= Delta.brg;
Delta.rgb += vec3(2.0, 4.0, 6.0);
Delta.brg = step(V, RGB) * Delta.brg;

float H;
H = max(Delta.r, max(Delta.g, Delta.b));
return frac(H / 6);
}

vec3 HSVComplement(vec3 HSV)
{
vec3 complement = HSV;
complement.x -= 0.5;

if (complement.x < 0.0) {
complement.x += 1.0;
}
return(complement);
}

float HueLerp(float h1, float h2, float v)
{
float d = abs(h1 - h2);

if (d <= 0.5)
{
return lerp(h1, h2, v);
}
else if (h1 < h2)
{
return frac(lerp((h1 + 1.0), h2, v));
}
else
{
return frac(lerp(h1, (h2 + 1.0), v));
}
}

vec4 ColorGradingPass(vec4 color, vec2 texcoord)
{
vec3 guide = vec3(RedGrading, GreenGrading, BlueGrading);

float amount = GradingStrength;
float correlation = Correlation;
float concentration = 2.00;

vec3 colorHSV = RGBtoHSV(color.rgb);
vec3 huePoleA = RGBtoHSV(guide);
vec3 huePoleB = HSVComplement(huePoleA);

float dist1 = abs(colorHSV.x - huePoleA.x);
if (dist1 > 0.5) dist1 = 1.0 - dist1;

float dist2 = abs(colorHSV.x - huePoleB.x);
if (dist2 > 0.5) dist2 = 1.0 - dist2;

float descent = smoothstep(0.0, correlation, colorHSV.y);

vec3 HSVColor = colorHSV;

    if (dist1 < dist2) {

float c = descent * amount * (1.0 - pow((dist1 * 2.0), 1.0 / concentration));

HSVColor.x = HueLerp(colorHSV.x, huePoleA.x, c);
HSVColor.y = lerp(colorHSV.y, huePoleA.y, c);
}
else
{
float c = descent * amount * (1.0 - pow((dist2 * 2.0), 1.0 / concentration));

HSVColor.x = HueLerp(colorHSV.x, huePoleB.x, c);
HSVColor.y = lerp(colorHSV.y, huePoleB.y, c);
}

color.rgb = HSVtoRGB(HSVColor);

color.a = AvgLuminance(color.rgb);

return saturate(color);
}
#endif




/*------------------------------------------------------------------------------
[TV COLORS EMU CODE SECTION]
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
SimoneT NTSC TV colors emulation 1.0 Shader
Copyright (C) 2016 SimoneT - [email protected]
Credit to SimoneT.
------------------------------------------------------------------------------*/

#if NTSC_TV_EMULATION == 1

// conversion from NTSC RGB Reference White D65 ( color space used by NA/Japan TV's ) to XYZ
vec3 NTSC(vec3 c)
{
vec3 v = vec3(pow(c.r, 2.2), pow(c.g, 2.2), pow(c.b, 2.2)); //Inverse Companding
return v*mat3(
0.6068909, 0.1735011, 0.2003480,
0.2989164, 0.5865990, 0.1144845,
0.0000000, 0.0660957, 1.1162243);
}

// conversion from XYZ to sRGB Reference White D65 ( color space used by windows )
vec3 sRGB(vec3 c)
{
vec3 v = c*mat3(
3.2404542, -1.5371385, -0.4985314,
-0.9692660, 1.8760108, 0.0415560,
0.0556434, -0.2040259, 1.0572252);

//Companding
v.r = (v.r > 0.0031308) ? ((1.055 * pow(v.r, (1.0 / 2.4))) - 0.055) : 12.92 * v.r;
v.g = (v.g > 0.0031308) ? ((1.055 * pow(v.g, (1.0 / 2.4))) - 0.055) : 12.92 * v.g;
v.b = (v.b > 0.0031308) ? ((1.055 * pow(v.b, (1.0 / 2.4))) - 0.055) : 12.92 * v.b;
return v;
}

// NTSC RGB to sRGB
vec3 NTSCtoSRGB(vec3 c)
{
return sRGB(NTSC(c));
}

// Ported from SimoneT TV colors emulation 1.0 Shader
vec4 TvColorsPass(vec4 color, vec2 texcoord)
{
color.rgb = NTSCtoSRGB(color.rgb);

return color;
}
#endif





/*------------------------------------------------------------------------------
[MAIN() & COMBINE PASS CODE SECTION]
------------------------------------------------------------------------------*/

void main()
{
vec2 texcoord = gl_TexCoord[0].xy;
vec4 color = texture2D(OGLTexture0, texcoord);

#if USE_FXAA == 1
color = FXAAPass(color, texcoord);
#endif

#if GAMMA_CORRECTION == 1
color = GammaPass(color, texcoord);
#endif

#if PIXEL_VIBRANCE == 1
color = VibrancePass(color, texcoord);
#endif

#if BLENDED_BLOOM == 1
color = BloomPass(color, texcoord);
#endif

#if SCENE_TONEMAPPING == 1
color = TonemapPass(color, texcoord);
#endif

#if USE_CURVES == 1
color = CurvesPass(color, texcoord);
#endif

#if COLOR_CORRECTION == 1
color = CorrectionPass(color, texcoord);
#endif

#if CROSS_PROCESSING == 1
color = CrossPass(color, texcoord);
#endif

#if COLOR_GRADING == 1
color = ColorGradingPass(color, texcoord);
#endif


#if NTSC_TV_EMULATION == 1
color = TvColorsPass(color, texcoord);
#endif


gl_FragColor = color;
}


DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #54 on: 2017-05-17 15:10:59 »
Turning options on there does lead to a very close psx look. Where did you find that shader?  Is it on this forum?

Kaldarasha

  • No life
  • *
  • Posts: 2138
  • Karma: 129
  • Prince of Model Editing
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #55 on: 2017-05-17 15:51:56 »
Yep, in the graphic section: http://forums.qhimm.com/index.php?topic=17411.0

Edit:
Some wrong colored pixels (the blue ones) at the jump-in-holes in gldgate (don't know if this is fixed already):


« Last Edit: 2017-05-17 18:08:09 by Kaldarasha »

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #56 on: 2017-05-18 04:04:24 »
colour issues are listed there in the database.  Gldgate has now been added to the list (field 24).  Thanks :)

In meantime, I've been tweaking that shader to conform as closely to PSX but with superior colour and so on.  I had to calibrate my monitor, which also led to me getting aura migraine.  But it was worth it.  I don't think it's going to get much better than this on PC:

[Add as psx.post into 'shaders' folder in 1998 game root (when using Aali's driver), then edit ff7_opengl.cfg so that it uses it with post processing option.]

Code: [Select]
/*===============================================================================*\
|#######################   [FINAL FANTASY 7 SHADER FX]    ########################|
|#########################   By Sunwalker 21/Jan/2017   ##########################|
||                                Version 1.05                                   ||
||                                                                               ||
||          This program is free software; you can redistribute it and/or        ||
||          modify it under the terms of the GNU General Public License          ||
||          as published by the Free Software Foundation; either version 2       ||
||          of the License, or (at your option) any later version.               ||
||                                                                               ||
||          This program is distributed in the hope that it will be useful,      ||
||          but WITHOUT ANY WARRANTY; without even the implied warranty of       ||
||          MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        ||
||          GNU General Public License for more details. (c)2016                 ||
||                                                                               ||
|#################################################################################|
\*===============================================================================*/
#version 120

#extension GL_NV_gpu_shader5 : enable
#extension GL_ARB_gpu_shader5 : enable
#extension GL_ARB_shader_precision : enable
#extension GL_ARB_sample_shading : enable
#extension GL_ARB_texture_rectangle : enable
#extension GL_ARB_shader_storage_buffer_object : enable
#extension GL_ARB_shader_image_load_store : enable
#extension GL_ARB_bindless_texture : enable
#extension GL_ARB_shading_language_420pack : enable


/*------------------------------------------------------------------------------
[DEFINITIONS & ON/OFF OPTIONS]
------------------------------------------------------------------------------*/
//--------------------------#[CHOOSE EFFECTS]#--------------------------------\\
//#[ANTIALIASING TECHNIQUES]   [1=ON|0=OFF]  # NOTE:
#define USE_FXAA                  1      //# [0 or 1] FXAA Fast Anti-aliasing

//#[LIGHTING & COLOUR]         [1=ON|0=OFF]  # NOTE: This one can enable all
#define GAMMA_CORRECTION            1      //# RGB Gamma Correction. Fixed expansion to variable compression gamma correction curve.
#define BLENDED_BLOOM               1      //# High Quality SP Bloom. Soft lighting with blending techniques, for a natural looking bloom.
#define SCENE_TONEMAPPING           0      //# HDR Scene Tonemapping. Layered component conversion, and applies scene tone mapping.
#define COLOR_CORRECTION            1      //# Component Color Correction. Colorspace conversion, with correction curves, and multiple palette types.
#define CROSS_PROCESSING            0      //# Filmic Cross Processing. Alters the tone of the scene, crossing the game's color set, with another.
#define PIXEL_VIBRANCE              1      //# Pixel Vibrance. Intelligently adjusts pixel vibrance depending on original color saturation.
#define COLOR_GRADING               0      //# Post-Complement Colour Grading. Alters individual colour components on a scene, to enhance selected

colour tones.
#define USE_CURVES            1    //# [0 or 1] Curves : Contrast adjustments using S-curves.


//#[MISC]                      [1=ON|0=OFF]  # NOTE: Enable one only
#define NTSC_TV_EMULATION           0      //# SimoneT's TV Colors Emulation Shader. Use to emulate the original PSX color space tone, and vibrancy.
/*------------------------------------------------------------------------------
[EFFECT CONFIG OPTIONS]
------------------------------------------------------------------------------*/

//##[GAMMA_CORRECTION]
#define Gamma 2.20                            //[1.5 to 4.0] Gamma correction. Decrease for lower gamma(darker). Increase for higher gamma(brighter). (Default:

2.2)

//##[BLENDED_BLOOM]
#define BloomType BlendScreen                   //[BlendGlow, BlendAddGlow, BlendAddLight, BlendScreen, BlendLuma, BlendOverlay] The type of blended

bloom. Light<->Dark.
#define BloomStrength 0.200                   //[0.000 to 1.000] Overall strength of the bloom. You may want to readjust for each blend type.
#define BlendStrength 1.000                   //[0.000 to 1.000] Strength of the blending. This is a modifier based on bloom. 1.0 equates to 100% strength.
#define BloomDefocus 2.000                    //[1.000 to 4.000] The initial bloom defocus value. Increases the softness of light, bright objects, etc.
#define BloomWidth 3.200                      //[1.000 to 8.000] Width of the bloom. Adjusts the width of the spread and soft glow. Scales with BloomStrength.
#define BloomReds 0.040                       //[0.000 to 1.000] Red channel correction of the bloom. Raising will increase the bloom of reds.
#define BloomGreens 0.030                     //[0.000 to 1.000] Green channel correction of the bloom. Raising will increase the bloom of greens.
#define BloomBlues 0.020                      //[0.000 to 1.000] Blue channel correction of the bloom. Raising will increase the bloom of blues.

//##[SCENE_TONEMAPPING]
#define TonemapType 2                         //[0|1|2|3] The base tone mapping operator. 0 is LDR, 1 is HDR(original), 2 & 3 are Filmic HDR(slight grading).
#define TonemapMask 1                         //[0 or 1] Enables an ALU tone masking curve. Produces a nice cinematic look. Suits some games more than

others.
#define MaskStrength 0.10                     //[0.000 to 1.000] Strength of the tone masking. Higher for a stronger effect. This is a dependency of

TonemapMask.
#define ToneAmount 0.360                      //[0.050 to 1.000] Tonemap strength (tone correction). Higher for stronger tone mapping, lower for lighter.
#define BlackLevels 0.060                     //[0.000 to 1.000] Black level balance (shadow correction). Increase to deepen blacks, lower to lighten them.
#define Exposure 1.000                        //[0.100 to 2.000] White correction (brightness). Higher values for more scene exposure, lower for less.
#define Luminance 1.000                       //[0.100 to 2.000] Luminance average (luminance correction). Higher values will lower scene luminance average.
#define WhitePoint 1.075                      //[0.100 to 2.000] Whitepoint average (wp lum correction). Higher values will lower the maximum scene white point.

//##[COLOR_CORRECTION]
#define CorrectionPalette 1                   //[1|2|3|4|5] The colorspace palette type. 1: RGB, 2: YXY, 3: XYZ, 4: HSV, 5: YUV. Each one will produce a different

combination of shades & hues.
#define ChannelR 1.40                         //[0.00 to 8.00] R(1), Y(2), X(3), H(4), Y(5) component channel varies with the colorspace used. Higher values

increase correction strength.
#define ChannelG 1.60                         //[0.00 to 8.00] G(1), X(2), Y(3), S(4), U(5) component channel varies with the colorspace used. Higher values

increase correction strength.
#define ChannelB 1.80                         //[0.00 to 8.00] B(1), Y(2), Z(3), V(4), V(5) component channel varies with the colorspace used. Higher values

increase correction strength.
#define PaletteStrength 2.00                  //[0.00 to 4.00] The interpolated strength ratio between the base color, and the corrected color. Raise to increase

saturation.

//##[PIXEL_VIBRANCE]
#define Vibrance 0.15                          //[-1.00 to 1.00] Overall vibrance strength. Locally adjusts the vibrance of pixels depending on their original

saturation.
#define RedVibrance 1.00                       //[-8.00 to 8.00] Red channel coefficient of the vibrance strength. Adjusting the vibrance of the red channel

independently.
#define GreenVibrance 1.00                     //[-8.00 to 8.00] Green channel coefficient of the vibrance strength. Adjusting the vibrance of the green channel

independently.
#define BlueVibrance 1.00                      //[-8.00 to 8.00] Blue channel coefficient of the vibrance strength. Adjusting the vibrance of the blue channel

independently.

//##[CROSS_PROCESSING]
#define FilmicProcess 1                         //[1|2|3] The color conversion type for the cross process. 1: cool, 2: warm, 3: dusk. You can achieve different

results with each.
#define RedShift 0.65                           //[0.10 to 1.00] Red color component shift of the filmic processing. Alters the red balance of the shift.
#define GreenShift 0.50                         //[0.10 to 1.00] Green color component shift of the filmic processing. Alters the green balance of the shift.
#define BlueShift 0.50                          //[0.10 to 1.00] Blue color component shift of the filmic processing. Alters the blue balance of the shift.
#define ShiftRatio 0.50                         //[0.10 to 2.00] The blending ratio for the base color and the color shift. Higher for a stronger effect.

//##[COLOR_GRADING]
#define RedGrading 1.20                         //[0.00 to 3.00] Red colour grading coefficient. Adjust to influence the red channel coefficients of the grading, and

highlight tones.
#define GreenGrading 1.10                       //[0.00 to 3.00] Green colour grading coefficient. Adjust to influence the Green channel coefficients of the

grading, and highlight tones.
#define BlueGrading 1.10                        //[0.00 to 3.00] Blue colour grading coefficient. Adjust to influence the Blue channel coefficients of the grading,

and highlight tones.
#define GradingStrength 0.35                    //[0.00 to 1.00] The overall max strength of the colour grading effect. Raise to increase, lower to decrease the

amount.
#define Correlation 1.00                        //[0.10 to 1.00] Correlation between the base colour, and the grading influence. Lower = more of the scene is

graded, Higher = less of the scene is graded.

//##[USE_CURVES]
#define Curves_mode        2             //[0|1|2] Choose what to apply contrast to. 0 = Luma, 1 = Chroma, 2 = both Luma and

Chroma. Default is 0 (Luma)
#define Curves_contrast 0.20         //[-1.00 to 1.00] The amount of contrast you want

//##[Advanced curve settings]
#define Curves_formula      3             //[1|2|3|4|5|6|7|8|9|10] The contrast s-curve you want to use.
                                      //1 = Sine, 2 = Abs split, 3 = Smoothstep, 4 = Exp formula, 5 = Simplified Catmull-Rom (0,0,1,1), 6 =

Perlins Smootherstep
                                      //7 = Abs add, 8 = Techicolor Cinestyle, 9 = Parabola, 10 = Half-circles.
                                      //Note that Technicolor Cinestyle is practically identical to Sine, but runs slower. In fact I think the difference

might only be due to rounding errors.
                                      //I prefer 2 myself, but 3 is a nice alternative with a little more effect (but harsher on the highlight and

shadows) and it's the fastest formula


//[END OF USER OPTIONS]

/*------------------------------------------------------------------------------
[GLOBALS|FUNCTIONS]
------------------------------------------------------------------------------*/

//Global variables
#define saturate(x) clamp(x, 0.0, 1.0)
#define lerp mix
#define frac fract
#define fmod mod
#define mul(x, y) (y * x)
#define float4x3 mat4x3
#define float3x3 mat3
#define float4x4 mat4
#define lumCoeff vec3(0.212656, 0.715158, 0.072186)
#define PI 3.1415972

//OGL Uniforms
uniform sampler2D OGLTexture;
uniform sampler2D OGLTexture0;

//varying
uniform vec2 texcoord;

float Epsilon = 1e-10;

#define texture_width   1024.0
#define texture_height  1024.0

#define texel_size_x  (1.0 / texture_width)
#define texel_size_y  (1.0 / texture_height)

#define OGLSize     vec2(texture_width, texture_height)
#define OGLInvSize  vec2(texel_size_x, texel_size_y)

//Average Relative Luminance (HSP Color Model)
float AvgLuminance(vec3 color)
{
return sqrt(dot(color * color, lumCoeff));
}

//Smoothstep alt
float smootherstep(float a, float b, float x)
{
x = saturate((x - a) / (b - a));
return x*x*x*(x*(x * 6 - 15) + 10);
}

//Conversion matrices
vec3 RGBtoXYZ(vec3 RGB)
{
const mat3 RGBtoXYZ = mat3(
0.6068909, 0.1735011, 0.2003480,
0.2989164, 0.5865990, 0.1144845,
0.0000000, 0.0660957, 1.1162243);

return RGBtoXYZ*RGB;
}

vec3 XYZtoRGB(vec3 XYZ)
{
const mat3 XYZtoRGB = mat3(
1.9099961, -0.5324542, -0.2882091,
-0.9846663, 1.9991710, -0.0283082,
0.0583056, -0.1183781, 0.8975535);

return XYZtoRGB*XYZ;
}

vec3 XYZtoSRGB(vec3 XYZ)
{
const mat3 XYZtoSRGB = mat3(
3.2404542, -1.5371385, -0.4985314,
-0.9692660, 1.8760108, 0.0415560,
0.0556434, -0.2040259, 1.0572252);

return XYZtoSRGB*XYZ;
}

vec3 RGBtoYUV(vec3 RGB)
{
const mat3 RGBtoYUV = mat3(
0.2126, 0.7152, 0.0722,
-0.09991, -0.33609, 0.436,
0.615, -0.55861, -0.05639);

return RGBtoYUV*RGB;
}

vec3 YUVtoRGB(vec3 YUV)
{
const mat3 YUVtoRGB = mat3(
1.000, 0.000, 1.28033,
1.000, -0.21482, -0.38059,
1.000, 2.12798, 0.000);

return YUVtoRGB*YUV;
}

vec3 XYZtoYxy(vec3 XYZ)
{
float w = (XYZ.r + XYZ.g + XYZ.b);
vec3 Yxy;

Yxy.r = XYZ.g;
Yxy.g = XYZ.r / w;
Yxy.b = XYZ.g / w;

return Yxy;
}

vec3 YxytoXYZ(vec3 Yxy)
{
vec3 XYZ;
XYZ.g = Yxy.r;
XYZ.r = Yxy.r * Yxy.g / Yxy.b;
XYZ.b = Yxy.r * (1.0 - Yxy.g - Yxy.b) / Yxy.b;

return XYZ;
}

/*------------------------------------------------------------------------------
[FXAA CODE SECTION]
Code from http://www.geeks3d.com/20110405/fxaa-fast-approximate-anti-aliasing-demo-glsl-opengl-test-radeon-geforce/3/
Credit to original Author
------------------------------------------------------------------------------*/
#if USE_FXAA == 1
float xbrthreshold = 0.020;
vec2 rcpFrame = OGLInvSize;
vec3 FXAA(sampler2D OGLTexture, vec2 texcoord)
{
float FXAA_SPAN_MAX = 8.0;                     //[4.0 t0 8.0]             
float FXAA_REDUCE_MUL = (1.0 / FXAA_SPAN_MAX); //[Default]
float FXAA_REDUCE_MIN = (1.0 / 128.0);         //[Default]
float FXAA_SUBPIX_SHIFT = (1.0 / 4.0);         //[Default]

vec4 posPos = vec4(texcoord.xy, texcoord.xy - (rcpFrame * (0.5 + FXAA_SUBPIX_SHIFT)));

/*---------------------------------------------------------*/
vec3 rgbNW = texture2D(OGLTexture, posPos.zw, 0.0).rgb;
vec3 rgbNE = texture2D(OGLTexture, posPos.zw + vec2(1., 0.)*rcpFrame.xy, 0.0).rgb;
vec3 rgbSW = texture2D(OGLTexture, posPos.zw + vec2(0., 1.)*rcpFrame.xy, 0.0).rgb;
vec3 rgbSE = texture2D(OGLTexture, posPos.zw + vec2(1., 1.)*rcpFrame.xy, 0.0).rgb;
vec3 rgbM = texture2D(OGLTexture, texcoord.xy, 0.0).rgb;
/*---------------------------------------------------------*/
//vec3 luma = vec3(0.299, 0.587, 0.114);
float lumaNW = AvgLuminance(rgbNW);
float lumaNE = AvgLuminance(rgbNE);
float lumaSW = AvgLuminance(rgbSW);
float lumaSE = AvgLuminance(rgbSE);
float lumaM = AvgLuminance(rgbM);
/*---------------------------------------------------------*/
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));

float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
/*---------------------------------------------------------*/
vec2 dir;

dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));

dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
/*---------------------------------------------------------*/
float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) * (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);

float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);

dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX), max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX), dir * rcpDirMin)) *

rcpFrame.xy;
/*--------------------------------------------------------*/

vec3 rgbA = (1.0 / 2.0) * (texture2D(OGLTexture, texcoord.xy + dir * (1.0 / 3.0 - 0.5)).rgb + texture2D(OGLTexture, texcoord.xy + dir * (2.0 / 3.0 -

0.5)).rgb);
vec3 rgbB = rgbA * (1.0 / 2.0) + (1.0 / 4.0) * (texture2D(OGLTexture, texcoord.xy + dir * (0.0 / 3.0 - 0.5)).rgb + texture2D(OGLTexture,

texcoord.xy + dir * (3.0 / 3.0 - 0.5)).rgb);

float lumaB = AvgLuminance(rgbB);

return ((lumaB < lumaMin) || (lumaB > lumaMax)) ? rgbA.rgb : rgbB.rgb;
}

//Hyllian's xBR Level 2 shader
//Copyright(C) 2011 / 2014 Hyllian / Jararaca - [email protected]
//Credit to Hyllian
float x_Width = texture_width;
float y_Height = texture_height;

float x_coef = texel_size_x;
float y_coef = texel_size_y;

float coef = 2.0;
vec3 rgbw = vec3(14.352, 28.176, 5.472);

float x = 0.5 * (1.0 / x_Width);
float y = 0.5 * (1.0 / y_Height);

//vec2 dx = vec2(x, 0.0);
//vec2 dy = vec2(0.0, y);
vec2 dx = vec2(0.0009765625, 0.0);//vec2(x, 0.0);//
vec2 dy = vec2(0.0, 0.001953125);//vec2(0.0, y);//
vec2 x2 = vec2(0.001953125, 0.0);//vec2(y, 0);//
vec2 y2 = vec2(0.0, 0.00390625);//vec2( 0.0 , y*2.0 );//
vec4 xy = vec4(0.0009765625, 0.001953125, -0.0009765625, -0.001953125);//vec4( x, y,-x,-y);//
vec4 zw = vec4(0.001953125, 0.001953125, -0.001953125, -0.00390625);//vec4( y , y,-y ,-(y*2.0));//
vec4 wz = vec4(0.0009765625, 0.00390625, -0.0009765625, -0.00390625);  //vec4( x, y*2.0 ,-x,-(y*2.0));//

vec4 df(vec4 A, vec4 B)
{
return abs(A - B);
}

vec4 weighted_distance(vec4 a, vec4 b, vec4 c, vec4 d, vec4 e, vec4 f, vec4 g, vec4 h)
{
return (df(a, b) + df(a, c) + df(d, e) + df(d, f) + 4.0*df(g, h));
}


vec3 xBR(sampler2D OGLTexture, vec2 texcoord)
{
vec4 edr, edr_left, edr_up; bvec4 px; // px = pixel, edr = edge detection rule
vec4 interp_restriction_lv1, interp_restriction_lv2_left, interp_restriction_lv2_up;
bvec4 nc; // new_color
vec4 fx, fx_left, fx_up; // inequations of straight lines.

vec2 fp = fract(texcoord.xy*vec2(x_Width, y_Height));
vec2 vTex = texcoord.xy - fp*vec2(0.0009765625*x_coef, 0.001953125*y_coef);//vec2(x, y);

vec3 A = texture2D(OGLTexture, vTex + xy.zw).rgb;
vec3 B = texture2D(OGLTexture, vTex - dy).rgb;
vec3 C = texture2D(OGLTexture, vTex + xy.xw).rgb;
vec3 D = texture2D(OGLTexture, vTex - dx).rgb;
vec3 E = texture2D(OGLTexture, vTex).rgb;
vec3 F = texture2D(OGLTexture, vTex + dx).rgb;
vec3 G = texture2D(OGLTexture, vTex + xy.zy).rgb;
vec3 H = texture2D(OGLTexture, vTex + dy).rgb;
vec3 I = texture2D(OGLTexture, vTex + xy.xy).rgb;
vec3 A1 = texture2D(OGLTexture, vTex + wz.zw).rgb;
vec3 C1 = texture2D(OGLTexture, vTex + wz.xw).rgb;
vec3 A0 = texture2D(OGLTexture, vTex + zw.zw).rgb;
vec3 G0 = texture2D(OGLTexture, vTex + zw.zy).rgb;
vec3 C4 = texture2D(OGLTexture, vTex + zw.xw).rgb;
vec3 I4 = texture2D(OGLTexture, vTex + zw.xy).rgb;
vec3 G5 = texture2D(OGLTexture, vTex + wz.zy).rgb;
vec3 I5 = texture2D(OGLTexture, vTex + wz.xy).rgb;
vec3 B1 = texture2D(OGLTexture, vTex - y2).rgb;
vec3 D0 = texture2D(OGLTexture, vTex - x2).rgb;
vec3 H5 = texture2D(OGLTexture, vTex + y2).rgb;
vec3 F4 = texture2D(OGLTexture, vTex + x2).rgb;

vec4 b = vec4(dot(B, rgbw), dot(D, rgbw), dot(H, rgbw), dot(F, rgbw));
vec4 c = vec4(dot(C, rgbw), dot(A, rgbw), dot(G, rgbw), dot(I, rgbw));
vec4 d = b.yzwx;
vec4 e = vec4(dot(E, rgbw));
vec4 f = b.wxyz;
vec4 g = c.zwxy;
vec4 h = b.zwxy;
vec4 i = c.wxyz;
vec4 i4 = vec4(dot(I4, rgbw), dot(C1, rgbw), dot(A0, rgbw), dot(G5, rgbw));
vec4 i5 = vec4(dot(I5, rgbw), dot(C4, rgbw), dot(A1, rgbw), dot(G0, rgbw));
vec4 h5 = vec4(dot(H5, rgbw), dot(F4, rgbw), dot(B1, rgbw), dot(D0, rgbw));
vec4 f4 = h5.yzwx;

vec4 Ao = vec4(1.0, -1.0, -1.0, 1.0);
vec4 Bo = vec4(1.0, 1.0, -1.0, -1.0);
vec4 Co = vec4(1.5, 0.5, -0.5, 0.5);
vec4 Ax = vec4(1.0, -1.0, -1.0, 1.0);
vec4 Bx = vec4(0.5, 2.0, -0.5, -2.0);
vec4 Cx = vec4(1.0, 1.0, -0.5, 0.0);
vec4 Ay = vec4(1.0, -1.0, -1.0, 1.0);
vec4 By = vec4(2.0, 0.5, -2.0, -0.5);
vec4 Cy = vec4(2.0, 0.0, -1.0, 0.5);
vec4 Ci = vec4(0.25, 0.25, 0.25, 0.25);

// These inequations define the line below which interpolation occurs.
fx = vec4(greaterThan(Ao*fp.y + Bo*fp.x, Co));
fx_left = vec4(greaterThan(Ax*fp.y + Bx*fp.x, Cx));
fx_up = vec4(greaterThan(Ay*fp.y + By*fp.x, Cy));

interp_restriction_lv1 = vec4(notEqual(e, f))*vec4(notEqual(e, h));
interp_restriction_lv2_left = vec4(notEqual(e, g))*vec4(notEqual(d, g));
interp_restriction_lv2_up = vec4(notEqual(e, c))*vec4(notEqual(b, c));

edr = vec4(lessThan(weighted_distance(e, c, g, i, h5, f4, h, f), weighted_distance(h, d, i5, f, i4, b, e, i)))*interp_restriction_lv1;
edr_left = vec4(lessThanEqual(coef*df(f, g), df(h, c)))*interp_restriction_lv2_left;
edr_up = vec4(greaterThanEqual(df(f, g), coef*df(h, c)))*interp_restriction_lv2_up;

nc = bvec4(edr*(max(max(fx, edr_left*fx_left), edr_up*fx_up)));

px = lessThanEqual(df(e, f), df(e, h));

vec3 res = nc.x ? px.x ? F : H : nc.y ? px.y ? B : F : nc.z ? px.z ? D : B : nc.w ? px.w ? H : D : E;

return res;
}

float diff2D(vec2 coord)
{
vec3 dt = vec3(1.0, 1.0, 1.0);

vec3 c00 = texture2D(OGLTexture, coord + 0.25*(-dx - dy)).xyz;
vec3 c20 = texture2D(OGLTexture, coord + 0.25*(dx - dy)).xyz;
vec3 c02 = texture2D(OGLTexture, coord + 0.25*(-dx + dy)).xyz;
vec3 c22 = texture2D(OGLTexture, coord + 0.25*(dx + dy)).xyz;

vec3 mn = min(min(c00, c20), min(c02, c22));
vec3 mx = max(max(c00, c20), max(c02, c22));

return dot(mx - mn, dt);
}

vec4 FXAAPass(vec4 color, vec2 texcoord)
{
vec2 fp = fract(texcoord * OGLSize);
vec2 vTex = texcoord - fp * OGLInvSize + 0.5 * OGLInvSize;
vec2 locator = sign(fp - vec2(0.5000000001, 0.5000000001));

float maxdiff = max(max(diff2D(vTex + locator*dx), diff2D(vTex + locator*dy)), diff2D(vTex));

if (maxdiff <= xbrthreshold) { color.rgb = xBR(OGLTexture, texcoord); }
else { color.rgb = FXAA(OGLTexture, texcoord); }

color.a = AvgLuminance(color.rgb);

return color;
}
#endif

/*------------------------------------------------------------------------------
[GAMMA CORRECTION CODE SECTION]
------------------------------------------------------------------------------*/

vec3 EncodeGamma(vec3 color, float gamma)
{
color = saturate(color);
color.r = (color.r <= 0.0404482362771082) ? color.r / 12.92 : pow((color.r + 0.055) / 1.055, gamma);
color.g = (color.g <= 0.0404482362771082) ? color.g / 12.92 : pow((color.g + 0.055) / 1.055, gamma);
color.b = (color.b <= 0.0404482362771082) ? color.b / 12.92 : pow((color.b + 0.055) / 1.055, gamma);

return color;
}

vec3 DecodeGamma(vec3 color, float gamma)
{
color = saturate(color);
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;
}

#if GAMMA_CORRECTION == 1
vec4 GammaPass(vec4 color, vec2 texcoord)
{
const float GammaConst = 2.233333;
color.rgb = EncodeGamma(color.rgb, GammaConst);
color.rgb = DecodeGamma(color.rgb, float(Gamma));
color.a = AvgLuminance(color.rgb);

return color;
}
#endif

/*------------------------------------------------------------------------------
[PIXEL VIBRANCE CODE SECTION]
------------------------------------------------------------------------------*/

#if PIXEL_VIBRANCE == 1
vec4 VibrancePass(vec4 color, vec2 texcoord)
{
float vib = Vibrance;

float lum = AvgLuminance(color.rgb);
vec3 luma = vec3(lum, lum, lum);

float colorMax = max(color.r, max(color.g, color.b));
float colorMin = min(color.r, min(color.g, color.b));

float colorSaturation = colorMax - colorMin;
vec3 colorCoeff = vec3(RedVibrance * vib, GreenVibrance * vib, BlueVibrance * vib);

color.rgb = lerp(luma, color.rgb, (1.0 + (colorCoeff * (1.0 - (sign(colorCoeff) * colorSaturation)))));
color.a = AvgLuminance(color.rgb);

return saturate(color); //Debug: return colorSaturation.xxxx;
}
#endif

/*------------------------------------------------------------------------------
[BLENDED BLOOM CODE SECTION]
------------------------------------------------------------------------------*/

#if BLENDED_BLOOM == 1
vec3 BlendAddLight(vec3 bloom, vec3 blend)
{
return saturate(bloom + blend);
}

vec3 BlendScreen(vec3 bloom, vec3 blend)
{
return (bloom + blend) - (bloom * blend);
}

vec3 BlendGlow(vec3 bloom, vec3 blend)
{
float glow = AvgLuminance(bloom);
return lerp((bloom + blend) - (bloom * blend), (blend + blend) - (blend * blend), glow);
}

vec3 BlendAddGlow(vec3 bloom, vec3 blend)
{
float addglow = smootherstep(0.0, 1.0, AvgLuminance(bloom));
return lerp(saturate(bloom + blend), (blend + blend) - (blend * blend), addglow);
}

vec3 BlendLuma(vec3 bloom, vec3 blend)
{
float lumavg = smootherstep(0.0, 1.0, AvgLuminance(bloom + blend));
return lerp((bloom * blend), (1.0 - ((1.0 - bloom) * (1.0 - blend))), lumavg);
}

vec3 BlendOverlay(vec3 bloom, vec3 blend)
{
vec3 overlay = step(0.5, bloom);
return lerp((bloom * blend * 2.0), (1.0 - (2.0 *(1.0 - bloom) * (1.0 - blend))), overlay);
}

vec3 BloomCorrection(vec3 color)
{
vec3 bloom = color;

bloom.r = 2.0 / 3.0 * (1.0 - (bloom.r * bloom.r));
bloom.g = 2.0 / 3.0 * (1.0 - (bloom.g * bloom.g));
bloom.b = 2.0 / 3.0 * (1.0 - (bloom.b * bloom.b));

bloom.r = saturate(color.r + float(BloomReds) * bloom.r);
bloom.g = saturate(color.g + float(BloomGreens) * bloom.g);
bloom.b = saturate(color.b + float(BloomBlues) * bloom.b);
color = bloom;
return color;
}

vec4 DefocusFilter(sampler2D OGLTexture, vec2 texcoord, vec2 defocus)
{
defocus = clamp(defocus, 1.0, 1.5);
vec2 texel = vec2(texel_size_x, texel_size_y) * defocus;

vec4 sampleA = texture2D(OGLTexture, texcoord + vec2(0.5, 0.5) * texel);
vec4 sampleB = texture2D(OGLTexture, texcoord + vec2(-0.5, 0.5) * texel);
vec4 sampleC = texture2D(OGLTexture, texcoord + vec2(0.5, -0.5) * texel);
vec4 sampleD = texture2D(OGLTexture, texcoord + vec2(-0.5, -0.5) * texel);

float fx = frac(texcoord.x * texture_width);
float fy = frac(texcoord.y * texture_height);

vec4 interpolateA = lerp(sampleA, sampleB, fx);
vec4 interpolateB = lerp(sampleC, sampleD, fx);
return lerp(interpolateA, interpolateB, fy);
}

vec4 BloomPass(vec4 color, vec2 texcoord)
{
float anflare = 4.0;
float width = BloomWidth;

vec2 defocus = vec2(BloomDefocus, BloomDefocus);
vec4 bloom = DefocusFilter(OGLTexture, texcoord, defocus);

vec2 dx = vec2(texel_size_x * width, 0.0);
vec2 dy = vec2(0.0, texel_size_y * width);

vec2 mdx = vec2(dx.x * defocus.x, 0.0);
vec2 mdy = vec2(0.0, dy.y * defocus.y);

vec4 blend = bloom * 0.22520613262190495;

blend += 0.002589001911021066 * texture2D(OGLTexture, texcoord - mdx + mdy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord - dx + mdy);
blend += 0.024146616900339800 * texture2D(OGLTexture, texcoord + mdy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord + dx + mdy);
blend += 0.002589001911021066 * texture2D(OGLTexture, texcoord + mdx + mdy);

blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord - mdx + dy);
blend += 0.044875475183061630 * texture2D(OGLTexture, texcoord - dx + dy);
blend += 0.100529757860782610 * texture2D(OGLTexture, texcoord + dy);
blend += 0.044875475183061630 * texture2D(OGLTexture, texcoord + dx + dy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord + mdx + dy);

blend += 0.024146616900339800 * texture2D(OGLTexture, texcoord - mdx);
blend += 0.100529757860782610 * texture2D(OGLTexture, texcoord - dx);
blend += 0.100529757860782610 * texture2D(OGLTexture, texcoord + dx);
blend += 0.024146616900339800 * texture2D(OGLTexture, texcoord + mdx);

blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord - mdx - dy);
blend += 0.044875475183061630 * texture2D(OGLTexture, texcoord - dx - dy);
blend += 0.100529757860782610 * texture2D(OGLTexture, texcoord - dy);
blend += 0.044875475183061630 * texture2D(OGLTexture, texcoord + dx - dy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord + mdx - dy);

blend += 0.002589001911021066 * texture2D(OGLTexture, texcoord - mdx - mdy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord - dx - mdy);
blend += 0.024146616900339800 * texture2D(OGLTexture, texcoord - mdy);
blend += 0.010778807494659370 * texture2D(OGLTexture, texcoord + dx - mdy);
blend += 0.002589001911021066 * texture2D(OGLTexture, texcoord + mdx - mdy);
blend = lerp(color, blend, float(BlendStrength));

bloom.xyz = BloomType(bloom.xyz, blend.xyz);
bloom.xyz = BloomCorrection(bloom.xyz);

color.w = AvgLuminance(color.xyz);
bloom.w = AvgLuminance(bloom.xyz);
bloom.w *= anflare;

color = lerp(color, bloom, float(BloomStrength));

return color;
}
#endif

/*------------------------------------------------------------------------------
[SCENE TONE MAPPING CODE SECTION]
------------------------------------------------------------------------------*/

#if SCENE_TONEMAPPING == 1

vec3 ScaleLuminance(vec3 x)
{
float W = 1.02; // WhitePoint Scale
float L = 0.16; // Luminance Scale
float C = 1.02; // Compression Scale

float N = clamp(0.82 + ToneAmount, 1.0, 2.0);
float K = (N - L * C) / C;

vec3 tone = L * C + (1.0 - L * C) * (1.0 + K * (x - L) / ((W - L) * (W - L))) * (x - L) / (x - L + K);

vec3 color;
color.r = (x.r > L) ? tone.r : C * x.r;
color.g = (x.g > L) ? tone.g : C * x.g;
color.b = (x.b > L) ? tone.b : C * x.b;

return color;
}

vec3 TmMask(vec3 color)
{
vec3 tone = color;

float highTone = 6.2;
float greyTone = 0.4;
float midTone = 1.62;
float lowTone = 0.06;

tone.r = (tone.r * (highTone * tone.r + greyTone)) / (tone.r * (highTone * tone.r + midTone) + lowTone);
tone.g = (tone.g * (highTone * tone.g + greyTone)) / (tone.g * (highTone * tone.g + midTone) + lowTone);
tone.b = (tone.b * (highTone * tone.b + greyTone)) / (tone.b * (highTone * tone.b + midTone) + lowTone);

const float gamma = 2.42;
tone = EncodeGamma(tone, gamma);

color = lerp(color, tone, float(MaskStrength));

return color;
}

vec3 TmCurve(vec3 color)
{
vec3 T = color;

float tnamn = ToneAmount;
float blevel = length(T);
float bmask = pow(blevel, 0.02);

float A = 0.100; float B = 0.300;
float C = 0.100; float D = tnamn;
float E = 0.020; float F = 0.300;

float W = 1.000;

T.r = ((T.r*(A*T.r + C*B) + D*E) / (T.r*(A*T.r + B) + D*F)) - E / F;
T.g = ((T.g*(A*T.g + C*B) + D*E) / (T.g*(A*T.g + B) + D*F)) - E / F;
T.b = ((T.b*(A*T.b + C*B) + D*E) / (T.b*(A*T.b + B) + D*F)) - E / F;

float denom = ((W*(A*W + C*B) + D*E) / (W*(A*W + B) + D*F)) - E / F;

vec3 black = vec3(bmask, bmask, bmask);
vec3 white = vec3(denom, denom, denom);

T = T / white;
T = T * black;

color = saturate(T);

return color;
}

vec4 TonemapPass(vec4 color, vec2 texcoord)
{
float L = Luminance;

vec3 tonemap = color.rgb;
vec3 luma = vec3(L, L, L);

float blackLevel = length(tonemap);
tonemap = ScaleLuminance(tonemap);

float luminanceAverage = AvgLuminance(luma);

if (TonemapMask == 1) { tonemap = TmMask(tonemap); }
if (TonemapType == 1) { tonemap = TmCurve(tonemap); }

// RGB -> XYZ conversion
vec3 XYZ = RGBtoXYZ(tonemap);

// XYZ -> Yxy conversion
vec3 Yxy;

Yxy.r = XYZ.g;                                  // copy luminance Y
Yxy.g = XYZ.r / (XYZ.r + XYZ.g + XYZ.b);        // x = X / (X + Y + Z)
Yxy.b = XYZ.g / (XYZ.r + XYZ.g + XYZ.b);        // y = Y / (X + Y + Z)

// (Wt) Tone mapped scaling of the initial wp before input modifiers
float Wt = saturate(Yxy.r / AvgLuminance(XYZ));

if (TonemapType == 2) { Yxy.r = TmCurve(Yxy).r; }

// (Lp) Map average luminance to the middlegrey zone by scaling pixel luminance
float Lp = Yxy.r * float(Exposure) / (luminanceAverage + Epsilon);

// (Wp) White point calculated, based on the toned white, and input modifier
float Wp = dot(abs(Wt), float(WhitePoint));

// (Ld) Scale all luminance within a displayable range of 0 to 1
Yxy.r = (Lp * (1.0 + Lp / (Wp * Wp))) / (1.0 + Lp);

// Yxy -> XYZ conversion
XYZ.r = Yxy.r * Yxy.g / Yxy.b;                  // X = Y * x / y
XYZ.g = Yxy.r;                                  // copy luminance Y
XYZ.b = Yxy.r * (1.0 - Yxy.g - Yxy.b) / Yxy.b;  // Z = Y * (1-x-y) / y

if (TonemapType == 3) { XYZ = TmCurve(XYZ); }

// XYZ -> RGB conversion
tonemap = XYZtoRGB(XYZ);

float shadowmask = pow(saturate(blackLevel), float(BlackLevels));
tonemap = tonemap * vec3(shadowmask, shadowmask, shadowmask);

color.rgb = tonemap;

color.a = AvgLuminance(color.rgb);

return color;
}
#endif

/*------------------------------------------------------------------------------
[COLOR CORRECTION CODE SECTION]
------------------------------------------------------------------------------*/

// Converting pure hue to RGB
vec3 HUEtoRGB(float H)
{
float R = abs(H * 6.0 - 3.0) - 1.0;
float G = 2.0 - abs(H * 6.0 - 2.0);
float B = 2.0 - abs(H * 6.0 - 4.0);

return saturate(vec3(R, G, B));
}

// Converting RGB to hue/chroma/value
vec3 RGBtoHCV(vec3 RGB)
{
vec4 BG = vec4(RGB.bg, -1.0, 2.0 / 3.0);
vec4 GB = vec4(RGB.gb, 0.0, -1.0 / 3.0);

vec4 P = (RGB.g < RGB.b) ? BG : GB;

vec4 XY = vec4(P.xyw, RGB.r);
vec4 YZ = vec4(RGB.r, P.yzx);

vec4 Q = (RGB.r < P.x) ? XY : YZ;

float C = Q.x - min(Q.w, Q.y);
float H = abs((Q.w - Q.y) / (6.0 * C + Epsilon) + Q.z);

return vec3(H, C, Q.x);
}

// Converting RGB to HSV
vec3 RGBtoHSV(vec3 RGB)
{
vec3 HCV = RGBtoHCV(RGB);
float S = HCV.y / (HCV.z + Epsilon);

return vec3(HCV.x, S, HCV.z);
}

// Converting HSV to RGB
vec3 HSVtoRGB(vec3 HSV)
{
vec3 RGB = HUEtoRGB(HSV.x);
return ((RGB - 1.0) * HSV.y + 1.0) * HSV.z;
}

#if COLOR_CORRECTION == 1
// Pre correction color mask
vec3 PreCorrection(vec3 color)
{
vec3 RGB = color;

RGB.r = 2.0 / 3.0 * (1.0 - (RGB.r * RGB.r));
RGB.g = 2.0 / 3.0 * (1.0 - (RGB.g * RGB.g));
RGB.b = 2.0 / 3.0 * (1.0 - (RGB.b * RGB.b));

RGB.r = saturate(color.r + (float(ChannelR) / 200.0) * RGB.r);
RGB.g = saturate(color.g + (float(ChannelG) / 200.0) * RGB.g);
RGB.b = saturate(color.b + (float(ChannelB) / 200.0) * RGB.b);

color = saturate(RGB);

return color;
}

vec3 ColorCorrection(vec3 color)
{
float X = 1.0 / (1.0 + exp(float(ChannelR) / 2.0));
float Y = 1.0 / (1.0 + exp(float(ChannelG) / 2.0));
float Z = 1.0 / (1.0 + exp(float(ChannelB) / 2.0));

color.r = (1.0 / (1.0 + exp(float(-ChannelR) * (color.r - 0.5))) - X) / (1.0 - 2.0 * X);
color.g = (1.0 / (1.0 + exp(float(-ChannelG) * (color.g - 0.5))) - Y) / (1.0 - 2.0 * Y);
color.b = (1.0 / (1.0 + exp(float(-ChannelB) * (color.b - 0.5))) - Z) / (1.0 - 2.0 * Z);

return saturate(color);
}

vec4 CorrectionPass(vec4 color, vec2 texcoord)
{
vec3 colorspace = PreCorrection(color.rgb);

#if CorrectionPalette == 1
colorspace = ColorCorrection(colorspace);

#elif CorrectionPalette == 2
vec3 XYZ = RGBtoXYZ(colorspace);
vec3 Yxy = XYZtoYxy(XYZ);

Yxy = ColorCorrection(Yxy);
XYZ = YxytoXYZ(Yxy);
colorspace = XYZtoRGB(XYZ);

#elif CorrectionPalette == 3
vec3 XYZ = RGBtoXYZ(colorspace);
vec3 Yxy = XYZtoYxy(XYZ);
XYZ = YxytoXYZ(Yxy);
XYZ = ColorCorrection(XYZ);
colorspace = XYZtoRGB(XYZ);

#elif CorrectionPalette == 4
vec3 hsv = RGBtoHSV(colorspace);
hsv = ColorCorrection(hsv);
colorspace = HSVtoRGB(hsv);

#elif CorrectionPalette == 5
vec3 yuv = RGBtoYUV(colorspace);
yuv = ColorCorrection(yuv);
colorspace = YUVtoRGB(yuv);
#endif

color.rgb = lerp(color.rgb, colorspace, float(PaletteStrength));

color.a = AvgLuminance(color.rgb);

return color;
}
#endif

/*------------------------------------------------------------------------------
[S-CURVE CONTRAST CODE SECTION]
------------------------------------------------------------------------------*/

#if USE_CURVES == 1

vec4 CurvesPass(vec4 color, vec2 texcoord)
{
float Curves_contrast_blend = Curves_contrast;


/*-----------------------------------------------------------.
/               Separation of Luma and Chroma                 /
'-----------------------------------------------------------*/

// -- Calculate Luma and Chroma if needed --
#if Curves_mode != 2

//calculate luma (grey)
float luma = dot(lumCoeff, color.rgb);

//calculate chroma
vec3 chroma = color.rgb - luma;
#endif

// -- Which value to put through the contrast formula? --
// I name it x because makes it easier to copy-paste to Graphtoy or Wolfram Alpha or another graphing program
#if Curves_mode == 2
vec3 x = color.rgb; //if the curve should be applied to both Luma and Chroma
#elif Curves_mode == 1
vec3 x = chroma; //if the curve should be applied to Chroma
x = x * 0.5 + 0.5; //adjust range of Chroma from -1 -> 1 to 0 -> 1
#else // Curves_mode == 0
float x = luma; //if the curve should be applied to Luma
#endif

    // Contrast formulas
// -- Curve 1 --
#if Curves_formula == 1
x = sin(PI * 0.5 * x); // Sin - 721 amd fps, +vign 536 nv
x *= x;

//x = 0.5 - 0.5*cos(PI*x);
//x = 0.5 * -sin(PI * -x + (PI*0.5)) + 0.5;
#endif

// -- Curve 2 --
#if Curves_formula == 2
x = x - 0.5;
x = (x / (0.5 + abs(x))) + 0.5;

//x = ( (x - 0.5) / (0.5 + abs(x-0.5)) ) + 0.5;
#endif

// -- Curve 3 --
#if Curves_formula == 3
//x = smoothstep(0.0,1.0,x); //smoothstep
x = x*x*(3.0 - 2.0*x); //faster smoothstep alternative - 776 amd fps, +vign 536 nv
//x = x - 2.0 * (x - 1.0) * x* (x- 0.5);  //2.0 is contrast. Range is 0.0 to 2.0
#endif

// -- Curve 4 --
#if Curves_formula == 4
x = (1.0524 * exp(6.0 * x) - 1.05248) / (20.0855 + exp(6.0 * x)); //exp formula
#endif

// -- Curve 5 --
#if Curves_formula == 5
//x = 0.5 * (x + 3.0 * x * x - 2.0 * x * x * x); //a simplified catmull-rom (0,0,1,1) - btw smoothstep can also be expressed as a simplified catmull-

rom using (1,0,1,0)
//x = (0.5 * x) + (1.5 -x) * x*x; //estrin form - faster version
x = x * (x * (1.5 - x) + 0.5); //horner form - fastest version

Curves_contrast_blend = Curves_contrast * 2.0; //I multiply by two to give it a strength closer to the other curves.
#endif

// -- Curve 6 --
#if Curves_formula == 6
x = x*x*x*(x*(x*6.0 - 15.0) + 10.0); //Perlins smootherstep
#endif

// -- Curve 7 --
#if Curves_formula == 7
//x = ((x-0.5) / ((0.5/(4.0/3.0)) + abs((x-0.5)*1.25))) + 0.5;
x = x - 0.5;
x = x / ((abs(x)*1.25) + 0.375) + 0.5;
//x = ( (x-0.5) / ((abs(x-0.5)*1.25) + (0.5/(4.0/3.0))) ) + 0.5;
#endif

// -- Curve 8 --
#if Curves_formula == 8
x = (x * (x * (x * (x * (x * (x * (1.6 * x - 7.2) + 10.8) - 4.2) - 3.6) + 2.7) - 1.8) + 2.7) * x * x; //Techicolor Cinestyle - almost identical to curve 1
#endif

// -- Curve 9 --
#if Curves_formula == 9
x = -0.5 * (x*2.0 - 1.0) * (abs(x*2.0 - 1.0) - 2.0) + 0.5; //parabola
#endif

// -- Curve 10 --
#if Curves_formula == 10 //Half-circles

#if Curves_mode == 0
float xstep = step(x, 0.5);
float xstep_shift = (xstep - 0.5);
float shifted_x = x + xstep_shift;
#else
vec3 xstep = step(x, 0.5);
vec3 xstep_shift = (xstep - 0.5);
vec3 shifted_x = x + xstep_shift;

#endif

x = abs(xstep - sqrt(-shifted_x * shifted_x + shifted_x)) - xstep_shift;

//x = abs(step(x,0.5)-sqrt(-(x+step(x,0.5)-0.5)*(x+step(x,0.5)-0.5)+(x+step(x,0.5)-0.5)))-(step(x,0.5)-0.5); //single line version of the above

//x = 0.5 + (sign(x-0.5)) * sqrt(0.25-(x-trunc(x*2))*(x-trunc(x*2))); //worse

/* // if/else - even worse
if (x-0.5)
x = 0.5-sqrt(0.25-x*x);
else
x = 0.5+sqrt(0.25-(x-1)*(x-1));
*/

//x = (abs(step(0.5,x)-clamp( 1-sqrt(1-abs(step(0.5,x)- frac(x*2%1)) * abs(step(0.5,x)- frac(x*2%1))),0 ,1))+ step(0.5,x) )*0.5; //worst so far

//TODO: Check if I could use an abs split instead of step. It might be more efficient

Curves_contrast_blend = Curves_contrast * 0.5; //I divide by two to give it a strength closer to the other curves.
#endif

// -- Curve 11 --
#if Curves_formula == 11 //Cubic catmull
float a = 1.00; //control point 1
float b = 0.00; //start point
float c = 1.00; //endpoint
float d = 0.20; //control point 2
x = 0.5 * ((-a + 3 * b - 3 * c + d)*x*x*x + (2 * a - 5 * b + 4 * c - d)*x*x + (-a + c)*x + 2 * b); //A customizable cubic catmull-rom spline
#endif

// -- Curve 12 --
#if Curves_formula == 12 //Cubic Bezier spline
float a = 0.00; //start point
float b = 0.00; //control point 1
float c = 1.00; //control point 2
float d = 1.00; //endpoint

float r = (1 - x);
float r2 = r*r;
float r3 = r2 * r;
float x2 = x*x;
float x3 = x2*x;
//x = dot(float4(a,b,c,d),float4(r3,3*r2*x,3*r*x2,x3));

//x = a * r*r*r + r * (3 * b * r * x + 3 * c * x*x) + d * x*x*x;
//x = a*(1-x)*(1-x)*(1-x) +(1-x) * (3*b * (1-x) * x + 3 * c * x*x) + d * x*x*x;
x = a*(1 - x)*(1 - x)*(1 - x) + 3 * b*(1 - x)*(1 - x)*x + 3 * c*(1 - x)*x*x + d*x*x*x;
#endif

// -- Curve 13 --
#if Curves_formula == 13 //Cubic Bezier spline - alternative implementation.
vec3 a = vec3(0.00, 0.00, 0.00); //start point
vec3 b = vec3(0.25, 0.15, 0.85); //control point 1
vec3 c = vec3(0.75, 0.85, 0.15); //control point 2
vec3 d = vec3(1.00, 1.00, 1.00); //endpoint

vec3 ab = lerp(a, b, x);           // point between a and b
vec3 bc = lerp(b, c, x);           // point between b and c
vec3 cd = lerp(c, d, x);           // point between c and d
vec3 abbc = lerp(ab, bc, x);       // point between ab and bc
vec3 bccd = lerp(bc, cd, x);       // point between bc and cd
vec3 dest = lerp(abbc, bccd, x);   // point on the bezier-curve
x = dest;
#endif

// -- Curve 14 --
#if Curves_formula == 14
x = 1.0 / (1.0 + exp(-(x * 10.0 - 5.0))); //alternative exp formula
#endif

   //Joining of Luma and Chroma                 
#if Curves_mode == 2 //Both Luma and Chroma
vec3 col = x;  //if the curve should be applied to both Luma and Chroma
color.rgb = lerp(color.rgb, col, Curves_contrast_blend); //Blend by Curves_contrast

#elif Curves_mode == 1 //Only Chroma
x = x * 2.0 - 1.0; //adjust the Chroma range back to -1 -> 1
vec3 col = luma + x; //Luma + Chroma
color.rgb = lerp(color.rgb, col, Curves_contrast_blend); //Blend by Curves_contrast

#else // Curves_mode == 0 //Only Luma
x = lerp(luma, x, Curves_contrast_blend); //Blend by Curves_contrast
color.rgb = x + chroma; //Luma + Chroma
#endif
//Return the result
color.a = AvgLuminance(color.rgb);

return saturate(color);
}
#endif

/*------------------------------------------------------------------------------
[CROSS PROCESSING CODE SECTION]
------------------------------------------------------------------------------*/
#if CROSS_PROCESSING == 1

vec3 CrossShift(vec3 color)
{
vec3 cross;

vec2 CrossMatrix[3] = vec2[](
vec2(0.960, 0.040 * color.x),
vec2(0.980, 0.020 * color.y),
vec2(0.970, 0.030 * color.z));

cross.x = float(RedShift) * CrossMatrix[0].x + CrossMatrix[0].y;
cross.y = float(GreenShift) * CrossMatrix[1].x + CrossMatrix[1].y;
cross.z = float(BlueShift) * CrossMatrix[2].x + CrossMatrix[2].y;

float lum = AvgLuminance(color);
vec3 black = vec3(0.0, 0.0, 0.0);
vec3 white = vec3(1.0, 1.0, 1.0);

cross = lerp(black, cross, saturate(lum * 2.0));
cross = lerp(cross, white, saturate(lum - 0.5) * 2.0);
color = lerp(color, cross, saturate(lum * float(ShiftRatio)));

return color;
}

vec4 CrossPass(vec4 color, vec2 texcoord)
{
#if FilmicProcess == 1
color.rgb = CrossShift(color.rgb);

#elif FilmicProcess == 2
vec3 XYZ = RGBtoXYZ(color.rgb);
vec3 Yxy = XYZtoYxy(XYZ);

Yxy = CrossShift(Yxy);
XYZ = YxytoXYZ(Yxy);

color.rgb = XYZtoRGB(XYZ);

#elif FilmicProcess == 3
vec3 XYZ = RGBtoXYZ(color.rgb);
vec3 Yxy = XYZtoYxy(XYZ);

XYZ = YxytoXYZ(Yxy);
XYZ = CrossShift(XYZ);

color.rgb = XYZtoRGB(XYZ);
#endif

color.a = AvgLuminance(color.rgb);

return saturate(color);
}
#endif

/*------------------------------------------------------------------------------
[COLOR GRADING CODE SECTION]
------------------------------------------------------------------------------*/

#if COLOR_GRADING == 1
float RGBCVtoHUE(vec3 RGB, float C, float V)
{
vec3 Delta = (V - RGB) / C;

Delta.rgb -= Delta.brg;
Delta.rgb += vec3(2.0, 4.0, 6.0);
Delta.brg = step(V, RGB) * Delta.brg;

float H;
H = max(Delta.r, max(Delta.g, Delta.b));
return frac(H / 6);
}

vec3 HSVComplement(vec3 HSV)
{
vec3 complement = HSV;
complement.x -= 0.5;

if (complement.x < 0.0) {
complement.x += 1.0;
}
return(complement);
}

float HueLerp(float h1, float h2, float v)
{
float d = abs(h1 - h2);

if (d <= 0.5)
{
return lerp(h1, h2, v);
}
else if (h1 < h2)
{
return frac(lerp((h1 + 1.0), h2, v));
}
else
{
return frac(lerp(h1, (h2 + 1.0), v));
}
}

vec4 ColorGradingPass(vec4 color, vec2 texcoord)
{
vec3 guide = vec3(RedGrading, GreenGrading, BlueGrading);

float amount = GradingStrength;
float correlation = Correlation;
float concentration = 2.00;

vec3 colorHSV = RGBtoHSV(color.rgb);
vec3 huePoleA = RGBtoHSV(guide);
vec3 huePoleB = HSVComplement(huePoleA);

float dist1 = abs(colorHSV.x - huePoleA.x);
if (dist1 > 0.5) dist1 = 1.0 - dist1;

float dist2 = abs(colorHSV.x - huePoleB.x);
if (dist2 > 0.5) dist2 = 1.0 - dist2;

float descent = smoothstep(0.0, correlation, colorHSV.y);

vec3 HSVColor = colorHSV;

    if (dist1 < dist2) {

float c = descent * amount * (1.0 - pow((dist1 * 2.0), 1.0 / concentration));

HSVColor.x = HueLerp(colorHSV.x, huePoleA.x, c);
HSVColor.y = lerp(colorHSV.y, huePoleA.y, c);
}
else
{
float c = descent * amount * (1.0 - pow((dist2 * 2.0), 1.0 / concentration));

HSVColor.x = HueLerp(colorHSV.x, huePoleB.x, c);
HSVColor.y = lerp(colorHSV.y, huePoleB.y, c);
}

color.rgb = HSVtoRGB(HSVColor);

color.a = AvgLuminance(color.rgb);

return saturate(color);
}
#endif




/*------------------------------------------------------------------------------
[TV COLORS EMU CODE SECTION]
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
SimoneT NTSC TV colors emulation 1.0 Shader
Copyright (C) 2016 SimoneT - [email protected]
Credit to SimoneT.
------------------------------------------------------------------------------*/

#if NTSC_TV_EMULATION == 1

// conversion from NTSC RGB Reference White D65 ( color space used by NA/Japan TV's ) to XYZ
vec3 NTSC(vec3 c)
{
vec3 v = vec3(pow(c.r, 2.2), pow(c.g, 2.2), pow(c.b, 2.2)); //Inverse Companding
return v*mat3(
0.6068909, 0.1735011, 0.2003480,
0.2989164, 0.5865990, 0.1144845,
0.0000000, 0.0660957, 1.1162243);
}

// conversion from XYZ to sRGB Reference White D65 ( color space used by windows )
vec3 sRGB(vec3 c)
{
vec3 v = c*mat3(
3.2404542, -1.5371385, -0.4985314,
-0.9692660, 1.8760108, 0.0415560,
0.0556434, -0.2040259, 1.0572252);

//Companding
v.r = (v.r > 0.0031308) ? ((1.055 * pow(v.r, (1.0 / 2.4))) - 0.055) : 12.92 * v.r;
v.g = (v.g > 0.0031308) ? ((1.055 * pow(v.g, (1.0 / 2.4))) - 0.055) : 12.92 * v.g;
v.b = (v.b > 0.0031308) ? ((1.055 * pow(v.b, (1.0 / 2.4))) - 0.055) : 12.92 * v.b;
return v;
}

// NTSC RGB to sRGB
vec3 NTSCtoSRGB(vec3 c)
{
return sRGB(NTSC(c));
}

// Ported from SimoneT TV colors emulation 1.0 Shader
vec4 TvColorsPass(vec4 color, vec2 texcoord)
{
color.rgb = NTSCtoSRGB(color.rgb);

return color;
}
#endif





/*------------------------------------------------------------------------------
[MAIN() & COMBINE PASS CODE SECTION]
------------------------------------------------------------------------------*/

void main()
{
vec2 texcoord = gl_TexCoord[0].xy;
vec4 color = texture2D(OGLTexture0, texcoord);

#if USE_FXAA == 1
color = FXAAPass(color, texcoord);
#endif

#if GAMMA_CORRECTION == 1
color = GammaPass(color, texcoord);
#endif

#if PIXEL_VIBRANCE == 1
color = VibrancePass(color, texcoord);
#endif

#if BLENDED_BLOOM == 1
color = BloomPass(color, texcoord);
#endif

#if SCENE_TONEMAPPING == 1
color = TonemapPass(color, texcoord);
#endif

#if USE_CURVES == 1
color = CurvesPass(color, texcoord);
#endif

#if COLOR_CORRECTION == 1
color = CorrectionPass(color, texcoord);
#endif

#if CROSS_PROCESSING == 1
color = CrossPass(color, texcoord);
#endif

#if COLOR_GRADING == 1
color = ColorGradingPass(color, texcoord);
#endif


#if NTSC_TV_EMULATION == 1
color = TvColorsPass(color, texcoord);
#endif


gl_FragColor = color;
}


How it looks

PSX
Truck Scene
http://pho.to/AhTsk/uh/original

Old PC

Truck Scene
http://pho.to/AhTsk/up/original

Costa del Sol
http://pho.to/AhTsk/x8/original

Kalm
http://pho.to/AhTsk/3g/original

New PC

Truck Scene
http://pho.to/AhTsk/g4/original

Costa del Sol
http://pho.to/AhTsk/os/original

Kalm
http://pho.to/AhTsk/cq/original



Note:  The above are the shader + modified light exe function.  PS... I have slightly altered the contrast in the above shader since these screenshots were taken, as I felt it was too great.
« Last Edit: 2017-05-18 06:45:53 by DLPB »

NFITC1

  • No life
  • *
  • Posts: 2763
  • Karma: 61
  • I just don't know what went wrong.
    • View Profile
    • WM/PrC Blog
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #57 on: 2017-05-18 04:27:45 »
As Luksy has posted the PSX calculates and renders the colors differently.

I think it's more basic than that. I think it's the limitation of the composite video connection. Since it can't do better than 240i and most CRTs do their own blending (though not necessarily on purpose) it takes more color variation to make an obvious contrast. As such, the backgrounds were designed to be oddly blocky with random flecks of color sprinkled in to make a smooth appearance despite the source's jaggy appearance. The designers of the PSX's GPU knew this and probably force each pixels' color to slightly influence the ones next to it. So to compensate, set designers have to be creative to cause realistic gradients. The source would look dirty, but the interpretation looks smooth because it can't show each pixel in its true color.

I noticed this a few years back when I got a video adapter for the PS2 that was both composite and component in the same cord. The composite looked smoother because the resolution was lower and made my set do some interpolation. When I switched to component (which maxes at 480p) I immediately regretted my decision as all the color artifacts came shining through and less interpolation was done on the image.

Now we play games at 1080p and up so lots more time is spent on making 32-bit colored textures at 4K resolutions so more accurate gradients can be achieved.

Sega Chief

  • No life
  • *
  • Posts: 2516
  • Karma: 151
  • These guys is sick
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #58 on: 2017-05-18 15:29:30 »
Either my Notepad isn't set up properly-

Edit: Never mind, it was Notepad. Copy-pasting the code into Notepad++ retains the proper formatting.

Edit2: It looks great; world map doesn't seem as dreary and as an added bonus the backgrounds don't seem as messed up now either; one thing though is that oranges come through a bit too strong.
« Last Edit: 2017-05-18 15:37:21 by Sega Chief »

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #59 on: 2017-05-18 17:56:31 »
Is your monitor calibrated? If so, check vibrance option. And contrast
« Last Edit: 2017-05-18 18:00:33 by DLPB »

Sega Chief

  • No life
  • *
  • Posts: 2516
  • Karma: 151
  • These guys is sick
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #60 on: 2017-05-18 19:19:58 »
Is your monitor calibrated? If so, check vibrance option. And contrast


Good thing you mentioned, a while back I set the monitor up to display certain colours more vibrantly cause it looked very washed out on normal settings. That's probably what it was.

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #61 on: 2017-05-18 19:55:39 »
Finally, if you really want the PSX experience, a Gaussian blur needs adding to the above shader.  I like 0.5, but 1.0 pixels in Adobe makes it look very close at the expense of less detail (like the PSX)

Observe:

http://pho.to/AhWQH/ma/original

The models, of course, are still too rendered to fit with the background.  That's why the filtering for 3d objects needs to be disabled in aali's driver (like Steam allows). I'll see if JWP knows how.

Also, PSX is in 4:3 AR. For some reason, 1280 * 960 does not seem to give the exact same result as Mednafen does. Checking.


edit

http://forum.fobby.net/index.php?t=msg&goto=3778&
« Last Edit: 2017-05-18 20:11:22 by DLPB »

Kaldarasha

  • No life
  • *
  • Posts: 2138
  • Karma: 129
  • Prince of Model Editing
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #62 on: 2017-05-18 20:13:21 »
Looks a bit like the ps4 images I've seen. BTW. there is a problem with try the new light setting. As it looks now only the body and the head gets the light from above, but arms and legs get the light from below.  :|

Covarr

  • Covarr-Let
  • Administrator
  • No life
  • *
  • Posts: 3915
  • Karma: 115
  • The Great Redarr.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #63 on: 2017-05-18 20:14:58 »
Finally, if you really want the PSX experience, a Gaussian blur needs adding to the above shader.
I mean, if you really want to be authentic to how the art looked in the '90s, you'd need a CRT shader and/or a NTSC (or PAL) signal shader. The emulation community loves that stuff. I'm not sure it's really worth the effort, though.

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #64 on: 2017-05-18 20:19:48 »
True.  The gaussian + shader + disabled filtering of 3D will be very close though.

@Kal. Yup. I'm aware it ain't perfect shading and probably never will be.  I think the entire thing would need recalculating, but I'll keep on looking. They've decided to shade this way.
« Last Edit: 2017-05-18 20:46:43 by DLPB »

Ansem

  • Crazy poster
  • *
  • Posts: 127
  • Karma: 8
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #65 on: 2017-05-18 21:15:12 »
Tbh the blurriness in that last image is just butt-ugly. I just booted up my PS2 and did a comparison, and the PS2 has a much sharper image. It is, of course, slightly blurred when compared against a completely unfiltered image, but only very slightly. It is so slight, in fact, that I'd say it's more or less perfect, as it doesn't smoothen out any details, but it smoothens out a little of the pixellation. If you're curious, I used a Component cable and a modern display, so it's not a CRT or composite signal thing either.

I did take a couple of screenshots for you to compare as well, but I don't think they'll be much useful since I don't have a capture card, and had to take them with my phone camera. So ignore the stupid blue tint, that doesn't belong there.

Either way, a postprocessing effect that destroys any and all detail is certainly not the way to go. If anything, that would be a major downgrade.

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #66 on: 2017-05-18 21:22:14 »
That is more or less exactly what mednafen gives out.  You have to compare it like for like.  A PC is never going to give you the PSX look, as Covarr said. And we can't really emulate it.  But Mednafen is about as close as you're likely to get for a PSX game output onto a screen (minus the scan lines you can artificially add).  Output from a real PS with cables has already done things that no shader is probably capable of.

The gaussian + shader looks almost identical for me when compared to Mednafen (I prefer 0.5 pixel Gaussian or no Gaussian at all - but that's because I think the PSX is inferior to the PC when it comes to the blurriness and all the dithering).

To me your screen shot looks just as bad in other ways (dithering / scan line / jagged).  Can you get me one in Kalm in the same place I took the Mednafen shot?  I can put them all along side then too.

« Last Edit: 2017-05-18 21:26:45 by DLPB »

Ansem

  • Crazy poster
  • *
  • Posts: 127
  • Karma: 8
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #67 on: 2017-05-18 21:39:38 »

To me your screen shot looks just as bad in other ways (dithering / scan line / jagged).  Can you get me one in Kalm in the same place I took the Mednafen shot?  I can put them all along side then too.


Yeah the jaggedness and lines going here and there was definitely my bad, the display was configured like bollocks so it stretched the image one way and shrunk it the other way. Dithering, however, is unavoidable, simply because it is a PS1 game. Still, the fact that the dithering is visible through even a shitty screenshot, is a testament to how much more accurate the Component signal is next to that old PAL/NTSC crap. :P

I can get a Kalm screenshot too, but it'll probably take a couple hours because I need to fiddle around with save files and get them on the Memcard.

Update: Well, here it is. This time around, I decided to use the screen (HDTV) I always use for pretty much everything since the other one turned out to be a big hunk of $#!!.

Now, this picture will only tell you so much, but it confirmed my gut feeling. The pixellation is very much there, but then again so is that dithering, because, well, HDTV. Also, using an external camera to make screencaps for this sort of purpose is bad since each screen has adjustable sharpness and brightness and all that (although mine are set to default.) It also adds that blue tint and the picture is much brighter than the image itself was.

So, just for reference, I wanted to see what another emulator produces. With a color depth of 32 bits, there is obviously no dithering involved, and no external camera involved. Which results in this.

I may have been wrong the first time. Neither PS2 nor ePSXe look like they make an effort to blur the image in any way, unless instructed otherwise. The blurring is not part of the game, it's part of the displays of that era. Mednafen might be simply trying to replicate that, because it's often considered part of the nostalgic experience. I know the GPU plugin I use with ePSXe has an option for fullscreen smoothing, which produces an almost identical result, but if it's disabled, it doesn't blur anything.

What do you make of this?
« Last Edit: 2017-05-18 23:17:05 by Ansem »

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #68 on: 2017-05-19 01:00:43 »
You may be right. Mednafen may be adding something... but I am not sure why it would when it's supposed to be direct.  Perhaps it does (it could be the bilinear filtering).   Either way, we can safely say that gaussian as an option would be ok.  Personally, I'd never use it.  I much  prefer the output from the tweaked shader I posted on its own. I think that beats the lot, tbh.

Do you think that needs any more work?  Any thoughts on it?

Edit.

Yeah, it's bilinear filtering with mednafen.  I thought I'd disabled it.  It looks awful without it, though.  I think we have a winner then.... it's the shader alone. No blur.
« Last Edit: 2017-05-19 01:06:06 by DLPB »

Ansem

  • Crazy poster
  • *
  • Posts: 127
  • Karma: 8
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #69 on: 2017-05-19 01:40:07 »
Gaussian could work wonders if it's applied in a very, very small dose, but any more and it's just going to make the details vanish. Also, it should be configured to avoid blurring 3D geometry, because it does slightly negate what you gain from using a high internal resolution. It would make battles especially look as if you'd been drinking for 14 hours straight.

I haven't even tried out the shader yet, but if it breathes life into the colors, then why the hell not.

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #70 on: 2017-05-19 20:37:05 »
fr_e field bug.

I think everyone is about ready to sign off on this problem. The Diamond Weapon shadow that traverses the screen in the PSX version seems to have been deliberately disabled in the PC version.  Placing it back, even by altering tiles, has failed (Ilducci and Spy__Dragon tried). It could well be that this particular effect cannot be made to work due to some sort of limitation with the PC field files. Importing a working field from PSX doesn't work either, because Makou Reactor cannot properly import field backgrounds.  Even if it could, it again may be that PC field format doesn't allow for this layer to work properly.

So, I've started thinking about other ways to add the effect back into the game. For me, the only good way would seem to be adding the shadow shape to a file and using that in-game (a hrc / p file, like the Great Glacier map).  Transparency could be added using the field model function. Of course, I'd need someone else to make this.  Do you think you could do it, Kaldarasha?

Kaldarasha

  • No life
  • *
  • Posts: 2138
  • Karma: 129
  • Prince of Model Editing
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #71 on: 2017-05-19 21:24:18 »
At the time I read it I got the idea to use a model object to solve the problem.
I have an already textured plane from my drop shadow tests. I could use that and add a texture with the shape of Dimond to it.

Edit:
How's that?


Blending is on by default.

Edit2:
https://mega.nz/#!3d0QDZjC!mI3i1s_FwcXH2AFcZCr1OkvMbnXhtSq2CMcNrfo9__I
« Last Edit: 2017-05-19 21:31:47 by Kaldarasha »

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #72 on: 2017-05-19 21:49:29 »
Since the shadow cast is supposed to be part of it from a distance, this is how it should look (note only black with outline is needed... since I can make it move right to left)

>>

https://www.youtube.com/watch?v=93JwjEcRyLU&t=08m56s

8:56

It's a very simple shape.  Straight on one end (since that end will never be seen),  and a curve shape on the other end.  Width 512 pixels.  Height 256.

Then I just make it move right to left... which simulates Weapon moving.

In fact, I could probably record the psx game and send you the exact shape.

Edit.  Actually, it has a shape on both sides, but on PSX version's release you never see the left side (maybe even because of bad script programming).

Here is the final shape:

Left
http://pho.to/AhazS/e3/original

Right
http://pho.to/AhazS/6y/original

So, that's what I need.  That shape. 512 pixels across. A rectangle, starting with the left side curve, ending with right side curve. 224 pixels high.
« Last Edit: 2017-05-19 23:05:48 by DLPB »

Sega Chief

  • No life
  • *
  • Posts: 2516
  • Karma: 151
  • These guys is sick
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #73 on: 2017-05-20 02:16:57 »
You could maybe just fade the tint of the screen to be darker then fade it back to normal as a replacement effect if the shadow thing doesn't work out.

DLPB

  • No life
  • *
  • Posts: 8826
  • Karma: 252
  • My love is as sharp as a needle in your eye.
    • View Profile
Re: [FF7PC] The Bug Database - post bug reports here
« Reply #74 on: 2017-05-20 02:27:59 »
That would be plan C...  but it would suck not to have a good shadow.