Merge pull request #693 from Sonicadvance1/PP-shaders-improvement

Improved system for post processing shaders.
This commit is contained in:
Ryan Houdek 2014-08-13 02:41:15 -05:00
commit f2a1dd91fe
65 changed files with 1381 additions and 579 deletions

View File

@ -1,10 +1,3 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
//Change this number to increase the pixel size.
@ -14,9 +7,9 @@ void main()
float green = 0.0;
float blue = 0.0;
vec2 pos = floor(uv0 * resolution.xy / pixelSize) * pixelSize * resolution.zw;
float2 pos = floor(GetCoordinates() * GetResolution() / pixelSize) * pixelSize * GetInvResolution();
vec4 c0 = texture(samp9, pos);
float4 c0 = SampleLocation(pos);
if (c0.r < 0.1)
red = 0.1;
@ -57,5 +50,5 @@ void main()
else
green = 1.0;
ocol0 = vec4(red, green, blue, c0.a);
SetOutput(float4(red, green, blue, c0.a));
}

View File

@ -1,10 +1,3 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
//Change this number to increase the pixel size.
@ -14,9 +7,9 @@ void main()
float green = 0.0;
float blue = 0.0;
vec2 pos = floor(uv0 * resolution.xy / pixelSize) * pixelSize * resolution.zw;
float2 pos = floor(GetCoordinates() * GetResolution() / pixelSize) * pixelSize * GetInvResolution();
vec4 c0 = texture(samp9, pos);
float4 c0 = SampleLocation(pos);
if (c0.r < 0.06)
red = 0.06;
@ -82,5 +75,5 @@ void main()
else
green = 1.0;
ocol0 = vec4(red, green, blue, c0.a);
SetOutput(float4(red, green, blue, c0.a));
}

View File

@ -12,26 +12,20 @@
// 0. You just DO WHAT THE FUCK YOU WANT TO.
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
#define FXAA_REDUCE_MIN (1.0/ 128.0)
#define FXAA_REDUCE_MUL (1.0 / 8.0)
#define FXAA_SPAN_MAX 8.0
vec4 applyFXAA(vec2 fragCoord, sampler2D tex)
float4 applyFXAA(float2 fragCoord)
{
vec4 color;
vec2 inverseVP = resolution.zw;
vec3 rgbNW = texture(tex, (fragCoord + vec2(-1.0, -1.0)) * inverseVP).xyz;
vec3 rgbNE = texture(tex, (fragCoord + vec2(1.0, -1.0)) * inverseVP).xyz;
vec3 rgbSW = texture(tex, (fragCoord + vec2(-1.0, 1.0)) * inverseVP).xyz;
vec3 rgbSE = texture(tex, (fragCoord + vec2(1.0, 1.0)) * inverseVP).xyz;
vec3 rgbM = texture(tex, fragCoord * inverseVP).xyz;
vec3 luma = vec3(0.299, 0.587, 0.114);
float4 color;
float2 inverseVP = GetInvResolution();
float3 rgbNW = SampleLocation((fragCoord + float2(-1.0, -1.0)) * inverseVP).xyz;
float3 rgbNE = SampleLocation((fragCoord + float2(1.0, -1.0)) * inverseVP).xyz;
float3 rgbSW = SampleLocation((fragCoord + float2(-1.0, 1.0)) * inverseVP).xyz;
float3 rgbSE = SampleLocation((fragCoord + float2(1.0, 1.0)) * inverseVP).xyz;
float3 rgbM = SampleLocation(fragCoord * inverseVP).xyz;
float3 luma = float3(0.299, 0.587, 0.114);
float lumaNW = dot(rgbNW, luma);
float lumaNE = dot(rgbNE, luma);
float lumaSW = dot(rgbSW, luma);
@ -39,8 +33,8 @@ vec4 applyFXAA(vec2 fragCoord, sampler2D tex)
float lumaM = dot(rgbM, luma);
float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));
float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));
vec2 dir;
float2 dir;
dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));
dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));
@ -48,26 +42,26 @@ vec4 applyFXAA(vec2 fragCoord, sampler2D tex)
(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 = min(float2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),
max(float2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),
dir * rcpDirMin)) * inverseVP;
vec3 rgbA = 0.5 * (
texture(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +
texture(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);
vec3 rgbB = rgbA * 0.5 + 0.25 * (
texture(tex, fragCoord * inverseVP + dir * -0.5).xyz +
texture(tex, fragCoord * inverseVP + dir * 0.5).xyz);
float3 rgbA = 0.5 * (
SampleLocation(fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +
SampleLocation(fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);
float3 rgbB = rgbA * 0.5 + 0.25 * (
SampleLocation(fragCoord * inverseVP + dir * -0.5).xyz +
SampleLocation(fragCoord * inverseVP + dir * 0.5).xyz);
float lumaB = dot(rgbB, luma);
if ((lumaB < lumaMin) || (lumaB > lumaMax))
color = vec4(rgbA, 1.0);
color = float4(rgbA, 1.0);
else
color = vec4(rgbB, 1.0);
color = float4(rgbB, 1.0);
return color;
}
void main()
{
ocol0 = applyFXAA(uv0 * resolution.xy, samp9);
SetOutput(applyFXAA(GetCoordinates() * GetResolution()));
}

View File

@ -1,18 +0,0 @@
//dummy shader:
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
ocol0 = texture(samp9, uv0);
}
/*
And now that's over with, the contents of this readme file!
For best results, turn Wordwrap formatting on...
The shaders shown in the dropdown box in the video plugin configuration window are kept in the directory named User/Data/Shaders. They are linked in to the dolphin source from the repository at <http://dolphin-shaders-database.googlecode.com/svn/trunk/>. See <http://code.google.com/p/dolphin-shaders-database/wiki/Documentation> for more details on the way shaders work.
This file will hopefully hold more content in future...
*/

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
float red = 0.0;
float blue = 0.0;
@ -17,5 +12,5 @@ void main()
float green = max(c0.r + c0.b, c0.g);
ocol0 = vec4(red, green, blue, 1.0);
SetOutput(float4(red, green, blue, 1.0));
}

View File

@ -1,11 +1,4 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
ocol0 = (texture(samp9, uv0+resolution.zw) - texture(samp9, uv0-resolution.zw)) * 8.0;
SetOutput((SampleOffset(int2(1, 1)) - SampleOffset(int2(-1, -1))) * 8.0);
}

View File

@ -1,13 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
vec4 a = texture(samp9, uv0+resolution.zw);
vec4 b = texture(samp9, uv0-resolution.zw);
ocol0 = ( a*a*1.3 - b ) * 8.0;
float4 a = SampleOffset(int2( 1, 1));
float4 b = SampleOffset(int2(-1, -1));
SetOutput(( a*a*1.3 - b ) * 8.0);
}

View File

@ -1,48 +1,39 @@
// textures
SAMPLER_BINDING(8) uniform sampler2D samp8;
SAMPLER_BINDING(9) uniform sampler2D samp9;
const int char_width = 8;
const int char_height = 13;
const int char_count = 95;
const int char_pixels = char_width*char_height;
const vec2 char_dim = vec2(char_width, char_height);
const vec2 font_scale = vec2(1.0/float(char_width)/float(char_count), 1.0/float(char_height));
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
const float2 char_dim = float2(char_width, char_height);
const float2 font_scale = float2(1.0/float(char_width)/float(char_count), 1.0/float(char_height));
void main()
{
vec2 char_pos = floor(uv0*resolution.xy/char_dim);
vec2 pixel_offset = floor(uv0*resolution.xy) - char_pos*char_dim;
float2 char_pos = floor(GetCoordinates()*GetResolution()/char_dim);
float2 pixel_offset = floor(GetCoordinates()*GetResolution()) - char_pos*char_dim;
// just a big number
float mindiff = float(char_width*char_height) * 100.0;
float minc = 0.0;
vec4 mina = vec4(0.0, 0.0, 0.0, 0.0);
vec4 minb = vec4(0.0, 0.0, 0.0, 0.0);
float4 mina = float4(0.0, 0.0, 0.0, 0.0);
float4 minb = float4(0.0, 0.0, 0.0, 0.0);
for (int i=0; i<char_count; i++)
{
vec4 ff = vec4(0.0, 0.0, 0.0, 0.0);
vec4 f = vec4(0.0, 0.0, 0.0, 0.0);
vec4 ft = vec4(0.0, 0.0, 0.0, 0.0);
vec4 t = vec4(0.0, 0.0, 0.0, 0.0);
vec4 tt = vec4(0.0, 0.0, 0.0, 0.0);
float4 ff = float4(0.0, 0.0, 0.0, 0.0);
float4 f = float4(0.0, 0.0, 0.0, 0.0);
float4 ft = float4(0.0, 0.0, 0.0, 0.0);
float4 t = float4(0.0, 0.0, 0.0, 0.0);
float4 tt = float4(0.0, 0.0, 0.0, 0.0);
for (int x=0; x<char_width; x++)
{
for (int y=0; y<char_height; y++)
{
vec2 tex_pos = char_pos*char_dim + vec2(x,y) + 0.5;
vec4 tex = texture(samp9, tex_pos * resolution.zw);
float2 tex_pos = char_pos*char_dim + float2(x,y) + 0.5;
float4 tex = SampleLocation(tex_pos * GetInvResolution());
vec2 font_pos = vec2(x+i*char_width, y) + 0.5;
vec4 font = texture(samp8, font_pos * font_scale);
float2 font_pos = float2(x+i*char_width, y) + 0.5;
float4 font = SampleFontLocation(font_pos * font_scale);
// generates sum of texture and font and their squares
ff += font*font;
@ -63,7 +54,7 @@ void main()
// In the next steps, "a" is the font color, "b" is the background color, "f" is the font value at this pixel, "t" is the texture value
// So the square error of one pixel is:
// So the square error of one pixel is:
// e = ( t - a⋅f - b⋅(1-f) ) ^ 2
// In longer:
@ -78,11 +69,11 @@ void main()
// So, both equations must be zero at minimum and there is only one solution.
vec4 a = (f*ft - ff*t + f*t - ft*float(char_pixels)) / (f*f - ff*float(char_pixels));
vec4 b = (f*ft - ff*t) / (f*f - ff*float(char_pixels));
float4 a = (f*ft - ff*t + f*t - ft*float(char_pixels)) / (f*f - ff*float(char_pixels));
float4 b = (f*ft - ff*t) / (f*f - ff*float(char_pixels));
vec4 diff = a*a*ff + 2.0*a*b*f - 2.0*a*b*ff - 2.0*a*ft + b*b *(-2.0*f + ff + float(char_pixels)) + 2.0*b*ft - 2.0*b*t + tt;
float diff_f = dot(diff, vec4(1.0, 1.0, 1.0, 1.0));
float4 diff = a*a*ff + 2.0*a*b*f - 2.0*a*b*ff - 2.0*a*ft + b*b *(-2.0*f + ff + float(char_pixels)) + 2.0*b*ft - 2.0*b*t + tt;
float diff_f = dot(diff, float4(1.0, 1.0, 1.0, 1.0));
if (diff_f < mindiff)
{
@ -93,8 +84,8 @@ void main()
}
}
vec2 font_pos_res = vec2(minc * float(char_width), 0.0) + pixel_offset + 0.5;
float2 font_pos_res = float2(minc * float(char_width), 0.0) + pixel_offset + 0.5;
vec4 col = texture(samp8, font_pos_res * font_scale);
ocol0 = mina * col + minb * (vec4(1.0,1.0,1.0,1.0) - col);
float4 col = SampleFontLocation(font_pos_res * font_scale);
SetOutput(mina * col + minb * (float4(1.0,1.0,1.0,1.0) - col));
}

View File

@ -1,22 +1,15 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
vec4 to_gray = vec4(0.3,0.59,0.11,0);
float4 to_gray = float4(0.3,0.59,0.11,0);
float x1 = dot(to_gray, texture(samp9, uv0+vec2(1,1)*resolution.zw));
float x0 = dot(to_gray, texture(samp9, uv0+vec2(-1,-1)*resolution.zw));
float x3 = dot(to_gray, texture(samp9, uv0+vec2(1,-1)*resolution.zw));
float x2 = dot(to_gray, texture(samp9, uv0+vec2(-1,1)*resolution.zw));
float x1 = dot(to_gray, SampleOffset(int2( 1, 1)));
float x0 = dot(to_gray, SampleOffset(int2(-1,-1)));
float x3 = dot(to_gray, SampleOffset(int2( 1,-1)));
float x2 = dot(to_gray, SampleOffset(int2(-1, 1)));
float edge = (x1 - x0) * (x1 - x0) + (x3 - x2) * (x3 - x2);
float4 color = texture(samp9, uv0).rgba;
float4 color = Sample();
ocol0 = color - vec4(edge, edge, edge, edge) * 12.0;
SetOutput(color - float4(edge, edge, edge, edge) * 12.0);
}

View File

@ -1,23 +1,15 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
//Changethis to increase the number of colors.
int numColors =8;
float4 to_gray = float4(0.3,0.59,0.11,0);
float x1 = dot(to_gray, texture(samp9, uv0+vec2(1,1)*resolution.zw));
float x0 = dot(to_gray, texture(samp9, uv0+vec2(-1,-1)*resolution.zw));
float x3 = dot(to_gray, texture(samp9, uv0+vec2(1,-1)*resolution.zw));
float x2 = dot(to_gray, texture(samp9, uv0+vec2(-1,1)*resolution.zw));
float x1 = dot(to_gray, SampleOffset(int2( 1, 1)));
float x0 = dot(to_gray, SampleOffset(int2(-1,-1)));
float x3 = dot(to_gray, SampleOffset(int2( 1,-1)));
float x2 = dot(to_gray, SampleOffset(int2(-1, 1)));
float edge = (x1 - x0) * (x1 - x0) + (x3 - x2) * (x3 - x2);
float4 color = texture(samp9, uv0).rgba;
float4 color = Sample();
float4 c0 = color - float4(edge, edge, edge, edge) * 12.0;
@ -66,7 +58,7 @@ void main()
blue = 0.95;
else
blue = colorN ;
bb = true;
}
@ -92,5 +84,5 @@ void main()
break;
}
ocol0 = float4(red, green, blue, c0.a);
SetOutput(float4(red, green, blue, c0.a));
}

View File

@ -1,43 +1,36 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
float4 c_center = texture(samp9, uv0);
float4 c_center = Sample();
float4 bloom_sum = float4(0.0, 0.0, 0.0, 0.0);
vec2 pos = uv0 + float2(0.3, 0.3) * resolution.zw;
float2 radius1 = 1.3 * resolution.zw;
bloom_sum += texture(samp9, pos + float2(-1.5, -1.5) * radius1);
bloom_sum += texture(samp9, pos + float2(-2.5, 0.0) * radius1);
bloom_sum += texture(samp9, pos + float2(-1.5, 1.5) * radius1);
bloom_sum += texture(samp9, pos + float2(0.0, 2.5) * radius1);
bloom_sum += texture(samp9, pos + float2(1.5, 1.5) * radius1);
bloom_sum += texture(samp9, pos + float2(2.5, 0.0) * radius1);
bloom_sum += texture(samp9, pos + float2(1.5, -1.5) * radius1);
bloom_sum += texture(samp9, pos + float2(0.0, -2.5) * radius1);
float2 pos = GetCoordinates() + float2(0.3, 0.3) * GetInvResolution();
float2 radius1 = 1.3 * GetInvResolution();
bloom_sum += SampleLocation(pos + float2(-1.5, -1.5) * radius1);
bloom_sum += SampleLocation(pos + float2(-2.5, 0.0) * radius1);
bloom_sum += SampleLocation(pos + float2(-1.5, 1.5) * radius1);
bloom_sum += SampleLocation(pos + float2(0.0, 2.5) * radius1);
bloom_sum += SampleLocation(pos + float2(1.5, 1.5) * radius1);
bloom_sum += SampleLocation(pos + float2(2.5, 0.0) * radius1);
bloom_sum += SampleLocation(pos + float2(1.5, -1.5) * radius1);
bloom_sum += SampleLocation(pos + float2(0.0, -2.5) * radius1);
float2 radius2 = 4.6 * resolution.zw;
bloom_sum += texture(samp9, pos + float2(-1.5, -1.5) * radius2);
bloom_sum += texture(samp9, pos + float2(-2.5, 0.0) * radius2);
bloom_sum += texture(samp9, pos + float2(-1.5, 1.5) * radius2);
bloom_sum += texture(samp9, pos + float2(0.0, 2.5) * radius2);
bloom_sum += texture(samp9, pos + float2(1.5, 1.5) * radius2);
bloom_sum += texture(samp9, pos + float2(2.5, 0.0) * radius2);
bloom_sum += texture(samp9, pos + float2(1.5, -1.5) * radius2);
bloom_sum += texture(samp9, pos + float2(0.0, -2.5) * radius2);
float2 radius2 = 4.6 * GetInvResolution();
bloom_sum += SampleLocation(pos + float2(-1.5, -1.5) * radius2);
bloom_sum += SampleLocation(pos + float2(-2.5, 0.0) * radius2);
bloom_sum += SampleLocation(pos + float2(-1.5, 1.5) * radius2);
bloom_sum += SampleLocation(pos + float2(0.0, 2.5) * radius2);
bloom_sum += SampleLocation(pos + float2(1.5, 1.5) * radius2);
bloom_sum += SampleLocation(pos + float2(2.5, 0.0) * radius2);
bloom_sum += SampleLocation(pos + float2(1.5, -1.5) * radius2);
bloom_sum += SampleLocation(pos + float2(0.0, -2.5) * radius2);
bloom_sum *= 0.07;
bloom_sum -= float4(0.3, 0.3, 0.3, 0.3);
bloom_sum = max(bloom_sum, float4(0.0, 0.0, 0.0, 0.0));
float2 vpos = (uv0 - float2(0.5, 0.5)) * 2.0;
float2 vpos = (GetCoordinates() - float2(0.5, 0.5)) * 2.0;
float dist = (dot(vpos, vpos));
dist = 1.0 - 0.4*dist;
ocol0 = (c_center * 0.7 + bloom_sum) * dist;
SetOutput((c_center * 0.7 + bloom_sum) * dist);
}

View File

@ -1,9 +1,4 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
ocol0 = texture(samp9, uv0) * 3.0;
SetOutput(Sample()* 3.0);
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
float red = 0.0;
float green = 0.0;
@ -14,5 +9,5 @@ void main()
else
red = c0.r + 0.4;
ocol0 = vec4(red, green, 0.0, 1.0);
SetOutput(float4(red, green, 0.0, 1.0));
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
float red = 0.0;
float green = 0.0;
float blue = 0.0;
@ -21,5 +16,5 @@ void main()
green = c0.r;
}
ocol0 = vec4(red, green, blue, 1.0);
SetOutput(float4(red, green, blue, 1.0));
}

View File

@ -1,17 +1,10 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
float4 c0 = texture(samp9, uv0);
float4 c1 = texture(samp9, uv0 - float2(1.0, 0.0) * resolution.zw);
float4 c2 = texture(samp9, uv0 - float2(0.0, 1.0) * resolution.zw);
float4 c3 = texture(samp9, uv0 + float2(1.0, 0.0) * resolution.zw);
float4 c4 = texture(samp9, uv0 + float2(0.0, 1.0) * resolution.zw);
float4 c0 = Sample();
float4 c1 = SampleOffset(int2(-1, 0));
float4 c2 = SampleOffset(int2( 0, -1));
float4 c3 = SampleOffset(int2( 1, 0));
float4 c4 = SampleOffset(int2( 0, 1));
float red = c0.r;
float blue = c0.b;
@ -36,5 +29,5 @@ void main()
else
blue = c0.b - c0.b / 2.0;
ocol0 = float4(red, green, blue, c0.a);
SetOutput(float4(red, green, blue, c0.a));
}

View File

@ -1,24 +1,17 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
float4 c0 = texture(samp9, uv0).rgba;
float4 c1 = texture(samp9, uv0 + float2(5.0,5.0)*resolution.zw).rgba;
float y = (0.222 * c1.r) + (0.707 * c1.g) + (0.071 * c1.b);
float y2 = ((0.222 * c0.r) + (0.707 * c0.g) + (0.071 * c0.b)) / 3.0;
float red = c0.r;
float green = c0.g;
float blue = c0.b;
float alpha = c0.a;
float4 c0 = Sample();
float4 c1 = SampleOffset(int2(5, 5));
float y = (0.222 * c1.r) + (0.707 * c1.g) + (0.071 * c1.b);
float y2 = ((0.222 * c0.r) + (0.707 * c0.g) + (0.071 * c0.b)) / 3.0;
float red = c0.r;
float green = c0.g;
float blue = c0.b;
float alpha = c0.a;
red = y2 + (1.0 - y);
green = y2 + (1.0 - y);
blue = y2 + (1.0 - y);
ocol0 = float4(red, green, blue, alpha);
SetOutput(float4(red, green, blue, alpha));
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
float red = 0.0;
float green = 0.0;
float blue = 0.0;
@ -30,5 +25,5 @@ void main()
if (((c0.r + c0.g + c0.b) / 3.0) > 0.9)
green = c0.r / 3.0;
ocol0 = vec4(red, green, blue, 1.0);
SetOutput(float4(red, green, blue, 1.0));
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
float red = 0.0;
float green = 0.0;
float blue = 0.0;
@ -14,5 +9,5 @@ void main()
red = c0.r + (c0.g / 2.0) + (c0.b / 3.0);
green = c0.r / 3.0;
ocol0 = vec4(red, green, blue, 1.0);
SetOutput(float4(red, green, blue, 1.0));
}

View File

@ -1,15 +1,8 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
float4 c0 = texture(samp9, uv0);
float4 c1 = texture(samp9, uv0 + float2(1,1)*resolution.zw);
float4 c2 = texture(samp9, uv0 + float2(-1,-1)*resolution.zw);
float4 c0 = Sample();
float4 c1 = SampleOffset(int2( 1, 1));
float4 c2 = SampleOffset(int2(-1, -1));
float red = c0.r;
float green = c0.g;
float blue = c0.b;
@ -18,5 +11,5 @@ void main()
red = c0.r - c1.b;
blue = c0.b - c2.r + (c0.g - c0.r);
ocol0 = float4(red, 0.0, blue, alpha);
SetOutput(float4(red, 0.0, blue, alpha));
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
float avg = (c0.r + c0.g + c0.b) / 3.0;
ocol0 = vec4(avg, avg, avg, c0.a);
SetOutput(float4(avg, avg, avg, c0.a));
}

View File

@ -1,12 +1,7 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
// Info: http://www.oreillynet.com/cs/user/view/cs_msg/8691
float avg = (0.222 * c0.r) + (0.707 * c0.g) + (0.071 * c0.b);
ocol0 = vec4(avg, avg, avg, c0.a);
SetOutput(float4(avg, avg, avg, c0.a));
}

View File

@ -1,9 +1,4 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
ocol0 = vec4(1.0, 1.0, 1.0, 1.0) - texture(samp9, uv0);
SetOutput(float4(1.0, 1.0, 1.0, 1.0) - Sample());
}

View File

@ -1,9 +1,4 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
ocol0 = vec4(0.0, 0.0, 0.7, 1.0) - texture(samp9, uv0);
SetOutput(float4(0.0, 0.0, 0.7, 1.0) - Sample());
}

View File

@ -1,14 +1,7 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
float4 c0 = texture(samp9, uv0);
float4 c1 = texture(samp9, uv0 + float2(5,5)*resolution.zw);
float4 c0 = Sample();
float4 c1 = SampleOffset(int2(5, 5));
ocol0 = c0 - c1;
SetOutput(c0 - c1);
}

View File

@ -1,26 +1,19 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
float4 emboss = (texture(samp9, uv0+resolution.zw) - texture(samp9, uv0-resolution.zw))*2.0;
emboss -= (texture(samp9, uv0+float2(1,-1)*resolution.zw).rgba - texture(samp9, uv0+float2(-1,1)*resolution.zw).rgba);
float4 color = texture(samp9, uv0).rgba;
float4 emboss = (SampleLocation(GetCoordinates()+GetInvResolution()) - SampleLocation(GetCoordinates()-GetInvResolution()))*2.0;
emboss -= (SampleLocation(GetCoordinates()+float2(1,-1)*GetInvResolution()).rgba - SampleLocation(GetCoordinates()+float2(-1,1)*GetInvResolution()).rgba);
float4 color = Sample();
if (color.r > 0.8 && color.b + color.b < 0.2)
{
ocol0 = float4(1,0,0,0);
SetOutput(float4(1,0,0,0));
}
else
{
color += emboss;
if (dot(color.rgb, float3(0.3, 0.5, 0.2)) > 0.5)
ocol0 = float4(1,1,1,1);
SetOutput(float4(1,1,1,1));
else
ocol0 = float4(0,0,0,0);
SetOutput(float4(0,0,0,0));
}
}

View File

@ -1,15 +1,10 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
float4 c0 = texture(samp9, uv0).rgba;
float4 c0 = Sample();
float green = c0.g;
if (c0.g < 0.50)
green = c0.r + c0.b;
ocol0 = float4(0.0, green, 0.0, 1.0);
SetOutput(float4(0.0, green, 0.0, 1.0));
}

View File

@ -1,27 +1,20 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
//variables
float internalresolution = 1278.0;
float4 c0 = texture(samp9, uv0).rgba;
float4 c0 = Sample();
//blur
float4 blurtotal = float4(0.0, 0.0, 0.0, 0.0);
float blursize = 1.5;
blurtotal += texture(samp9, uv0 + float2(-blursize, -blursize) * resolution.zw);
blurtotal += texture(samp9, uv0 + float2(-blursize, blursize) * resolution.zw);
blurtotal += texture(samp9, uv0 + float2( blursize, -blursize) * resolution.zw);
blurtotal += texture(samp9, uv0 + float2( blursize, blursize) * resolution.zw);
blurtotal += texture(samp9, uv0 + float2(-blursize, 0.0) * resolution.zw);
blurtotal += texture(samp9, uv0 + float2( blursize, 0.0) * resolution.zw);
blurtotal += texture(samp9, uv0 + float2( 0.0, -blursize) * resolution.zw);
blurtotal += texture(samp9, uv0 + float2( 0.0, blursize) * resolution.zw);
blurtotal += SampleLocation(GetCoordinates() + float2(-blursize, -blursize) * GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2(-blursize, blursize) * GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2( blursize, -blursize) * GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2( blursize, blursize) * GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2(-blursize, 0.0) * GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2( blursize, 0.0) * GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2( 0.0, -blursize) * GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2( 0.0, blursize) * GetInvResolution());
blurtotal *= 0.125;
c0 = blurtotal;
@ -32,8 +25,8 @@ void main()
grey = grey * 0.5 + 0.7;
// darken edges
float x = uv0.x * resolution.x;
float y = uv0.y * resolution.y;
float x = GetCoordinates().x * GetResolution().x;
float y = GetCoordinates().y * GetResolution().y;
if (x > internalresolution/2.0)
x = internalresolution-x;
if (y > internalresolution/2.0)
@ -65,5 +58,5 @@ void main()
grey -= y / 200.0;
// output
ocol0 = float4(0.0, grey, 0.0, 1.0);
SetOutput(float4(0.0, grey, 0.0, 1.0));
}

View File

@ -1,27 +1,20 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
//variables
float internalresolution = 1278.0;
float4 c0 = texture(samp9, uv0).rgba;
float4 c0 = Sample();
//blur
float4 blurtotal = float4(0.0, 0.0, 0.0, 0.0);
float blursize = 1.5;
blurtotal += texture(samp9, uv0 + float2(-blursize, -blursize)*resolution.zw);
blurtotal += texture(samp9, uv0 + float2(-blursize, blursize)*resolution.zw);
blurtotal += texture(samp9, uv0 + float2( blursize, -blursize)*resolution.zw);
blurtotal += texture(samp9, uv0 + float2( blursize, blursize)*resolution.zw);
blurtotal += texture(samp9, uv0 + float2(-blursize, 0.0)*resolution.zw);
blurtotal += texture(samp9, uv0 + float2( blursize, 0.0)*resolution.zw);
blurtotal += texture(samp9, uv0 + float2( 0.0, -blursize)*resolution.zw);
blurtotal += texture(samp9, uv0 + float2( 0.0, blursize)*resolution.zw);
blurtotal += SampleLocation(GetCoordinates() + float2(-blursize, -blursize)*GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2(-blursize, blursize)*GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2( blursize, -blursize)*GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2( blursize, blursize)*GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2(-blursize, 0.0)*GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2( blursize, 0.0)*GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2( 0.0, -blursize)*GetInvResolution());
blurtotal += SampleLocation(GetCoordinates() + float2( 0.0, blursize)*GetInvResolution());
blurtotal *= 0.125;
c0 = blurtotal;
@ -31,14 +24,14 @@ void main()
// brighten and apply horizontal scanlines
// This would have been much simpler if I could get the stupid modulo (%) to work
// If anyone who is more well versed in Cg knows how to do this it'd be slightly more efficient
// float lineIntensity = ((uv0[1] % 9) - 4) / 40;
float vPos = uv0.y*resolution.y / 9.0;
// float lineIntensity = ((GetCoordinates()[1] % 9) - 4) / 40;
float vPos = GetCoordinates().y*GetResolution().y / 9.0;
float lineIntensity = (((vPos - floor(vPos)) * 9.0) - 4.0) / 40.0;
grey = grey * 0.5 + 0.7 + lineIntensity;
// darken edges
float x = uv0.x * resolution.x;
float y = uv0.y * resolution.y;
float x = GetCoordinates().x * GetResolution().x;
float y = GetCoordinates().y * GetResolution().y;
if (x > internalresolution/2.0)
x = internalresolution-x;
@ -74,5 +67,5 @@ void main()
grey -= y / 200.0;
// output
ocol0 = float4(0.0, grey, 0.0, 1.0);
SetOutput(float4(0.0, grey, 0.0, 1.0));
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
float4 c0 = texture(samp9, uv0).rgba;
float4 c0 = Sample();
float red = 0.0;
float green = 0.0;
float blue = 0.0;
@ -19,5 +14,5 @@ void main()
if (c0.b > 0.25)
blue = c0.b;
ocol0 = float4(red, green, blue, 1.0);
SetOutput(float4(red, green, blue, 1.0));
}

View File

@ -1,8 +1,3 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
float bound(float color)
{
if (color < 0.35)
@ -18,6 +13,6 @@ float bound(float color)
void main()
{
float4 c0 = texture(samp9, uv0);
ocol0 = float4(bound(c0.r), bound(c0.g), bound(c0.b), c0.a);
float4 c0 = Sample();
SetOutput(float4(bound(c0.r), bound(c0.g), bound(c0.b), c0.a));
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
float red = c0.r;
float blue = c0.b;
float green = c0.g;
@ -78,5 +73,5 @@ void main()
green = 0.05;
}
}
ocol0 = vec4(red, green, blue, c0.a);
SetOutput(float4(red, green, blue, c0.a));
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
// Same coefficients as grayscale2 at this point
float avg = (0.222 * c0.r) + (0.707 * c0.g) + (0.071 * c0.b);
@ -14,5 +9,5 @@ void main()
// Not sure about these coefficients, they just seem to produce the proper yellow
float green=avg*.75;
float blue=avg*.5;
ocol0 = vec4(red, green, blue, c0.a);
SetOutput(float4(red, green, blue, c0.a));
}

View File

@ -1,24 +1,17 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
float4 c0 = texture(samp9, uv0).rgba;
float4 c0 = Sample();
float4 tmp = float4(0.0, 0.0, 0.0, 0.0);
tmp += c0 - texture(samp9, uv0 + float2(2.0, 2.0)*resolution.zw).rgba;
tmp += c0 - texture(samp9, uv0 - float2(2.0, 2.0)*resolution.zw).rgba;
tmp += c0 - texture(samp9, uv0 + float2(2.0, -2.0)*resolution.zw).rgba;
tmp += c0 - texture(samp9, uv0 - float2(2.0, -2.0)*resolution.zw).rgba;
tmp += c0 - SampleOffset(int2( 2, 2));
tmp += c0 - SampleOffset(int2(-2, -2));
tmp += c0 - SampleOffset(int2( 2, -2));
tmp += c0 - SampleOffset(int2(-2, 2));
float grey = ((0.222 * tmp.r) + (0.707 * tmp.g) + (0.071 * tmp.b));
// get rid of the bottom line, as it is incorrect.
if (uv0.y*resolution.y < 163.0)
if (GetCoordinates().y*GetResolution().y < 163.0)
tmp = float4(1.0, 1.0, 1.0, 1.0);
c0 = c0 + 1.0 - grey * 7.0;
ocol0 = float4(c0.r, c0.g, c0.b, 1.0);
SetOutput(float4(c0.r, c0.g, c0.b, 1.0));
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
float red = 0.0;
float blue = 0.0;
@ -19,5 +14,5 @@ void main()
blue = c0.r + c0.b;
}
ocol0 = vec4(red, 0.0, blue, 1.0);
SetOutput(float4(red, 0.0, blue, 1.0));
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
float red = 0.0;
float green = 0.0;
float blue = 0.0;
@ -21,5 +16,5 @@ void main()
green = c0.r + c0.b;
}
ocol0 = vec4(red, green, blue, 1.0);
SetOutput(float4(red, green, blue, 1.0));
}

View File

@ -1,31 +1,24 @@
// Omega's 3D Stereoscopic filtering
// TODO: Need depth info!
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
// Source Color
float4 c0 = texture(samp9, uv0).rgba;
float sep = 5.0;
float red = c0.r;
float green = c0.g;
float blue = c0.b;
float4 c0 = Sample();
const int sep = 5;
float red = c0.r;
float green = c0.g;
float blue = c0.b;
// Left Eye (Red)
float4 c1 = texture(samp9, uv0 + float2(sep,0.0)*resolution.zw).rgba;
float4 c1 = SampleOffset(int2(sep, 0));
red = max(c0.r, c1.r);
// Right Eye (Cyan)
float4 c2 = texture(samp9, uv0 + float2(-sep,0.0)*resolution.zw).rgba;
float4 c2 = SampleOffset(int2(-sep, 0));
float cyan = (c2.g + c2.b) / 2.0;
green = max(c0.g, cyan);
blue = max(c0.b, cyan);
ocol0 = float4(red, green, blue, c0.a);
SetOutput(float4(red, green, blue, c0.a));
}

View File

@ -1,31 +1,24 @@
// Omega's 3D Stereoscopic filtering (Amber/Blue)
// TODO: Need depth info!
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
uniform vec4 resolution;
void main()
{
// Source Color
float4 c0 = texture(samp9, uv0).rgba;
float4 c0 = Sample();
float sep = 5.0;
float red = c0.r;
float green = c0.g;
float blue = c0.b;
// Left Eye (Amber)
float4 c2 = texture(samp9, uv0 + float2(sep,0.0)*resolution.zw).rgba;
float4 c2 = SampleLocation(GetCoordinates() + float2(sep,0.0)*GetInvResolution()).rgba;
float amber = (c2.r + c2.g) / 2.0;
red = max(c0.r, amber);
green = max(c0.g, amber);
// Right Eye (Blue)
float4 c1 = texture(samp9, uv0 + float2(-sep,0.0)*resolution.zw).rgba;
float4 c1 = SampleLocation(GetCoordinates() + float2(-sep,0.0)*GetInvResolution()).rgba;
blue = max(c0.b, c1.b);
ocol0 = float4(red, green, blue, c0.a);
SetOutput(float4(red, green, blue, c0.a));
}

View File

@ -1,10 +1,5 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
ocol0 = vec4(c0.r * 1.5, c0.g, c0.b * 0.5, c0.a);
float4 c0 = Sample();
SetOutput(float4(c0.r * 1.5, c0.g, c0.b * 0.5, c0.a));
}

View File

@ -1,9 +1,4 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
ocol0 = texture(samp9, uv0).bgra;
SetOutput(Sample().bgra);
}

View File

@ -1,9 +1,4 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
ocol0 = texture(samp9, uv0).brga;
SetOutput(Sample().brga);
}

View File

@ -1,9 +1,4 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
ocol0 = texture(samp9, uv0).gbra;
SetOutput(Sample());
}

View File

@ -1,9 +1,4 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
ocol0 = texture(samp9, uv0).grba;
SetOutput(Sample());
}

View File

@ -1,9 +1,4 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
ocol0 = texture(samp9, uv0).rbga;
SetOutput(Sample().rbga);
}

View File

@ -1,11 +1,6 @@
SAMPLER_BINDING(9) uniform sampler2D samp9;
out vec4 ocol0;
in vec2 uv0;
void main()
{
vec4 c0 = texture(samp9, uv0);
float4 c0 = Sample();
float red = 0.0;
float green = 0.0;
float blue = 0.0;
@ -21,5 +16,5 @@ void main()
green = c0.r + c0.b;
}
ocol0 = vec4(red, green, blue, 1.0);
SetOutput(float4(red, green, blue, 1.0));
}

View File

@ -19,9 +19,7 @@
#include "Common/IniFile.h"
#include "Common/StringUtil.h"
namespace {
void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut)
void IniFile::ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut)
{
if (line[0] == '#')
return;
@ -40,8 +38,6 @@ void ParseLine(const std::string& line, std::string* keyOut, std::string* valueO
}
}
}
const std::string& IniFile::NULL_STRING = "";
void IniFile::Section::Set(const std::string& key, const std::string& newValue)

View File

@ -116,6 +116,11 @@ public:
Section* GetOrCreateSection(const std::string& section);
// This function is related to parsing data from lines of INI files
// It's used outside of IniFile, which is why it is exposed publicly
// In particular it is used in PostProcessing for its configuration
static void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut);
private:
std::list<Section> sections;

View File

@ -75,6 +75,23 @@ static bool TryParse(const std::string &str, N *const output)
return false;
}
template <typename N>
bool TryParseVector(const std::string& str, std::vector<N>* output, const char delimiter = ',')
{
output->clear();
std::istringstream buffer(str);
std::string variable;
while (std::getline(buffer, variable, delimiter))
{
N tmp = 0;
if (!TryParse(variable, &tmp))
return false;
output->push_back(tmp);
}
return true;
}
// TODO: kill this
bool AsciiToHex(const std::string& _szValue, u32& result);

View File

@ -62,6 +62,7 @@ set(GUI_SRCS
MemoryCards/WiiSaveCrypted.cpp
NetWindow.cpp
PatchAddEdit.cpp
PostProcessingConfigDiag.cpp
SoftwareVideoConfigDialog.cpp
TASInputDlg.cpp
VideoConfigDiag.cpp

View File

@ -97,6 +97,7 @@
</ClCompile>
<ClCompile Include="TASInputDlg.cpp" />
<ClCompile Include="VideoConfigDiag.cpp" />
<ClCompile Include="PostProcessingConfigDiag.cpp" />
<ClCompile Include="WiimoteConfigDiag.cpp" />
<ClCompile Include="WXInputBase.cpp" />
<ClCompile Include="WxUtils.cpp" />
@ -144,6 +145,7 @@
<ClInclude Include="stdafx.h" />
<ClInclude Include="TASInputDlg.h" />
<ClInclude Include="VideoConfigDiag.h" />
<ClInclude Include="PostProcessingConfigDiag.h" />
<ClInclude Include="WiimoteConfigDiag.h" />
<ClInclude Include="WXInputBase.h" />
<ClInclude Include="WxUtils.h" />
@ -228,4 +230,4 @@
<Message Text="Copy: @(BinaryFiles) -&gt; $(BinaryOutputDir)" Importance="High" />
<Copy SourceFiles="@(BinaryFiles)" DestinationFolder="$(BinaryOutputDir)" />
</Target>
</Project>
</Project>

View File

@ -93,6 +93,9 @@
<ClCompile Include="Debugger\DebuggerPanel.cpp">
<Filter>GUI\Video</Filter>
</ClCompile>
<ClCompile Include="PostProcessingConfigDiag.cpp">
<Filter>GUI\Video</Filter>
</ClCompile>
<ClCompile Include="VideoConfigDiag.cpp">
<Filter>GUI\Video</Filter>
</ClCompile>
@ -217,6 +220,9 @@
<ClInclude Include="Debugger\DebuggerPanel.h">
<Filter>GUI\Video</Filter>
</ClInclude>
<ClInclude Include="PostProcessingConfigDiag.h">
<Filter>GUI\Video</Filter>
</ClInclude>
<ClInclude Include="VideoConfigDiag.h">
<Filter>GUI\Video</Filter>
</ClInclude>
@ -296,4 +302,4 @@
<Filter>Resources</Filter>
</Image>
</ItemGroup>
</Project>
</Project>

View File

@ -0,0 +1,316 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <math.h>
#include <unordered_map>
#include <wx/button.h>
#include <wx/notebook.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/slider.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include "Common/StringUtil.h"
#include "DolphinWX/PostProcessingConfigDiag.h"
#include "VideoCommon/RenderBase.h"
PostProcessingConfigDiag::PostProcessingConfigDiag(wxWindow* parent, const std::string& shader)
: wxDialog(parent, -1,
wxString::Format(_("Post Processing Shader Configuration"))),
m_shader(shader)
{
// Depending on if we are running already, either use the one from the videobackend
// or generate our own.
if (g_renderer && g_renderer->GetPostProcessor())
{
m_post_processor = g_renderer->GetPostProcessor()->GetConfig();
}
else
{
m_post_processor = new PostProcessingShaderConfiguration();
m_post_processor->LoadShader(m_shader);
}
// Create our UI classes
const PostProcessingShaderConfiguration::ConfigMap& config_map = m_post_processor->GetOptions();
for (const auto& it : config_map)
{
if (it.second.m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_BOOL)
{
ConfigGrouping* group = new ConfigGrouping(ConfigGrouping::WidgetType::TYPE_TOGGLE,
it.second.m_gui_name, it.first, it.second.m_dependent_option,
&it.second);
m_config_map[it.first] = group;
}
else
{
ConfigGrouping* group = new ConfigGrouping(ConfigGrouping::WidgetType::TYPE_SLIDER,
it.second.m_gui_name, it.first, it.second.m_dependent_option,
&it.second);
m_config_map[it.first] = group;
}
}
// Arrange our vectors based on dependency
for (const auto& it : m_config_map)
{
const std::string parent_name = it.second->GetParent();
if (parent_name.size())
{
// Since it depends on a different object, push it to a parent's object
m_config_map[parent_name]->AddChild(m_config_map[it.first]);
}
else
{
// It doesn't have a child, just push it to the vector
m_config_groups.push_back(m_config_map[it.first]);
}
}
// Generate our UI
wxNotebook* const notebook = new wxNotebook(this, -1);
wxPanel* const page_general = new wxPanel(notebook, -1);
wxFlexGridSizer* const szr_general = new wxFlexGridSizer(2, 5, 5);
// Now let's actually populate our window with our information
bool add_general_page = false;
for (const auto& it : m_config_groups)
{
if (it->HasChildren())
{
// Options with children get their own tab
wxPanel* const page_option = new wxPanel(notebook, -1);
wxFlexGridSizer* const szr_option = new wxFlexGridSizer(2, 10, 5);
it->GenerateUI(this, page_option, szr_option);
// Add all the children
for (const auto& child : it->GetChildren())
{
child->GenerateUI(this, page_option, szr_option);
}
page_option->SetSizerAndFit(szr_option);
notebook->AddPage(page_option, _(it->GetGUIName()));
}
else
{
// Options with no children go in to the general tab
if (!add_general_page)
{
// Make it so it doesn't show up if there aren't any options without children.
add_general_page = true;
}
it->GenerateUI(this, page_general, szr_general);
}
}
if (add_general_page)
{
page_general->SetSizerAndFit(szr_general);
notebook->InsertPage(0, page_general, _("General"));
}
// Close Button
wxButton* const btn_close = new wxButton(this, wxID_OK, _("Close"));
btn_close->Bind(wxEVT_BUTTON, &PostProcessingConfigDiag::Event_ClickClose, this);
Bind(wxEVT_CLOSE_WINDOW, &PostProcessingConfigDiag::Event_Close, this);
wxBoxSizer* const szr_main = new wxBoxSizer(wxVERTICAL);
szr_main->Add(notebook, 1, wxEXPAND | wxALL, 5);
szr_main->Add(btn_close, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5);
SetSizerAndFit(szr_main);
Center();
SetFocus();
UpdateWindowUI();
}
PostProcessingConfigDiag::~PostProcessingConfigDiag()
{
m_post_processor->SaveOptionsConfiguration();
if (g_renderer && g_renderer->GetPostProcessor())
m_post_processor = nullptr;
else
delete m_post_processor;
}
void PostProcessingConfigDiag::ConfigGrouping::GenerateUI(PostProcessingConfigDiag* dialog, wxWindow* parent, wxFlexGridSizer* sizer)
{
if (m_type == WidgetType::TYPE_TOGGLE)
{
m_option_checkbox = new wxCheckBox(parent, wxID_ANY, _(m_gui_name));
m_option_checkbox->SetValue(m_config_option->m_bool_value);
m_option_checkbox->Bind(wxEVT_CHECKBOX, &PostProcessingConfigDiag::Event_CheckBox,
dialog, wxID_ANY, wxID_ANY, new UserEventData(m_option));
sizer->Add(m_option_checkbox);
sizer->AddStretchSpacer();
}
else
{
size_t vector_size = 0;
if (m_config_option->m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_INTEGER)
vector_size = m_config_option->m_integer_values.size();
else
vector_size = m_config_option->m_float_values.size();
wxFlexGridSizer* const szr_values = new wxFlexGridSizer(vector_size + 1, 0, 0);
wxStaticText* const option_static_text = new wxStaticText(parent, wxID_ANY, _(m_gui_name));
sizer->Add(option_static_text);
for (size_t i = 0; i < vector_size; ++i)
{
// wxSlider uses a signed integer for it's minimum and maximum values
// This won't work for floats.
// Let's determine how many steps we can take and use that instead.
int steps = 0;
int current_value = 0;
std::string string_value;
if (m_config_option->m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_INTEGER)
{
// Find out our range by taking the max subtracting the minimum.
double range = m_config_option->m_integer_max_values[i] - m_config_option->m_integer_min_values[i];
// How many steps we have is the range divided by the step interval configured.
// This may not be 100% spot on accurate since developers can have odd stepping intervals set.
// Round up so if it is outside our range, then set it to the minimum or maximum
steps = ceil(range / (double)m_config_option->m_integer_step_values[i]);
// Default value is just the currently set value here
current_value = m_config_option->m_integer_values[i];
string_value = std::to_string(m_config_option->m_integer_values[i]);
}
else
{
// Same as above but with floats
float range = m_config_option->m_float_max_values[i] - m_config_option->m_float_min_values[i];
steps = ceil(range / m_config_option->m_float_step_values[i]);
// We need to convert our default float value from a float to the nearest step value range
current_value = (m_config_option->m_float_values[i] / m_config_option->m_float_step_values[i]);
string_value = std::to_string(m_config_option->m_float_values[i]);
}
wxSlider* slider = new wxSlider(parent, wxID_ANY, current_value, 0, steps,
wxDefaultPosition, wxSize(200, -1), wxSL_HORIZONTAL | wxSL_BOTTOM);
wxTextCtrl* text_ctrl = new wxTextCtrl(parent, wxID_ANY, string_value);
// Disable the textctrl, it's only there to show the absolute value from the slider
text_ctrl->Enable(false);
// wxWidget takes over the pointer provided to it in the event handler.
// This won't be a memory leak, it'll be destroyed on dialog close.
slider->Bind(wxEVT_SLIDER, &PostProcessingConfigDiag::Event_Slider,
dialog, wxID_ANY, wxID_ANY, new UserEventData(m_option));
m_option_sliders.push_back(slider);
m_option_text_ctrls.push_back(text_ctrl);
}
if (vector_size == 1)
{
szr_values->Add(m_option_sliders[0], wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
szr_values->Add(m_option_text_ctrls[0]);
sizer->Add(szr_values);
}
else
{
wxFlexGridSizer* const szr_inside = new wxFlexGridSizer(2, 0, 0);
for (size_t i = 0; i < vector_size; ++i)
{
szr_inside->Add(m_option_sliders[i], wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
szr_inside->Add(m_option_text_ctrls[i]);
}
szr_values->Add(szr_inside);
sizer->Add(szr_values);
}
}
}
void PostProcessingConfigDiag::ConfigGrouping::EnableDependentChildren(bool enable)
{
// Enable or disable all the children
for (auto& it : m_children)
{
if (it->m_type == ConfigGrouping::WidgetType::TYPE_TOGGLE)
{
it->m_option_checkbox->Enable(enable);
}
else
{
for (auto& slider : it->m_option_sliders)
slider->Enable(enable);
}
// Set this objects children as well
it->EnableDependentChildren(enable);
}
}
void PostProcessingConfigDiag::Event_CheckBox(wxCommandEvent &ev)
{
UserEventData* config_option = (UserEventData*)ev.GetEventUserData();
ConfigGrouping* config = m_config_map[config_option->GetData()];
m_post_processor->SetOptionb(config->GetOption(), ev.IsChecked());
config->EnableDependentChildren(ev.IsChecked());
ev.Skip();
}
void PostProcessingConfigDiag::Event_Slider(wxCommandEvent &ev)
{
UserEventData* config_option = (UserEventData*)ev.GetEventUserData();
ConfigGrouping* config = m_config_map[config_option->GetData()];
const auto& option_data = m_post_processor->GetOption(config->GetOption());
size_t vector_size = 0;
if (option_data.m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_INTEGER)
vector_size = option_data.m_integer_values.size();
else
vector_size = option_data.m_float_values.size();
for (size_t i = 0; i < vector_size; ++i)
{
// Got to do this garbage again.
// Convert current step in to the real range value
int current_step = config->GetSliderValue(i);
std::string string_value;
if (option_data.m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_INTEGER)
{
s32 value = option_data.m_integer_step_values[i] * current_step + option_data.m_integer_min_values[i];
m_post_processor->SetOptioni(config->GetOption(), i, value);
string_value = std::to_string(value);
}
else
{
float value = option_data.m_float_step_values[i] * current_step + option_data.m_float_min_values[i];
m_post_processor->SetOptionf(config->GetOption(), i, value);
string_value = std::to_string(value);
}
// Update the text box to include the new value
config->SetSliderText(i, string_value);
}
ev.Skip();
}
void PostProcessingConfigDiag::Event_ClickClose(wxCommandEvent&)
{
Close();
}
void PostProcessingConfigDiag::Event_Close(wxCloseEvent& ev)
{
EndModal(wxID_OK);
}

View File

@ -0,0 +1,106 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <map>
#include <string>
#include <vector>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/dialog.h>
#include <wx/sizer.h>
#include <wx/slider.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include "VideoCommon/PostProcessing.h"
class PostProcessingConfigDiag : public wxDialog
{
public:
PostProcessingConfigDiag(wxWindow* parent, const std::string& shader);
~PostProcessingConfigDiag();
private:
// This is literally the stupidest thing ever
// wxWidgets takes ownership of any pointer given to a event handler
// Instead of passing them a pointer to a std::string, we wrap around it here.
class UserEventData : public wxObject
{
public:
UserEventData(const std::string& data) : m_data(data) {}
const std::string& GetData() { return m_data; }
private:
const std::string m_data;
};
class ConfigGrouping
{
public:
enum WidgetType
{
TYPE_TOGGLE,
TYPE_SLIDER,
};
ConfigGrouping(WidgetType type, const std::string& gui_name,
const std::string& option_name, const std::string& parent,
const PostProcessingShaderConfiguration::ConfigurationOption* config_option)
: m_type(type), m_gui_name(gui_name),
m_option(option_name), m_parent(parent),
m_config_option(config_option) {}
void AddChild(ConfigGrouping* child) { m_children.push_back(child); }
bool HasChildren() { return m_children.size() != 0; }
std::vector<ConfigGrouping*>& GetChildren() { return m_children; }
// Gets the string that is shown in the UI for the option
const std::string& GetGUIName() { return m_gui_name; }
// Gets the option name for use in the shader
// Also is a unique identifier for the option's configuration
const std::string& GetOption() { return m_option; }
// Gets the option name of the parent of this option
const std::string& GetParent() { return m_parent; }
void GenerateUI(PostProcessingConfigDiag* dialog, wxWindow* parent, wxFlexGridSizer* sizer);
void EnableDependentChildren(bool enable);
int GetSliderValue(const int index) { return m_option_sliders[index]->GetValue(); }
void SetSliderText(const int index, const std::string& text) { m_option_text_ctrls[index]->SetValue(text); }
private:
const WidgetType m_type;
const std::string m_gui_name;
const std::string m_option;
const std::string m_parent;
const PostProcessingShaderConfiguration::ConfigurationOption* m_config_option;
// For TYPE_TOGGLE
wxCheckBox* m_option_checkbox;
// For TYPE_SLIDER
// Can have up to 4
std::vector<wxSlider*> m_option_sliders;
std::vector<wxTextCtrl*> m_option_text_ctrls;
std::vector<ConfigGrouping*> m_children;
};
// WX UI things
void Event_Close(wxCloseEvent&);
void Event_ClickClose(wxCommandEvent&);
void Event_Slider(wxCommandEvent &ev);
void Event_CheckBox(wxCommandEvent &ev);
const std::string& m_shader;
PostProcessingShaderConfiguration* m_post_processor;
std::map<std::string, ConfigGrouping*> m_config_map;
std::vector<ConfigGrouping*> m_config_groups;
};

View File

@ -1,3 +1,7 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <map>
#include <string>
#include <utility>
@ -32,6 +36,7 @@
#include "DolphinWX/VideoConfigDiag.h"
#include "DolphinWX/WxUtils.h"
#include "VideoBackends/OGL/main.h"
#include "VideoCommon/PostProcessing.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
@ -401,10 +406,13 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
// postproc shader
if (vconfig.backend_info.PPShaders.size())
{
wxFlexGridSizer* const szr_pp = new wxFlexGridSizer(3, 5, 5);
wxChoice *const choice_ppshader = new wxChoice(page_enh, -1);
RegisterControl(choice_ppshader, wxGetTranslation(ppshader_desc));
choice_ppshader->AppendString(_("(off)"));
button_config_pp = new wxButton(page_enh, wxID_ANY, _("Config"));
for (const std::string& shader : vconfig.backend_info.PPShaders)
{
choice_ppshader->AppendString(StrToWxStr(shader));
@ -415,10 +423,18 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string &title, con
else
choice_ppshader->SetStringSelection(StrToWxStr(vconfig.sPostProcessingShader));
// Should the configuration button be loaded by default?
PostProcessingShaderConfiguration postprocessing_shader;
postprocessing_shader.LoadShader(vconfig.sPostProcessingShader);
button_config_pp->Enable(postprocessing_shader.HasOptions());
choice_ppshader->Bind(wxEVT_CHOICE, &VideoConfigDiag::Event_PPShader, this);
button_config_pp->Bind(wxEVT_BUTTON, &VideoConfigDiag::Event_ConfigurePPShader, this);
szr_enh->Add(new wxStaticText(page_enh, -1, _("Post-Processing Effect:")), 1, wxALIGN_CENTER_VERTICAL, 0);
szr_enh->Add(choice_ppshader);
szr_pp->Add(choice_ppshader);
szr_pp->Add(button_config_pp);
szr_enh->Add(szr_pp);
}
// Scaled copy, PL, Bilinear filter

View File

@ -1,9 +1,14 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <cstddef>
#include <map>
#include <string>
#include <vector>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/choice.h>
#include <wx/defs.h>
@ -22,7 +27,9 @@
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreParameter.h"
#include "DolphinWX/PostProcessingConfigDiag.h"
#include "DolphinWX/WxUtils.h"
#include "VideoCommon/PostProcessing.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
@ -142,6 +149,19 @@ protected:
else
vconfig.sPostProcessingShader.clear();
// Should we enable the configuration button?
PostProcessingShaderConfiguration postprocessing_shader;
postprocessing_shader.LoadShader(vconfig.sPostProcessingShader);
button_config_pp->Enable(postprocessing_shader.HasOptions());
ev.Skip();
}
void Event_ConfigurePPShader(wxCommandEvent &ev)
{
PostProcessingConfigDiag dialog(this, vconfig.sPostProcessingShader);
dialog.ShowModal();
ev.Skip();
}
@ -188,6 +208,8 @@ protected:
wxStaticText* text_aamode;
SettingChoice* choice_aamode;
wxButton* button_config_pp;
SettingCheckBox* borderless_fullscreen;
SettingRadioButton* efbcopy_texture;

View File

@ -4,6 +4,7 @@
#include "Common/CommonPaths.h"
#include "Common/FileUtil.h"
#include "Common/StringUtil.h"
#include "VideoBackends/OGL/FramebufferManager.h"
#include "VideoBackends/OGL/GLUtil.h"
@ -16,20 +17,6 @@
namespace OGL
{
namespace PostProcessing
{
static std::string s_currentShader;
static SHADER s_shader;
static bool s_enable;
static u32 s_width;
static u32 s_height;
static GLuint s_fbo;
static GLuint s_texture;
static GLuint s_uniform_resolution;
static char s_vertex_shader[] =
"out vec2 uv0;\n"
"void main(void) {\n"
@ -38,119 +25,278 @@ static char s_vertex_shader[] =
" uv0 = rawpos;\n"
"}\n";
void Init()
OpenGLPostProcessing::OpenGLPostProcessing()
{
s_currentShader = "";
s_enable = 0;
s_width = 0;
s_height = 0;
m_enable = false;
m_width = 0;
m_height = 0;
glGenFramebuffers(1, &s_fbo);
glGenTextures(1, &s_texture);
glBindTexture(GL_TEXTURE_2D, s_texture);
glGenFramebuffers(1, &m_fbo);
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); // disable mipmaps
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glBindFramebuffer(GL_FRAMEBUFFER, s_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, s_texture, 0);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture, 0);
FramebufferManager::SetFramebuffer(0);
CreateHeader();
}
void Shutdown()
OpenGLPostProcessing::~OpenGLPostProcessing()
{
s_shader.Destroy();
m_shader.Destroy();
glDeleteFramebuffers(1, &s_fbo);
glDeleteTextures(1, &s_texture);
glDeleteFramebuffers(1, &m_fbo);
glDeleteTextures(1, &m_texture);
}
void ReloadShader()
void OpenGLPostProcessing::BindTargetFramebuffer()
{
s_currentShader = "";
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_enable ? m_fbo : 0);
}
void BindTargetFramebuffer ()
void OpenGLPostProcessing::BlitToScreen()
{
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, s_enable ? s_fbo : 0);
}
void BlitToScreen()
{
if (!s_enable) return;
if (!m_enable) return;
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glViewport(0, 0, s_width, s_height);
glViewport(0, 0, m_width, m_height);
s_shader.Bind();
m_shader.Bind();
glUniform4f(s_uniform_resolution, (float)s_width, (float)s_height, 1.0f/(float)s_width, 1.0f/(float)s_height);
glUniform4f(m_uniform_resolution, (float)m_width, (float)m_height, 1.0f/(float)m_width, 1.0f/(float)m_height);
glUniform1ui(m_uniform_time, (GLuint)m_timer.GetTimeElapsed());
if (m_config.IsDirty())
{
for (auto& it : m_config.GetOptions())
{
if (it.second.m_dirty)
{
switch (it.second.m_type)
{
case PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_BOOL:
glUniform1i(m_uniform_bindings[it.first], it.second.m_bool_value);
break;
case PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_INTEGER:
switch (it.second.m_integer_values.size())
{
case 1:
glUniform1i(m_uniform_bindings[it.first], it.second.m_integer_values[0]);
break;
case 2:
glUniform2i(m_uniform_bindings[it.first],
it.second.m_integer_values[0],
it.second.m_integer_values[1]);
break;
case 3:
glUniform3i(m_uniform_bindings[it.first],
it.second.m_integer_values[0],
it.second.m_integer_values[1],
it.second.m_integer_values[2]);
break;
case 4:
glUniform4i(m_uniform_bindings[it.first],
it.second.m_integer_values[0],
it.second.m_integer_values[1],
it.second.m_integer_values[2],
it.second.m_integer_values[3]);
break;
}
break;
case PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_FLOAT:
switch (it.second.m_float_values.size())
{
case 1:
glUniform1f(m_uniform_bindings[it.first], it.second.m_float_values[0]);
break;
case 2:
glUniform2f(m_uniform_bindings[it.first],
it.second.m_float_values[0],
it.second.m_float_values[1]);
break;
case 3:
glUniform3f(m_uniform_bindings[it.first],
it.second.m_float_values[0],
it.second.m_float_values[1],
it.second.m_float_values[2]);
break;
case 4:
glUniform4f(m_uniform_bindings[it.first],
it.second.m_float_values[0],
it.second.m_float_values[1],
it.second.m_float_values[2],
it.second.m_float_values[3]);
break;
}
break;
}
it.second.m_dirty = false;
}
}
m_config.SetDirty(false);
}
glActiveTexture(GL_TEXTURE0+9);
glBindTexture(GL_TEXTURE_2D, s_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
/* glBindFramebuffer(GL_READ_FRAMEBUFFER, s_fbo);
glBlitFramebuffer(rc.left, rc.bottom, rc.right, rc.top,
rc.left, rc.bottom, rc.right, rc.top,
GL_COLOR_BUFFER_BIT, GL_NEAREST);*/
}
void Update ( u32 width, u32 height )
void OpenGLPostProcessing::Update(u32 width, u32 height)
{
ApplyShader();
if (s_enable && (width != s_width || height != s_height)) {
s_width = width;
s_height = height;
if (m_enable && (width != m_width || height != m_height))
{
m_width = width;
m_height = height;
// alloc texture for framebuffer
glActiveTexture(GL_TEXTURE0+9);
glBindTexture(GL_TEXTURE_2D, s_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
}
}
void ApplyShader()
void OpenGLPostProcessing::ApplyShader()
{
// shader didn't changed
if (s_currentShader == g_ActiveConfig.sPostProcessingShader) return;
s_currentShader = g_ActiveConfig.sPostProcessingShader;
s_enable = false;
s_shader.Destroy();
if (m_config.GetShader() == g_ActiveConfig.sPostProcessingShader) return;
m_enable = false;
m_shader.Destroy();
m_uniform_bindings.clear();
// shader disabled
if (g_ActiveConfig.sPostProcessingShader == "") return;
// so need to compile shader
std::string code = m_config.LoadShader();
// loading shader code
std::string code;
std::string path = File::GetUserPath(D_SHADERS_IDX) + g_ActiveConfig.sPostProcessingShader + ".glsl";
if (!File::Exists(path))
{
// Fallback to shared user dir
path = File::GetSysDirectory() + SHADERS_DIR DIR_SEP + g_ActiveConfig.sPostProcessingShader + ".glsl";
}
if (!File::ReadFileToString(path, code)) {
ERROR_LOG(VIDEO, "Post-processing shader not found: %s", path.c_str());
return;
}
if (code == "") return;
code = LoadShaderOptions(code);
// and compile it
if (!ProgramShaderCache::CompileShader(s_shader, s_vertex_shader, code.c_str())) {
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", s_currentShader.c_str());
if (!ProgramShaderCache::CompileShader(m_shader, s_vertex_shader, code.c_str())) {
ERROR_LOG(VIDEO, "Failed to compile post-processing shader %s", m_config.GetShader().c_str());
return;
}
// read uniform locations
s_uniform_resolution = glGetUniformLocation(s_shader.glprogid, "resolution");
m_uniform_resolution = glGetUniformLocation(m_shader.glprogid, "resolution");
m_uniform_time = glGetUniformLocation(m_shader.glprogid, "time");
for (const auto& it : m_config.GetOptions())
{
std::string glsl_name = "option_" + it.first;
m_uniform_bindings[it.first] = glGetUniformLocation(m_shader.glprogid, glsl_name.c_str());
}
// successful
s_enable = true;
m_enable = true;
}
} // namespace
void OpenGLPostProcessing::CreateHeader()
{
m_glsl_header =
// Required variables
// Shouldn't be accessed directly by the PP shader
// Texture sampler
"SAMPLER_BINDING(8) uniform sampler2D samp8;\n"
"SAMPLER_BINDING(9) uniform sampler2D samp9;\n"
// Output variable
"out float4 ocol0;\n"
// Input coordinates
"in float2 uv0;\n"
// Resolution
"uniform float4 resolution;\n"
// Time
"uniform uint time;\n"
// Interfacing functions
"float4 Sample()\n"
"{\n"
"\treturn texture(samp9, uv0);\n"
"}\n"
"float4 SampleLocation(float2 location)\n"
"{\n"
"\treturn texture(samp9, location);\n"
"}\n"
"#define SampleOffset(offset) textureOffset(samp9, uv0, offset)\n"
"float4 SampleFontLocation(float2 location)\n"
"{\n"
"\treturn texture(samp8, location);\n"
"}\n"
"float2 GetResolution()\n"
"{\n"
"\treturn resolution.xy;\n"
"}\n"
"float2 GetInvResolution()\n"
"{\n"
"\treturn resolution.zw;\n"
"}\n"
"float2 GetCoordinates()\n"
"{\n"
"\treturn uv0;\n"
"}\n"
"uint GetTime()\n"
"{\n"
"\treturn time;\n"
"}\n"
"void SetOutput(float4 color)\n"
"{\n"
"\tocol0 = color;\n"
"}\n"
"#define GetOption(x) (option_#x)\n"
"#define OptionEnabled(x) (option_#x != 0)\n";
}
std::string OpenGLPostProcessing::LoadShaderOptions(const std::string& code)
{
std::string glsl_options = "";
m_uniform_bindings.clear();
for (const auto& it : m_config.GetOptions())
{
if (it.second.m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_BOOL)
{
glsl_options += StringFromFormat("uniform int option_%s;\n", it.first.c_str());
}
else if (it.second.m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_INTEGER)
{
u32 count = it.second.m_integer_values.size();
if (count == 1)
glsl_options += StringFromFormat("uniform int option_%s;\n", it.first.c_str());
else
glsl_options += StringFromFormat("uniform int%d option_%s;\n", count, it.first.c_str());
}
else if (it.second.m_type == PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_FLOAT)
{
u32 count = it.second.m_float_values.size();
if (count == 1)
glsl_options += StringFromFormat("uniform float option_%s;\n", it.first.c_str());
else
glsl_options += StringFromFormat("uniform float%d option_%s;\n", count, it.first.c_str());
}
m_uniform_bindings[it.first] = 0;
}
return m_glsl_header + glsl_options + code;
}
} // namespace OGL

View File

@ -4,26 +4,40 @@
#pragma once
#include <string>
#include <unordered_map>
#include "VideoBackends/OGL/GLUtil.h"
#include "VideoCommon/PostProcessing.h"
#include "VideoCommon/VideoCommon.h"
namespace OGL
{
namespace PostProcessing
class OpenGLPostProcessing : public PostProcessingShaderImplementation
{
public:
OpenGLPostProcessing();
~OpenGLPostProcessing();
void Init();
void Shutdown();
void BindTargetFramebuffer() override;
void BlitToScreen() override;
void Update(u32 width, u32 height) override;
void ApplyShader() override;
void BindTargetFramebuffer();
void BlitToScreen();
void Update(u32 width, u32 height);
private:
GLuint m_fbo;
GLuint m_texture;
SHADER m_shader;
GLuint m_uniform_resolution;
GLuint m_uniform_time;
std::string m_glsl_header;
void ReloadShader();
std::unordered_map<std::string, GLuint> m_uniform_bindings;
void ApplyShader();
} // namespace
void CreateHeader();
std::string LoadShaderOptions(const std::string& code);
};
} // namespace

View File

@ -641,6 +641,9 @@ void Renderer::Shutdown()
delete s_pfont;
s_pfont = nullptr;
s_ShowEFBCopyRegions.Destroy();
delete m_post_processor;
m_post_processor = nullptr;
}
void Renderer::Init()
@ -649,6 +652,8 @@ void Renderer::Init()
g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height,
s_MSAASamples);
m_post_processor = new OpenGLPostProcessing();
s_pfont = new RasterFont();
ProgramShaderCache::CompileShader(s_ShowEFBCopyRegions,
@ -1331,7 +1336,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl
ResetAPIState();
PostProcessing::Update(s_backbuffer_width, s_backbuffer_height);
m_post_processor->Update(s_backbuffer_width, s_backbuffer_height);
UpdateDrawRectangle(s_backbuffer_width, s_backbuffer_height);
TargetRectangle flipped_trc = GetTargetRectangle();
@ -1354,7 +1359,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl
if (g_ActiveConfig.bUseXFB)
{
// Render to the real/postprocessing buffer now.
PostProcessing::BindTargetFramebuffer();
m_post_processor->BindTargetFramebuffer();
// draw each xfb source
glBindFramebuffer(GL_READ_FRAMEBUFFER, FramebufferManager::GetXFBFramebuffer());
@ -1413,7 +1418,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl
FramebufferManager::ResolveAndGetRenderTarget(rc);
// Render to the real/postprocessing buffer now. (resolve have changed this in msaa mode)
PostProcessing::BindTargetFramebuffer();
m_post_processor->BindTargetFramebuffer();
// always the non-msaa fbo
GLuint fb = s_MSAASamples>1?FramebufferManager::GetResolvedFramebuffer():FramebufferManager::GetEFBFramebuffer();
@ -1424,7 +1429,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangl
GL_COLOR_BUFFER_BIT, GL_LINEAR);
}
PostProcessing::BlitToScreen();
m_post_processor->BlitToScreen();
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);

View File

@ -210,7 +210,6 @@ void VideoBackend::Video_Prepare()
VertexShaderManager::Init();
PixelShaderManager::Init();
ProgramShaderCache::Init();
PostProcessing::Init();
g_texture_cache = new TextureCache();
g_sampler_cache = new SamplerCache();
Renderer::Init();
@ -250,7 +249,6 @@ void VideoBackend::Video_Cleanup() {
g_sampler_cache = nullptr;
delete g_texture_cache;
g_texture_cache = nullptr;
PostProcessing::Shutdown();
ProgramShaderCache::Shutdown();
VertexShaderManager::Shutdown();
PixelShaderManager::Shutdown();

View File

@ -18,6 +18,7 @@ set(SRCS BPFunctions.cpp
PixelEngine.cpp
PixelShaderGen.cpp
PixelShaderManager.cpp
PostProcessing.cpp
RenderBase.cpp
Statistics.cpp
TextureCacheBase.cpp

View File

@ -0,0 +1,304 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <string>
#include "Common/CommonPaths.h"
#include "Common/FileUtil.h"
#include "Common/IniFile.h"
#include "Common/StringUtil.h"
#include "VideoCommon/PostProcessing.h"
#include "VideoCommon/VideoConfig.h"
PostProcessingShaderImplementation::PostProcessingShaderImplementation()
{
m_timer.Start();
}
PostProcessingShaderImplementation::~PostProcessingShaderImplementation()
{
m_timer.Stop();
}
std::string PostProcessingShaderConfiguration::LoadShader(std::string shader)
{
// Load the shader from the configuration if there isn't one sent to us.
if (shader == "")
shader = g_ActiveConfig.sPostProcessingShader;
m_current_shader = shader;
// loading shader code
std::string code;
std::string path = File::GetUserPath(D_SHADERS_IDX) + shader + ".glsl";
if (!File::Exists(path))
{
// Fallback to shared user dir
path = File::GetSysDirectory() + SHADERS_DIR DIR_SEP + shader + ".glsl";
}
if (!File::ReadFileToString(path, code))
{
ERROR_LOG(VIDEO, "Post-processing shader not found: %s", path.c_str());
return "";
}
LoadOptions(code);
LoadOptionsConfiguration();
return code;
}
void PostProcessingShaderConfiguration::LoadOptions(const std::string& code)
{
const std::string config_start_delimiter = "[configuration]";
const std::string config_end_delimiter = "[/configuration]";
size_t configuration_start = code.find(config_start_delimiter);
size_t configuration_end = code.find(config_end_delimiter);
m_options.clear();
m_any_options_dirty = true;
if (configuration_start == std::string::npos ||
configuration_end == std::string::npos)
{
// Issue loading configuration or there isn't one.
return;
}
std::string configuration_string = code.substr(configuration_start + config_start_delimiter.size(),
configuration_end - configuration_start - config_start_delimiter.size());
std::istringstream in(configuration_string);
struct GLSLStringOption
{
std::string m_type;
std::vector<std::pair<std::string, std::string>> m_options;
};
std::vector<GLSLStringOption> option_strings;
GLSLStringOption* current_strings = nullptr;
while (!in.eof())
{
std::string line;
if (std::getline(in, line))
{
#ifndef _WIN32
// Check for CRLF eol and convert it to LF
if (!line.empty() && line.at(line.size()-1) == '\r')
{
line.erase(line.size()-1);
}
#endif
if (line.size() > 0)
{
if (line[0] == '[')
{
size_t endpos = line.find("]");
if (endpos != std::string::npos)
{
// New section!
std::string sub = line.substr(1, endpos - 1);
option_strings.push_back({ sub });
current_strings = &option_strings.back();
}
}
else
{
if (current_strings)
{
std::string key, value;
IniFile::ParseLine(line, &key, &value);
if (!(key == "" && value == ""))
current_strings->m_options.push_back(std::make_pair(key, value));
}
}
}
}
}
for (const auto& it : option_strings)
{
ConfigurationOption option;
option.m_dirty = true;
if (it.m_type == "OptionBool")
option.m_type = ConfigurationOption::OptionType::OPTION_BOOL;
else if (it.m_type == "OptionRangeFloat")
option.m_type = ConfigurationOption::OptionType::OPTION_FLOAT;
else if (it.m_type == "OptionRangeInteger")
option.m_type = ConfigurationOption::OptionType::OPTION_INTEGER;
for (const auto& string_option : it.m_options)
{
if (string_option.first == "GUIName")
{
option.m_gui_name = string_option.second;
}
else if (string_option.first == "OptionName")
{
option.m_option_name = string_option.second;
}
else if (string_option.first == "DependentOption")
{
option.m_dependent_option = string_option.second;
}
else if (string_option.first == "MinValue" ||
string_option.first == "MaxValue" ||
string_option.first == "DefaultValue" ||
string_option.first == "StepAmount")
{
std::vector<s32>* output_integer = nullptr;
std::vector<float>* output_float = nullptr;
if (string_option.first == "MinValue")
{
output_integer = &option.m_integer_min_values;
output_float = &option.m_float_min_values;
}
else if (string_option.first == "MaxValue")
{
output_integer = &option.m_integer_max_values;
output_float = &option.m_float_max_values;
}
else if (string_option.first == "DefaultValue")
{
output_integer = &option.m_integer_values;
output_float = &option.m_float_values;
}
else if (string_option.first == "StepAmount")
{
output_integer = &option.m_integer_step_values;
output_float = &option.m_float_step_values;
}
if (option.m_type == ConfigurationOption::OptionType::OPTION_BOOL)
{
TryParse(string_option.second, &option.m_bool_value);
}
else if (option.m_type == ConfigurationOption::OptionType::OPTION_INTEGER)
{
TryParseVector(string_option.second, output_integer);
if (output_integer->size() > 4)
output_integer->erase(output_integer->begin() + 4, output_integer->end());
}
else if (option.m_type == ConfigurationOption::OptionType::OPTION_FLOAT)
{
TryParseVector(string_option.second, output_float);
if (output_float->size() > 4)
output_float->erase(output_float->begin() + 4, output_float->end());
}
}
}
m_options[option.m_option_name] = option;
}
}
void PostProcessingShaderConfiguration::LoadOptionsConfiguration()
{
IniFile ini;
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
std::string section = m_current_shader + "-options";
for (auto& it : m_options)
{
switch (it.second.m_type)
{
case ConfigurationOption::OptionType::OPTION_BOOL:
ini.GetOrCreateSection(section)->Get(it.second.m_option_name, &it.second.m_bool_value, it.second.m_bool_value);
break;
case ConfigurationOption::OptionType::OPTION_INTEGER:
{
std::string value;
ini.GetOrCreateSection(section)->Get(it.second.m_option_name, &value);
if (value != "")
TryParseVector(value, &it.second.m_integer_values);
}
break;
case ConfigurationOption::OptionType::OPTION_FLOAT:
{
std::string value;
ini.GetOrCreateSection(section)->Get(it.second.m_option_name, &value);
if (value != "")
TryParseVector(value, &it.second.m_float_values);
}
break;
}
}
}
void PostProcessingShaderConfiguration::SaveOptionsConfiguration()
{
IniFile ini;
ini.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
std::string section = m_current_shader + "-options";
for (auto& it : m_options)
{
switch (it.second.m_type)
{
case ConfigurationOption::OptionType::OPTION_BOOL:
{
ini.GetOrCreateSection(section)->Set(it.second.m_option_name, it.second.m_bool_value);
}
break;
case ConfigurationOption::OptionType::OPTION_INTEGER:
{
std::string value = "";
for (size_t i = 0; i < it.second.m_integer_values.size(); ++i)
value += StringFromFormat("%d%s", it.second.m_integer_values[i], i == (it.second.m_integer_values.size() - 1) ? "": ", ");
ini.GetOrCreateSection(section)->Set(it.second.m_option_name, value);
}
break;
case ConfigurationOption::OptionType::OPTION_FLOAT:
{
std::string value = "";
for (size_t i = 0; i < it.second.m_float_values.size(); ++i)
value += StringFromFormat("%f%s", it.second.m_float_values[i], i == (it.second.m_float_values.size() - 1) ? "": ", ");
ini.GetOrCreateSection(section)->Set(it.second.m_option_name, value);
}
break;
}
}
ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX));
}
void PostProcessingShaderConfiguration::ReloadShader()
{
m_current_shader = "";
}
void PostProcessingShaderConfiguration::SetOptionf(std::string option, int index, float value)
{
auto it = m_options.find(option);
it->second.m_float_values[index] = value;
it->second.m_dirty = true;
m_any_options_dirty = true;
}
void PostProcessingShaderConfiguration::SetOptioni(std::string option, int index, s32 value)
{
auto it = m_options.find(option);
it->second.m_integer_values[index] = value;
it->second.m_dirty = true;
m_any_options_dirty = true;
}
void PostProcessingShaderConfiguration::SetOptionb(std::string option, bool value)
{
auto it = m_options.find(option);
it->second.m_bool_value = value;
it->second.m_dirty = true;
m_any_options_dirty = true;
}

View File

@ -0,0 +1,104 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <map>
#include <string>
#include <vector>
#include "Common/StringUtil.h"
#include "Common/Timer.h"
class PostProcessingShaderConfiguration
{
public:
struct ConfigurationOption
{
enum OptionType
{
OPTION_BOOL = 0,
OPTION_FLOAT,
OPTION_INTEGER,
};
bool m_bool_value;
std::vector<float> m_float_values;
std::vector<s32> m_integer_values;
std::vector<float> m_float_min_values;
std::vector<s32> m_integer_min_values;
std::vector<float> m_float_max_values;
std::vector<s32> m_integer_max_values;
std::vector<float> m_float_step_values;
std::vector<s32> m_integer_step_values;
OptionType m_type;
std::string m_gui_name;
std::string m_option_name;
std::string m_dependent_option;
bool m_dirty;
};
typedef std::map<std::string, ConfigurationOption> ConfigMap;
PostProcessingShaderConfiguration() : m_current_shader("") {}
virtual ~PostProcessingShaderConfiguration() {}
// Loads the configuration with a shader
// If the argument is "" the class will load the shader from the g_activeConfig option.
// Returns the loaded shader source from file
std::string LoadShader(std::string shader = "");
void SaveOptionsConfiguration();
void ReloadShader();
std::string GetShader() { return m_current_shader; }
bool IsDirty() { return m_any_options_dirty; }
void SetDirty(bool dirty) { m_any_options_dirty = dirty; }
bool HasOptions() { return m_options.size() > 0; }
ConfigMap& GetOptions() { return m_options; }
const ConfigurationOption& GetOption(const std::string& option) { return m_options[option]; }
// For updating option's values
void SetOptionf(std::string option, int index, float value);
void SetOptioni(std::string option, int index, s32 value);
void SetOptionb(std::string option, bool value);
private:
bool m_any_options_dirty;
std::string m_current_shader;
ConfigMap m_options;
void LoadOptions(const std::string& code);
void LoadOptionsConfiguration();
};
class PostProcessingShaderImplementation
{
public:
PostProcessingShaderImplementation();
virtual ~PostProcessingShaderImplementation();
PostProcessingShaderConfiguration* GetConfig() { return &m_config; }
// Should be implemented by the backends for backend specific code
virtual void BindTargetFramebuffer() = 0;
virtual void BlitToScreen() = 0;
virtual void Update(u32 width, u32 height) = 0;
virtual void ApplyShader() = 0;
protected:
bool m_enable;
u32 m_width;
u32 m_height;
// Timer for determining our time value
Common::Timer m_timer;
PostProcessingShaderConfiguration m_config;
};

View File

@ -59,6 +59,8 @@ int Renderer::s_target_height;
int Renderer::s_backbuffer_width;
int Renderer::s_backbuffer_height;
PostProcessingShaderImplementation* Renderer::m_post_processor;
TargetRectangle Renderer::target_rc;
int Renderer::s_LastEFBScale;

View File

@ -24,6 +24,8 @@
#include "VideoCommon/NativeVertexFormat.h"
#include "VideoCommon/VideoCommon.h"
class PostProcessingShaderImplementation;
// TODO: Move these out of here.
extern int frameCount;
extern int OSDChoice;
@ -115,6 +117,8 @@ public:
static PEControl::PixelFormat GetPrevPixelFormat() { return prev_efb_format; }
static void StorePixelFormat(PEControl::PixelFormat new_format) { prev_efb_format = new_format; }
PostProcessingShaderImplementation* GetPostProcessor() { return m_post_processor; }
protected:
static void CalculateTargetScale(int x, int y, int &scaledX, int &scaledY);
@ -153,6 +157,8 @@ protected:
FPSCounter m_fps_counter;
static PostProcessingShaderImplementation* m_post_processor;
private:
static PEControl::PixelFormat prev_efb_format;
static unsigned int efb_scale_numeratorX;

View File

@ -56,6 +56,7 @@
<ClCompile Include="PixelEngine.cpp" />
<ClCompile Include="PixelShaderGen.cpp" />
<ClCompile Include="PixelShaderManager.cpp" />
<ClCompile Include="PostProcessing.cpp" />
<ClCompile Include="RenderBase.cpp" />
<ClCompile Include="Statistics.cpp" />
<ClCompile Include="stdafx.cpp">
@ -105,6 +106,7 @@
<ClInclude Include="PixelEngine.h" />
<ClInclude Include="PixelShaderGen.h" />
<ClInclude Include="PixelShaderManager.h" />
<ClInclude Include="PostProcessing.h" />
<ClInclude Include="RenderBase.h" />
<ClInclude Include="ShaderGenCommon.h" />
<ClInclude Include="Statistics.h" />
@ -148,4 +150,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -107,6 +107,9 @@
<ClCompile Include="OnScreenDisplay.cpp">
<Filter>Util</Filter>
</ClCompile>
<ClCompile Include="PostProcessing.cpp">
<Filter>Util</Filter>
</ClCompile>
<ClCompile Include="Statistics.cpp">
<Filter>Util</Filter>
</ClCompile>
@ -234,6 +237,9 @@
<ClInclude Include="OnScreenDisplay.h">
<Filter>Util</Filter>
</ClInclude>
<ClInclude Include="PostProcessing.h">
<Filter>Util</Filter>
</ClInclude>
<ClInclude Include="Statistics.h">
<Filter>Util</Filter>
</ClInclude>
@ -266,4 +272,4 @@
<ItemGroup>
<Text Include="CMakeLists.txt" />
</ItemGroup>
</Project>
</Project>