From 293b05fec6cf6b5cbd8e2a689f7e82c40483c811 Mon Sep 17 00:00:00 2001 From: Filippo Scognamiglio Date: Mon, 5 Nov 2018 00:16:52 +0100 Subject: [PATCH] Add subpixels rasterization and improve existing ones. --- app/qml/ApplicationSettings.qml | 3 + app/qml/SettingsScreenTab.qml | 2 +- app/qml/ShaderTerminal.qml | 30 +++------- app/qml/TerminalContainer.qml | 100 +++++++++++++++++--------------- 4 files changed, 65 insertions(+), 70 deletions(-) diff --git a/app/qml/ApplicationSettings.qml b/app/qml/ApplicationSettings.qml index 37f330d..74a282a 100644 --- a/app/qml/ApplicationSettings.qml +++ b/app/qml/ApplicationSettings.qml @@ -89,6 +89,7 @@ QtObject{ readonly property int no_rasterization: 0 readonly property int scanline_rasterization: 1 readonly property int pixel_rasterization: 2 + readonly property int subpixel_rasterization: 3 property int rasterization: no_rasterization @@ -113,6 +114,8 @@ QtObject{ State { when: rasterization == scanline_rasterization PropertyChanges {target: fontManager; source: "FontScanlines.qml" } }, State { when: rasterization == pixel_rasterization; + PropertyChanges {target: fontManager; source: "FontPixels.qml" } }, + State { when: rasterization == subpixel_rasterization; PropertyChanges {target: fontManager; source: "FontPixels.qml" } } ] diff --git a/app/qml/SettingsScreenTab.qml b/app/qml/SettingsScreenTab.qml index 5777e65..f8d234f 100644 --- a/app/qml/SettingsScreenTab.qml +++ b/app/qml/SettingsScreenTab.qml @@ -33,7 +33,7 @@ Tab{ id: rasterizationBox property string selectedElement: model[currentIndex] anchors.fill: parent - model: [qsTr("Default"), qsTr("Scanlines"), qsTr("Pixels")] + model: [qsTr("Default"), qsTr("Scanlines"), qsTr("Pixels"), qsTr("Subpixels")] currentIndex: appSettings.rasterization onCurrentIndexChanged: { appSettings.rasterization = currentIndex diff --git a/app/qml/ShaderTerminal.qml b/app/qml/ShaderTerminal.qml index e0938a9..122a65f 100644 --- a/app/qml/ShaderTerminal.qml +++ b/app/qml/ShaderTerminal.qml @@ -27,6 +27,7 @@ ShaderEffect { property ShaderEffectSource source property ShaderEffectSource blurredSource property ShaderEffectSource bloomSource + property ShaderEffectSource rasterizationSource property color fontColor: appSettings.fontColor property color backgroundColor: appSettings.backgroundColor @@ -58,12 +59,6 @@ ShaderEffect { property real screen_brightness: appSettings.brightness * 1.5 + 0.5 - // This is the average value of the abs(sin) function. Needed to avoid aliasing. - readonly property real absSinAvg: 0.63661828335466886 - property size rasterizationSmooth: Qt.size( - Utils.clamp(2.0 * virtual_resolution.width / (width * devicePixelRatio), 0.0, 1.0), - Utils.clamp(2.0 * virtual_resolution.height / (height * devicePixelRatio), 0.0, 1.0)) - property real dispX property real dispY property size virtual_resolution @@ -165,10 +160,12 @@ ShaderEffect { uniform lowp float screen_brightness; uniform highp vec2 virtual_resolution; - uniform highp vec2 rasterizationSmooth; uniform highp float dispX; uniform highp float dispY;" + + (appSettings.rasterization != appSettings.no_rasterization ? + "uniform lowp sampler2D rasterizationSource;" : "") + + (bloom !== 0 ? " uniform highp sampler2D bloomSource; uniform lowp float bloom;" : "") + @@ -207,20 +204,7 @@ ShaderEffect { return fract(smoothstep(-120.0, 0.0, coords.y - (virtual_resolution.y + 120.0) * fract(time * 0.00015))); }" : "") + - "highp float getScanlineIntensity(vec2 coords) { - highp float result = 1.0;" + - - (appSettings.rasterization != appSettings.no_rasterization ? - "float val = abs(sin(coords.y * virtual_resolution.y * "+Math.PI+")); - result *= mix(val, " + absSinAvg + ", rasterizationSmooth.y);" : "") + - (appSettings.rasterization == appSettings.pixel_rasterization ? - "val = abs(sin(coords.x * virtual_resolution.x * "+Math.PI+")); - result *= mix(val, " + absSinAvg + ", rasterizationSmooth.x);" : "") + " - - return result; - } - - float min2(vec2 v) { + "float min2(vec2 v) { return min(v.x, v.y); } @@ -310,7 +294,9 @@ ShaderEffect { : "vec3 finalColor = mix(backgroundColor.rgb, fontColor.rgb, greyscale_color);") + - "finalColor *= getScanlineIntensity(coords);" + + (appSettings.rasterization != appSettings.no_rasterization ? " + finalColor *= texture2D(rasterizationSource, staticCoords * (virtual_resolution)).rgb; + " : "") + (bloom !== 0 ? "vec4 bloomFullColor = texture2D(bloomSource, coords); diff --git a/app/qml/TerminalContainer.qml b/app/qml/TerminalContainer.qml index 90ee1f3..5fddd2a 100644 --- a/app/qml/TerminalContainer.qml +++ b/app/qml/TerminalContainer.qml @@ -69,64 +69,70 @@ ShaderTerminal{ bloomSource: bloomSourceLoader.item - // This shader might be useful in the future. Since we used it only for a couple - // of calculations is probably best to move those in the main shader. If in the future - // we need to store another fullScreen channel this might be handy. + Loader { + id: rasterizationEffectLoader + active: appSettings.rasterization != appSettings.no_rasterization + asynchronous: true + sourceComponent: ShaderEffect { + id: rasterizationEffect + width: 16 + height: 16 -// ShaderEffect { -// id: rasterizationEffect -// width: parent.width -// height: parent.height -// property real outColor: 0.0 -// property real dispX: (5 / width) * appSettings.windowScaling -// property real dispY: (5 / height) * appSettings.windowScaling -// property size virtual_resolution: terminal.virtualResolution + blending: false -// blending: false + fragmentShader: + "uniform lowp float qt_Opacity;" + -// fragmentShader: -// "uniform lowp float qt_Opacity;" + + "varying highp vec2 qt_TexCoord0; -// "varying highp vec2 qt_TexCoord0; -// uniform highp vec2 virtual_resolution; -// uniform highp float dispX; -// uniform highp float dispY; -// uniform mediump float outColor; + highp float getScanlineIntensity(vec2 coords) { + highp float result = 1.0;" + -// highp float getScanlineIntensity(vec2 coords) { -// highp float result = 1.0;" + + (appSettings.rasterization == appSettings.scanline_rasterization ? + "result *= (smoothstep(0.0, 0.5, coords.y) - smoothstep(0.5, 1.0, coords.y));" : "") + -// (appSettings.rasterization != appSettings.no_rasterization ? -// "result *= abs(sin(coords.y * virtual_resolution.y * "+Math.PI+"));" : "") + -// (appSettings.rasterization == appSettings.pixel_rasterization ? -// "result *= abs(sin(coords.x * virtual_resolution.x * "+Math.PI+"));" : "") + " + (appSettings.rasterization == appSettings.pixel_rasterization ? + "result *= (smoothstep(0.0, 0.25, coords.y) - smoothstep(0.75, 1.0, coords.y)); + result *= (smoothstep(0.0, 0.25, coords.x) - smoothstep(0.75, 1.0, coords.x));" : "") + -// return result; -// }" + + (appSettings.rasterization == appSettings.subpixel_rasterization ? + "result *= (smoothstep(0.0, 0.25, coords.y) - smoothstep(0.75, 1.0, coords.y));" : "") + " -// "void main() {" + -// "highp float color = getScanlineIntensity(qt_TexCoord0);" + + return result; + }" + -// "float distance = length(vec2(0.5) - qt_TexCoord0);" + -// "color = mix(color, 0.0, 1.2 * distance * distance);" + + "void main() {" + -// "color *= outColor + smoothstep(0.00, dispX, qt_TexCoord0.x) * (1.0 - outColor);" + -// "color *= outColor + smoothstep(0.00, dispY, qt_TexCoord0.y) * (1.0 - outColor);" + -// "color *= outColor + (1.0 - smoothstep(1.00 - dispX, 1.00, qt_TexCoord0.x)) * (1.0 - outColor);" + -// "color *= outColor + (1.0 - smoothstep(1.00 - dispY, 1.00, qt_TexCoord0.y)) * (1.0 - outColor);" + + (appSettings.rasterization == appSettings.subpixel_rasterization ? + "highp vec3 color = vec3(0.0); + color += vec3(1.0, 0.25, 0.25) * (step(0.0, qt_TexCoord0.x) - step(1.0/3.0, qt_TexCoord0.x)); + color += vec3(0.25, 1.0, 0.25) * (step(1.0/3.0, qt_TexCoord0.x) - step(2.0/3.0, qt_TexCoord0.x)); + color += vec3(0.25, 0.25, 1.0) * (step(2.0/3.0, qt_TexCoord0.x) - step(3.0/3.0, qt_TexCoord0.x));" + : + "highp vec3 color = vec3(1.0);" ) + -// "gl_FragColor.a = color;" + -// "}" + "color *= getScanlineIntensity(qt_TexCoord0); + gl_FragColor = vec4(color, 1.0);" + + "}" -// onStatusChanged: if (log) console.log(log) //Print warning messages -// } + onStatusChanged: if (log) console.log(log) //Print warning messages + } + } -// rasterizationSource: ShaderEffectSource{ -// id: rasterizationEffectSource -// sourceItem: rasterizationEffect -// hideSource: true -// smooth: true -// wrapMode: ShaderEffectSource.ClampToEdge -// visible: false -// } + Loader { + id: rasterizationSourceLoader + active: appSettings.rasterization != appSettings.no_rasterization + asynchronous: true + + sourceComponent: ShaderEffectSource { + sourceItem: rasterizationEffectLoader.item + hideSource: true + smooth: true + wrapMode: ShaderEffectSource.Repeat + visible: false + mipmap: true + } + } + + rasterizationSource: rasterizationSourceLoader.item }