mirror of
https://github.com/Swordfish90/cool-retro-term.git
synced 2025-01-18 20:20:45 +00:00
Important burn-in optimization. It is much lighter on resources.
This commit is contained in:
parent
272bc5fe89
commit
92e82c203f
126
app/qml/BurnInEffect.qml
Normal file
126
app/qml/BurnInEffect.qml
Normal file
@ -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
|
||||||
|
}
|
||||||
|
}
|
@ -30,9 +30,9 @@ Item{
|
|||||||
|
|
||||||
property size virtualResolution: Qt.size(kterminal.width, kterminal.height)
|
property size virtualResolution: Qt.size(kterminal.width, kterminal.height)
|
||||||
property alias mainTerminal: kterminal
|
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 fontWidth: 1.0
|
||||||
property real screenScaling: 1.0
|
property real screenScaling: 1.0
|
||||||
property real scaleTexture: 1.0
|
property real scaleTexture: 1.0
|
||||||
@ -44,14 +44,6 @@ Item{
|
|||||||
anchors.topMargin: frame.displacementTop * appSettings.windowScaling
|
anchors.topMargin: frame.displacementTop * appSettings.windowScaling
|
||||||
anchors.bottomMargin: frame.displacementBottom * 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 terminalSize: kterminal.terminalSize
|
||||||
property size fontMetrics: kterminal.fontMetrics
|
property size fontMetrics: kterminal.fontMetrics
|
||||||
|
|
||||||
@ -232,117 +224,8 @@ Item{
|
|||||||
visible: false
|
visible: false
|
||||||
textureSize: Qt.size(kterminal.width * scaleTexture, kterminal.height * scaleTexture);
|
textureSize: Qt.size(kterminal.width * scaleTexture, kterminal.height * scaleTexture);
|
||||||
}
|
}
|
||||||
Loader{
|
|
||||||
id: blurredSourceLoader
|
|
||||||
asynchronous: true
|
|
||||||
active: burnIn !== 0
|
|
||||||
|
|
||||||
sourceComponent: ShaderEffectSource{
|
BurnInEffect {
|
||||||
property bool updateBurnIn: false
|
id: burnInEffect
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import "utils.js" as Utils
|
|||||||
|
|
||||||
ShaderEffect {
|
ShaderEffect {
|
||||||
property ShaderEffectSource source
|
property ShaderEffectSource source
|
||||||
property ShaderEffectSource blurredSource
|
property BurnInEffect burnInEffect
|
||||||
property ShaderEffectSource bloomSource
|
property ShaderEffectSource bloomSource
|
||||||
property ShaderEffectSource rasterizationSource
|
property ShaderEffectSource rasterizationSource
|
||||||
|
|
||||||
@ -33,7 +33,10 @@ ShaderEffect {
|
|||||||
property color backgroundColor: appSettings.backgroundColor
|
property color backgroundColor: appSettings.backgroundColor
|
||||||
property real bloom: appSettings.bloom * 2.0
|
property real bloom: appSettings.bloom * 2.0
|
||||||
|
|
||||||
|
property ShaderEffectSource burnInSource: burnInEffect.source
|
||||||
property real burnIn: appSettings.burnIn
|
property real burnIn: appSettings.burnIn
|
||||||
|
property real burnInLastUpdate: burnInEffect.lastUpdate
|
||||||
|
property real burnInTime: burnInEffect.burnInFadeTime
|
||||||
|
|
||||||
property real jitter: appSettings.jitter * 0.007
|
property real jitter: appSettings.jitter * 0.007
|
||||||
property real staticNoise: appSettings.staticNoise
|
property real staticNoise: appSettings.staticNoise
|
||||||
@ -63,12 +66,7 @@ ShaderEffect {
|
|||||||
property real dispY
|
property real dispY
|
||||||
property size virtual_resolution
|
property size virtual_resolution
|
||||||
|
|
||||||
TimeManager{
|
property real time: timeManager.time
|
||||||
id: timeManager
|
|
||||||
enableTimer: terminalWindow.visible
|
|
||||||
}
|
|
||||||
|
|
||||||
property alias time: timeManager.time
|
|
||||||
property ShaderEffectSource noiseSource: noiseShaderSource
|
property ShaderEffectSource noiseSource: noiseShaderSource
|
||||||
|
|
||||||
// If something goes wrong activate the fallback version of the shader.
|
// 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);
|
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)));" +
|
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);"
|
"vec4 initialNoiseTexel = texture2D(noiseSource, coords);"
|
||||||
: "") +
|
: "") +
|
||||||
|
|
||||||
@ -178,7 +176,9 @@ ShaderEffect {
|
|||||||
uniform highp sampler2D bloomSource;
|
uniform highp sampler2D bloomSource;
|
||||||
uniform lowp float bloom;" : "") +
|
uniform lowp float bloom;" : "") +
|
||||||
(burnIn !== 0 ? "
|
(burnIn !== 0 ? "
|
||||||
uniform sampler2D blurredSource;" : "") +
|
uniform sampler2D burnInSource;
|
||||||
|
uniform highp float burnInLastUpdate;
|
||||||
|
uniform highp float burnInTime;" : "") +
|
||||||
(staticNoise !== 0 ? "
|
(staticNoise !== 0 ? "
|
||||||
uniform highp float staticNoise;" : "") +
|
uniform highp float staticNoise;" : "") +
|
||||||
(((staticNoise !== 0 || jitter !== 0 || rbgShift)
|
(((staticNoise !== 0 || jitter !== 0 || rbgShift)
|
||||||
@ -228,7 +228,7 @@ ShaderEffect {
|
|||||||
"float distance = length(cc);" +
|
"float distance = length(cc);" +
|
||||||
|
|
||||||
//FallBack if there are problems
|
//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)));
|
"vec2 initialCoords = vec2(fract(time/(1024.0*2.0)), fract(time/(1024.0*1024.0)));
|
||||||
vec4 initialNoiseTexel = texture2D(noiseSource, initialCoords);"
|
vec4 initialNoiseTexel = texture2D(noiseSource, initialCoords);"
|
||||||
: "") +
|
: "") +
|
||||||
@ -292,8 +292,9 @@ ShaderEffect {
|
|||||||
" : "") +
|
" : "") +
|
||||||
|
|
||||||
(burnIn !== 0 ? "
|
(burnIn !== 0 ? "
|
||||||
vec4 txt_blur = texture2D(blurredSource, txt_coords);
|
vec4 txt_blur = texture2D(burnInSource, txt_coords);
|
||||||
txt_color = max(txt_color, txt_blur.rgb * txt_blur.a);"
|
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;" +
|
"txt_color += fontColor.rgb * color;" +
|
||||||
|
@ -3,7 +3,7 @@ import QtGraphicalEffects 1.0
|
|||||||
|
|
||||||
import "utils.js" as Utils
|
import "utils.js" as Utils
|
||||||
|
|
||||||
ShaderTerminal{
|
ShaderTerminal {
|
||||||
property alias title: terminal.title
|
property alias title: terminal.title
|
||||||
property alias terminalSize: terminal.terminalSize
|
property alias terminalSize: terminal.terminalSize
|
||||||
|
|
||||||
@ -13,11 +13,16 @@ ShaderTerminal{
|
|||||||
blending: false
|
blending: false
|
||||||
|
|
||||||
source: terminal.mainSource
|
source: terminal.mainSource
|
||||||
blurredSource: terminal.blurredSource
|
burnInEffect: terminal.burnInEffect
|
||||||
dispX: (12 / width) * appSettings.windowScaling
|
dispX: (12 / width) * appSettings.windowScaling
|
||||||
dispY: (12 / height) * appSettings.windowScaling
|
dispY: (12 / height) * appSettings.windowScaling
|
||||||
virtual_resolution: terminal.virtualResolution
|
virtual_resolution: terminal.virtualResolution
|
||||||
|
|
||||||
|
TimeManager{
|
||||||
|
id: timeManager
|
||||||
|
enableTimer: terminalWindow.visible
|
||||||
|
}
|
||||||
|
|
||||||
Loader{
|
Loader{
|
||||||
id: frame
|
id: frame
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
@ -51,5 +51,6 @@
|
|||||||
<file>fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf</file>
|
<file>fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf</file>
|
||||||
<file>fonts/1985-ibm-pc-vga/PxPlus_IBM_VGA8.ttf</file>
|
<file>fonts/1985-ibm-pc-vga/PxPlus_IBM_VGA8.ttf</file>
|
||||||
<file>fonts/1977-commodore-pet/PetMe.ttf</file>
|
<file>fonts/1977-commodore-pet/PetMe.ttf</file>
|
||||||
|
<file>BurnInEffect.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user