mirror of
				https://github.com/Swordfish90/cool-retro-term.git
				synced 2025-10-31 07:04:20 +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