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