mirror of
				https://github.com/Swordfish90/cool-retro-term.git
				synced 2025-11-04 00:52:11 +00:00 
			
		
		
		
	Important burn-in optimization. It is much lighter on resources.
This commit is contained in:
		
							
								
								
									
										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 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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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;" +
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -51,5 +51,6 @@
 | 
			
		||||
        <file>fonts/1981-ibm-pc/PxPlus_IBM_BIOS.ttf</file>
 | 
			
		||||
        <file>fonts/1985-ibm-pc-vga/PxPlus_IBM_VGA8.ttf</file>
 | 
			
		||||
        <file>fonts/1977-commodore-pet/PetMe.ttf</file>
 | 
			
		||||
        <file>BurnInEffect.qml</file>
 | 
			
		||||
    </qresource>
 | 
			
		||||
</RCC>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user