From 92e82c203f873ad4f60348f6ea678eff95c16599 Mon Sep 17 00:00:00 2001 From: Filippo Scognamiglio Date: Wed, 7 Nov 2018 22:36:51 +0100 Subject: [PATCH] Important burn-in optimization. It is much lighter on resources. --- app/qml/BurnInEffect.qml | 126 +++++++++++++++++++++++++++++++ app/qml/PreprocessedTerminal.qml | 125 +----------------------------- app/qml/ShaderTerminal.qml | 25 +++--- app/qml/TerminalContainer.qml | 9 ++- app/qml/resources.qrc | 1 + 5 files changed, 151 insertions(+), 135 deletions(-) create mode 100644 app/qml/BurnInEffect.qml diff --git a/app/qml/BurnInEffect.qml b/app/qml/BurnInEffect.qml new file mode 100644 index 0000000..f5a3ff2 --- /dev/null +++ b/app/qml/BurnInEffect.qml @@ -0,0 +1,126 @@ +import QtQuick 2.0 + +import "utils.js" as Utils + +Item { + id: burnInEffect + + readonly property alias source: burnInEffectSource + + property real lastUpdate: 0 + property real prevLastUpdate: 0 + + property real delay: (1.0 / appSettings.fps) * 1000 + property real burnIn: appSettings.burnIn + property real burnInFadeTime: 1 / Utils.lint(_minBurnInFadeTime, _maxBurnInFadeTime, burnIn) + property real _minBurnInFadeTime: 160 + property real _maxBurnInFadeTime: 1600 + + function completelyUpdate() { + prevLastUpdate = lastUpdate; + lastUpdate = timeManager.time; + burnInEffectSource.scheduleUpdate(); + } + + function restartBlurSource(){ + prevLastUpdate = 0; + lastUpdate = 0; + completelyUpdate() + } + + ShaderEffectSource { + id: burnInEffectSource + + sourceItem: burnInShaderEffect + live: false + recursive: true + hideSource: true + wrapMode: kterminalSource.wrapMode + + format: ShaderEffectSource.RGBA + + visible: false + + Connections { + target: kterminal + onImagePainted: completelyUpdate() + } + // Restart blurred source settings change. + Connections{ + target: appSettings + onBurnInChanged: burnInEffect.restartBlurSource(); + onTerminalFontChanged: burnInEffect.restartBlurSource(); + onRasterizationChanged: burnInEffect.restartBlurSource(); + onBurnInQualityChanged: burnInEffect.restartBlurSource(); + } + + Connections { + target: kterminalScrollbar + onOpacityChanged: burnInEffect.restartBlurSource() + } + } + + ShaderEffect { + id: burnInShaderEffect + + property int burnInScaling: scaleTexture * appSettings.burnInQuality + + width: appSettings.lowResolutionFont + ? kterminal.width * Math.max(1, burnInScaling) + : kterminal.width * scaleTexture * appSettings.burnInQuality + + height: appSettings.lowResolutionFont + ? kterminal.height * Math.max(1, burnInScaling) + : kterminal.height * scaleTexture * appSettings.burnInQuality + + property variant txt_source: kterminalSource + property variant burnInSource: burnInEffectSource + property real burnInTime: burnInFadeTime + property alias lastUpdate: burnInEffect.lastUpdate + property alias prevLastUpdate: burnInEffect.prevLastUpdate + + blending: false + + fragmentShader: + "#ifdef GL_ES + precision mediump float; + #endif\n" + + + "uniform lowp float qt_Opacity;" + + "uniform lowp sampler2D txt_source;" + + + "varying highp vec2 qt_TexCoord0; + + uniform lowp sampler2D burnInSource; + uniform highp float burnInTime; + + uniform highp float lastUpdate; + + uniform highp float prevLastUpdate;" + + + "float max3(vec3 v) { + return max (max (v.x, v.y), v.z); + }" + + + "void main() { + vec2 coords = qt_TexCoord0; + + vec3 txtColor = texture2D(txt_source, coords).rgb * 0.70; + vec4 accColor = texture2D(burnInSource, coords); + + float prevMask = accColor.a; + float currMask = 1.0 - max3(txtColor); + + highp float blurDecay = prevMask * clamp((lastUpdate - prevLastUpdate) * burnInTime, 0.0, 1.0); + vec3 blurColor = accColor.rgb - vec3(blurDecay); + + blurColor = clamp(blurColor, vec3(0.0), vec3(1.0)); + vec3 color = max(blurColor, txtColor); + + gl_FragColor = vec4(color, currMask); + } + " + + onStatusChanged: if (log) console.log(log) //Print warning messages + } +} diff --git a/app/qml/PreprocessedTerminal.qml b/app/qml/PreprocessedTerminal.qml index fac5479..aa90835 100644 --- a/app/qml/PreprocessedTerminal.qml +++ b/app/qml/PreprocessedTerminal.qml @@ -30,9 +30,9 @@ Item{ property size virtualResolution: Qt.size(kterminal.width, kterminal.height) property alias mainTerminal: kterminal - property ShaderEffectSource mainSource: kterminalSource - property ShaderEffectSource blurredSource: blurredSourceLoader.item + property ShaderEffectSource mainSource: kterminalSource + property BurnInEffect burnInEffect: burnInEffect property real fontWidth: 1.0 property real screenScaling: 1.0 property real scaleTexture: 1.0 @@ -44,14 +44,6 @@ Item{ anchors.topMargin: frame.displacementTop * appSettings.windowScaling anchors.bottomMargin: frame.displacementBottom * appSettings.windowScaling - //Parameters for the burnIn effect. - property real burnIn: appSettings.burnIn - property real fps: appSettings.fps !== 0 ? appSettings.fps : 60 - property real burnInFadeTime: Utils.lint(_minBurnInFadeTime, _maxBurnInFadeTime, burnIn) - property real motionBlurCoefficient: 1.0 / (fps * burnInFadeTime) - property real _minBurnInFadeTime: 0.16 - property real _maxBurnInFadeTime: 1.6 - property size terminalSize: kterminal.terminalSize property size fontMetrics: kterminal.fontMetrics @@ -232,117 +224,8 @@ Item{ visible: false textureSize: Qt.size(kterminal.width * scaleTexture, kterminal.height * scaleTexture); } - Loader{ - id: blurredSourceLoader - asynchronous: true - active: burnIn !== 0 - sourceComponent: ShaderEffectSource{ - property bool updateBurnIn: false - - id: _blurredSourceEffect - sourceItem: blurredTerminalLoader.item - recursive: true - live: false - hideSource: true - wrapMode: kterminalSource.wrapMode - - visible: false - - function restartBlurSource(){ - livetimer.restart(); - } - - // This updates the burnin synched with the timer. - Connections { - target: updateBurnIn ? mainShader : null - ignoreUnknownSignals: false - onTimeChanged: _blurredSourceEffect.scheduleUpdate(); - } - - Timer{ - id: livetimer - - // The interval assumes 60 fps. This is the time needed burnout a white pixel. - // We multiply 1.1 to have a little bit of margin over the theoretical value. - // This solution is not extremely clean, but it's probably the best to avoid measuring fps. - - interval: burnInFadeTime * 1000 * 1.1 - running: true - onTriggered: _blurredSourceEffect.updateBurnIn = false; - } - Connections{ - target: kterminal - onImagePainted:{ - _blurredSourceEffect.scheduleUpdate(); - _blurredSourceEffect.updateBurnIn = true; - livetimer.restart(); - } - } - // Restart blurred source settings change. - Connections{ - target: appSettings - onBurnInChanged: _blurredSourceEffect.restartBlurSource(); - onTerminalFontChanged: _blurredSourceEffect.restartBlurSource(); - onRasterizationChanged: _blurredSourceEffect.restartBlurSource(); - onBurnInQualityChanged: _blurredSourceEffect.restartBlurSource(); - } - Connections { - target: kterminalScrollbar - onOpacityChanged: _blurredSourceEffect.restartBlurSource(); - } - } - } - - Loader{ - id: blurredTerminalLoader - - property int burnInScaling: scaleTexture * appSettings.burnInQuality - - width: appSettings.lowResolutionFont - ? kterminal.width * Math.max(1, burnInScaling) - : kterminal.width * scaleTexture * appSettings.burnInQuality - height: appSettings.lowResolutionFont - ? kterminal.height * Math.max(1, burnInScaling) - : kterminal.height * scaleTexture * appSettings.burnInQuality - - active: burnIn !== 0 - asynchronous: true - - sourceComponent: ShaderEffect { - property variant txt_source: kterminalSource - property variant blurredSource: blurredSourceLoader.item - property real blurCoefficient: motionBlurCoefficient - - blending: false - - fragmentShader: - "#ifdef GL_ES - precision mediump float; - #endif\n" + - - "uniform lowp float qt_Opacity;" + - "uniform lowp sampler2D txt_source;" + - - "varying highp vec2 qt_TexCoord0; - - uniform lowp sampler2D blurredSource; - uniform highp float blurCoefficient;" + - - "float max3(vec3 v) { - return max (max (v.x, v.y), v.z); - }" + - - "void main() {" + - "vec2 coords = qt_TexCoord0;" + - "vec3 origColor = texture2D(txt_source, coords).rgb;" + - "vec3 blur_color = texture2D(blurredSource, coords).rgb - vec3(blurCoefficient);" + - "vec3 color = min(origColor + blur_color, max(origColor, blur_color));" + - - "gl_FragColor = vec4(color, max3(color - origColor));" + - "}" - - onStatusChanged: if (log) console.log(log) //Print warning messages - } + BurnInEffect { + id: burnInEffect } } diff --git a/app/qml/ShaderTerminal.qml b/app/qml/ShaderTerminal.qml index 35a939f..604d2cf 100644 --- a/app/qml/ShaderTerminal.qml +++ b/app/qml/ShaderTerminal.qml @@ -25,7 +25,7 @@ import "utils.js" as Utils ShaderEffect { property ShaderEffectSource source - property ShaderEffectSource blurredSource + property BurnInEffect burnInEffect property ShaderEffectSource bloomSource property ShaderEffectSource rasterizationSource @@ -33,7 +33,10 @@ ShaderEffect { property color backgroundColor: appSettings.backgroundColor property real bloom: appSettings.bloom * 2.0 + property ShaderEffectSource burnInSource: burnInEffect.source property real burnIn: appSettings.burnIn + property real burnInLastUpdate: burnInEffect.lastUpdate + property real burnInTime: burnInEffect.burnInFadeTime property real jitter: appSettings.jitter * 0.007 property real staticNoise: appSettings.staticNoise @@ -63,12 +66,7 @@ ShaderEffect { property real dispY property size virtual_resolution - TimeManager{ - id: timeManager - enableTimer: terminalWindow.visible - } - - property alias time: timeManager.time + property real time: timeManager.time property ShaderEffectSource noiseSource: noiseShaderSource // If something goes wrong activate the fallback version of the shader. @@ -133,7 +131,7 @@ ShaderEffect { qt_TexCoord0.y = (qt_MultiTexCoord0.y - disp_top) / (1.0 - disp_top - disp_bottom); vec2 coords = vec2(fract(time/(1024.0*2.0)), fract(time/(1024.0*1024.0)));" + - (!fallBack && (flickering !== 0.0 || horizontalSync !== 0.0 || rgbShift !== 0) ? + (!fallBack && (flickering !== 0.0 || horizontalSync !== 0.0 || rbgShift !== 0) ? "vec4 initialNoiseTexel = texture2D(noiseSource, coords);" : "") + @@ -178,7 +176,9 @@ ShaderEffect { uniform highp sampler2D bloomSource; uniform lowp float bloom;" : "") + (burnIn !== 0 ? " - uniform sampler2D blurredSource;" : "") + + uniform sampler2D burnInSource; + uniform highp float burnInLastUpdate; + uniform highp float burnInTime;" : "") + (staticNoise !== 0 ? " uniform highp float staticNoise;" : "") + (((staticNoise !== 0 || jitter !== 0 || rbgShift) @@ -228,7 +228,7 @@ ShaderEffect { "float distance = length(cc);" + //FallBack if there are problems - (fallBack && (flickering !== 0.0 || horizontalSync !== 0.0) ? + (fallBack && (flickering !== 0.0 || horizontalSync !== 0.0 || rbgShift !== 0.0) ? "vec2 initialCoords = vec2(fract(time/(1024.0*2.0)), fract(time/(1024.0*1024.0))); vec4 initialNoiseTexel = texture2D(noiseSource, initialCoords);" : "") + @@ -292,8 +292,9 @@ ShaderEffect { " : "") + (burnIn !== 0 ? " - vec4 txt_blur = texture2D(blurredSource, txt_coords); - txt_color = max(txt_color, txt_blur.rgb * txt_blur.a);" + vec4 txt_blur = texture2D(burnInSource, txt_coords); + float blurDecay = clamp((time - burnInLastUpdate) * burnInTime, 0.0, 1.0); + txt_color = max(txt_color, txt_blur.rgb - vec3(blurDecay));" : "") + "txt_color += fontColor.rgb * color;" + diff --git a/app/qml/TerminalContainer.qml b/app/qml/TerminalContainer.qml index 5fddd2a..bd93199 100644 --- a/app/qml/TerminalContainer.qml +++ b/app/qml/TerminalContainer.qml @@ -3,7 +3,7 @@ import QtGraphicalEffects 1.0 import "utils.js" as Utils -ShaderTerminal{ +ShaderTerminal { property alias title: terminal.title property alias terminalSize: terminal.terminalSize @@ -13,11 +13,16 @@ ShaderTerminal{ blending: false source: terminal.mainSource - blurredSource: terminal.blurredSource + burnInEffect: terminal.burnInEffect dispX: (12 / width) * appSettings.windowScaling dispY: (12 / height) * appSettings.windowScaling virtual_resolution: terminal.virtualResolution + TimeManager{ + id: timeManager + enableTimer: terminalWindow.visible + } + Loader{ id: frame anchors.fill: parent diff --git a/app/qml/resources.qrc b/app/qml/resources.qrc index d9fe74c..c27f626 100644 --- a/app/qml/resources.qrc +++ b/app/qml/resources.qrc @@ -51,5 +51,6 @@ fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf fonts/1985-ibm-pc-vga/PxPlus_IBM_VGA8.ttf fonts/1977-commodore-pet/PetMe.ttf + BurnInEffect.qml