1
0
mirror of https://github.com/Swordfish90/cool-retro-term.git synced 2026-02-08 00:32:27 +00:00

41 Commits

Author SHA1 Message Date
Filippo Scognamiglio
002c85e35f Fix missing key repeats on macos. 2025-12-13 22:55:24 +01:00
Filippo Scognamiglio
fed2bf21fe Remove warnings related qt6 signal handlers. 2025-12-10 23:20:31 +01:00
Filippo Scognamiglio
3f51308057 Improve noise scale and frameskip for effects. 2025-12-10 23:14:15 +01:00
Filippo Scognamiglio
70d7d1b9ce Build qbs files with qmake. 2025-12-10 23:13:38 +01:00
Filippo Scognamiglio
c1082f2e3e Fix sizing issues with fractional scaling. 2025-12-10 00:41:16 +01:00
Filippo Scognamiglio
7038b30381 Migrate all shaders to compiled qsb files. 2025-12-09 23:51:39 +01:00
Filippo Scognamiglio
1d73abda51 Make it compile with Qt6. 2025-12-09 10:41:41 +01:00
Filippo Scognamiglio
f157648d1e Merge pull request #711 from razziel89/feature/appimage-in-github-actions
Feature/appimage in GitHub actions
2022-03-31 07:18:37 +02:00
Torsten Sachse
d4baaeccfc Undo unneeded code changes 2022-03-29 08:22:59 +02:00
Torsten Sachse
d412b66c6e Add github action for building an appimage 2022-03-29 08:16:02 +02:00
Filippo Scognamiglio
74ae511f92 Bump version. Yeeee 2022-01-29 15:15:52 +01:00
Filippo Scognamiglio
a3fbafe4ae Update README.md 2022-01-29 15:10:08 +01:00
Filippo Scognamiglio
8a45fbe9ed Tweak settings window and label sizes. 2022-01-16 09:40:20 +01:00
Filippo Scognamiglio
01c7929ee3 Increase size of settings window. 2022-01-12 21:11:58 +01:00
Filippo Scognamiglio
2261af17d7 Restore legacy Connection slots. Restore compilation on Qt 5.12. 2022-01-12 21:08:58 +01:00
Filippo Scognamiglio
41f34c3992 Disable Fusion style which has issues with dark themes. 2022-01-12 21:00:11 +01:00
Filippo Scognamiglio
36b1cd2dde Add github funding links. 2022-01-09 15:11:08 +01:00
Filippo Scognamiglio
80374b3ec6 Update README.md 2022-01-09 15:08:15 +01:00
Filippo Scognamiglio
bc00d1e45f Bump version. 2022-01-09 14:08:36 +01:00
Filippo Scognamiglio
6ddb507247 Merge pull request #694 from Swordfish90/osx-fixes
MacOS improvements
2022-01-09 10:56:30 +01:00
Filippo Scognamiglio
b0f3b8f3d0 Update QMLTermWidget submodule. 2022-01-09 10:53:35 +01:00
Filippo Scognamiglio
06e7191056 Disable Qt5 Connections warnings. 2022-01-09 10:47:02 +01:00
Filippo Scognamiglio
997131ba64 Tiny fixes to burn-in. 2022-01-08 23:15:29 +01:00
Filippo Scognamiglio
ef9f412e5f Clip profiles list. 2022-01-08 22:36:02 +01:00
Filippo Scognamiglio
7b69d41c60 Remove slow burn-in effect. 2022-01-08 22:32:42 +01:00
Filippo Scognamiglio
552947f507 Improve burn-in timings. 2022-01-08 22:20:44 +01:00
Filippo Scognamiglio
f69f2df63c More Connections refactorings. 2022-01-03 21:06:33 +01:00
Filippo Scognamiglio
aa270067f6 Improve settings window. 2022-01-03 20:56:49 +01:00
Filippo Scognamiglio
28977313da UI/UX fixes for OSX version. 2022-01-03 18:43:07 +01:00
Filippo Scognamiglio
cfe35d7795 Merge pull request #665 from Swordfish90/unstable
Improve rasterization and terminal frame. Some refactoring.
2021-07-15 23:43:06 +02:00
Filippo Scognamiglio
4abbe332db Improve terminal frame and expose frame size setting. 2021-07-15 23:20:42 +02:00
Filippo Scognamiglio
3104abd4ad Add subpixel rasterization. 2021-07-07 00:09:10 +02:00
Filippo Scognamiglio
7714f7b503 Improve rasterization rendering and add LCD rasterization (with subpixels). 2021-07-03 16:14:02 +02:00
Dmytro Pashchenko
9d06f10a9b some grammar fixes (#636) 2021-07-01 23:14:53 +02:00
Mizumoto Ryohei
8c27f7683b update brew command (#664)
* update brew command

* Update README.md
2021-07-01 23:12:26 +02:00
Filippo Scognamiglio
bf1a491789 Merge pull request #638 from amake/patch-1
Mention MacPorts in readme
2021-07-01 23:10:42 +02:00
Filippo Scognamiglio
0f18a0349a Merge pull request #589 from rbanffy/master
Update 3270 font to 2.3.1
2021-06-30 08:49:39 +02:00
Ricardo Bánffy
39181f42cf Update font version to 2.3.1 2021-03-25 09:52:21 +00:00
Aaron Madlon-Kay
3d706ad1a7 Mention MacPorts in readme 2021-01-27 14:42:57 +09:00
Ricardo Bánffy
a31b77e5bc Update 3270 font with version 2.0.4.
See https://github.com/rbanffy/3270font/tree/v2.0.4 for changes.
2020-05-17 12:29:24 +01:00
Ricardo Bánffy
b417643415 Renamed 3270 font to latest binary version 2020-05-17 12:21:13 +01:00
45 changed files with 1443 additions and 1196 deletions

4
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,4 @@
# These are supported funding model platforms
patreon: swordfish90
custom: ['https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=flscogna%40gmail.com&item_name=Support+CRT&currency_code=EUR&source=url']

98
.github/workflows/appimage.yml vendored Normal file
View File

@@ -0,0 +1,98 @@
name: "ci"
on:
push:
tags: "**"
workflow_dispatch:
defaults:
run:
shell: bash
jobs:
appimage:
runs-on: ubuntu-18.04
steps:
- name: Checkout repository
uses: actions/checkout@v2
with:
submodules: true
- name: Install dependencies
run: |
sudo add-apt-repository -y ppa:beineri/opt-qt-5.15.2-bionic
sudo apt-get update -qq
sudo apt-get install -y \
build-essential make wget libgl1-mesa-dev \
qt515declarative qt515graphicaleffects \
qt515quickcontrols qt515quickcontrols2
- name: Download QT appimage builder
run: |
wget -c -O linuxdeployqt.AppImage \
https://github.com/probonopd/linuxdeployqt/releases/download/continuous/linuxdeployqt-continuous-x86_64.AppImage
chmod a+x linuxdeployqt.AppImage
- name: Build project
run: |
source /opt/qt*/bin/qt*-env.sh && \
qmake -v && \
qmake CONFIG+=release PREFIX=/usr && \
make -j$(nproc)
- name: Install to appdir
run: |
source /opt/qt*/bin/qt*-env.sh && \
make INSTALL_ROOT=appdir -j$(nproc) install
- name: Extract version number
run: |
# Extract version for linuxdeployqt to name the file. Use the tag as
# release name but remove prefix.
echo "VERSION=$(echo '${{ github.ref }}' | sed 's;.*/;;')" >> $GITHUB_ENV
- name: Build appimage directory
run: |
mkdir -p \
appdir/usr/bin \
appdir/usr/lib \
appdir/usr/share/applications \
appdir/usr/share/metainfo \
appdir/usr/share/icons/hicolor/128x128/apps
cp cool-retro-term appdir/usr/bin/
cp cool-retro-term.desktop appdir/usr/share/applications/
cp packaging/appdata/cool-retro-term.appdata.xml appdir/usr/share/metainfo/
cp app/icons/128x128/cool-retro-term.png appdir/usr/share/icons/hicolor/128x128/apps/
cp -r ./app/qml appdir/usr/
# Workaround for https://github.com/probonopd/linuxdeployqt/issues/78
cp -r ./qmltermwidget/QMLTermWidget appdir/usr/qml/
find appdir | sort
- name: Build appimage
run: |
source /opt/qt*/bin/qt*-env.sh && \
./linuxdeployqt.AppImage appdir/usr/share/applications/cool-retro-term.desktop \
-verbose=1 -appimage \
-qmldir=./app/qml/ \
-qmldir=./qmltermwidget/
env:
# Unset environment variables
QTDIR:
QT_PLUGIN_PATH:
LD_LIBRARY_PATH:
- name: Upload release
uses: softprops/action-gh-release@v1
with:
body: appimage release
files: ./**/Cool_Retro_Term-*-x86_64.AppImage
- name: Clean up
if: always()
run: |
find appdir -executable -type f -exec ldd {} \; | grep " => /usr" | cut -d " " -f 2-3 | sort | uniq
make clean
rm -rf appdir

1
.gitignore vendored
View File

@@ -43,6 +43,7 @@ Makefile*
# Excludes compiled files # Excludes compiled files
imports imports
cool-retro-term cool-retro-term
build
# Mac OSX # Mac OSX

193
README.md
View File

@@ -8,9 +8,9 @@
cool-retro-term is a terminal emulator which mimics the look and feel of the old cathode tube screens. cool-retro-term is a terminal emulator which mimics the look and feel of the old cathode tube screens.
It has been designed to be eye-candy, customizable, and reasonably lightweight. It has been designed to be eye-candy, customizable, and reasonably lightweight.
It uses the QML port of qtermwidget (Konsole) developed by me: https://github.com/Swordfish90/qmltermwidget . It uses the QML port of qtermwidget (Konsole): https://github.com/Swordfish90/qmltermwidget.
This terminal emulator works under Linux and macOS and requires Qt 5.2 or higher. This terminal emulator works under Linux and macOS and requires Qt5. It's suggested that you stick to the latest LTS version.
Settings such as colors, fonts, and effects can be accessed via context menu. Settings such as colors, fonts, and effects can be accessed via context menu.
@@ -20,192 +20,11 @@ Settings such as colors, fonts, and effects can be accessed via context menu.
![Image](<https://i.imgur.com/GYRDPzJ.jpg>) ![Image](<https://i.imgur.com/GYRDPzJ.jpg>)
## Install ## Install
Walk the easy way and install cool-retro-term using one of these convenient packages:
Just grab the latest AppImage from the release page and make it executable and run it: If you want to get a hold of the latest version, just go to the Releases page and grab the latest AppImage (Linux) or dmg (macOS).
wget https://github.com/Swordfish90/cool-retro-term/releases/download/1.1.1/Cool-Retro-Term-1.1.1-x86_64.AppImage Alternatively, most distributions such as Ubuntu, Fedora or Arch already package cool-retro-term in their official repositories.
chmod a+x Cool-Retro-Term-1.1.1-x86_64.AppImage
./Cool-Retro-Term-1.1.1-x86_64.AppImage
**Fedora** has the `cool-retro-term` in the official repositories. All you have to do is `sudo dnf install cool-retro-term`. ## Building
Users of **openSUSE** can grab a package from [Open Build Service](http://software.opensuse.org/package/cool-retro-term). Check out the wiki and follow the instructions on how to build it on [Linux](https://github.com/Swordfish90/cool-retro-term/wiki/Build-Instructions-(Linux)) and [macOS](https://github.com/Swordfish90/cool-retro-term/wiki/Build-Instructions-(macOS)).
**Arch** users can install this [package](https://aur.archlinux.org/packages/cool-retro-term-git/) directly via the [AUR](https://aur.archlinux.org):
trizen -S aur/cool-retro-term-git
or use:
pacman -S cool-retro-term
to install precompiled from community repository.
Users of **Ubuntu 14.04 LTS (Trusty) up to 15.10 (Wily)** can use [this PPA](https://launchpad.net/~bugs-launchpad-net-falkensweb).
**Ubuntu 17.10** can use [this PPA](https://launchpad.net/%7Evantuz/+archive/ubuntu/cool-retro-term)
**Solus** users can install using `eopg`:
```
eopkg it cool-retro-term
```
**macOS** users can grab the latest dmg from the [release page](https://github.com/Swordfish90/cool-retro-term/releases) or install via Homebrew:
```
brew cask install cool-retro-term
```
**FreeBSD** users can install cool-retro-term with `pkg`:
pkg install cool-retro-term
## Build instructions (FreeBSD)
Grab a copy of [the FreeBSD Ports Collection](https://www.freebsd.org/doc/en_US.ISO8859-1/books/handbook/ports-using.html), modify [`/usr/ports/x11/cool-retro-term/Makefile`](https://svnweb.freebsd.org/ports/head/x11/cool-retro-term/Makefile?view=markup) as you like, and then run `make install` to build and install the emulator:
```
cd /usr/ports/x11/cool-retro-term
make install
```
## Build instructions (Linux)
Build cool-retro-term yourself, you know, the retro way.
## Dependencies
Make sure to install these first.
---
**Ubuntu 14.04**
sudo apt-get install build-essential qmlscene qt5-qmake qt5-default qtdeclarative5-dev qtdeclarative5-controls-plugin qtdeclarative5-qtquick2-plugin libqt5qml-graphicaleffects qtdeclarative5-dialogs-plugin qtdeclarative5-localstorage-plugin qtdeclarative5-window-plugin
---
**Ubuntu 16.10**
sudo apt-get install build-essential qmlscene qt5-qmake qt5-default qtdeclarative5-dev qml-module-qtquick-controls qtdeclarative5-qtquick2-plugin libqt5qml-graphicaleffects qml-module-qtquick-dialogs qtdeclarative5-localstorage-plugin qtdeclarative5-window-plugin
---
**Ubuntu 17.04**
sudo apt install build-essential libqt5qml-graphicaleffects qml-module-qt-labs-folderlistmodel qml-module-qt-labs-settings qml-module-qtquick-controls qml-module-qtquick-dialogs qmlscene qt5-default qt5-qmake qtdeclarative5-dev qtdeclarative5-localstorage-plugin qtdeclarative5-qtquick2-plugin qtdeclarative5-window-plugin
---
**Ubuntu 17.10**
sudo apt-get install build-essential qml-module-qtgraphicaleffects qml-module-qt-labs-folderlistmodel qml-module-qt-labs-settings qml-module-qtquick-controls qml-module-qtquick-dialogs qmlscene qt5-default qt5-qmake qtdeclarative5-dev qtdeclarative5-localstorage-plugin qtdeclarative5-qtquick2-plugin qtdeclarative5-window-plugin
---
**snapcraft (most of distros)**
sudo snap install cool-retro-term --classic
---
**Debian Jessie and above**
sudo apt install build-essential qmlscene qt5-qmake qt5-default qtdeclarative5-dev qml-module-qtquick-controls qml-module-qtgraphicaleffects qml-module-qtquick-dialogs qml-module-qtquick-localstorage qml-module-qtquick-window2 qml-module-qt-labs-settings qml-module-qt-labs-folderlistmodel
---
**Fedora**
This command should install the known fedora dependencies:
sudo yum -y install qt5-qtbase qt5-qtbase-devel qt5-qtdeclarative qt5-qtdeclarative-devel qt5-qtgraphicaleffects qt5-qtquickcontrols redhat-rpm-config
or:
sudo dnf -y install qt5-qtbase qt5-qtbase-devel qt5-qtdeclarative qt5-qtdeclarative-devel qt5-qtgraphicaleffects qt5-qtquickcontrols redhat-rpm-config
---
**Arch Linux**
sudo pacman -S qt5-base qt5-declarative qt5-quickcontrols qt5-graphicaleffects
---
**openSUSE**
Add repository with latest Qt 5 (this is only needed on openSUSE 13.1, Factory already has it):
sudo zypper ar http://download.opensuse.org/repositories/KDE:/Qt5/openSUSE_13.1/ KDE:Qt5
Install dependencies:
sudo zypper install libqt5-qtbase-devel libqt5-qtdeclarative-devel libqt5-qtquickcontrols libqt5-qtgraphicaleffects
---
**Anyone else**
Install Qt directly from here http://qt-project.org/downloads . Once done export them in you path (replace "_/opt/Qt5.3.1/5.3/gcc_64/bin_" with your correct folder):
export PATH=/opt/Qt5.3.1/5.3/gcc_64/bin/:$PATH
---
### Compile
Once you installed all dependencies (Qt is installed and in your path) you need to compile and run the application:
```bash
# Get it from GitHub
git clone --recursive https://github.com/Swordfish90/cool-retro-term.git
# Build it
cd cool-retro-term
# Compile (Fedora and OpenSUSE user should use qmake-qt5 instead of qmake)
qmake && make
# Have fun!
./cool-retro-term
```
## Build instructions (macOS)
1. Install [Xcode](https://developer.apple.com/xcode/) and agree to the licence agreement
2. Enter the following commands into the terminal:
**Brew**
```sh
brew install qt5
git clone --recursive https://github.com/Swordfish90/cool-retro-term.git
export CPPFLAGS="-I/usr/local/opt/qt5/include"
export LDFLAGS="-L/usr/local/opt/qt5/lib"
export PATH=/usr/local/opt/qt5/bin:$PATH
cd cool-retro-term
qmake && make
mkdir cool-retro-term.app/Contents/PlugIns
cp -r qmltermwidget/QMLTermWidget cool-retro-term.app/Contents/PlugIns
open cool-retro-term.app
```
**MacPorts**
```sh
sudo port install qt5
git clone --recursive https://github.com/Swordfish90/cool-retro-term.git
cd cool-retro-term
/opt/local/libexec/qt5/bin/qmake && make
mkdir cool-retro-term.app/Contents/PlugIns
cp -r qmltermwidget/QMLTermWidget cool-retro-term.app/Contents/PlugIns
open cool-retro-term.app
```
**Homebrew**
```sh
brew cask install cool-retro-term
```
## Donations
I made this project in my spare time because I love what I'm doing. If you are enjoying it and you want to buy me a beer click [here](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=flscogna%40gmail%2ecom&lc=IT&item_name=Filippo%20Scognamiglio&currency_code=EUR&bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted).
You can also add "bounties" on your favourite issues. More information on the [Bountysource](https://www.bountysource.com/teams/crt/issues) page.

View File

@@ -1,4 +1,4 @@
QT += qml quick widgets sql QT += qml quick widgets sql quickcontrols2
TARGET = cool-retro-term TARGET = cool-retro-term
DESTDIR = $$OUT_PWD/../ DESTDIR = $$OUT_PWD/../
@@ -15,6 +15,23 @@ macx:ICON = icons/crt.icns
RESOURCES += qml/resources.qrc RESOURCES += qml/resources.qrc
# Shader compilation (Qt Shader Baker)
QSB_BIN = $$[QT_HOST_BINS]/qsb
isEmpty(QSB_BIN): QSB_BIN = $$[QT_INSTALL_BINS]/qsb
SHADERS_DIR = $${_PRO_FILE_PWD_}/shaders
SHADERS += $$files($$SHADERS_DIR/*.frag) $$files($$SHADERS_DIR/*.vert)
qsb.input = SHADERS
qsb.output = ../../app/shaders/${QMAKE_FILE_NAME}.qsb
qsb.commands = $$QSB_BIN --glsl \"100 es,120,150\" --hlsl 50 --msl 12 --qt6 -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
qsb.clean = $$qsb.output
qsb.name = qsb ${QMAKE_FILE_IN}
qsb.variable_out = QSB_FILES
QMAKE_EXTRA_COMPILERS += qsb
PRE_TARGETDEPS += $$QSB_FILES
OTHER_FILES += $$SHADERS $$QSB_FILES
######################################### #########################################
## INTALLS ## INTALLS
######################################### #########################################

View File

@@ -6,15 +6,21 @@
#include <QtWidgets/QApplication> #include <QtWidgets/QApplication>
#include <QIcon> #include <QIcon>
#include <QQuickStyle>
#include <QDebug> #include <QDebug>
#include <stdlib.h> #include <stdlib.h>
#include <QFontDatabase> #include <QFontDatabase>
#include <QLoggingCategory>
#include <fileio.h> #include <fileio.h>
#include <monospacefontmanager.h> #include <monospacefontmanager.h>
#if defined(Q_OS_MAC)
#include <CoreFoundation/CoreFoundation.h>
#endif
QString getNamedArgument(QStringList args, QString name, QString defaultName) QString getNamedArgument(QStringList args, QString name, QString defaultName)
{ {
int index = args.indexOf(name); int index = args.indexOf(name);
@@ -29,45 +35,50 @@ QString getNamedArgument(QStringList args, QString name)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// Some environmental variable are necessary on certain platforms. // Some environmental variable are necessary on certain platforms.
// Disable Connections slot warnings
QLoggingCategory::setFilterRules("qt.qml.connections.warning=false");
// This disables QT appmenu under Ubuntu, which is not working with QML apps. // TODO FILIPPO... This should not be hardcoded but handled as a fallback of sort!
setenv("QT_QPA_PLATFORMTHEME", "", 1); QQuickStyle::setStyle("Material");
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
#if defined (Q_OS_LINUX) // #if defined (Q_OS_LINUX)
setenv("QSG_RENDER_LOOP", "threaded", 0); // setenv("QSG_RENDER_LOOP", "threaded", 0);
#endif // #endif
#if defined(Q_OS_MAC) #if defined(Q_OS_MAC)
// This allows UTF-8 characters usage in OSX. // This allows UTF-8 characters usage in OSX.
setenv("LC_CTYPE", "UTF-8", 1); setenv("LC_CTYPE", "UTF-8", 1);
// Ensure key repeat works for letter keys (disable macOS press-and-hold for this app).
CFPreferencesSetAppValue(CFSTR("ApplePressAndHoldEnabled"), kCFBooleanFalse, kCFPreferencesCurrentApplication);
CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication);
#endif #endif
if (argc>1 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help"))) { if (argc>1 && (!strcmp(argv[1],"-h") || !strcmp(argv[1],"--help"))) {
QTextStream cout(stdout, QIODevice::WriteOnly); QTextStream cout(stdout, QIODevice::WriteOnly);
cout << "Usage: " << argv[0] << " [--default-settings] [--workdir <dir>] [--program <prog>] [-p|--profile <prof>] [--fullscreen] [-h|--help]" << endl; cout << "Usage: " << argv[0] << " [--default-settings] [--workdir <dir>] [--program <prog>] [-p|--profile <prof>] [--fullscreen] [-h|--help]" << Qt::endl;
cout << " --default-settings Run cool-retro-term with the default settings" << endl; cout << " --default-settings Run cool-retro-term with the default settings" << Qt::endl;
cout << " --workdir <dir> Change working directory to 'dir'" << endl; cout << " --workdir <dir> Change working directory to 'dir'" << Qt::endl;
cout << " -e <cmd> Command to execute. This option will catch all following arguments, so use it as the last option." << endl; cout << " -e <cmd> Command to execute. This option will catch all following arguments, so use it as the last option." << Qt::endl;
cout << " -T <title> Set window title to 'title'." << endl; cout << " -T <title> Set window title to 'title'." << Qt::endl;
cout << " --fullscreen Run cool-retro-term in fullscreen." << endl; cout << " --fullscreen Run cool-retro-term in fullscreen." << Qt::endl;
cout << " -p|--profile <prof> Run cool-retro-term with the given profile." << endl; cout << " -p|--profile <prof> Run cool-retro-term with the given profile." << Qt::endl;
cout << " -h|--help Print this help." << endl; cout << " -h|--help Print this help." << Qt::endl;
cout << " --verbose Print additional information such as profiles and settings." << endl; cout << " --verbose Print additional information such as profiles and settings." << Qt::endl;
return 0; return 0;
} }
QString appVersion("1.1.1"); QString appVersion("1.2.0");
if (argc>1 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version"))) { if (argc>1 && (!strcmp(argv[1],"-v") || !strcmp(argv[1],"--version"))) {
QTextStream cout(stdout, QIODevice::WriteOnly); QTextStream cout(stdout, QIODevice::WriteOnly);
cout << "cool-retro-term " << appVersion << endl; cout << "cool-retro-term " << appVersion << Qt::endl;
return 0; return 0;
} }
QApplication app(argc, argv); QApplication app(argc, argv);
// set application attributes app.setAttribute(Qt::AA_MacDontSwapCtrlAndMeta, true);
// Has no effects, see https://bugreports.qt.io/browse/QTBUG-51293
// app.setAttribute(Qt::AA_MacDontSwapCtrlAndMeta, true);
QQmlApplicationEngine engine; QQmlApplicationEngine engine;
FileIO fileIO; FileIO fileIO;

View File

@@ -31,8 +31,10 @@ QtObject {
readonly property real minimumFontScaling: 0.25 readonly property real minimumFontScaling: 0.25
readonly property real maximumFontScaling: 2.50 readonly property real maximumFontScaling: 2.50
readonly property real minBurnInFadeTime: 160 readonly property real minBurnInFadeTime: 0.16
readonly property real maxBurnInFadeTime: 1600 readonly property real maxBurnInFadeTime: 1.6
property bool isMacOS: Qt.platform.os === "osx"
// GENERAL SETTINGS /////////////////////////////////////////////////////// // GENERAL SETTINGS ///////////////////////////////////////////////////////
property int x: 100 property int x: 100
@@ -41,20 +43,18 @@ QtObject {
property int height: 768 property int height: 768
property bool fullscreen: false property bool fullscreen: false
property bool showMenubar: Qt.platform.os === "osx" ? true : false property bool showMenubar: false
property string wintitle: "cool-retro-term" property string wintitle: "cool-retro-term"
property bool showTerminalSize: true property bool showTerminalSize: true
property real windowScaling: 1.0 property real windowScaling: 1.0
property real fps: 20 property int effectsFrameSkip: 2
property bool verbose: false property bool verbose: false
property real bloomQuality: 0.5 property real bloomQuality: 0.5
property real burnInQuality: 0.5 property real burnInQuality: 0.5
property bool useFastBurnIn: Qt.platform.os === "osx" ? false : true
property bool blinkingCursor: false property bool blinkingCursor: false
@@ -99,11 +99,17 @@ QtObject {
property real rbgShift: 0.0 property real rbgShift: 0.0
property real _margin: 0.5 property real _margin: 0.5
property real _frameMargin: 0.5
property real margin: Utils.lint(1.0, 20.0, _margin) property real margin: Utils.lint(1.0, 20.0, _margin)
property real frameMargin: Utils.lint(1.0, 50.0, _frameMargin)
property real totalMargin: frameMargin + margin
readonly property int no_rasterization: 0 readonly property int no_rasterization: 0
readonly property int scanline_rasterization: 1 readonly property int scanline_rasterization: 1
readonly property int pixel_rasterization: 2 readonly property int pixel_rasterization: 2
readonly property int subpixel_rasterization: 3
property int rasterization: no_rasterization property int rasterization: no_rasterization
@@ -145,6 +151,13 @@ QtObject {
target: fontManager target: fontManager
source: "FontPixels.qml" source: "FontPixels.qml"
} }
},
State {
when: rasterization == subpixel_rasterization
PropertyChanges {
target: fontManager
source: "FontPixels.qml"
}
} }
] ]
@@ -216,7 +229,7 @@ QtObject {
function composeSettingsString() { function composeSettingsString() {
var settings = { var settings = {
"fps": fps, "effectsFrameSkip": effectsFrameSkip,
"x": x, "x": x,
"y": y, "y": y,
"width": width, "width": width,
@@ -229,9 +242,7 @@ QtObject {
"bloomQuality": bloomQuality, "bloomQuality": bloomQuality,
"burnInQuality": burnInQuality, "burnInQuality": burnInQuality,
"useCustomCommand": useCustomCommand, "useCustomCommand": useCustomCommand,
"customCommand": customCommand, "customCommand": customCommand
"useFastBurnIn": useFastBurnIn,
"blinkingCursor": blinkingCursor
} }
return stringify(settings) return stringify(settings)
} }
@@ -258,7 +269,9 @@ QtObject {
"windowOpacity": windowOpacity, "windowOpacity": windowOpacity,
"fontName": fontNames[rasterization], "fontName": fontNames[rasterization],
"fontWidth": fontWidth, "fontWidth": fontWidth,
"margin": _margin "margin": _margin,
"blinkingCursor": blinkingCursor,
"frameMargin": _frameMargin,
} }
return settings return settings
} }
@@ -302,7 +315,7 @@ QtObject {
showTerminalSize = settings.showTerminalSize showTerminalSize = settings.showTerminalSize
!== undefined ? settings.showTerminalSize : showTerminalSize !== undefined ? settings.showTerminalSize : showTerminalSize
fps = settings.fps !== undefined ? settings.fps : fps effectsFrameSkip = settings.effectsFrameSkip !== undefined ? settings.effectsFrameSkip : effectsFrameSkip
windowScaling = settings.windowScaling windowScaling = settings.windowScaling
!== undefined ? settings.windowScaling : windowScaling !== undefined ? settings.windowScaling : windowScaling
@@ -324,12 +337,6 @@ QtObject {
!== undefined ? settings.useCustomCommand : useCustomCommand !== undefined ? settings.useCustomCommand : useCustomCommand
customCommand = settings.customCommand customCommand = settings.customCommand
!== undefined ? settings.customCommand : customCommand !== undefined ? settings.customCommand : customCommand
useFastBurnIn = settings.useFastBurnIn
!== undefined ? settings.useFastBurnIn : useFastBurnIn
blinkingCursor = settings.blinkingCursor
!== undefined ? settings.blinkingCursor : blinkingCursor
} }
function loadProfileString(profileString) { function loadProfileString(profileString) {
@@ -371,6 +378,9 @@ QtObject {
fontWidth = settings.fontWidth !== undefined ? settings.fontWidth : fontWidth fontWidth = settings.fontWidth !== undefined ? settings.fontWidth : fontWidth
_margin = settings.margin !== undefined ? settings.margin : _margin _margin = settings.margin !== undefined ? settings.margin : _margin
_frameMargin = settings.frameMargin !== undefined ? settings.frameMargin : _frameMargin
blinkingCursor = settings.blinkingCursor !== undefined ? settings.blinkingCursor : blinkingCursor
handleFontChanged() handleFontChanged()
} }
@@ -451,7 +461,9 @@ QtObject {
"screenCurvature": 0.3, "screenCurvature": 0.3,
"staticNoise": 0.1198, "staticNoise": 0.1198,
"windowOpacity": 1, "windowOpacity": 1,
"margin": 0.5 "margin": 0.5,
"blinkingCursor": false,
"frameMargin": 0.1
}' }'
builtin: true builtin: true
} }
@@ -478,7 +490,9 @@ QtObject {
"screenCurvature": 0.3, "screenCurvature": 0.3,
"staticNoise": 0.1198, "staticNoise": 0.1198,
"windowOpacity": 1, "windowOpacity": 1,
"margin": 0.5 "margin": 0.5,
"blinkingCursor": false,
"frameMargin": 0.1
}' }'
builtin: true builtin: true
} }
@@ -505,7 +519,9 @@ QtObject {
"screenCurvature": 0.3, "screenCurvature": 0.3,
"staticNoise": 0.15, "staticNoise": 0.15,
"windowOpacity": 1, "windowOpacity": 1,
"margin": 0.5 "margin": 0.5,
"blinkingCursor": false,
"frameMargin": 0.1
}' }'
builtin: true builtin: true
} }
@@ -532,7 +548,9 @@ QtObject {
"screenCurvature": 0, "screenCurvature": 0,
"staticNoise": 0.15, "staticNoise": 0.15,
"windowOpacity": 1, "windowOpacity": 1,
"margin": 0.5 "margin": 0.5,
"blinkingCursor": false,
"frameMargin": 0.1
}' }'
builtin: true builtin: true
} }
@@ -559,7 +577,9 @@ QtObject {
"screenCurvature": 0.5, "screenCurvature": 0.5,
"staticNoise": 0.099, "staticNoise": 0.099,
"windowOpacity": 1, "windowOpacity": 1,
"margin": 0.5 "margin": 0.5,
"blinkingCursor": false,
"frameMargin": 0.2
}' }'
builtin: true builtin: true
} }
@@ -586,7 +606,9 @@ QtObject {
"screenCurvature": 0.5, "screenCurvature": 0.5,
"staticNoise": 0.2969, "staticNoise": 0.2969,
"windowOpacity": 1, "windowOpacity": 1,
"margin": 0.5 "margin": 0.5,
"blinkingCursor": false,
"frameMargin": 0.5
}' }'
builtin: true builtin: true
} }
@@ -613,7 +635,9 @@ QtObject {
"screenCurvature": 0.4, "screenCurvature": 0.4,
"staticNoise": 0.0503, "staticNoise": 0.0503,
"windowOpacity": 1, "windowOpacity": 1,
"margin": 0.5 "margin": 0.5,
"blinkingCursor": false,
"frameMargin": 0.2
}' }'
builtin: true builtin: true
} }
@@ -640,7 +664,9 @@ QtObject {
"screenCurvature": 0.2, "screenCurvature": 0.2,
"staticNoise": 0, "staticNoise": 0,
"windowOpacity": 1, "windowOpacity": 1,
"margin": 0.5 "margin": 0.5,
"blinkingCursor": false,
"frameMargin": 0.1
}' }'
builtin: true builtin: true
} }
@@ -667,7 +693,9 @@ QtObject {
"screenCurvature": 0, "screenCurvature": 0,
"staticNoise": 0.0955, "staticNoise": 0.0955,
"windowOpacity": 0.7, "windowOpacity": 0.7,
"margin": 0.1 "margin": 0.1,
"blinkingCursor": false,
"frameMargin": 0
}' }'
builtin: true builtin: true
} }

View File

@@ -29,26 +29,29 @@ Loader {
property real lastUpdate: 0 property real lastUpdate: 0
property real prevLastUpdate: 0 property real prevLastUpdate: 0
property real delay: (1.0 / appSettings.fps) * 1000
property real burnIn: appSettings.burnIn property real burnIn: appSettings.burnIn
property real burnInFadeTime: 1 / Utils.lint(_minBurnInFadeTime, _maxBurnInFadeTime, burnIn) property real burnInFadeTime: 1 / Utils.lint(_minBurnInFadeTime, _maxBurnInFadeTime, burnIn)
property real _minBurnInFadeTime: appSettings.minBurnInFadeTime property real _minBurnInFadeTime: appSettings.minBurnInFadeTime
property real _maxBurnInFadeTime: appSettings.maxBurnInFadeTime property real _maxBurnInFadeTime: appSettings.maxBurnInFadeTime
active: appSettings.useFastBurnIn && appSettings.burnIn !== 0 active: appSettings.burnIn !== 0
anchors.fill: parent anchors.fill: parent
function completelyUpdate() { function completelyUpdate() {
prevLastUpdate = lastUpdate; let newTime = timeManager.time
lastUpdate = timeManager.time; if (newTime > lastUpdate) {
item.source.scheduleUpdate(); prevLastUpdate = lastUpdate
lastUpdate = newTime
}
item.source.scheduleUpdate()
} }
function restartBlurSource(){ function restartBlurSource() {
prevLastUpdate = timeManager.time; prevLastUpdate = timeManager.time
lastUpdate = prevLastUpdate; lastUpdate = prevLastUpdate
completelyUpdate(); completelyUpdate()
} }
sourceComponent: Item { sourceComponent: Item {
@@ -72,20 +75,30 @@ Loader {
Connections { Connections {
target: kterminal target: kterminal
onImagePainted: completelyUpdate()
onImagePainted: {
completelyUpdate()
}
} }
// Restart blurred source settings change. // Restart blurred source settings change.
Connections{
target: appSettings
onBurnInChanged: burnInEffect.restartBlurSource();
onTerminalFontChanged: burnInEffect.restartBlurSource();
onRasterizationChanged: burnInEffect.restartBlurSource();
onBurnInQualityChanged: burnInEffect.restartBlurSource();
}
Connections { Connections {
target: kterminalScrollbar target: appSettings
onOpacityChanged: completelyUpdate()
onBurnInChanged: {
burnInEffect.restartBlurSource()
}
onTerminalFontChanged: {
burnInEffect.restartBlurSource()
}
onRasterizationChanged: {
burnInEffect.restartBlurSource()
}
onBurnInQualityChanged: {
burnInEffect.restartBlurSource()
}
} }
} }
@@ -95,50 +108,44 @@ Loader {
property variant txt_source: kterminalSource property variant txt_source: kterminalSource
property variant burnInSource: burnInEffectSource property variant burnInSource: burnInEffectSource
property real burnInTime: burnInFadeTime property real burnInTime: burnInFadeTime
property real lastUpdate: burnInEffect.lastUpdate property real burnInLastUpdate: burnInEffect.lastUpdate
property real prevLastUpdate: burnInEffect.prevLastUpdate property real prevLastUpdate: burnInEffect.prevLastUpdate
anchors.fill: parent anchors.fill: parent
blending: false blending: false
fragmentShader: // Extra uniforms required by shared block
"#ifdef GL_ES property real qt_Opacity: 1.0
precision mediump float; property real time: timeManager.time
#endif\n" + property color fontColor: appSettings.fontColor
property color backgroundColor: appSettings.backgroundColor
property real shadowLength: 0
property size virtualResolution: Qt.size(width, height)
property real rasterizationIntensity: 0
property int rasterizationMode: 0
property real burnIn: appSettings.burnIn
property real staticNoise: 0
property real screenCurvature: 0
property real glowingLine: 0
property real chromaColor: 0
property size jitterDisplacement: Qt.size(0, 0)
property real ambientLight: 0
property real jitter: 0
property real horizontalSync: 0
property real horizontalSyncStrength: 0
property real flickering: 0
property real displayTerminalFrame: 0
property size scaleNoiseSize: Qt.size(0, 0)
property real screen_brightness: 1.0
property real bloom: 0
property real rbgShift: 0
property real screenShadowCoeff: 0
property real frameShadowCoeff: 0
property color frameColor: backgroundColor
property size margin: Qt.size(0, 0)
"uniform lowp float qt_Opacity;" + fragmentShader: "qrc:/shaders/burn_in.frag.qsb"
"uniform lowp sampler2D txt_source;" + vertexShader: "qrc:/shaders/passthrough.vert.qsb"
"varying highp vec2 qt_TexCoord0;
uniform lowp sampler2D burnInSource;
uniform highp float burnInTime;
uniform highp float lastUpdate;
uniform highp float prevLastUpdate;" +
"float rgb2grey(vec3 v){
return dot(v, vec3(0.21, 0.72, 0.04));
}" +
"void main() {
vec2 coords = qt_TexCoord0;
vec3 txtColor = texture2D(txt_source, coords).rgb;
vec4 accColor = texture2D(burnInSource, coords);
float prevMask = accColor.a;
float currMask = rgb2grey(txtColor);
highp float blurDecay = clamp((lastUpdate - prevLastUpdate) * burnInTime, 0.0, 1.0);
blurDecay = max(0.0, blurDecay - prevMask);
vec3 blurColor = accColor.rgb - vec3(blurDecay);
vec3 color = max(blurColor, txtColor);
gl_FragColor = vec4(color, currMask);
}
"
onStatusChanged: if (log) console.log(log) //Print warning messages onStatusChanged: if (log) console.log(log) //Print warning messages
} }

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/ *******************************************************************************/
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs
Item { Item {
id: rootItem id: rootItem
@@ -31,13 +31,13 @@ Item {
id: colorDialog id: colorDialog
title: qsTr("Choose a color") title: qsTr("Choose a color")
modality: Qt.ApplicationModal modality: Qt.ApplicationModal
visible: false selectedColor: rootItem.color
//This is a workaround to a Qt 5.2 bug. onSelectedColorChanged: {
onColorChanged: if (Qt.platform.os !== "osx") if (!appSettings.isMacOS && visible)
colorSelected(color) colorSelected(selectedColor)
onAccepted: if (Qt.platform.os === "osx") }
colorSelected(color) onAccepted: colorSelected(selectedColor)
} }
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
@@ -59,6 +59,6 @@ Item {
} }
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: colorDialog.visible = true onClicked: colorDialog.open()
} }
} }

View File

@@ -213,7 +213,7 @@ QtObject {
ListElement { ListElement {
name: "IBM_3278" name: "IBM_3278"
text: "HD: IBM 3278 (1971)" text: "HD: IBM 3278 (1971)"
source: "fonts/1971-ibm-3278/3270Medium.ttf" source: "fonts/1971-ibm-3278/3270-Regular.ttf"
lineSpacing: 0.2 lineSpacing: 0.2
pixelSize: 32 pixelSize: 32
fontWidth: 1.0 fontWidth: 1.0

View File

@@ -21,7 +21,7 @@ import QtQuick 2.2
import QtQuick.Window 2.0 import QtQuick.Window 2.0
import QtQuick.Controls 2.0 import QtQuick.Controls 2.0
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs
Window { Window {
id: insertnamedialog id: insertnamedialog

View File

@@ -1,97 +0,0 @@
/*******************************************************************************
* Copyright (c) 2013-2021 "Filippo Scognamiglio"
* https://github.com/Swordfish90/cool-retro-term
*
* This file is part of cool-retro-term.
*
* cool-retro-term is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
import QtQuick 2.0
import "utils.js" as Utils
ShaderEffect {
property color _staticFrameColor: "#ffffff"
property color _backgroundColor: appSettings.backgroundColor
property color _fontColor: appSettings.fontColor
property color _lightColor: Utils.mix(_fontColor, _backgroundColor, 0.2)
property real _ambientLight: Utils.lint(0.2, 0.8, appSettings.ambientLight)
property color frameColor: Utils.mix(_staticFrameColor, _lightColor, _ambientLight)
property real screenCurvature: appSettings.screenCurvature * appSettings.screenCurvatureSize
property real shadowLength: 0.5 * screenCurvature * Utils.lint(0.50, 1.5, _ambientLight)
property size aadelta: Qt.size(1.0 / width, 1.0 / height)
fragmentShader: "
#ifdef GL_ES
precision mediump float;
#endif
uniform lowp float screenCurvature;
uniform lowp float shadowLength;
uniform highp float qt_Opacity;
uniform lowp vec4 frameColor;
uniform mediump vec2 aadelta;
varying highp vec2 qt_TexCoord0;
vec2 distortCoordinates(vec2 coords){
vec2 cc = (coords - vec2(0.5));
float dist = dot(cc, cc) * screenCurvature;
return (coords + cc * (1.0 + dist) * dist);
}
float max2(vec2 v) {
return max(v.x, v.y);
}
float min2(vec2 v) {
return min(v.x, v.y);
}
float prod2(vec2 v) {
return v.x * v.y;
}
float sum2(vec2 v) {
return v.x + v.y;
}
void main(){
vec2 staticCoords = qt_TexCoord0;
vec2 coords = distortCoordinates(staticCoords);
vec3 color = vec3(0.0);
float alpha = 0.0;
float outShadowLength = shadowLength;
float inShadowLength = shadowLength * 0.5;
float outShadow = max2(1.0 - smoothstep(vec2(-outShadowLength), vec2(0.0), coords) + smoothstep(vec2(1.0), vec2(1.0 + outShadowLength), coords));
outShadow = clamp(sqrt(outShadow), 0.0, 1.0);
color += frameColor.rgb * outShadow;
alpha = sum2(1.0 - smoothstep(vec2(0.0), aadelta, coords) + smoothstep(vec2(1.0) - aadelta, vec2(1.0), coords));
alpha = clamp(alpha, 0.0, 1.0) * mix(1.0, 0.9, outShadow);
float inShadow = 1.0 - prod2(smoothstep(0.0, inShadowLength, coords) - smoothstep(1.0 - inShadowLength, 1.0, coords));
inShadow = 0.5 * inShadow * inShadow;
alpha = max(alpha, inShadow);
gl_FragColor = vec4(color * alpha, alpha);
}
"
onStatusChanged: if (log) console.log(log) //Print warning messages
}

View File

@@ -34,7 +34,6 @@ Item{
property ShaderEffectSource mainSource: kterminalSource property ShaderEffectSource mainSource: kterminalSource
property BurnInEffect burnInEffect: burnInEffect property BurnInEffect burnInEffect: burnInEffect
property SlowBurnIn slowBurnInEffect: slowBurnInEffect
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
@@ -45,35 +44,61 @@ Item{
property size fontMetrics: kterminal.fontMetrics property size fontMetrics: kterminal.fontMetrics
// Manage copy and paste // Manage copy and paste
Connections{ Connections {
target: copyAction target: copyAction
onTriggered: kterminal.copyClipboard();
onTriggered: {
kterminal.copyClipboard()
}
} }
Connections{ Connections {
target: pasteAction target: pasteAction
onTriggered: kterminal.pasteClipboard()
onTriggered: {
kterminal.pasteClipboard()
}
} }
//When settings are updated sources need to be redrawn. //When settings are updated sources need to be redrawn.
Connections{ Connections {
target: appSettings target: appSettings
onFontScalingChanged: terminalContainer.updateSources();
onFontWidthChanged: terminalContainer.updateSources(); onFontScalingChanged: {
terminalContainer.updateSources()
}
onFontWidthChanged: {
terminalContainer.updateSources()
}
} }
Connections{ Connections {
target: terminalContainer target: terminalContainer
onWidthChanged: terminalContainer.updateSources();
onHeightChanged: terminalContainer.updateSources(); onWidthChanged: {
terminalContainer.updateSources()
}
onHeightChanged: {
terminalContainer.updateSources()
}
} }
Connections {
target: terminalWindow
onActiveChanged: {
kterminal.forceActiveFocus()
}
}
function updateSources() { function updateSources() {
kterminal.update(); kterminal.update()
} }
QMLTermWidget { QMLTermWidget {
id: kterminal id: kterminal
property int textureResolutionScale: appSettings.lowResolutionFont ? devicePixelRatio : 1 property int textureResolutionScale: appSettings.lowResolutionFont ? devicePixelRatio : 1
property int margin: appSettings.margin / screenScaling property int margin: appSettings.totalMargin / screenScaling
property int totalWidth: Math.floor(parent.width / (screenScaling * fontWidth)) property int totalWidth: Math.floor(parent.width / (screenScaling * fontWidth))
property int totalHeight: Math.floor(parent.height / screenScaling) property int totalHeight: Math.floor(parent.height / screenScaling)
@@ -143,7 +168,7 @@ Item{
var args = Utils.tokenizeCommandLine(appSettings.customCommand); var args = Utils.tokenizeCommandLine(appSettings.customCommand);
ksession.setShellProgram(args[0]); ksession.setShellProgram(args[0]);
ksession.setArgs(args.slice(1)); ksession.setArgs(args.slice(1));
} else if (!defaultCmd && Qt.platform.os === "osx") { } else if (!defaultCmd && appSettings.isMacOS) {
// OSX Requires the following default parameters for auto login. // OSX Requires the following default parameters for auto login.
ksession.setArgs(["-i", "-l"]); ksession.setArgs(["-i", "-l"]);
} }
@@ -173,41 +198,41 @@ Item{
Loader { Loader {
id: menuLoader id: menuLoader
sourceComponent: (Qt.platform.os === "osx" || appSettings.showMenubar ? shortContextMenu : fullContextMenu) sourceComponent: (appSettings.isMacOS || appSettings.showMenubar ? shortContextMenu : fullContextMenu)
} }
property alias contextmenu: menuLoader.item property alias contextmenu: menuLoader.item
MouseArea{ MouseArea {
property real margin: appSettings.margin property real margin: appSettings.totalMargin
acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton acceptedButtons: Qt.LeftButton | Qt.MiddleButton | Qt.RightButton
anchors.fill: parent anchors.fill: parent
cursorShape: kterminal.terminalUsesMouse ? Qt.ArrowCursor : Qt.IBeamCursor cursorShape: kterminal.terminalUsesMouse ? Qt.ArrowCursor : Qt.IBeamCursor
onWheel:{ onWheel: function(wheel) {
if(wheel.modifiers & Qt.ControlModifier){ if (wheel.modifiers & Qt.ControlModifier) {
wheel.angleDelta.y > 0 ? zoomIn.trigger() : zoomOut.trigger(); wheel.angleDelta.y > 0 ? zoomIn.trigger() : zoomOut.trigger();
} else { } else {
var coord = correctDistortion(wheel.x, wheel.y); var coord = correctDistortion(wheel.x, wheel.y);
kterminal.simulateWheel(coord.x, coord.y, wheel.buttons, wheel.modifiers, wheel.angleDelta); kterminal.simulateWheel(coord.x, coord.y, wheel.buttons, wheel.modifiers, wheel.angleDelta);
} }
} }
onDoubleClicked: { onDoubleClicked: function(mouse) {
var coord = correctDistortion(mouse.x, mouse.y); var coord = correctDistortion(mouse.x, mouse.y);
kterminal.simulateMouseDoubleClick(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers); kterminal.simulateMouseDoubleClick(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers);
} }
onPressed: { onPressed: function(mouse) {
if((!kterminal.terminalUsesMouse || mouse.modifiers & Qt.ShiftModifier) && mouse.button == Qt.RightButton) { if ((!kterminal.terminalUsesMouse || mouse.modifiers & Qt.ShiftModifier) && mouse.button == Qt.RightButton) {
contextmenu.popup(); contextmenu.popup();
} else { } else {
var coord = correctDistortion(mouse.x, mouse.y); var coord = correctDistortion(mouse.x, mouse.y);
kterminal.simulateMousePress(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers) kterminal.simulateMousePress(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers)
} }
} }
onReleased: { onReleased: function(mouse) {
var coord = correctDistortion(mouse.x, mouse.y); var coord = correctDistortion(mouse.x, mouse.y);
kterminal.simulateMouseRelease(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers); kterminal.simulateMouseRelease(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers);
} }
onPositionChanged: { onPositionChanged: function(mouse) {
var coord = correctDistortion(mouse.x, mouse.y); var coord = correctDistortion(mouse.x, mouse.y);
kterminal.simulateMouseMove(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers); kterminal.simulateMouseMove(coord.x, coord.y, mouse.button, mouse.buttons, mouse.modifiers);
} }
@@ -219,8 +244,8 @@ Item{
var cc = Qt.size(0.5 - x, 0.5 - y); var cc = Qt.size(0.5 - x, 0.5 - y);
var distortion = (cc.height * cc.height + cc.width * cc.width) * appSettings.screenCurvature * appSettings.screenCurvatureSize; var distortion = (cc.height * cc.height + cc.width * cc.width) * appSettings.screenCurvature * appSettings.screenCurvatureSize;
return Qt.point((x - cc.width * (1+distortion) * distortion) * kterminal.totalWidth, return Qt.point((x - cc.width * (1+distortion) * distortion) * (kterminal.totalWidth),
(y - cc.height * (1+distortion) * distortion) * kterminal.totalHeight) (y - cc.height * (1+distortion) * distortion) * (kterminal.totalHeight))
} }
} }
ShaderEffectSource{ ShaderEffectSource{
@@ -250,9 +275,5 @@ Item{
BurnInEffect { BurnInEffect {
id: burnInEffect id: burnInEffect
} }
SlowBurnIn {
id: slowBurnInEffect
}
} }
} }

View File

@@ -73,24 +73,17 @@ ColumnLayout {
Slider { Slider {
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: 2 Layout.columnSpan: 2
id: fpsSlider id: effectsFpsSlider
onValueChanged: { onValueChanged: appSettings.effectsFrameSkip = Math.round(value)
if (enabled) {
appSettings.fps = value !== 60 ? value + 1 : 0
}
}
stepSize: 1 stepSize: 1
enabled: false enabled: true
Component.onCompleted: { from: 5
from = 0 to: 1
to = 60 value: appSettings.effectsFrameSkip
value = appSettings.fps !== 0 ? appSettings.fps - 1 : 60
enabled = true
}
} }
Label { SizedLabel {
text: appSettings.fps !== 0 ? appSettings.fps : qsTr("Max") text: Math.round(100 / Math.max(1, Math.round(effectsFpsSlider.value))) + "%"
} }
Label { Label {
text: qsTr("Texture Quality") text: qsTr("Texture Quality")
@@ -99,17 +92,13 @@ ColumnLayout {
id: txtslider id: txtslider
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: 2 Layout.columnSpan: 2
onValueChanged: if (enabled) onValueChanged: appSettings.windowScaling = value
appSettings.windowScaling = value
stepSize: 0.05 stepSize: 0.05
enabled: false enabled: true
Component.onCompleted: { from: 0.25
from = 0.25 //Without this value gets set to 0.5 value: appSettings.windowScaling
value = appSettings.windowScaling
enabled = true
}
} }
Label { SizedLabel {
text: Math.round(txtslider.value * 100) + "%" text: Math.round(txtslider.value * 100) + "%"
} }
@@ -120,17 +109,13 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.columnSpan: 2 Layout.columnSpan: 2
id: bloomSlider id: bloomSlider
onValueChanged: if (enabled) onValueChanged: appSettings.bloomQuality = value
appSettings.bloomQuality = value
stepSize: 0.05 stepSize: 0.05
enabled: false enabled: true
Component.onCompleted: { from: 0.25
from = 0.25 value: appSettings.bloomQuality
value = appSettings.bloomQuality
enabled = true
}
} }
Label { SizedLabel {
text: Math.round(bloomSlider.value * 100) + "%" text: Math.round(bloomSlider.value * 100) + "%"
} }
@@ -141,25 +126,15 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
id: burnInSlider id: burnInSlider
Layout.columnSpan: 2 Layout.columnSpan: 2
onValueChanged: if (enabled) onValueChanged: appSettings.burnInQuality = value
appSettings.burnInQuality = value
stepSize: 0.05 stepSize: 0.05
enabled: false enabled: true
Component.onCompleted: { from: 0.25
from = 0.25 value: appSettings.burnInQuality
value = appSettings.burnInQuality
enabled = true
}
} }
Label { SizedLabel {
text: Math.round(burnInSlider.value * 100) + "%" text: Math.round(burnInSlider.value * 100) + "%"
} }
CheckBox {
Layout.columnSpan: 2
text: qsTr("Burnin optimization (Might display timing artifacts)")
checked: appSettings.useFastBurnIn
onCheckedChanged: appSettings.useFastBurnIn = checked
}
} }
} }
} }

View File

@@ -33,53 +33,53 @@ ColumnLayout {
CheckableSlider { CheckableSlider {
name: qsTr("Bloom") name: qsTr("Bloom")
onNewValue: appSettings.bloom = newValue onNewValue: function(newValue) { appSettings.bloom = newValue }
value: appSettings.bloom value: appSettings.bloom
} }
CheckableSlider { CheckableSlider {
name: qsTr("BurnIn") name: qsTr("BurnIn")
onNewValue: appSettings.burnIn = newValue onNewValue: function(newValue) { appSettings.burnIn = newValue }
value: appSettings.burnIn value: appSettings.burnIn
} }
CheckableSlider { CheckableSlider {
name: qsTr("Static Noise") name: qsTr("Static Noise")
onNewValue: appSettings.staticNoise = newValue onNewValue: function(newValue) { appSettings.staticNoise = newValue }
value: appSettings.staticNoise value: appSettings.staticNoise
} }
CheckableSlider { CheckableSlider {
name: qsTr("Jitter") name: qsTr("Jitter")
onNewValue: appSettings.jitter = newValue onNewValue: function(newValue) { appSettings.jitter = newValue }
value: appSettings.jitter value: appSettings.jitter
} }
CheckableSlider { CheckableSlider {
name: qsTr("Glow Line") name: qsTr("Glow Line")
onNewValue: appSettings.glowingLine = newValue onNewValue: function(newValue) { appSettings.glowingLine = newValue }
value: appSettings.glowingLine value: appSettings.glowingLine
} }
CheckableSlider { CheckableSlider {
name: qsTr("Screen Curvature") name: qsTr("Screen Curvature")
onNewValue: appSettings.screenCurvature = newValue onNewValue: function(newValue) { appSettings.screenCurvature = newValue }
value: appSettings.screenCurvature value: appSettings.screenCurvature
} }
CheckableSlider { CheckableSlider {
name: qsTr("Ambient Light") name: qsTr("Ambient Light")
onNewValue: appSettings.ambientLight = newValue onNewValue: function(newValue) { appSettings.ambientLight = newValue }
value: appSettings.ambientLight value: appSettings.ambientLight
enabled: appSettings.framesIndex !== 0 enabled: appSettings.framesIndex !== 0
} }
CheckableSlider { CheckableSlider {
name: qsTr("Flickering") name: qsTr("Flickering")
onNewValue: appSettings.flickering = newValue onNewValue: function(newValue) { appSettings.flickering = newValue }
value: appSettings.flickering value: appSettings.flickering
} }
CheckableSlider { CheckableSlider {
name: qsTr("Horizontal Sync") name: qsTr("Horizontal Sync")
onNewValue: appSettings.horizontalSync = newValue onNewValue: function(newValue) { appSettings.horizontalSync = newValue }
value: appSettings.horizontalSync value: appSettings.horizontalSync
} }
CheckableSlider { CheckableSlider {
name: qsTr("RGB Shift") name: qsTr("RGB Shift")
onNewValue: appSettings.rbgShift = newValue onNewValue: function(newValue) { appSettings.rbgShift = newValue }
value: appSettings.rbgShift value: appSettings.rbgShift
} }
} }

View File

@@ -20,7 +20,7 @@
import QtQuick 2.2 import QtQuick 2.2
import QtQuick.Controls 2.4 import QtQuick.Controls 2.4
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs
ColumnLayout { ColumnLayout {
GroupBox { GroupBox {
@@ -33,6 +33,7 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
Layout.fillHeight: true Layout.fillHeight: true
model: appSettings.profilesList model: appSettings.profilesList
clip: true
delegate: Rectangle { delegate: Rectangle {
width: label.width width: label.width
height: label.height height: label.height
@@ -206,12 +207,21 @@ ColumnLayout {
onValueChanged: appSettings._margin = value onValueChanged: appSettings._margin = value
value: appSettings._margin value: appSettings._margin
} }
Label {
text: qsTr("Frame size")
}
SimpleSlider {
onValueChanged: appSettings._frameMargin = value
value: appSettings._frameMargin
}
Label { Label {
text: qsTr("Opacity") text: qsTr("Opacity")
visible: !appSettings.isMacOS
} }
SimpleSlider { SimpleSlider {
onValueChanged: appSettings.windowOpacity = value onValueChanged: appSettings.windowOpacity = value
value: appSettings.windowOpacity value: appSettings.windowOpacity
visible: !appSettings.isMacOS
} }
} }
} }
@@ -227,6 +237,7 @@ ColumnLayout {
MessageDialog { MessageDialog {
id: messageDialog id: messageDialog
title: qsTr("File Error") title: qsTr("File Error")
buttons: MessageDialog.Ok
onAccepted: { onAccepted: {
messageDialog.close() messageDialog.close()
} }
@@ -238,10 +249,8 @@ ColumnLayout {
sourceComponent: FileDialog { sourceComponent: FileDialog {
nameFilters: ["Json files (*.json)"] nameFilters: ["Json files (*.json)"]
selectMultiple: false fileMode: fileDialog.selectExisting ? FileDialog.OpenFile : FileDialog.SaveFile
selectFolder: false onAccepted: callBack(selectedFile)
selectExisting: fileDialog.selectExisting
onAccepted: callBack(fileUrl)
} }
onSelectExistingChanged: reload() onSelectExistingChanged: reload()

View File

@@ -41,7 +41,7 @@ ColumnLayout {
property string selectedElement: model[currentIndex] property string selectedElement: model[currentIndex]
Layout.fillWidth: true Layout.fillWidth: true
model: [qsTr("Default"), qsTr("Scanlines"), qsTr("Pixels")] model: [qsTr("Default"), qsTr("Scanlines"), qsTr("Pixels"), qsTr("Sub-Pixels")]
currentIndex: appSettings.rasterization currentIndex: appSettings.rasterization
onCurrentIndexChanged: { onCurrentIndexChanged: {
appSettings.rasterization = currentIndex appSettings.rasterization = currentIndex
@@ -68,7 +68,10 @@ ColumnLayout {
} }
Connections { Connections {
target: appSettings target: appSettings
onTerminalFontChanged: fontChanger.updateIndex()
onTerminalFontChanged: {
fontChanger.updateIndex()
}
} }
Component.onCompleted: updateIndex() Component.onCompleted: updateIndex()
} }
@@ -137,12 +140,12 @@ ColumnLayout {
Layout.fillWidth: true Layout.fillWidth: true
CheckableSlider { CheckableSlider {
name: qsTr("Chroma Color") name: qsTr("Chroma Color")
onNewValue: appSettings.chromaColor = newValue onNewValue: function(newValue) { appSettings.chromaColor = newValue }
value: appSettings.chromaColor value: appSettings.chromaColor
} }
CheckableSlider { CheckableSlider {
name: qsTr("Saturation Color") name: qsTr("Saturation Color")
onNewValue: appSettings.saturationColor = newValue onNewValue: function(newValue) { appSettings.saturationColor = newValue }
value: appSettings.saturationColor value: appSettings.saturationColor
enabled: appSettings.chromaColor !== 0 enabled: appSettings.chromaColor !== 0
} }

View File

@@ -22,47 +22,54 @@ import QtQuick 2.2
import QtQuick.Controls 2.1 import QtQuick.Controls 2.1
import QtQuick.Window 2.1 import QtQuick.Window 2.1
import QtQuick.Layouts 1.3 import QtQuick.Layouts 1.3
import QtQuick.Dialogs 1.1 import QtQuick.Dialogs
Window { Window {
id: settings_window id: settings_window
title: qsTr("Settings") title: qsTr("Settings")
width: 800 width: 640
height: 600 height: 640
property int tabmargins: 15 property int tabmargins: 15
TabBar { Item {
id: bar anchors { fill: parent; margins: tabmargins }
width: parent.width
TabButton {
text: qsTr("General")
}
TabButton {
text: qsTr("Terminal")
}
TabButton {
text: qsTr("Effects")
}
TabButton {
text: qsTr("Advanced")
}
}
StackLayout { TabBar {
anchors { id: bar
top: bar.bottom anchors { left: parent.left; right: parent.right; top: parent.top; }
left: parent.left TabButton {
right: parent.right text: qsTr("General")
bottom: parent.bottom }
margins: tabmargins TabButton {
text: qsTr("Terminal")
}
TabButton {
text: qsTr("Effects")
}
TabButton {
text: qsTr("Advanced")
}
} }
currentIndex: bar.currentIndex Frame {
anchors {
top: bar.bottom
left: parent.left
right: parent.right
bottom: parent.bottom
}
SettingsGeneralTab { } StackLayout {
SettingsTerminalTab { } anchors.fill: parent
SettingsEffectsTab { }
SettingsAdvancedTab { } currentIndex: bar.currentIndex
SettingsGeneralTab { }
SettingsTerminalTab { }
SettingsEffectsTab { }
SettingsAdvancedTab { }
}
}
} }
} }

91
app/qml/ShaderLibrary.qml Normal file
View File

@@ -0,0 +1,91 @@
import QtQuick 2.0
QtObject {
property string rasterizationShader:
(appSettings.rasterization === appSettings.no_rasterization ? "
lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) {
return texel;
}" : "") +
(appSettings.rasterization === appSettings.scanline_rasterization ? "
#define INTENSITY 0.30
#define BRIGHTBOOST 0.30
lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) {
lowp vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel;
lowp vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel;
vec2 coords = fract(screenCoords * virtualResolution) * 2.0 - vec2(1.0);
lowp float mask = 1.0 - abs(coords.y);
lowp vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask);
return mix(texel, rasterizationColor, intensity);
}" : "") +
(appSettings.rasterization === appSettings.pixel_rasterization ? "
#define INTENSITY 0.30
#define BRIGHTBOOST 0.30
lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) {
lowp vec3 result = texel;
lowp vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel;
lowp vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel;
vec2 coords = fract(screenCoords * virtualResolution) * 2.0 - vec2(1.0);
coords = coords * coords;
lowp float mask = 1.0 - coords.x - coords.y;
lowp vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask);
return mix(texel, rasterizationColor, intensity);
}" : "") +
(appSettings.rasterization === appSettings.subpixel_rasterization ? "
#define INTENSITY 0.30
#define BRIGHTBOOST 0.30
#define SUBPIXELS 3.0
const vec3 offsets = vec3(3.141592654) * vec3(1.0/2.0,1.0/2.0 - 2.0/3.0,1.0/2.0-4.0/3.0);
lowp vec3 applyRasterization(vec2 screenCoords, lowp vec3 texel, vec2 virtualResolution, float intensity) {
vec2 omega = vec2(3.141592654) * vec2(2.0) * virtualResolution;
vec2 angle = screenCoords * omega;
vec3 xfactors = (SUBPIXELS + sin(angle.x + offsets)) / (SUBPIXELS + 1.0);
lowp vec3 result = texel * xfactors;
lowp vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * result)) * result;
lowp vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * result)) * result;
vec2 coords = fract(screenCoords * virtualResolution) * 2.0 - vec2(1.0);
lowp float mask = 1.0 - abs(coords.y);
lowp vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask);
return mix(texel, rasterizationColor, intensity);
}" : "") +
"\n\n"
property string min2: "
float min2(vec2 v) {
return min(v.x, v.y);
}\n\n"
property string rgb2grey: "
float rgb2grey(vec3 v) {
return dot(v, vec3(0.21, 0.72, 0.04));
}\n\n"
property string max2: "
float max2(vec2 v) {
return max(v.x, v.y);
}\n\n"
property string prod2: "
float prod2(vec2 v) {
return v.x * v.y;
}\n\n"
property string sum2: "
float sum2(vec2 v) {
return v.x + v.y;
}\n\n"
}

View File

@@ -19,12 +19,10 @@
*******************************************************************************/ *******************************************************************************/
import QtQuick 2.2 import QtQuick 2.2
import QtGraphicalEffects 1.0
import "utils.js" as Utils import "utils.js" as Utils
Item { Item {
property SlowBurnIn slowBurnInEffect
property ShaderEffectSource source property ShaderEffectSource source
property BurnInEffect burnInEffect property BurnInEffect burnInEffect
property ShaderEffectSource bloomSource property ShaderEffectSource bloomSource
@@ -38,498 +36,182 @@ Item {
property real ambientLight: appSettings.ambientLight * 0.2 property real ambientLight: appSettings.ambientLight * 0.2
property size virtual_resolution property size virtualResolution
property size screenResolution
ShaderEffect {
id: dynamicShader property real _screenDensity: Math.min(
screenResolution.width / virtualResolution.width,
property ShaderEffectSource screenBuffer: frameBuffer screenResolution.height / virtualResolution.height
property ShaderEffectSource burnInSource: burnInEffect.source )
property ShaderEffectSource frameSource: terminalFrameLoader.item
ShaderEffect {
property color fontColor: parent.fontColor id: dynamicShader
property color backgroundColor: parent.backgroundColor
property real screenCurvature: parent.screenCurvature property ShaderEffectSource screenBuffer: frameBuffer
property real chromaColor: parent.chromaColor property ShaderEffectSource burnInSource: burnInEffect.source
property real ambientLight: parent.ambientLight property ShaderEffectSource frameSource: terminalFrameLoader.item
property real flickering: appSettings.flickering property color fontColor: parent.fontColor
property real horizontalSync: appSettings.horizontalSync property color backgroundColor: parent.backgroundColor
property real horizontalSyncStrength: Utils.lint(0.05, 0.35, horizontalSync) property real screenCurvature: parent.screenCurvature
property real glowingLine: appSettings.glowingLine * 0.2 property real chromaColor: parent.chromaColor
property real ambientLight: parent.ambientLight
// Fast burnin properties
property real burnIn: appSettings.useFastBurnIn ? appSettings.burnIn : 0 property real flickering: appSettings.flickering
property real burnInLastUpdate: burnInEffect.lastUpdate property real horizontalSync: appSettings.horizontalSync
property real burnInTime: burnInEffect.burnInFadeTime property real horizontalSyncStrength: Utils.lint(0.05, 0.35, horizontalSync)
property real glowingLine: appSettings.glowingLine * 0.2
// Slow burnin properties
property real slowBurnIn: appSettings.useFastBurnIn ? 0 : appSettings.burnIn // Fast burnin properties
property ShaderEffectSource slowBurnInSource: slowBurnInEffect.source property real burnIn: appSettings.burnIn
property real burnInLastUpdate: burnInEffect.lastUpdate
property real jitter: appSettings.jitter property real burnInTime: burnInEffect.burnInFadeTime
property size jitterDisplacement: Qt.size(0.007 * jitter, 0.002 * jitter)
property real shadowLength: 0.25 * screenCurvature * Utils.lint(0.50, 1.5, ambientLight) property real jitter: appSettings.jitter
property real staticNoise: appSettings.staticNoise property size jitterDisplacement: Qt.size(0.007 * jitter, 0.002 * jitter)
property size scaleNoiseSize: Qt.size((width) / (noiseTexture.width * appSettings.windowScaling * appSettings.totalFontScaling), property real shadowLength: 0.25 * screenCurvature * Utils.lint(0.50, 1.5, ambientLight)
(height) / (noiseTexture.height * appSettings.windowScaling * appSettings.totalFontScaling)) property real staticNoise: appSettings.staticNoise
property size scaleNoiseSize: Qt.size((width * 0.75) / (noiseTexture.width * appSettings.windowScaling * appSettings.totalFontScaling),
property size virtual_resolution: parent.virtual_resolution (height * 0.75) / (noiseTexture.height * appSettings.windowScaling * appSettings.totalFontScaling))
property real time: timeManager.time
property ShaderEffectSource noiseSource: noiseShaderSource
// If something goes wrong activate the fallback version of the shader.
property bool fallBack: false
anchors.fill: parent
blending: false
//Smooth random texture used for flickering effect.
Image {
id: noiseTexture
source: "images/allNoise512.png"
width: 512
height: 512
fillMode: Image.Tile
visible: false
}
ShaderEffectSource {
id: noiseShaderSource
sourceItem: noiseTexture
wrapMode: ShaderEffectSource.Repeat
visible: false
smooth: true
}
//Print the number with a reasonable precision for the shader.
function str(num){
return num.toFixed(8);
}
vertexShader: "
uniform highp mat4 qt_Matrix;
uniform highp float time;
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 qt_TexCoord0;" +
(!fallBack ? "
uniform sampler2D noiseSource;" : "") +
(!fallBack && flickering !== 0.0 ?"
varying lowp float brightness;
uniform lowp float flickering;" : "") +
(!fallBack && horizontalSync !== 0.0 ?"
uniform lowp float horizontalSyncStrength;
varying lowp float distortionScale;
varying lowp float distortionFreq;" : "") +
"
void main() {
qt_TexCoord0 = qt_MultiTexCoord0;
vec2 coords = vec2(fract(time/(1024.0*2.0)), fract(time/(1024.0*1024.0)));" +
(!fallBack && (flickering !== 0.0 || horizontalSync !== 0.0) ?
"vec4 initialNoiseTexel = texture2D(noiseSource, coords);"
: "") +
(!fallBack && flickering !== 0.0 ? "
brightness = 1.0 + (initialNoiseTexel.g - 0.5) * flickering;"
: "") +
(!fallBack && horizontalSync !== 0.0 ? "
float randval = horizontalSyncStrength - initialNoiseTexel.r;
distortionScale = step(0.0, randval) * randval * horizontalSyncStrength;
distortionFreq = mix(4.0, 40.0, initialNoiseTexel.g);"
: "") +
"gl_Position = qt_Matrix * qt_Vertex;
}"
fragmentShader: "
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D screenBuffer;
uniform highp float qt_Opacity;
uniform highp float time;
varying highp vec2 qt_TexCoord0;
uniform highp vec4 fontColor;
uniform highp vec4 backgroundColor;
uniform lowp float shadowLength;
uniform highp vec2 virtual_resolution;" +
(burnIn !== 0 ? "
uniform sampler2D burnInSource;
uniform highp float burnInLastUpdate;
uniform highp float burnInTime;" : "") +
(slowBurnIn !== 0 ? "
uniform sampler2D slowBurnInSource;" : "") +
(staticNoise !== 0 ? "
uniform highp float staticNoise;" : "") +
(((staticNoise !== 0 || jitter !== 0)
||(fallBack && (flickering || horizontalSync))) ? "
uniform lowp sampler2D noiseSource;
uniform highp vec2 scaleNoiseSize;" : "") +
(screenCurvature !== 0 ? "
uniform highp float screenCurvature;
uniform lowp sampler2D frameSource;" : "") +
(glowingLine !== 0 ? "
uniform highp float glowingLine;" : "") +
(chromaColor !== 0 ? "
uniform lowp float chromaColor;" : "") +
(jitter !== 0 ? "
uniform lowp vec2 jitterDisplacement;" : "") +
(ambientLight !== 0 ? "
uniform lowp float ambientLight;" : "") +
(fallBack && horizontalSync !== 0 ? "
uniform lowp float horizontalSyncStrength;" : "") +
(fallBack && flickering !== 0.0 ?"
uniform lowp float flickering;" : "") +
(!fallBack && flickering !== 0 ? "
varying lowp float brightness;"
: "") +
(!fallBack && horizontalSync !== 0 ? "
varying lowp float distortionScale;
varying lowp float distortionFreq;" : "") +
(glowingLine !== 0 ? "
float randomPass(vec2 coords){
return fract(smoothstep(-120.0, 0.0, coords.y - (virtual_resolution.y + 120.0) * fract(time * 0.00015)));
}" : "") +
"float min2(vec2 v) {
return min(v.x, v.y);
}
float rgb2grey(vec3 v){
return dot(v, vec3(0.21, 0.72, 0.04));
}
float isInScreen(vec2 v) {
return min2(step(0.0, v) - step(1.0, v));
}
vec2 barrel(vec2 v, vec2 cc) {" +
(screenCurvature !== 0 ? "
float distortion = dot(cc, cc) * screenCurvature;
return (v - cc * (1.0 + distortion) * distortion);"
:
"return v;") +
"}" +
"vec3 convertWithChroma(vec3 inColor) {
vec3 outColor = inColor;" +
(chromaColor !== 0 ?
"outColor = fontColor.rgb * mix(vec3(rgb2grey(inColor)), inColor, chromaColor);"
:
"outColor = fontColor.rgb * rgb2grey(inColor);") +
" return outColor;
}" +
"void main() {" +
"vec2 cc = vec2(0.5) - qt_TexCoord0;" +
"float distance = length(cc);" +
//FallBack if there are problems
(fallBack && (flickering !== 0.0 || horizontalSync !== 0.0) ?
"vec2 initialCoords = vec2(fract(time/(1024.0*2.0)), fract(time/(1024.0*1024.0)));
vec4 initialNoiseTexel = texture2D(noiseSource, initialCoords);"
: "") +
(fallBack && flickering !== 0.0 ? "
float brightness = 1.0 + (initialNoiseTexel.g - 0.5) * flickering;"
: "") +
(fallBack && horizontalSync !== 0.0 ? "
float randval = horizontalSyncStrength - initialNoiseTexel.r;
float distortionScale = step(0.0, randval) * randval * horizontalSyncStrength;
float distortionFreq = mix(4.0, 40.0, initialNoiseTexel.g);"
: "") +
(staticNoise ? "
float noise = staticNoise;" : "") +
(screenCurvature !== 0 ? "
vec2 staticCoords = barrel(qt_TexCoord0, cc);"
:"
vec2 staticCoords = qt_TexCoord0;") +
"vec2 coords = qt_TexCoord0;" +
(horizontalSync !== 0 ? "
float dst = sin((coords.y + time * 0.001) * distortionFreq);
coords.x += dst * distortionScale;" +
(staticNoise ? "
noise += distortionScale * 7.0;" : "")
: "") +
(jitter !== 0 || staticNoise !== 0 ?
"vec4 noiseTexel = texture2D(noiseSource, scaleNoiseSize * coords + vec2(fract(time / 51.0), fract(time / 237.0)));"
: "") +
(jitter !== 0 ? "
vec2 offset = vec2(noiseTexel.b, noiseTexel.a) - vec2(0.5);
vec2 txt_coords = coords + offset * jitterDisplacement;"
: "vec2 txt_coords = coords;") +
"float color = 0.0001;" + property size virtualResolution: parent.virtualResolution
(staticNoise !== 0 ? " // Rasterization might display oversamping issues if virtual resolution is close to physical display resolution.
float noiseVal = noiseTexel.a; // We progressively disable rasterization from 4x up to 2x resolution.
color += noiseVal * noise * (1.0 - distance * 1.3);" : "") + property real rasterizationIntensity: Utils.smoothstep(2.0, 4.0, _screenDensity)
property int rasterizationMode: appSettings.rasterization
(glowingLine !== 0 ? "
color += randomPass(coords * virtual_resolution) * glowingLine;" : "") + property real displayTerminalFrame: appSettings._frameMargin > 0 || appSettings.screenCurvature > 0
"vec3 txt_color = texture2D(screenBuffer, txt_coords).rgb;" + property real time: timeManager.time
property ShaderEffectSource noiseSource: noiseShaderSource
(burnIn !== 0 ? "
vec4 txt_blur = texture2D(burnInSource, staticCoords); // Extra uniforms expected by the shared uniform block
float blurDecay = clamp((time - burnInLastUpdate) * burnInTime, 0.0, 1.0); property real screenShadowCoeff: 0
vec3 burnInColor = 0.65 * (txt_blur.rgb - vec3(blurDecay)); property real frameShadowCoeff: 0
txt_color = max(txt_color, convertWithChroma(burnInColor));" property color frameColor: backgroundColor
: "") + property size margin: Qt.size(0, 0)
property real prevLastUpdate: burnInEffect.prevLastUpdate
(slowBurnIn !== 0 ? " property real screen_brightness: Utils.lint(0.5, 1.5, appSettings.brightness)
vec4 txt_blur = texture2D(slowBurnInSource, staticCoords); property real bloom: appSettings.bloom
txt_color = max(txt_color, convertWithChroma(txt_blur.rgb * txt_blur.a)); property real rbgShift: (appSettings.rbgShift / Math.max(width, 1)) * appSettings.totalFontScaling
" : "") +
anchors.fill: parent
"txt_color += fontColor.rgb * vec3(color);" + blending: false
"vec3 finalColor = txt_color;" + Image {
id: noiseTexture
(flickering !== 0 ? " source: "images/allNoise512.png"
finalColor *= brightness;" : "") + width: 512
height: 512
(ambientLight !== 0 ? " fillMode: Image.Tile
finalColor += vec3(ambientLight) * (1.0 - distance) * (1.0 - distance);" : "") + visible: false
}
(screenCurvature !== 0 ? ShaderEffectSource {
"vec4 frameColor = texture2D(frameSource, qt_TexCoord0); id: noiseShaderSource
finalColor = mix(finalColor, frameColor.rgb, frameColor.a);" sourceItem: noiseTexture
: "") + wrapMode: ShaderEffectSource.Repeat
visible: false
"gl_FragColor = vec4(finalColor, qt_Opacity);" + smooth: true
"}" }
onStatusChanged: { vertexShader: "qrc:/shaders/terminal_dynamic.vert.qsb"
// Print warning messages fragmentShader: "qrc:/shaders/terminal_dynamic.frag.qsb"
if (log)
console.log(log); onStatusChanged: if (log) console.log(log)
}
// Activate fallback mode
if (status == ShaderEffect.Error) { Loader {
fallBack = true; id: terminalFrameLoader
}
} active: dynamicShader.displayTerminalFrame
}
width: staticShader.width
Loader { height: staticShader.height
id: terminalFrameLoader
sourceComponent: ShaderEffectSource {
active: screenCurvature !== 0
sourceItem: terminalFrame
width: staticShader.width hideSource: true
height: staticShader.height visible: false
format: ShaderEffectSource.RGBA
sourceComponent: ShaderEffectSource {
TerminalFrame {
sourceItem: terminalFrame id: terminalFrame
hideSource: true blending: false
visible: false anchors.fill: parent
format: ShaderEffectSource.RGBA }
}
NewTerminalFrame { }
id: terminalFrame
blending: false ShaderLibrary {
anchors.fill: parent id: shaderLibrary
} }
}
} ShaderEffect {
id: staticShader
ShaderEffect {
id: staticShader width: parent.width * appSettings.windowScaling
height: parent.height * appSettings.windowScaling
width: parent.width * appSettings.windowScaling
height: parent.height * appSettings.windowScaling property ShaderEffectSource source: parent.source
property ShaderEffectSource bloomSource: parent.bloomSource
property ShaderEffectSource source: parent.source
property ShaderEffectSource bloomSource: parent.bloomSource property color fontColor: parent.fontColor
property color backgroundColor: parent.backgroundColor
property color fontColor: parent.fontColor property real bloom: bloomSource ? appSettings.bloom * 2.5 : 0
property color backgroundColor: parent.backgroundColor
property real bloom: appSettings.bloom * 2.5 property real screenCurvature: parent.screenCurvature
property real screenCurvature: parent.screenCurvature property real chromaColor: appSettings.chromaColor;
property real chromaColor: appSettings.chromaColor; property real rbgShift: (appSettings.rbgShift / width) * appSettings.totalFontScaling
property real rbgShift: (appSettings.rbgShift / width) * appSettings.totalFontScaling // TODO FILIPPO width here is wrong. property int rasterization: appSettings.rasterization
property int rasterization: appSettings.rasterization property real screen_brightness: Utils.lint(0.5, 1.5, appSettings.brightness)
property real screen_brightness: Utils.lint(0.5, 1.5, appSettings.brightness) property real ambientLight: parent.ambientLight
property real ambientLight: parent.ambientLight property size virtualResolution: parent.virtualResolution
property size virtual_resolution: parent.virtual_resolution // Extra uniforms to match shared uniform block
property real time: timeManager.time
blending: false property real shadowLength: 0
visible: false property real rasterizationIntensity: Utils.smoothstep(2.0, 4.0, _screenDensity)
property int rasterizationMode: appSettings.rasterization
//Print the number with a reasonable precision for the shader. property real burnInLastUpdate: burnInEffect.lastUpdate
function str(num){ property real burnInTime: burnInEffect.burnInFadeTime
return num.toFixed(8); property real burnIn: appSettings.burnIn
} property real staticNoise: appSettings.staticNoise
property real glowingLine: appSettings.glowingLine * 0.2
fragmentShader: " property size jitterDisplacement: Qt.size(0, 0)
#ifdef GL_ES property real jitter: appSettings.jitter
precision mediump float; property real horizontalSync: appSettings.horizontalSync
#endif property real horizontalSyncStrength: Utils.lint(0.05, 0.35, horizontalSync)
property real flickering: appSettings.flickering
uniform sampler2D source; property real displayTerminalFrame: dynamicShader.displayTerminalFrame
uniform highp float qt_Opacity; property size scaleNoiseSize: Qt.size((width * 0.75) / (512 * appSettings.windowScaling * appSettings.totalFontScaling),
varying highp vec2 qt_TexCoord0; (height * 0.75) / (512 * appSettings.windowScaling * appSettings.totalFontScaling))
property real screenShadowCoeff: 0
uniform highp vec4 fontColor; property real frameShadowCoeff: 0
uniform highp vec4 backgroundColor; property color frameColor: backgroundColor
uniform lowp float screen_brightness; property size margin: Qt.size(0, 0)
property real prevLastUpdate: burnInEffect.prevLastUpdate
uniform highp vec2 virtual_resolution;" +
blending: false
(bloom !== 0 ? " visible: false
uniform highp sampler2D bloomSource;
uniform lowp float bloom;" : "") + vertexShader: "qrc:/shaders/passthrough.vert.qsb"
fragmentShader: "qrc:/shaders/terminal_static.frag.qsb"
(screenCurvature !== 0 ? "
uniform highp float screenCurvature;" : "") + onStatusChanged: if (log) console.log(log)
}
(chromaColor !== 0 ? "
uniform lowp float chromaColor;" : "") + ShaderEffectSource {
id: frameBuffer
(rbgShift !== 0 ? " visible: false
uniform lowp float rbgShift;" : "") + sourceItem: staticShader
hideSource: true
(ambientLight !== 0 ? " }
uniform lowp float ambientLight;" : "") +
"highp float getScanlineIntensity(vec2 coords) {
float result = 1.0;" +
(appSettings.rasterization != appSettings.no_rasterization ?
"float val = 0.0;
vec2 rasterizationCoords = fract(coords * virtual_resolution);
val += smoothstep(0.0, 0.5, rasterizationCoords.y);
val -= smoothstep(0.5, 1.0, rasterizationCoords.y);
result *= mix(0.5, 1.0, val);" : "") +
(appSettings.rasterization == appSettings.pixel_rasterization ?
"val = 0.0;
val += smoothstep(0.0, 0.5, rasterizationCoords.x);
val -= smoothstep(0.5, 1.0, rasterizationCoords.x);
result *= mix(0.5, 1.0, val);" : "") + "
return result;
}
float min2(vec2 v) {
return min(v.x, v.y);
}
float sum2(vec2 v) {
return v.x + v.y;
}
float rgb2grey(vec3 v){
return dot(v, vec3(0.21, 0.72, 0.04));
}" +
"vec3 convertWithChroma(vec3 inColor) {
vec3 outColor = inColor;" +
(chromaColor !== 0 ?
"outColor = fontColor.rgb * mix(vec3(rgb2grey(inColor)), inColor, chromaColor);"
:
"outColor = fontColor.rgb * rgb2grey(inColor);") +
" return outColor;
}" +
"void main() {" +
"vec2 cc = vec2(0.5) - qt_TexCoord0;" +
(screenCurvature !== 0 ? "
float distortion = dot(cc, cc) * screenCurvature;
vec2 curvatureCoords = (qt_TexCoord0 - cc * (1.0 + distortion) * distortion);
vec2 txt_coords = - 2.0 * curvatureCoords + 3.0 * step(vec2(0.0), curvatureCoords) * curvatureCoords - 3.0 * step(vec2(1.0), curvatureCoords) * curvatureCoords;"
:"
vec2 txt_coords = qt_TexCoord0;") +
"vec3 txt_color = texture2D(source, txt_coords).rgb;" +
(rbgShift !== 0 ? "
vec2 displacement = vec2(12.0, 0.0) * rbgShift;
vec3 rightColor = texture2D(source, txt_coords + displacement).rgb;
vec3 leftColor = texture2D(source, txt_coords - displacement).rgb;
txt_color.r = leftColor.r * 0.10 + rightColor.r * 0.30 + txt_color.r * 0.60;
txt_color.g = leftColor.g * 0.20 + rightColor.g * 0.20 + txt_color.g * 0.60;
txt_color.b = leftColor.b * 0.30 + rightColor.b * 0.10 + txt_color.b * 0.60;
" : "") +
"txt_color *= getScanlineIntensity(txt_coords);" +
"txt_color += vec3(0.0001);" +
"float greyscale_color = rgb2grey(txt_color);" +
(screenCurvature !== 0 ? "
float reflectionMask = sum2(step(vec2(0.0), curvatureCoords) - step(vec2(1.0), curvatureCoords));
reflectionMask = clamp(reflectionMask, 0.0, 1.0);"
:
"float reflectionMask = 1.0;") +
(chromaColor !== 0 ?
"vec3 foregroundColor = mix(fontColor.rgb, txt_color * fontColor.rgb / greyscale_color, chromaColor);
vec3 finalColor = mix(backgroundColor.rgb, foregroundColor, greyscale_color * reflectionMask);"
:
"vec3 finalColor = mix(backgroundColor.rgb, fontColor.rgb, greyscale_color * reflectionMask);") +
(bloom !== 0 ?
"vec4 bloomFullColor = texture2D(bloomSource, txt_coords);
vec3 bloomColor = bloomFullColor.rgb;
float bloomAlpha = bloomFullColor.a;
bloomColor = convertWithChroma(bloomColor);
finalColor += clamp(bloomColor * bloom * bloomAlpha, 0.0, 0.5);"
: "") +
"finalColor *= screen_brightness;" +
"gl_FragColor = vec4(finalColor, qt_Opacity);" +
"}"
onStatusChanged: {
// Print warning messages
if (log) console.log(log);
}
}
ShaderEffectSource {
id: frameBuffer
visible: false
sourceItem: staticShader
hideSource: true
}
} }

View File

@@ -1,140 +0,0 @@
/*******************************************************************************
* Copyright (c) 2013-2021 "Filippo Scognamiglio"
* https://github.com/Swordfish90/cool-retro-term
*
* This file is part of cool-retro-term.
*
* cool-retro-term is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
import QtQuick 2.0
import "utils.js" as Utils
Loader {
property ShaderEffectSource source: item ? item.source : null
active: !appSettings.useFastBurnIn && appSettings.burnIn !== 0
anchors.fill: parent
sourceComponent: Item {
property alias source: burnInSourceEffect
property int burnInScaling: scaleTexture * appSettings.burnInQuality
ShaderEffectSource {
property bool updateBurnIn: false
property real burnIn: appSettings.burnIn
property real fps: appSettings.fps !== 0 ? appSettings.fps : 60
property real burnInFadeTime: Utils.lint(minBurnInFadeTime, maxBurnInFadeTime, burnIn)
property real burnInCoefficient: 1000 / (fps * burnInFadeTime)
property real minBurnInFadeTime: appSettings.minBurnInFadeTime
property real maxBurnInFadeTime: appSettings.maxBurnInFadeTime
id: burnInSourceEffect
anchors.fill: parent
sourceItem: burnInEffect
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: burnInSourceEffect.updateBurnIn ? timeManager : null
ignoreUnknownSignals: false
onTimeChanged: {
burnInSourceEffect.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: burnInSourceEffect.burnInFadeTime * 1.1
running: true
onTriggered: burnInSourceEffect.updateBurnIn = false;
}
Connections {
target: kterminal
onImagePainted:{
burnInSourceEffect.scheduleUpdate();
burnInSourceEffect.updateBurnIn = true;
livetimer.restart();
}
}
// Restart blurred source settings change.
Connections {
target: appSettings
onBurnInChanged: burnInSourceEffect.restartBlurSource();
onTerminalFontChanged: burnInSourceEffect.restartBlurSource();
onRasterizationChanged: burnInSourceEffect.restartBlurSource();
onBurnInQualityChanged: burnInSourceEffect.restartBlurSource();
}
Connections {
target: kterminalScrollbar
onOpacityChanged: burnInSourceEffect.restartBlurSource();
}
ShaderEffect {
id: burnInEffect
property variant txt_source: kterminalSource
property variant blurredSource: burnInSourceEffect
property real burnInCoefficient: burnInSourceEffect.burnInCoefficient
anchors.fill: parent
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 burnInCoefficient;" +
"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(burnInCoefficient);" +
"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
}
}
}
}

View File

@@ -18,7 +18,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/ *******************************************************************************/
import QtQuick 2.2 import QtQuick 2.2
import QtGraphicalEffects 1.0 import Qt5Compat.GraphicalEffects
import "utils.js" as Utils import "utils.js" as Utils
@@ -26,13 +26,19 @@ ShaderTerminal {
property alias title: terminal.title property alias title: terminal.title
property alias terminalSize: terminal.terminalSize property alias terminalSize: terminal.terminalSize
property real devicePixelRatio: terminalWindow.screen.devicePixelRatio
id: mainShader id: mainShader
opacity: appSettings.windowOpacity * 0.3 + 0.7 opacity: appSettings.windowOpacity * 0.3 + 0.7
source: terminal.mainSource source: terminal.mainSource
burnInEffect: terminal.burnInEffect burnInEffect: terminal.burnInEffect
slowBurnInEffect: terminal.slowBurnInEffect virtualResolution: terminal.virtualResolution
virtual_resolution: terminal.virtualResolution screenResolution: Qt.size(
terminalWindow.width * devicePixelRatio * appSettings.windowScaling,
terminalWindow.height * devicePixelRatio * appSettings.windowScaling
)
bloomSource: bloomSourceLoader.item
TimeManager { TimeManager {
id: timeManager id: timeManager
@@ -70,6 +76,4 @@ ShaderTerminal {
visible: false visible: false
} }
} }
bloomSource: bloomSourceLoader.item
} }

75
app/qml/TerminalFrame.qml Normal file
View File

@@ -0,0 +1,75 @@
/*******************************************************************************
* Copyright (c) 2013-2021 "Filippo Scognamiglio"
* https://github.com/Swordfish90/cool-retro-term
*
* This file is part of cool-retro-term.
*
* cool-retro-term is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
import QtQuick 2.0
import "utils.js" as Utils
ShaderEffect {
property color _staticFrameColor: "#fff"
property color _backgroundColor: appSettings.backgroundColor
property color _fontColor: appSettings.fontColor
property color _lightColor: Utils.mix(_fontColor, _backgroundColor, 0.2)
property real _ambientLight: Utils.lint(0.2, 0.8, appSettings.ambientLight)
property color frameColor: Utils.mix(_staticFrameColor, _lightColor, _ambientLight)
property real screenCurvature: appSettings.screenCurvature * appSettings.screenCurvatureSize
// Coefficient of the log curve used to approximate shadowing
property real screenShadowCoeff: Utils.lint(20.0, 10.0, _ambientLight)
property real frameShadowCoeff: Utils.lint(20.0, 10.0, _ambientLight)
property size margin: Qt.size(
appSettings.frameMargin / width * appSettings.windowScaling,
appSettings.frameMargin / height * appSettings.windowScaling
)
// Uniforms required by the shared block
property real qt_Opacity: 1.0
property real time: timeManager.time
property color fontColor: appSettings.fontColor
property color backgroundColor: appSettings.backgroundColor
property real shadowLength: 0
property size virtualResolution: Qt.size(width, height)
property real rasterizationIntensity: 0
property int rasterizationMode: 0
property real burnInLastUpdate: 0
property real burnInTime: 0
property real burnIn: 0
property real staticNoise: 0
property real glowingLine: 0
property real chromaColor: 0
property size jitterDisplacement: Qt.size(0, 0)
property real ambientLight: _ambientLight
property real jitter: 0
property real horizontalSync: 0
property real horizontalSyncStrength: 0
property real flickering: 0
property real displayTerminalFrame: 0
property size scaleNoiseSize: Qt.size(0, 0)
property real screen_brightness: 1.0
property real bloom: 0
property real rbgShift: 0
property real prevLastUpdate: 0
vertexShader: "qrc:/shaders/passthrough.vert.qsb"
fragmentShader: "qrc:/shaders/terminal_frame.frag.qsb"
onStatusChanged: if (log) console.log(log) //Print warning messages
}

View File

@@ -17,22 +17,29 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/ *******************************************************************************/
import QtQuick 2.2 import QtQuick
Timer { QtObject {
default property bool enableTimer: false id: timeManager
property real time
NumberAnimation on time { property bool enableTimer: false
from: 0 property real time: 0
to: 100000
running: appSettings.fps === 0 && enableTimer property int framesPerUpdate: Math.max(1, appSettings.effectsFrameSkip)
duration: 100000 property int _frameCounter: 0
loops: Animation.Infinite
property var frameDriver: FrameAnimation {
running: enableTimer
onTriggered: {
timeManager._frameCounter += 1
if (timeManager._frameCounter >= timeManager.framesPerUpdate) {
time = elapsedTime
timeManager._frameCounter = 0
}
}
} }
onTriggered: time += interval onEnableTimerChanged: if (!enableTimer) _frameCounter = 0
running: appSettings.fps !== 0 && enableTimer onFramesPerUpdateChanged: _frameCounter = 0
interval: Math.round(1000 / appSettings.fps)
repeat: true
} }

Binary file not shown.

View File

@@ -53,20 +53,30 @@ ApplicationWindow {
property bool fullscreen: appSettings.fullscreen property bool fullscreen: appSettings.fullscreen
onFullscreenChanged: visibility = (fullscreen ? Window.FullScreen : Window.Windowed) onFullscreenChanged: visibility = (fullscreen ? Window.FullScreen : Window.Windowed)
menuBar: WindowMenu { menuBar: qtquickMenuLoader.item
id: mainMenu
visible: (Qt.platform.os === "osx" || appSettings.showMenubar) Loader {
id: qtquickMenuLoader
active: !appSettings.isMacOS && appSettings.showMenubar
sourceComponent: WindowMenu { }
}
Loader {
id: globalMenuLoader
active: appSettings.isMacOS
sourceComponent: OSXMenu { }
} }
property string wintitle: appSettings.wintitle property string wintitle: appSettings.wintitle
color: "#00000000" color: "#00000000"
title: terminalContainer.title || qsTr(appSettings.wintitle) title: terminalContainer.title || qsTr(appSettings.wintitle)
Action { Action {
id: showMenubarAction id: showMenubarAction
text: qsTr("Show Menubar") text: qsTr("Show Menubar")
enabled: Qt.platform.os !== "osx" enabled: !appSettings.isMacOS
shortcut: "Ctrl+Shift+M" shortcut: "Ctrl+Shift+M"
checkable: true checkable: true
checked: appSettings.showMenubar checked: appSettings.showMenubar
@@ -75,7 +85,7 @@ ApplicationWindow {
Action { Action {
id: fullscreenAction id: fullscreenAction
text: qsTr("Fullscreen") text: qsTr("Fullscreen")
enabled: Qt.platform.os !== "osx" enabled: !appSettings.isMacOS
shortcut: "Alt+F11" shortcut: "Alt+F11"
onTriggered: appSettings.fullscreen = !appSettings.fullscreen onTriggered: appSettings.fullscreen = !appSettings.fullscreen
checkable: true checkable: true
@@ -154,7 +164,7 @@ ApplicationWindow {
onClosing: { onClosing: {
// OSX Since we are currently supporting only one window // OSX Since we are currently supporting only one window
// quit the application when it is closed. // quit the application when it is closed.
if (Qt.platform.os === "osx") if (appSettings.isMacOS)
Qt.quit() Qt.quit()
} }
} }

View File

@@ -82,8 +82,8 @@ Menu {
appSettings.handleFontChanged() appSettings.handleFontChanged()
} }
} }
onObjectAdded: profilesMenu.insertItem(index, object) onObjectAdded: function(index, object) { profilesMenu.insertItem(index, object) }
onObjectRemoved: profilesMenu.removeItem(object) onObjectRemoved: function(object) { profilesMenu.removeItem(object) }
} }
} }
Menu { Menu {

89
app/qml/menus/OSXMenu.qml Normal file
View File

@@ -0,0 +1,89 @@
/*******************************************************************************
* Copyright (c) 2013-2021 "Filippo Scognamiglio"
* https://github.com/Swordfish90/cool-retro-term
*
* This file is part of cool-retro-term.
*
* cool-retro-term is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
import QtQuick 2.3
import Qt.labs.platform 1.1
MenuBar {
id: defaultMenuBar
Menu {
title: qsTr("File")
MenuItem {
text: quitAction.text
onTriggered: quitAction.trigger()
}
}
Menu {
title: qsTr("Edit")
MenuItem {
text: copyAction.text
shortcut: "Meta+C"
onTriggered: copyAction.trigger()
}
MenuItem {
text: pasteAction.text
shortcut: "Meta+V"
onTriggered: pasteAction.trigger()
}
MenuSeparator {}
MenuItem {
text: showsettingsAction.text
shortcut: showsettingsAction.shortcut
onTriggered: showsettingsAction.trigger()
}
}
Menu {
title: qsTr("View")
MenuItem {
text: zoomIn.text
shortcut: "Meta++"
onTriggered: zoomIn.trigger()
}
MenuItem {
text: zoomOut.text
shortcut: "Meta+-"
onTriggered: zoomOut.trigger()
}
}
Menu {
id: profilesMenu
title: qsTr("Profiles")
Instantiator {
model: appSettings.profilesList
delegate: MenuItem {
text: model.text
onTriggered: {
appSettings.loadProfileString(obj_string)
appSettings.handleFontChanged()
}
}
onObjectAdded: function(index, object) { profilesMenu.insertItem(index, object) }
onObjectRemoved: function(object) { profilesMenu.removeItem(object) }
}
}
Menu {
title: qsTr("Help")
MenuItem {
text: showAboutAction.text
onTriggered: showAboutAction.trigger()
}
}
}

View File

@@ -72,8 +72,8 @@ MenuBar {
appSettings.handleFontChanged() appSettings.handleFontChanged()
} }
} }
onObjectAdded: profilesMenu.insertItem(index, object) onObjectAdded: function(index, object) { profilesMenu.insertItem(index, object) }
onObjectRemoved: profilesMenu.removeItem(object) onObjectRemoved: function(object) { profilesMenu.removeItem(object) }
} }
} }
Menu { Menu {

View File

@@ -19,7 +19,7 @@
<file>SettingsTerminalTab.qml</file> <file>SettingsTerminalTab.qml</file>
<file>FontScanlines.qml</file> <file>FontScanlines.qml</file>
<file>fonts/1977-apple2/PrintChar21.ttf</file> <file>fonts/1977-apple2/PrintChar21.ttf</file>
<file>fonts/1971-ibm-3278/3270Medium.ttf</file> <file>fonts/1971-ibm-3278/3270-Regular.ttf</file>
<file>Storage.qml</file> <file>Storage.qml</file>
<file>SettingsAdvancedTab.qml</file> <file>SettingsAdvancedTab.qml</file>
<file>TerminalContainer.qml</file> <file>TerminalContainer.qml</file>
@@ -40,10 +40,17 @@
<file>fonts/1977-commodore-pet/PetMe.ttf</file> <file>fonts/1977-commodore-pet/PetMe.ttf</file>
<file>BurnInEffect.qml</file> <file>BurnInEffect.qml</file>
<file>fonts/modern-terminus/TerminusTTF-4.46.0.ttf</file> <file>fonts/modern-terminus/TerminusTTF-4.46.0.ttf</file>
<file>NewTerminalFrame.qml</file> <file>TerminalFrame.qml</file>
<file>SlowBurnIn.qml</file>
<file>menus/WindowMenu.qml</file> <file>menus/WindowMenu.qml</file>
<file>menus/FullContextMenu.qml</file> <file>menus/FullContextMenu.qml</file>
<file>menus/ShortContextMenu.qml</file> <file>menus/ShortContextMenu.qml</file>
<file>ShaderLibrary.qml</file>
<file>menus/OSXMenu.qml</file>
<file>../shaders/terminal_dynamic.vert.qsb</file>
<file>../shaders/terminal_dynamic.frag.qsb</file>
<file>../shaders/passthrough.vert.qsb</file>
<file>../shaders/terminal_static.frag.qsb</file>
<file>../shaders/terminal_frame.frag.qsb</file>
<file>../shaders/burn_in.frag.qsb</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -31,13 +31,18 @@ function lint(a, b, t) {
return (1 - t) * a + (t) * b; return (1 - t) * a + (t) * b;
} }
function mix(c1, c2, alpha){ function mix(c1, c2, alpha) {
return Qt.rgba(c1.r * alpha + c2.r * (1-alpha), return Qt.rgba(c1.r * alpha + c2.r * (1-alpha),
c1.g * alpha + c2.g * (1-alpha), c1.g * alpha + c2.g * (1-alpha),
c1.b * alpha + c2.b * (1-alpha), c1.b * alpha + c2.b * (1-alpha),
c1.a * alpha + c2.a * (1-alpha)) c1.a * alpha + c2.a * (1-alpha))
} }
function smoothstep(min, max, value) {
let x = Math.max(0, Math.min(1, (value - min) / (max - min)));
return x * x * (3 - 2 * x);
}
function strToColor(s){ function strToColor(s){
var r = parseInt(s.substring(1,3), 16) / 256; var r = parseInt(s.substring(1,3), 16) / 256;
var g = parseInt(s.substring(3,5), 16) / 256; var g = parseInt(s.substring(3,5), 16) / 256;

63
app/shaders/burn_in.frag Normal file
View File

@@ -0,0 +1,63 @@
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform ubuf {
mat4 qt_Matrix;
float qt_Opacity;
float time;
vec4 fontColor;
vec4 backgroundColor;
float shadowLength;
vec2 virtualResolution;
float rasterizationIntensity;
int rasterizationMode;
float burnInLastUpdate;
float burnInTime;
float burnIn;
float staticNoise;
float screenCurvature;
float glowingLine;
float chromaColor;
vec2 jitterDisplacement;
float ambientLight;
float jitter;
float horizontalSync;
float horizontalSyncStrength;
float flickering;
float displayTerminalFrame;
vec2 scaleNoiseSize;
float screen_brightness;
float bloom;
float rbgShift;
float screenShadowCoeff;
float frameShadowCoeff;
vec4 frameColor;
vec2 margin;
float prevLastUpdate;
};
layout(binding = 1) uniform sampler2D txt_source;
layout(binding = 2) uniform sampler2D burnInSource;
float rgb2grey(vec3 v) {
return dot(v, vec3(0.21, 0.72, 0.04));
}
void main() {
vec2 coords = qt_TexCoord0;
vec3 txtColor = texture(txt_source, coords).rgb;
vec4 accColor = texture(burnInSource, coords);
float prevMask = accColor.a;
float currMask = rgb2grey(txtColor);
float blurDecay = clamp((burnInLastUpdate - prevLastUpdate) * burnInTime, 0.0, 1.0);
blurDecay = max(0.0, blurDecay - prevMask);
vec3 blurColor = accColor.rgb - vec3(blurDecay);
vec3 color = max(blurColor, txtColor);
fragColor = vec4(color, currMask) * qt_Opacity;
}

Binary file not shown.

View File

@@ -0,0 +1,46 @@
#version 440
layout(location = 0) in vec4 qt_Vertex;
layout(location = 1) in vec2 qt_MultiTexCoord0;
layout(std140, binding = 0) uniform ubuf {
mat4 qt_Matrix;
float qt_Opacity;
float time;
vec4 fontColor;
vec4 backgroundColor;
float shadowLength;
vec2 virtualResolution;
float rasterizationIntensity;
int rasterizationMode;
float burnInLastUpdate;
float burnInTime;
float burnIn;
float staticNoise;
float screenCurvature;
float glowingLine;
float chromaColor;
vec2 jitterDisplacement;
float ambientLight;
float jitter;
float horizontalSync;
float horizontalSyncStrength;
float flickering;
float displayTerminalFrame;
vec2 scaleNoiseSize;
float screen_brightness;
float bloom;
float rbgShift;
float screenShadowCoeff;
float frameShadowCoeff;
vec4 frameColor;
vec2 margin;
float prevLastUpdate;
};
layout(location = 0) out vec2 qt_TexCoord0;
void main() {
qt_TexCoord0 = qt_MultiTexCoord0;
gl_Position = qt_Matrix * qt_Vertex;
}

Binary file not shown.

View File

@@ -0,0 +1,163 @@
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 1) in float vBrightness;
layout(location = 2) in float vDistortionScale;
layout(location = 3) in float vDistortionFreq;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform ubuf {
mat4 qt_Matrix;
float qt_Opacity;
float time;
vec4 fontColor;
vec4 backgroundColor;
float shadowLength;
vec2 virtualResolution;
float rasterizationIntensity;
int rasterizationMode;
float burnInLastUpdate;
float burnInTime;
float burnIn;
float staticNoise;
float screenCurvature;
float glowingLine;
float chromaColor;
vec2 jitterDisplacement;
float ambientLight;
float jitter;
float horizontalSync;
float horizontalSyncStrength;
float flickering;
float displayTerminalFrame;
vec2 scaleNoiseSize;
float screen_brightness;
float bloom;
float rbgShift;
float screenShadowCoeff;
float frameShadowCoeff;
vec4 frameColor;
vec2 margin;
float prevLastUpdate;
};
layout(binding = 0) uniform sampler2D noiseSource;
layout(binding = 1) uniform sampler2D screenBuffer;
layout(binding = 2) uniform sampler2D burnInSource;
layout(binding = 3) uniform sampler2D frameSource;
float min2(vec2 v) { return min(v.x, v.y); }
float prod2(vec2 v) { return v.x * v.y; }
float sum2(vec2 v) { return v.x + v.y; }
float rgb2grey(vec3 v) { return dot(v, vec3(0.21, 0.72, 0.04)); }
vec3 applyRasterization(vec2 screenCoords, vec3 texel, vec2 virtualRes, float intensity, int mode) {
if (intensity <= 0.0 || mode == 0) {
return texel;
}
const float INTENSITY = 0.30;
const float BRIGHTBOOST = 0.30;
if (mode == 1) { // scanline
vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel;
vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel;
vec2 coords = fract(screenCoords * virtualRes) * 2.0 - vec2(1.0);
float mask = 1.0 - abs(coords.y);
vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask);
return mix(texel, rasterizationColor, intensity);
} else if (mode == 2) { // pixel
vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * texel)) * texel;
vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * texel)) * texel;
vec2 coords = fract(screenCoords * virtualRes) * 2.0 - vec2(1.0);
coords = coords * coords;
float mask = 1.0 - coords.x - coords.y;
vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask);
return mix(texel, rasterizationColor, intensity);
} else if (mode == 3) { // subpixel
const float SUBPIXELS = 3.0;
vec3 offsets = vec3(3.141592654) * vec3(0.5, 0.5 - 2.0 / 3.0, 0.5 - 4.0 / 3.0);
vec2 omega = vec2(3.141592654) * vec2(2.0) * virtualRes;
vec2 angle = screenCoords * omega;
vec3 xfactors = (SUBPIXELS + sin(angle.x + offsets)) / (SUBPIXELS + 1.0);
vec3 result = texel * xfactors;
vec3 pixelHigh = ((1.0 + BRIGHTBOOST) - (0.2 * result)) * result;
vec3 pixelLow = ((1.0 - INTENSITY) + (0.1 * result)) * result;
vec2 coords = fract(screenCoords * virtualRes) * 2.0 - vec2(1.0);
float mask = 1.0 - abs(coords.y);
vec3 rasterizationColor = mix(pixelLow, pixelHigh, mask);
return mix(texel, rasterizationColor, intensity);
}
return texel;
}
float randomPass(vec2 coords){
return fract(smoothstep(-120.0, 0.0, coords.y - (virtualResolution.y + 120.0) * fract(time * 0.15)));
}
vec2 barrel(vec2 v, vec2 cc) {
float distortion = dot(cc, cc) * screenCurvature;
return (v - cc * (1.0 + distortion) * distortion);
}
vec3 convertWithChroma(vec3 inColor) {
vec3 outColor = fontColor.rgb * rgb2grey(inColor);
if (chromaColor != 0.0) {
outColor = fontColor.rgb * mix(vec3(rgb2grey(inColor)), inColor, chromaColor);
}
return outColor;
}
void main() {
vec2 cc = vec2(0.5) - qt_TexCoord0;
float distance = length(cc);
vec2 staticCoords = barrel(qt_TexCoord0, cc);
vec2 coords = qt_TexCoord0;
float dst = sin((coords.y + time) * vDistortionFreq);
coords.x += dst * vDistortionScale;
vec4 noiseTexel = texture(noiseSource, scaleNoiseSize * coords + vec2(fract(time / 0.051), fract(time / 0.237)));
vec2 txt_coords = coords + (noiseTexel.ba - vec2(0.5)) * jitterDisplacement * jitter;
float color = 0.0001;
color += noiseTexel.a * staticNoise * (1.0 - distance * 1.3);
color += randomPass(coords * virtualResolution) * glowingLine;
vec3 txt_color = texture(screenBuffer, txt_coords).rgb;
if (burnIn > 0.0) {
vec4 txt_blur = texture(burnInSource, staticCoords);
float blurDecay = clamp((time - burnInLastUpdate) * burnInTime, 0.0, 1.0);
vec3 burnInColor = 0.65 * (txt_blur.rgb - vec3(blurDecay));
txt_color = max(txt_color, convertWithChroma(burnInColor));
}
txt_color += fontColor.rgb * vec3(color);
txt_color = applyRasterization(staticCoords, txt_color, virtualResolution, rasterizationIntensity, rasterizationMode);
vec3 finalColor = txt_color;
float brightness = mix(1.0, vBrightness, step(0.0, flickering));
finalColor *= brightness;
finalColor += vec3(ambientLight) * (1.0 - distance) * (1.0 - distance);
if (displayTerminalFrame > 0.0) {
vec4 frameColor = texture(frameSource, qt_TexCoord0);
finalColor = mix(finalColor, frameColor.rgb, frameColor.a);
}
fragColor = vec4(finalColor, qt_Opacity);
}

Binary file not shown.

View File

@@ -0,0 +1,61 @@
#version 440
layout(location = 0) in vec4 qt_Vertex;
layout(location = 1) in vec2 qt_MultiTexCoord0;
layout(std140, binding = 0) uniform ubuf {
mat4 qt_Matrix;
float qt_Opacity;
float time;
vec4 fontColor;
vec4 backgroundColor;
float shadowLength;
vec2 virtualResolution;
float rasterizationIntensity;
int rasterizationMode;
float burnInLastUpdate;
float burnInTime;
float burnIn;
float staticNoise;
float screenCurvature;
float glowingLine;
float chromaColor;
vec2 jitterDisplacement;
float ambientLight;
float jitter;
float horizontalSync;
float horizontalSyncStrength;
float flickering;
float displayTerminalFrame;
vec2 scaleNoiseSize;
float screen_brightness;
float bloom;
float rbgShift;
float screenShadowCoeff;
float frameShadowCoeff;
vec4 frameColor;
vec2 margin;
float prevLastUpdate;
};
layout(binding = 0) uniform sampler2D noiseSource;
layout(location = 0) out vec2 qt_TexCoord0;
layout(location = 1) out float vBrightness;
layout(location = 2) out float vDistortionScale;
layout(location = 3) out float vDistortionFreq;
void main() {
qt_TexCoord0 = qt_MultiTexCoord0;
vec2 coords = vec2(fract(time / 2.048), fract(time / 1048.576));
vec4 initialNoiseTexel = texture(noiseSource, coords);
vBrightness = 1.0 + (initialNoiseTexel.g - 0.5) * flickering;
float randval = horizontalSyncStrength - initialNoiseTexel.r;
vDistortionScale = step(0.0, randval) * randval * horizontalSyncStrength * horizontalSync;
vDistortionFreq = mix(4.0, 40.0, initialNoiseTexel.g) * step(0.0, horizontalSync);
gl_Position = qt_Matrix * qt_Vertex;
}

Binary file not shown.

View File

@@ -0,0 +1,77 @@
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform ubuf {
mat4 qt_Matrix;
float qt_Opacity;
float time;
vec4 fontColor;
vec4 backgroundColor;
float shadowLength;
vec2 virtualResolution;
float rasterizationIntensity;
int rasterizationMode;
float burnInLastUpdate;
float burnInTime;
float burnIn;
float staticNoise;
float screenCurvature;
float glowingLine;
float chromaColor;
vec2 jitterDisplacement;
float ambientLight;
float jitter;
float horizontalSync;
float horizontalSyncStrength;
float flickering;
float displayTerminalFrame;
vec2 scaleNoiseSize;
float screen_brightness;
float bloom;
float rbgShift;
float screenShadowCoeff;
float frameShadowCoeff;
vec4 frameColor;
vec2 margin;
float prevLastUpdate;
};
float min2(vec2 v) { return min(v.x, v.y); }
float max2(vec2 v) { return max(v.x, v.y); }
float prod2(vec2 v) { return v.x * v.y; }
float sum2(vec2 v) { return v.x + v.y; }
vec2 distortCoordinates(vec2 coords){
vec2 cc = (coords - vec2(0.5));
float dist = dot(cc, cc) * screenCurvature;
return (coords + cc * (1.0 + dist) * dist);
}
vec2 positiveLog(vec2 x) {
return clamp(log(x), vec2(0.0), vec2(100.0));
}
void main() {
vec2 staticCoords = qt_TexCoord0;
vec2 coords = distortCoordinates(staticCoords) * (vec2(1.0) + margin * 2.0) - margin;
vec2 vignetteCoords = staticCoords * (1.0 - staticCoords.yx);
float vignette = pow(prod2(vignetteCoords) * 15.0, 0.25);
vec3 color = frameColor.rgb * vec3(1.0 - vignette);
float alpha = 0.0;
float frameShadow = max2(positiveLog(-coords * frameShadowCoeff + vec2(1.0)) + positiveLog(coords * frameShadowCoeff - (vec2(frameShadowCoeff) - vec2(1.0))));
frameShadow = max(sqrt(frameShadow), 0.0);
color *= frameShadow;
alpha = sum2(1.0 - step(vec2(0.0), coords) + step(vec2(1.0), coords));
alpha = clamp(alpha, 0.0, 1.0);
alpha *= mix(1.0, 0.9, frameShadow);
float screenShadow = 1.0 - prod2(positiveLog(coords * screenShadowCoeff + vec2(1.0)) * positiveLog(-coords * screenShadowCoeff + vec2(screenShadowCoeff + 1.0)));
alpha = max(0.8 * screenShadow, alpha);
fragColor = vec4(color * alpha, alpha) * qt_Opacity;
}

Binary file not shown.

View File

@@ -0,0 +1,104 @@
#version 440
layout(location = 0) in vec2 qt_TexCoord0;
layout(location = 0) out vec4 fragColor;
layout(std140, binding = 0) uniform ubuf {
mat4 qt_Matrix;
float qt_Opacity;
float time;
vec4 fontColor;
vec4 backgroundColor;
float shadowLength;
vec2 virtualResolution;
float rasterizationIntensity;
int rasterizationMode;
float burnInLastUpdate;
float burnInTime;
float burnIn;
float staticNoise;
float screenCurvature;
float glowingLine;
float chromaColor;
vec2 jitterDisplacement;
float ambientLight;
float jitter;
float horizontalSync;
float horizontalSyncStrength;
float flickering;
float displayTerminalFrame;
vec2 scaleNoiseSize;
float screen_brightness;
float bloom;
float rbgShift;
float screenShadowCoeff;
float frameShadowCoeff;
vec4 frameColor;
vec2 margin;
float prevLastUpdate;
};
layout(binding = 1) uniform sampler2D source;
layout(binding = 2) uniform sampler2D bloomSource;
float sum2(vec2 v) { return v.x + v.y; }
float rgb2grey(vec3 v) { return dot(v, vec3(0.21, 0.72, 0.04)); }
vec3 convertWithChroma(vec3 inColor) {
vec3 outColor = fontColor.rgb * rgb2grey(inColor);
if (chromaColor != 0.0) {
outColor = fontColor.rgb * mix(vec3(rgb2grey(inColor)), inColor, chromaColor);
}
return outColor;
}
void main() {
vec2 cc = vec2(0.5) - qt_TexCoord0;
vec2 txt_coords = qt_TexCoord0;
if (screenCurvature != 0.0) {
float distortion = dot(cc, cc) * screenCurvature;
vec2 curvatureCoords = (qt_TexCoord0 - cc * (1.0 + distortion) * distortion);
txt_coords = -2.0 * curvatureCoords + 3.0 * step(vec2(0.0), curvatureCoords) * curvatureCoords - 3.0 * step(vec2(1.0), curvatureCoords) * curvatureCoords;
}
vec3 txt_color = texture(source, txt_coords).rgb;
if (rbgShift != 0.0) {
vec2 displacement = vec2(12.0, 0.0) * rbgShift;
vec3 rightColor = texture(source, txt_coords + displacement).rgb;
vec3 leftColor = texture(source, txt_coords - displacement).rgb;
txt_color.r = leftColor.r * 0.10 + rightColor.r * 0.30 + txt_color.r * 0.60;
txt_color.g = leftColor.g * 0.20 + rightColor.g * 0.20 + txt_color.g * 0.60;
txt_color.b = leftColor.b * 0.30 + rightColor.b * 0.10 + txt_color.b * 0.60;
}
txt_color += vec3(0.0001);
float greyscale_color = rgb2grey(txt_color);
float reflectionMask = 1.0;
if (screenCurvature != 0.0) {
float distortion = dot(cc, cc) * screenCurvature;
vec2 curvatureCoords = (qt_TexCoord0 - cc * (1.0 + distortion) * distortion);
reflectionMask = sum2(step(vec2(0.0), curvatureCoords) - step(vec2(1.0), curvatureCoords));
reflectionMask = clamp(reflectionMask, 0.0, 1.0);
}
vec3 finalColor;
if (chromaColor != 0.0) {
vec3 foregroundColor = mix(fontColor.rgb, txt_color * fontColor.rgb / greyscale_color, chromaColor);
finalColor = mix(backgroundColor.rgb, foregroundColor, greyscale_color * reflectionMask);
} else {
finalColor = mix(backgroundColor.rgb, fontColor.rgb, greyscale_color * reflectionMask);
}
if (bloom != 0.0) {
vec4 bloomFullColor = texture(bloomSource, txt_coords);
vec3 bloomColor = convertWithChroma(bloomFullColor.rgb);
float bloomAlpha = bloomFullColor.a;
finalColor += clamp(bloomColor * bloom * bloomAlpha, 0.0, 0.5);
}
finalColor *= screen_brightness;
fragColor = vec4(finalColor, qt_Opacity);
}

Binary file not shown.