I bet I can fix number 14 (reviving dead characters with damaging scripts). That'll either be a field fix or a exe tweak.Make sure to specify which tab. There are a few #14s... though I assume you mean Field #14.
Make sure to specify which tab. There are a few #14s... though I assume you mean Field #14.didn't notice the tabs. Yes, I meant the field bug. The trick is "don't revive, but don't kill either". The field opcode probably needs an asm edit.
the whole alpha blending transparency issue which also affects the savepoints and other stuff. The issue is that the PC renderer has two different alpha values (vertex alpha, texture alpha) and the game doesn't specify which one to use (AFAIK), so sometimes the correct thing to do is to just use texture alpha, sometimes vertex alpha and sometimes the two should be combined to produce the correct result. The way it works now is correct most of the time but not always.
the world map is already completely broken (shadows follow the rotation of the camera instead of being fixed in the world)
I think the function needs to be able to do that in other places though. To be able to revive or kill based on simple assignments to HP of a character. I'm not sure where else it's used. What was really needed was a function to set HP to an absolute number rather than "decrease" and "increase". They likely came up with the idea of "make HP 1 after being hit with the needles" later in development.Then the fault is in the field script. I just checked it and it just removes 501 HP and restores 1. That will heal all dead characters.
What I am doing for Weapon is simply making these needles and so on an instant death or other bad effect like decrease HP. If all 3 chars are 0 HP, then game over. The latter is already another bug (all 3 chars can be dead on field), which will need fixing.
#General - FF7 -exe - the coordination for the light sources are wrong (field and WM), which produce a different light on PC as on PSX (I would say its 90° clock-wise, it looks as if x and y are swapped[?]). The field could be fixed by changing the values in the model loader.
(http://i.imgur.com/jlUhv7q.jpg) | (http://www.gameranx.com/img/13-May/ff7-ps-vs-pc-version-1-1.jpg) |
I can't believe I never noticed that before. The lighting on the PC version looks almost... inverted. It's not flipped on an axis. Rather, the areas that should be dark are light and the areas that should be light are dark. It's like a sign on a variable for light value got flipped somewhere.
The PSOne has a co-processor called the Graphics Transform Engine, which is meant to perform many 3D operations like matrix-vector multiplication, lighting and fog. It was fixed-point
- (aka: integer) based and couldn't work with floating point numbers. The X, Y and Z coordinates of vectors are stored as 16-bit values: 1-bit for sign, 3-bits for integral part and 12-bits for the decimal part. It only supported 3x3 rotation matrices with translation being a separate operation using vectors with 32-bit XYZ integer components (no fractional parts).
This seems to be one reason behind the wobbliness: while drawing a scene, the objects's polygons must be transformed from their local space into world space (at the very least one rotate and one translate command) and then from world into camera space (another rotate and translate). Since translation is integer-only (no fractional), it will "snap" around, the severity depending on the scale of the scene elements. Also, if you have multiple rotations and translations stacking on top of each other, the precision errors will build up quickly.
(http://i.imgur.com/ei3C9Cz.jpg) | (http://i.imgur.com/xLXEEAd.jpg) |
positive value | negative value |
(http://i.imgur.com/Qm2rGw2.jpg) | (http://i.imgur.com/ZADHJsF.jpg) |
positive value | negative value |
(http://i.imgur.com/gyuKGU8.jpg) | (http://i.imgur.com/YVrFOm2.jpg) |
positive value | negative value |
//== PROGRAM LINK STATUS = TRUE
//== PROGRAM VALIDATE STATUS = TRUE
//======================================================
// Vertex Shader 2
//======================================================
//== SHADER COMPILE STATUS = TRUE
#version 110
uniform int vertextype;
uniform bool fb_texture;
uniform int blend_mode;
uniform mat4 d3dprojection_matrix;
uniform mat4 d3dviewport_matrix;
void main()
{
vec4 pos = gl_Vertex;
gl_FrontColor.rgba = gl_Color.bgra;
// TLVERTEX
if(vertextype == 3)
{
pos.w = 1.0 / pos.w;
pos.xyz *= pos.w;
pos = gl_ProjectionMatrix * pos;
}
// LVERTEX and VERTEX
else
{
pos = d3dviewport_matrix * d3dprojection_matrix * gl_ModelViewMatrix * pos;
if(gl_FrontColor.a > 0.5) gl_FrontColor.a = 0.5;
}
// BLEND_NONE
if(blend_mode == 4) gl_FrontColor.a = 1.0;
// BLEND_25P
else if(blend_mode == 3) gl_FrontColor.a = 0.25;
gl_TexCoord[0] = gl_MultiTexCoord0;
if(fb_texture) gl_TexCoord[0].t = 1.0 - gl_TexCoord[0].t;
gl_Position = pos;
}
//======================================================
// Fragment Shader 3
//======================================================
//== SHADER COMPILE STATUS = TRUE
#version 110
uniform int vertextype;
uniform sampler2D tex;
uniform bool texture;
uniform bool fb_texture;
uniform bool modulate_alpha;
void main()
{
vec4 color = gl_Color;
vec4 texture_color;
texture_color = texture2D(tex, gl_TexCoord[0].st);
if(texture)
{
if(fb_texture && texture_color.rgb == vec3(0.0, 0.0, 0.0)) discard;
if(texture_color.a == 0.0) discard;
color *= texture_color;
if(!modulate_alpha) color.a = texture_color.a;
}
gl_FragColor = color;
}
The Playstations RGB values aren't linear to normal RGB values (as used on PCs). The min/max values are of course the same, but the medium values differ:
Intensity PC PSX
Minimum 0 0
Medium (circa) 16 8
Maximum 31 31
Ie. on the PSX, the intensity increases steeply from 0 to 15, and less steeply from 16 to 31.
Could this be anything to do with
http://problemkaputt.de/psx-spx.htm
Also, I don't think the "shading issue" is all that much of a problem. When you compare to PSX, using my own tweaked shaders, the colour and so on is superior in PC (right).A bit off topic, but why is the background such better quality on the psx?
https://e63i.imgup.net/test1fef9.png
A bit off topic, but why is the background such better quality on the psx?
(http://i.imgur.com/YrwmSFr.jpg) | (http://i.imgur.com/sFDbPKq.jpg) |
no shader | with shader |
/*===============================================================================*\
|####################### [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;
}
/*===============================================================================*\
|####################### [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;
}
As Luksy has posted the PSX calculates and renders the colors differently.
Is your monitor calibrated? If so, check vibrance option. And contrast
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.
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.
I'll also be adding dialogue issues, but only if it's an original Japanese error. For example, chocobos having belly buttons :P
I don't think the engine supports transparent layers in the PC port.
sidenote, do you have any idea what tifa is supposed to be doing in this map when she does that weird ass animation
https://youtu.be/29euU5fNqk8?t=369
Daniel Burke: let's see
No i dont
i dont think she is meant to stay there like a lemon at any rate
also sinin2_1 you will see a "memory" dialogue
Anonymous Dinosaur: she's lemoning so hard and it bugs the strawberries out of me
Daniel Burke: that is erroneous and v likely a left over message from the script programmer to himself
I'll have to look into it
i dont think she is meant to do that
Anonymous Dinosaur: she does that animation twice, then, and when she picks up the Premium Heart
its so weird
Daniel Burke: It's not the first time either that that happens in regards to left over script. At Junon, the programmer left in "1 2 3 " set with a var - to tell him the timing in game as we was struggling to work out why Cloud wasn't lining up right and so on. I fixed it.
he*
in gme you literally see "And... 1" "and...2" "and.... 3" Poor Baskett had no ferning clue what it was
Anonymous Dinosaur: lmaooooo
Daniel Burke: also the "switch on" dialogue in the reactor is also a debug message
in the elevator
Anonymous Dinosaur: that makes so much sense
Daniel Burke: they forgot to take it the fern out
usually debug messages are removed. Like when Barrett comes running into seventh heaven. The dialogue is hidden "THUD THUD THUD sound should come in here"
Anonymous Dinosaur: makes you realise how much less proofing these games had
Daniel Burke: well they were rushed and the testers obv thought that "switch on" was intended
lmao
Anonymous Dinosaur: ahahaha
oh well
it has now been solved years later
Daniel Burke: also fun note, the high mid low game at the gold saucer was meant to have better odds... but the programmer made a common mistake with probability. He didn't factor in how it works in those cases and assumed that overall odds would be like 400-1
he made it 3709-1 to beat the game
as a consequence, no tester ever beat it and so if you ever do there is a bug leading to an invisible final opponent.
the game is meant to end after the superman
luksy and i fixed it
Anonymous Dinosaur: amazing
Daniel Burke: in fact when I noted this issue... a member of Qhimm made the EXACT SAME mistake
that the programmer did
Daniel Burke: http://forums.qhimm.com/index.php?topic=12667.msg176030#msg176030 this guy thinks i'm being sarcastic. I'm not.
Erzfreund calculates it properly using math further down
Anonymous Dinosaur: ferning hell
Daniel Burke: It's not as simple as it first appears eh ;)
In any case... changing the rounds to 5 instead of 10 fixes the odds to around 300-1
so you can actually win the game now?
Daniel Burke: yeah. Odds are good and also last opponent is correctly last opponent
If you played the fight game 100 times, then you'd beat the Girl ~66 times.
------------
Not true.. you might beat her 0, might beat her 100 ;)
<< thats the error in thinking
that because the odds of winning 10 rounds is 66% that means you will always win 66%. That isnt how it works. I mean, it's theoretically possible to win ALL 40 rounds without losing a point
and to lose all 10 in a singl round
Anonymous Dinosaur: yeah thats like...... fundamentally how probability works
Daniel Burke: If you played the fight game 100 times, then you'd beat the Girl ~66 times.
This is only correct of course if you played a million times... then it will be much closer to 66%
100 times.. forget it.
Anonymous Dinosaur: truly a beginners mistake
Daniel Burke: yes! script programmer should have gotten off his fat arse and walked across to ken narita and asked him
Anonymous Dinosaur: and the programmer literally programmed that faulty logic into the game hahaha
Daniel Burke: hiroki was the script programmer from what I can see
yeah!
haha
when i was a kid i could never beat the 3rd opponent. To beat 1 2 and 3 has odds if i recall of around 400-1
beating 4th too is 3709-1
So i knew something was amiss
Anonymous Dinosaur: same, i tried and tried and tired
I agree. It does look a little bloody silly, though. Haha.Yes - one might well ask why she has a "pickup" animation like that in the first place, while Cloud's is the more sensible kneeling variety. Let's just say that methinks someone at Square had a bit of fun animating Tifa. ;)
The mansion theme should be fixed with Anxious Heart. I'm sure I've had this convo at least 5 times. Please check for me. We definitely discussed the other bugs. They are fixed. :)
Here's a funny one: if you access the menu while you are moving in the buggy, the menu sfx are all higher pitched. It appears the buggy simply has the one engine noise that is pitched up when accelerating, but it affects all sfx across the board.I'm 90% sure to have noticed the same issue when i played the Steam version ages ago... no it's probably not happening on PSX.
Aeroga (and Supernova) both use effect 00163, which, as Cicciolo pointed out, is wrong in PC original. This is an error in audio.dat. 163 is accidentally the same as 162. This means there will be a totally wrong effect in Supernova too lol and other places. But since I worked entirely off the PSX version, this effect has been fixed.Ahah, thanks for fixing it, and for putting my name in the database. But i never noticed that for Supernova, perhaps i defeated Sephiroth before he could use it lol (i had everything already maxed out)
On a side note, has anyone noticed a weird bug with Bizarro Sephiroth duplicating/triplicating his model during the boss battle? I'm not sure if i could replicate it though...
Well, I mean he is placed five times in the formation to give the illusion of five targets, but the four additional models are invisible by default. I guess some sort of script error could cause them to become visible. Typically something you'd see in mods developed by inexperienced modders, but I've literally never seen it myself, ever.
213.SetEffect [Channel 4, Balance 64, 00441 [SB - Clapping, looped].ogg]
213.SetLoop [LoopStart 200618]
213.SetVolume [Channel 4, Volume 127]
--------------------------------------------------------------------------
214.SetVolumeTransition [Channel 4, TargetVolume 0, Time 5000]
I couldn't find this in the database, so just to make sure; has the Soldier First and Second classes' multi-slash attack been fixed? It was always broken in the vanilla game, since the enemies' animation scripts for that attack are incomplete.
The animations themselves function, they just look a bit choppy. Soldier 1st uses the first step of 4x-cut instead of the normal 03 slash animation for his physical attack which is why he ends up standing very close to the player party after the attack; like Hojo's combo, only the fourth attack 'returns' the actor to their starting position.
As for Bizarro... I am going to file it as a bug. There likely is 3 models loaded into battle due to the party being able to attack Bizarro from left right and front. I dunno if this is a PC issue alone. Sega Chief may be able to find a bug in the AI. Or it could be a porting issue.
Was this present on PSX?
Yeah, I fixed it. It's caused by poor scripting (the models should be hidden in the init section and aren't being - they're being hidden after a delay). Probably doesn't "show up" on PSX due to load differences, fade differences. But it's there too.
Yeah, all sfx related issues are likely fixed because I have replaced the audio functions entirely.
Shikun spotted a plot hole. I've looked into it and fixed it by removing the the exposition.
Major plot hole: Only one NPC mentions the Undersea Mako Reactor before Cait does aboard the Highwind (after Midhir). Other NPCs start to talk about it after Midhir. This is a problem because Cid immediately knows that the last Huge Materia is at the Undersea reactor after the Corel/Fort Condor mission.
Yeah but I am talking about the dimensions. Not the file size.
Melenia's Cloud has a 2k texture