Added LCD graphics filter; emulates low-resolution LCD artifacts

This commit is contained in:
Lior Halphon 2018-02-17 20:43:48 +02:00
parent f79af39ea2
commit d0202a3f9a
4 changed files with 77 additions and 4 deletions

View File

@ -28,6 +28,7 @@
@"NearestNeighbor", @"NearestNeighbor",
@"Bilinear", @"Bilinear",
@"SmoothBilinear", @"SmoothBilinear",
@"LCD",
@"Scale2x", @"Scale2x",
@"Scale4x", @"Scale4x",
@"AAScale2x", @"AAScale2x",

View File

@ -35,7 +35,7 @@
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6pP-kK-EEC"> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6pP-kK-EEC">
<rect key="frame" x="30" y="474" width="245" height="26"/> <rect key="frame" x="30" y="474" width="245" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" id="I1w-05-lGl"> <popUpButtonCell key="cell" type="push" title="Nearest Neighbor (Pixelated)" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="neN-eo-LA7" id="I1w-05-lGl">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/> <font key="font" metaFont="menu"/>
<menu key="menu" id="xDC-0T-Qg9"> <menu key="menu" id="xDC-0T-Qg9">
@ -45,6 +45,7 @@
</menuItem> </menuItem>
<menuItem title="Bilinear (Blurry)" id="iDe-si-atu"/> <menuItem title="Bilinear (Blurry)" id="iDe-si-atu"/>
<menuItem title="Smooth Bilinear (Less blurry)" id="1jN-pO-1iD"/> <menuItem title="Smooth Bilinear (Less blurry)" id="1jN-pO-1iD"/>
<menuItem title="LCD Display" id="b8u-LZ-UQf"/>
<menuItem title="Scale2x" id="C1I-L2-Up1"/> <menuItem title="Scale2x" id="C1I-L2-Up1"/>
<menuItem title="Scale4x" id="uWA-Zp-JY9"/> <menuItem title="Scale4x" id="uWA-Zp-JY9"/>
<menuItem title="Anti-aliased Scale2x" id="iP6-DJ-CVH"/> <menuItem title="Anti-aliased Scale2x" id="iP6-DJ-CVH"/>
@ -119,15 +120,15 @@
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7fg-Ww-JjR"> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="7fg-Ww-JjR">
<rect key="frame" x="30" y="286" width="245" height="26"/> <rect key="frame" x="30" y="286" width="245" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="Disabled" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="lxQ-4n-kEv" id="lvb-QF-0Ht"> <popUpButtonCell key="cell" type="push" title="Disabled" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="lxQ-4n-kEv" id="lvb-QF-0Ht">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="menu"/> <font key="font" metaFont="menu"/>
<menu key="menu" id="lbS-Lw-kQX"> <menu key="menu" id="lbS-Lw-kQX">
<items> <items>
<menuItem title="Disabled" id="lxQ-4n-kEv"> <menuItem title="Disabled" state="on" id="lxQ-4n-kEv">
<modifierMask key="keyEquivalentModifierMask"/> <modifierMask key="keyEquivalentModifierMask"/>
</menuItem> </menuItem>
<menuItem title="10 Seconds" state="on" tag="10" id="bPU-vT-d5z"/> <menuItem title="10 Seconds" tag="10" id="bPU-vT-d5z"/>
<menuItem title="30 Seconds" tag="30" id="aR8-IU-fFh"/> <menuItem title="30 Seconds" tag="30" id="aR8-IU-fFh"/>
<menuItem title="1 Minute" tag="60" id="E0R-mf-Hdl"/> <menuItem title="1 Minute" tag="60" id="E0R-mf-Hdl"/>
<menuItem title="2 Minutes" tag="120" id="zb2-uh-lvj"/> <menuItem title="2 Minutes" tag="120" id="zb2-uh-lvj"/>

View File

@ -350,6 +350,7 @@ struct shader_name {
{"NearestNeighbor", "Nearest Neighbor"}, {"NearestNeighbor", "Nearest Neighbor"},
{"Bilinear", "Bilinear"}, {"Bilinear", "Bilinear"},
{"SmoothBilinear", "Smooth Bilinear"}, {"SmoothBilinear", "Smooth Bilinear"},
{"LCD", "LCD Display"},
{"Scale2x", "Scale2x"}, {"Scale2x", "Scale2x"},
{"Scale4x", "Scale4x"}, {"Scale4x", "Scale4x"},
{"AAScale2x", "Anti-aliased Scale2x"}, {"AAScale2x", "Anti-aliased Scale2x"},

70
Shaders/LCD.fsh Normal file
View File

@ -0,0 +1,70 @@
#define COLOR_LOW 0.8
#define COLOR_HIGH 1.0
#define SCANLINE_DEPTH 0.1
vec4 scale(sampler2D image)
{
vec2 texCoord = vec2(gl_FragCoord.x, uResolution.y - gl_FragCoord.y) / uResolution;
vec2 pos = fract(texCoord * textureDimensions);
vec2 sub_pos = fract(texCoord * textureDimensions * 6);
vec4 center = texture(image, texCoord);
vec4 left = texture(image, texCoord - vec2(1.0 / textureDimensions.x, 0));
vec4 right = texture(image, texCoord + vec2(1.0 / textureDimensions.x, 0));
if (pos.y < 1.0 / 6.0) {
center = mix(center, texture(image, texCoord + vec2(0, -1.0 / textureDimensions.y)), 0.5 - sub_pos.y / 2.0);
left = mix(left, texture(image, texCoord + vec2(-1.0 / textureDimensions.x, -1.0 / textureDimensions.y)), 0.5 - sub_pos.y / 2.0);
right = mix(right, texture(image, texCoord + vec2( 1.0 / textureDimensions.x, -1.0 / textureDimensions.y)), 0.5 - sub_pos.y / 2.0);
center *= sub_pos.y * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH);
left *= sub_pos.y * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH);
right *= sub_pos.y * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH);
}
else if (pos.y > 5.0 / 6.0) {
center = mix(center, texture(image, texCoord + vec2(0, 1.0 / textureDimensions.y)), sub_pos.y / 2.0);
left = mix(left, texture(image, texCoord + vec2(-1.0 / textureDimensions.x, 1.0 / textureDimensions.y)), sub_pos.y / 2.0);
right = mix(right, texture(image, texCoord + vec2( 1.0 / textureDimensions.x, 1.0 / textureDimensions.y)), sub_pos.y / 2.0);
center *= (1.0 - sub_pos.y) * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH);
left *= (1.0 - sub_pos.y) * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH);
right *= (1.0 - sub_pos.y) * SCANLINE_DEPTH + (1 - SCANLINE_DEPTH);
}
vec4 midleft = mix(left, center, 0.5);
vec4 midright = mix(right, center, 0.5);
vec4 ret;
if (pos.x < 1.0 / 6.0) {
ret = mix(vec4(COLOR_HIGH * center.r, COLOR_LOW * center.g, COLOR_HIGH * left.b, 1),
vec4(COLOR_HIGH * center.r, COLOR_LOW * center.g, COLOR_LOW * left.b, 1),
sub_pos.x);
}
else if (pos.x < 2.0 / 6.0) {
ret = mix(vec4(COLOR_HIGH * center.r, COLOR_LOW * center.g, COLOR_LOW * left.b, 1),
vec4(COLOR_HIGH * center.r, COLOR_HIGH * center.g, COLOR_LOW * midleft.b, 1),
sub_pos.x);
}
else if (pos.x < 3.0 / 6.0) {
ret = mix(vec4(COLOR_HIGH * center.r , COLOR_HIGH * center.g, COLOR_LOW * midleft.b, 1),
vec4(COLOR_LOW * midright.r, COLOR_HIGH * center.g, COLOR_LOW * center.b, 1),
sub_pos.x);
}
else if (pos.x < 4.0 / 6.0) {
ret = mix(vec4(COLOR_LOW * midright.r, COLOR_HIGH * center.g , COLOR_LOW * center.b, 1),
vec4(COLOR_LOW * right.r , COLOR_HIGH * center.g, COLOR_HIGH * center.b, 1),
sub_pos.x);
}
else if (pos.x < 5.0 / 6.0) {
ret = mix(vec4(COLOR_LOW * right.r, COLOR_HIGH * center.g , COLOR_HIGH * center.b, 1),
vec4(COLOR_LOW * right.r, COLOR_LOW * midright.g, COLOR_HIGH * center.b, 1),
sub_pos.x);
}
else {
ret = mix(vec4(COLOR_LOW * right.r, COLOR_LOW * midright.g, COLOR_HIGH * center.b, 1),
vec4(COLOR_HIGH * right.r, COLOR_LOW * right.g , COLOR_HIGH * center.b, 1),
sub_pos.x);
}
return ret;
}