├── .gitignore
├── img
└── preview.png
├── CrtTextBox
├── Assets
│ ├── Fonts
│ │ └── VGA
│ │ │ ├── PxPlus_IBM_VGA8.ttf
│ │ │ └── LICENSE.TXT
│ └── crt.sksl
├── CrtTextBox.sln.DotSettings
├── App.axaml
├── CrtTextBox.sln
├── app.manifest
├── App.axaml.cs
├── Skins
│ ├── SimpleSkin.cs
│ ├── RetroGreenDos.cs
│ ├── RetroMonoDos.cs
│ ├── RetroPlasma.cs
│ └── SkinBase.cs
├── Program.cs
├── CrtTextBox.csproj
├── MainWindow.axaml
├── MainWindow.axaml.cs
└── ShaderControl.cs
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | */bin/
2 | */obj/
3 | */.*/
4 | */_*/
5 |
--------------------------------------------------------------------------------
/img/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deanthecoder/CrtTextBox/HEAD/img/preview.png
--------------------------------------------------------------------------------
/CrtTextBox/Assets/Fonts/VGA/PxPlus_IBM_VGA8.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/deanthecoder/CrtTextBox/HEAD/CrtTextBox/Assets/Fonts/VGA/PxPlus_IBM_VGA8.ttf
--------------------------------------------------------------------------------
/CrtTextBox/CrtTextBox.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | True
--------------------------------------------------------------------------------
/CrtTextBox/App.axaml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
9 |
10 | avares://CrtTextBox/Assets/Fonts/VGA#PxPlus IBM VGA8
11 |
12 |
--------------------------------------------------------------------------------
/CrtTextBox/CrtTextBox.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CrtTextBox", "CrtTextBox.csproj", "{428C3EE5-5D90-4C7A-A46C-4F7B43F563FD}"
4 | EndProject
5 | Global
6 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
7 | Debug|Any CPU = Debug|Any CPU
8 | Release|Any CPU = Release|Any CPU
9 | EndGlobalSection
10 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
11 | {428C3EE5-5D90-4C7A-A46C-4F7B43F563FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
12 | {428C3EE5-5D90-4C7A-A46C-4F7B43F563FD}.Debug|Any CPU.Build.0 = Debug|Any CPU
13 | {428C3EE5-5D90-4C7A-A46C-4F7B43F563FD}.Release|Any CPU.ActiveCfg = Release|Any CPU
14 | {428C3EE5-5D90-4C7A-A46C-4F7B43F563FD}.Release|Any CPU.Build.0 = Release|Any CPU
15 | EndGlobalSection
16 | EndGlobal
17 |
--------------------------------------------------------------------------------
/CrtTextBox/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 |
8 |
9 |
10 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/CrtTextBox/App.axaml.cs:
--------------------------------------------------------------------------------
1 | // Code authored by Dean Edis (DeanTheCoder).
2 | // Anyone is free to copy, modify, use, compile, or distribute this software,
3 | // either in source code form or as a compiled binary, for any non-commercial
4 | // purpose.
5 | //
6 | // If you modify the code, please retain this copyright header,
7 | // and consider contributing back to the repository or letting us know
8 | // about your modifications. Your contributions are valued!
9 | //
10 | // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND.
11 | using Avalonia;
12 | using Avalonia.Controls.ApplicationLifetimes;
13 | using Avalonia.Markup.Xaml;
14 |
15 | namespace RenderTest;
16 |
17 | public class App : Application
18 | {
19 | public override void Initialize()
20 | {
21 | AvaloniaXamlLoader.Load(this);
22 | }
23 |
24 | public override void OnFrameworkInitializationCompleted()
25 | {
26 | if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
27 | desktop.MainWindow = new MainWindow();
28 |
29 | base.OnFrameworkInitializationCompleted();
30 | }
31 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 Dean Edis
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/CrtTextBox/Skins/SimpleSkin.cs:
--------------------------------------------------------------------------------
1 | // // Code authored by Dean Edis (DeanTheCoder).
2 | // // Anyone is free to copy, modify, use, compile, or distribute this software,
3 | // // either in source code form or as a compiled binary, for any non-commercial
4 | // // purpose.
5 | // //
6 | // // If you modify the code, please retain this copyright header,
7 | // // and consider contributing back to the repository or letting us know
8 | // // about your modifications. Your contributions are valued!
9 | // //
10 | // // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND.
11 | namespace RenderTest.Skins;
12 |
13 | public class SimpleSkin : SkinBase
14 | {
15 | // Font properties
16 | public override string ForegroundColor => "#e0e000";
17 | public override string BackgroundColor => "#000080";
18 | public override string SelectionColor => "#004080";
19 | public override double FontSize => 16.0;
20 | public override double BrightnessBoost => 1.0;
21 |
22 | // Shader uniform properties
23 | public override bool EnableScanlines => false;
24 | public override bool EnableSurround => false;
25 | public override bool EnableSignalDistortion => false;
26 | public override bool EnableShadows => false;
27 | }
--------------------------------------------------------------------------------
/CrtTextBox/Program.cs:
--------------------------------------------------------------------------------
1 | // Code authored by Dean Edis (DeanTheCoder).
2 | // Anyone is free to copy, modify, use, compile, or distribute this software,
3 | // either in source code form or as a compiled binary, for any non-commercial
4 | // purpose.
5 | //
6 | // If you modify the code, please retain this copyright header,
7 | // and consider contributing back to the repository or letting us know
8 | // about your modifications. Your contributions are valued!
9 | //
10 | // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND.
11 | using System;
12 | using Avalonia;
13 |
14 | namespace RenderTest;
15 |
16 | static class Program
17 | {
18 | // Initialization code. Don't use any Avalonia, third-party APIs or any
19 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized
20 | // yet and stuff might break.
21 | [STAThread]
22 | public static void Main(string[] args)
23 | {
24 | BuildAvaloniaApp()
25 | .StartWithClassicDesktopLifetime(args);
26 | }
27 |
28 | // Avalonia configuration, don't remove; also used by visual designer.
29 | public static AppBuilder BuildAvaloniaApp()
30 | {
31 | return AppBuilder.Configure()
32 | .UsePlatformDetect()
33 | .WithInterFont()
34 | .LogToTrace();
35 | }
36 | }
--------------------------------------------------------------------------------
/CrtTextBox/Skins/RetroGreenDos.cs:
--------------------------------------------------------------------------------
1 | // // Code authored by Dean Edis (DeanTheCoder).
2 | // // Anyone is free to copy, modify, use, compile, or distribute this software,
3 | // // either in source code form or as a compiled binary, for any non-commercial
4 | // // purpose.
5 | // //
6 | // // If you modify the code, please retain this copyright header,
7 | // // and consider contributing back to the repository or letting us know
8 | // // about your modifications. Your contributions are valued!
9 | // //
10 | // // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND.
11 | namespace RenderTest.Skins;
12 |
13 | public class RetroGreenDos : SkinBase
14 | {
15 | // Font properties
16 | public override string ForegroundColor => "#40ff40";
17 | public override string BackgroundColor => "#082008";
18 | public override string SelectionColor => "#207020";
19 | public override double FontSize => 16.0; // Font size 16.0
20 | public override double BrightnessBoost => 1.1;
21 |
22 | // Shader uniform properties
23 | public override bool EnableScanlines => true; // Enable scanlines
24 | public override bool EnableSurround => true; // Enable CRT surround effect
25 | public override bool EnableSignalDistortion => true; // Enable signal distortion
26 | public override bool EnableShadows => true; // Enable shadows
27 | }
--------------------------------------------------------------------------------
/CrtTextBox/Skins/RetroMonoDos.cs:
--------------------------------------------------------------------------------
1 | // // Code authored by Dean Edis (DeanTheCoder).
2 | // // Anyone is free to copy, modify, use, compile, or distribute this software,
3 | // // either in source code form or as a compiled binary, for any non-commercial
4 | // // purpose.
5 | // //
6 | // // If you modify the code, please retain this copyright header,
7 | // // and consider contributing back to the repository or letting us know
8 | // // about your modifications. Your contributions are valued!
9 | // //
10 | // // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND.
11 | namespace RenderTest.Skins;
12 |
13 | public class RetroMonoDos : SkinBase
14 | {
15 | // Font properties
16 | public override string ForegroundColor => "#ffffff";
17 | public override string BackgroundColor => "#202020";
18 | public override string SelectionColor => "#505050";
19 | public override double FontSize => 16.0; // Font size 16.0
20 | public override double BrightnessBoost => 1.0;
21 |
22 | // Shader uniform properties
23 | public override bool EnableScanlines => true; // Enable scanlines
24 | public override bool EnableSurround => true; // Enable CRT surround effect
25 | public override bool EnableSignalDistortion => true; // Enable signal distortion
26 | public override bool EnableShadows => true; // Enable shadows
27 | }
--------------------------------------------------------------------------------
/CrtTextBox/Skins/RetroPlasma.cs:
--------------------------------------------------------------------------------
1 | // Code authored by Dean Edis (DeanTheCoder).
2 | // Anyone is free to copy, modify, use, compile, or distribute this software,
3 | // either in source code form or as a compiled binary, for any non-commercial
4 | // purpose.
5 | //
6 | // If you modify the code, please retain this copyright header,
7 | // and consider contributing back to the repository or letting us know
8 | // about your modifications. Your contributions are valued!
9 | //
10 | // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND.
11 |
12 | namespace RenderTest.Skins;
13 |
14 | public class RetroPlasma : SkinBase
15 | {
16 | // Font properties
17 | public override string ForegroundColor => "#ffa000"; // Orange foreground
18 | public override string BackgroundColor => "#402000"; // Brownish-orange background
19 | public override string SelectionColor => "#804000"; // Halfway color for selection
20 | public override double FontSize => 16.0; // Font size 16.0
21 | public override double BrightnessBoost => 1.2;
22 |
23 | // Shader uniform properties
24 | public override bool EnableScanlines => true; // Enable scanlines
25 | public override bool EnableSurround => true; // Enable CRT surround effect
26 | public override bool EnableSignalDistortion => true; // Enable signal distortion
27 | public override bool EnableShadows => true; // Enable shadows
28 | }
--------------------------------------------------------------------------------
/CrtTextBox/Skins/SkinBase.cs:
--------------------------------------------------------------------------------
1 | // Code authored by Dean Edis (DeanTheCoder).
2 | // Anyone is free to copy, modify, use, compile, or distribute this software,
3 | // either in source code form or as a compiled binary, for any non-commercial
4 | // purpose.
5 | //
6 | // If you modify the code, please retain this copyright header,
7 | // and consider contributing back to the repository or letting us know
8 | // about your modifications. Your contributions are valued!
9 | //
10 | // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND.
11 |
12 | namespace RenderTest.Skins;
13 |
14 | public abstract class SkinBase
15 | {
16 | // Font properties.
17 | public abstract string ForegroundColor { get; } // e.g., "#FFFFFF" for white text
18 | public abstract string BackgroundColor { get; } // e.g., "#000000" for black background
19 | public abstract string SelectionColor { get; } // e.g., "#FF0000" for red selection
20 | public abstract double FontSize { get; } // e.g., 16.0
21 |
22 | // Shader uniform properties
23 | public abstract double BrightnessBoost { get; }
24 | public abstract bool EnableScanlines { get; } // true to enable scanlines
25 | public abstract bool EnableSurround { get; } // true to enable CRT surround effect
26 | public abstract bool EnableSignalDistortion { get; } // true to enable signal distortion
27 | public abstract bool EnableShadows { get; } // true to enable shadows
28 | }
--------------------------------------------------------------------------------
/CrtTextBox/CrtTextBox.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | WinExe
4 | net7.0
5 | disable
6 | true
7 | app.manifest
8 | true
9 | true
10 | RenderTest
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/CrtTextBox/MainWindow.axaml:
--------------------------------------------------------------------------------
1 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
27 |
28 |
35 |
36 |
37 |
38 |
39 |
40 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/CrtTextBox/MainWindow.axaml.cs:
--------------------------------------------------------------------------------
1 | // Code authored by Dean Edis (DeanTheCoder).
2 | // Anyone is free to copy, modify, use, compile, or distribute this software,
3 | // either in source code form or as a compiled binary, for any non-commercial
4 | // purpose.
5 | //
6 | // If you modify the code, please retain this copyright header,
7 | // and consider contributing back to the repository or letting us know
8 | // about your modifications. Your contributions are valued!
9 | //
10 | // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND.
11 | using System;
12 | using System.IO;
13 | using Avalonia;
14 | using Avalonia.Controls;
15 | using Avalonia.Input;
16 | using Avalonia.Interactivity;
17 | using Avalonia.Media;
18 | using Avalonia.Platform;
19 | using RenderTest.Skins;
20 |
21 | namespace RenderTest;
22 |
23 | public partial class MainWindow : Window
24 | {
25 | public MainWindow()
26 | {
27 | InitializeComponent();
28 | }
29 |
30 | private void OnTextBoxLoaded(object sender, RoutedEventArgs _)
31 | {
32 | var textBox = (TextBox)sender;
33 | textBox.ContextMenu = null;
34 |
35 | // Preload the text box with the shader code.
36 | using var skslStream = new StreamReader(AssetLoader.Open(new Uri("avares://CrtTextBox/Assets/crt.sksl")));
37 | textBox.Text = skslStream.ReadToEnd();
38 | textBox.Focus();
39 |
40 | // Allow real-time SKSL updates using 'F5'.
41 | textBox.KeyDown += (_, args) =>
42 | {
43 | if (args.PhysicalKey == PhysicalKey.F5)
44 | Shader.SetSksl(textBox.Text);
45 | };
46 |
47 | // Configure the default CRT shader.
48 | ApplyRetroSkin(new RetroPlasma());
49 | }
50 |
51 | private void ApplyRetroSkin(SkinBase skin)
52 | {
53 | // Apply font and color settings.
54 | Source.Foreground = SolidColorBrush.Parse(skin.ForegroundColor);
55 | Source.Background = SolidColorBrush.Parse(skin.BackgroundColor);
56 | Source.SelectionBrush = SolidColorBrush.Parse(skin.SelectionColor);
57 | Source.FontSize = skin.FontSize;
58 |
59 | // Set the focused background color in the resources.
60 | Source.Resources["TextControlBackgroundFocused"] = Source.Background;
61 | Source.Resources["TextControlBorderThemeThicknessFocused"] = new Thickness(0);
62 |
63 | // Configure the CRT shader using the provided skin.
64 | Shader.AddUniform("brightnessBoost", (float)skin.BrightnessBoost);
65 | Shader.AddUniform("enableScanlines", skin.EnableScanlines);
66 | Shader.AddUniform("enableSurround", skin.EnableSurround);
67 | Shader.AddUniform("enableSignalDistortion", skin.EnableSignalDistortion);
68 | Shader.AddUniform("enableShadows", skin.EnableShadows);
69 |
70 | // Alignment.
71 | MarginPanel.Margin = new Thickness(skin.EnableSurround ? 20 : 0);
72 | }
73 |
74 | private void OnShaderControlLoaded(object sender, RoutedEventArgs _)
75 | {
76 | // Set ShaderControl's source control.
77 | ((ShaderControl)sender).ControlSource = Source;
78 | }
79 |
80 | public void SetTheme(string name)
81 | {
82 | switch (name)
83 | {
84 | case "RetroPlasma":
85 | ApplyRetroSkin(new RetroPlasma());
86 | return;
87 | case "RetroGreenDos":
88 | ApplyRetroSkin(new RetroGreenDos());
89 | return;
90 | case "RetroMonoDos":
91 | ApplyRetroSkin(new RetroMonoDos());
92 | return;
93 | case "SimpleSkin":
94 | ApplyRetroSkin(new SimpleSkin());
95 | return;
96 | }
97 | }
98 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://twitter.com/deanthecoder)
2 |
3 | # CrtTextBox
4 |
5 | **CrtTextBox** is an Avalonia C# project that enhances a standard TextBox control with a custom SKSL shader, giving it the appearance of a retro CRT screen. This effect adds a nostalgic touch to your UI with features like fish-eye distortion, scan lines, vignette, screen jitter, background noise, and a scrolling electron bar.
6 |
7 | 
8 |
9 | It makes use of a custom `ShaderControl` control, allowing any SKSL shader code to be applied to a source Avalonia UI control.
10 | The `CrtTextBox` example demonstrate how to use it with a `TextBox`, but any other source control can be used.
11 |
12 | ## Features
13 |
14 | - **Retro CRT Look**: The shader applies various effects to create a convincing retro CRT display, including:
15 | - Fish-eye distortion
16 | - Scan lines
17 | - Vignette effect
18 | - Screen jitter
19 | - Background noise
20 | - Scrolling electron bar
21 | - Monitor 'surround' with screen reflection
22 |
23 | - **Cross-Platform Compatibility**: Built with [Avalonia](https://avaloniaui.net/), ensuring compatibility across Windows, MacOS, and Linux.
24 |
25 | - **Customizable**: The shader can be easily integrated into any Avalonia application and modified to suit different visual styles.
26 |
27 | ## Getting Started
28 |
29 | ### Prerequisites
30 |
31 | - .NET compatible IDE such as [JetBrains Rider](https://www.jetbrains.com/rider/) or [Visual Studio 2022](https://visualstudio.microsoft.com/vs/).
32 | - Basic knowledge of C# and Avalonia UI.
33 |
34 | ### Building From Source
35 |
36 | 1. Clone the repository from GitHub.
37 | 2. Open the solution in your IDE.
38 | 3. Build and run the project.
39 |
40 | ### Using the Text Editor
41 |
42 | The main view is taken up with the shader code itself. Feel free to modify it and press `F5` to apply changes. Right-click outside of the text area to switch Themes.
43 |
44 | ### Create Your Own Theme
45 |
46 | Check out the `Themes` folder in the source tree. Modify the code to toggle features, or create your own theme from scratch.
47 |
48 | ### Using the `ShaderControl`
49 |
50 | The `ShaderControl` object is a standalone class and can be copied into your own project, and applied to any control with any shader code.
51 |
52 | 1. Add `ShaderControl` to your AXAML.
53 | 2. From the code-behind, set the `ControlSource` property to the UI control you wish to apply the shader to.
54 | 3. Set the `FPS` property, which determines the frequency the source control is sampled.
55 | 4. Set `ShaderUri` to point to the location of your SKSL shader code. Use `crt.sksl` as a reference.
56 |
57 | Custom `uniform` values can be passed into the shader code using `ShaderControl.AddUniform(name, value)`.
58 |
59 | ## Contribution and Improvements
60 |
61 | CrtTextBox is an open-source project, and contributions are welcome. If you have ideas for new features, improvements, or bug fixes, feel free to submit a pull request. Please note that this is a side project, so responses might not be immediate.
62 |
63 | ## Credits
64 |
65 | * Created with help from the blog: [Avalonia with Fragment Shaders](https://avaloniaui.net/blog/avalonia-with-fragment-shaders)
66 | * ...based on work by [Wiesław Šoltés](https://github.com/wieslawsoltes/EffectsDemo).
67 |
68 | The project is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
69 |
70 | ## Useful Resources
71 |
72 | - [Avalonia UI Documentation](https://docs.avaloniaui.net/)
73 | - [SKSL Shader Language](https://skia.org/docs/user/sksl/)
74 | - [The Oldschool PC Font Resource](https://int10h.org/oldschool-pc-fonts/fontlist/font?ibm_vga_8x16)
75 |
76 | ---
77 |
78 | Follow me on Twitter for more updates: [@deanthecoder](https://twitter.com/deanthecoder).
79 |
--------------------------------------------------------------------------------
/CrtTextBox/Assets/crt.sksl:
--------------------------------------------------------------------------------
1 | //
2 | // ╓――――――――――――――――――╖
3 | // ║ CRT Effect ║░
4 | // ║ by ║░
5 | // ║ DeanTheCoder ║░
6 | // ╙――――――――――――――――――╜░
7 | // ░░░░░░░░░░░░░░░░░░░░
8 | //
9 | // Effects: Fish eye, scan lines, vignette, screen jitter,
10 | // background noise, electron bar, shadows,
11 | // screen glare, fake surround (with reflections).
12 | //
13 | // License: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
14 |
15 | uniform float2 iResolution; // ShaderControl size
16 | uniform float iTime;
17 | uniform shader iImage1; // Source control image, sampled multiple times per second.
18 | uniform float2 iImageResolution; // Source control size.
19 |
20 | // Parameterized values
21 | uniform float brightnessBoost; // 1.0 = no boost.
22 | uniform float enableScanlines; // 1.0 to enable, 0.0 to disable
23 | uniform float enableSurround; // 1.0 to enable, 0.0 to disable
24 | uniform float enableSignalDistortion; // 1.0 to enable, 0.0 to disable
25 | uniform float enableShadows; // 1.0 to enable, 0.0 to disabl
26 |
27 | float smoothstep(float edge0, float edge1, float x)
28 | {
29 | float t = clamp((x - edge0) / (edge1 - edge0), 0.0, 1.0);
30 | return t * t * (3.0 - 2.0 * t);
31 | }
32 |
33 | float2 fisheye(float2 uv)
34 | {
35 | float r = 2.5;
36 | uv *= 1.05;
37 | return r * uv / sqrt(r * r - dot(uv, uv));
38 | }
39 |
40 | float bar(float y)
41 | {
42 | y += 0.5;
43 | y = fract(y * 0.7 - iTime * 0.1);
44 | return smoothstep(0.7, 0.98, y) + smoothstep(0.98, 1.0, 1.-y);
45 | }
46 |
47 | float h21(float2 p)
48 | {
49 | float3 p3 = fract(float3(p.xyx) * float3(0.1031, 0.11369, 0.13787));
50 | p3 += dot(p3, p3.yzx + 19.19);
51 | return fract((p3.x + p3.y) * p3.z);
52 | }
53 |
54 | float4 main(float2 fragCoord)
55 | {
56 | float2 res = iImageResolution;
57 | float fadeOn = 0.1 + 0.9 * smoothstep(0.5, 3.0, iTime);
58 |
59 | // UV coords in the range of -0.5 to 0.5
60 | float2 uv = (fragCoord / iImageResolution) - 0.5;
61 |
62 | // Apply fisheye and border effect (if enabled).
63 | float2 st = enableSurround > 0.5 ? fisheye(uv) : uv;
64 |
65 | float ns = h21(fragCoord); // Random number, to use later.
66 |
67 | // Monitor screen.
68 | float rnd = h21(fragCoord + iTime); // Jitter.
69 |
70 | float2 tuv = (st + 0.5) * res + float2(rnd * enableSignalDistortion * 0.5, 0);
71 | float3 imageRgb = float3(0);
72 | float ampSum = 0.0;
73 | for (float dx = -1.0; dx < 1.0; dx += 0.125)
74 | {
75 | for (float dy = -1.0; dy < 1.0; dy += 0.125)
76 | {
77 | // Multiple samples to add 'bloom'.
78 | float amp = exp(length(float2(dx, dy)) * -2.0);
79 | imageRgb += amp * sample(iImage1, tuv + float2(dx, dy) * 15.0).rgb;
80 | ampSum += amp;
81 | }
82 | }
83 | imageRgb /= ampSum;
84 | imageRgb = sample(iImage1, tuv).rgb * 0.7 + 0.5 * imageRgb;
85 | imageRgb *= fadeOn;
86 |
87 | float bev = enableSurround > 0.5 ? (max(abs(st.x), abs(st.y)) - 0.498) / 0.035 : 0.0;
88 | if (bev > 0.0)
89 | {
90 | // We're somewhere outside the CRT screen area.
91 | float3 col = float3(0.68, 0.68, 0.592);
92 | if (bev > 1.0)
93 | {
94 | // Monitor face.
95 | col -= ns * 0.05;
96 | }
97 | else
98 | {
99 | // Bevel area.
100 | col *= mix(0.1, 1.0, bev);
101 | col = mix(imageRgb * 0.5, col, 0.5 + 0.5 * smoothstep(0.0, 0.4, bev));
102 | col = col - float3(0.0, 0.05, 0.1) * ns;
103 |
104 | // Shadow.
105 | if (enableShadows > 0 && uv.y < 0.0)
106 | col *= min(1.0, 0.6 * smoothstep(0.8, 1.0, bev) + 0.8 + smoothstep(0.4, 0.3, length(uv * float2(0.4, 1.0))));
107 |
108 | // Screen reflection in the bevel.
109 | float dir = sign(-uv.x);
110 | float3 tint = float3(0);
111 | for (float i = -5.0; i < 5.0; i++)
112 | {
113 | for (float j = -5.0; j < 5.0; j++)
114 | tint += sample(iImage1, (st * 0.9 + float2(dir * i, j * 2.0) * 0.002 + 0.5) * res).rgb * fadeOn;
115 | }
116 |
117 | tint /= 80.0;
118 | col = mix(tint, col, 0.8 + 0.2 * bev);
119 | }
120 |
121 | return vec4(col, 1.0);
122 | }
123 |
124 | float lum = 1.0;
125 |
126 | // Background noise.
127 | lum += enableSignalDistortion * (rnd - 0.5) * 0.2;
128 |
129 | // Scrolling electron bar.
130 | lum += enableSignalDistortion * bar(uv.y) * 0.2;
131 |
132 | // Apply scanlines (if enabled).
133 | if (enableScanlines > 0.5 && (int(fragCoord.y) % 2) == 0)
134 | lum *= 0.8 + 0.2 * pow(1.0 - (imageRgb.r + imageRgb.g + imageRgb.b) / 3.0, 1.0);
135 |
136 | // Apply main text color tint.
137 | float3 col = imageRgb * lum * pow(brightnessBoost, 2.0);
138 |
139 | if (enableShadows > 0.5)
140 | {
141 | // Screen shadow.
142 | float bright = 1.0;
143 | if (uv.y < 0.0)
144 | bright = smoothstep(0.43, 0.38, length(uv * float2(0.4, 1.0)));
145 | col *= min(1.0, 0.3 + 0.7 * (bright + clamp(max(max(col.r, col.g), col.b), 0.0, 1.0)));
146 |
147 | // Glare.
148 | col = mix(col, float3(0.5 + 0.5 * ns), bright * 0.25 * smoothstep(0.7, 0.0, length((uv - float2(0.15, -0.3)) * float2(1.0, 2.0))));
149 |
150 | // Vignette.
151 | col *= 1.0 - 1.2 * dot(uv, uv);
152 | }
153 |
154 | return float4(col, 1.0);
155 | }
156 |
--------------------------------------------------------------------------------
/CrtTextBox/ShaderControl.cs:
--------------------------------------------------------------------------------
1 | // Code authored by Dean Edis (DeanTheCoder).
2 | // Anyone is free to copy, modify, use, compile, or distribute this software,
3 | // either in source code form or as a compiled binary, for any non-commercial
4 | // purpose.
5 | //
6 | // If you modify the code, please retain this copyright header,
7 | // and consider contributing back to the repository or letting us know
8 | // about your modifications. Your contributions are valued!
9 | //
10 | // THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND.
11 | using System;
12 | using System.Collections.Generic;
13 | using System.IO;
14 | using System.Numerics;
15 | using Avalonia;
16 | using Avalonia.Controls;
17 | using Avalonia.Media;
18 | using Avalonia.Media.Imaging;
19 | using Avalonia.Platform;
20 | using Avalonia.Rendering.Composition;
21 | using Avalonia.Skia;
22 | using Avalonia.Threading;
23 | using SkiaSharp;
24 |
25 | namespace RenderTest;
26 |
27 | ///
28 | /// A custom Avalonia control that applies a shader effect to a visual element.
29 | ///
30 | public class ShaderControl : UserControl
31 | {
32 | private readonly Dictionary> m_uniforms = new Dictionary>();
33 | private CompositionCustomVisual m_customVisual;
34 | private Control m_controlSource;
35 | private SKBitmap m_sourceControlBitmap;
36 | private ShaderVisualHandler m_visualHandler;
37 | private SKBitmap m_blurredControlBitmap;
38 | private RenderTargetBitmap m_renderTargetBitmap;
39 |
40 | ///
41 | /// Defines the Uri property for the shader source.
42 | ///
43 | public static readonly StyledProperty ShaderUriProperty =
44 | AvaloniaProperty.Register(nameof(ShaderUri));
45 |
46 | ///
47 | /// Defines the sampling frame rate of the source control.
48 | ///
49 | public static readonly StyledProperty FpsProperty = AvaloniaProperty.Register(nameof(Fps), 30);
50 |
51 | ///
52 | /// Defines whether phosphor trails are added.
53 | ///
54 | public static readonly StyledProperty TrailsProperty = AvaloniaProperty.Register(nameof(Trails));
55 |
56 | static ShaderControl()
57 | {
58 | AffectsRender(ShaderUriProperty);
59 | AffectsMeasure(ShaderUriProperty);
60 | }
61 |
62 | ///
63 | /// Gets or sets the frames per second (FPS) at which the source control is sampled.
64 | ///
65 | public int Fps
66 | {
67 | get => GetValue(FpsProperty);
68 | set => SetValue(FpsProperty, value);
69 | }
70 |
71 | ///
72 | /// Gets or sets the URI of the shader to be applied.
73 | ///
74 | public Uri ShaderUri
75 | {
76 | get => GetValue(ShaderUriProperty);
77 | set => SetValue(ShaderUriProperty, value);
78 | }
79 |
80 | ///
81 | /// Gets or sets whether phosphor trails are added.
82 | ///
83 | public bool Trails
84 | {
85 | get => GetValue(TrailsProperty);
86 | set => SetValue(TrailsProperty, value);
87 | }
88 |
89 | ///
90 | /// Gets or sets the control source to which the shader effect will be applied.
91 | ///
92 | ///
93 | /// Thrown if the control source is already set.
94 | ///
95 | ///
96 | /// Thrown if the control source is set to null.
97 | ///
98 | public Control ControlSource
99 | {
100 | get => m_controlSource;
101 | set
102 | {
103 | if (m_controlSource != null)
104 | throw new InvalidOperationException($"{nameof(ControlSource)} has already been set.");
105 | m_controlSource = value ?? throw new ArgumentNullException();
106 |
107 | DispatcherTimer.Run(() =>
108 | {
109 | RenderSourceAsImage();
110 | return true;
111 | }, TimeSpan.FromSeconds(1.0 / Fps));
112 | }
113 | }
114 |
115 | ///
116 | /// Call to set a constant boolean uniform value, to be passed (as 0.0 or 1.0) to the shader code each frame.
117 | ///
118 | ///
119 | /// To receive the value in the shader, use:
120 | /// uniform float iName;
121 | ///
122 | public void AddUniform(string name, bool value) =>
123 | AddUniform(name, value ? 1.0f : 0.0f);
124 |
125 | ///
126 | /// Call to set a constant uniform float/float2/float3/float4 value, to be passed to the shader code each frame.
127 | ///
128 | ///
129 | /// To receive the values in the shader, use:
130 | /// uniform float3 iName;
131 | ///
132 | public void AddUniform(string name, params float[] values) =>
133 | AddUniform(name, () => values);
134 |
135 | ///
136 | /// Call to set a variable uniform value using a callback function, to be passed to the shader code each frame.
137 | ///
138 | ///
139 | /// To receive the value in the shader, use:
140 | /// uniform float3 iName;
141 | ///
142 | public void AddUniform(string name, Func getValue) =>
143 | m_uniforms[name] = getValue;
144 |
145 | ///
146 | /// Called in response to the source control changing state, this method renders the source
147 | /// control into a bitmap, allowing for its appearance to later be modified when displayed
148 | /// to the screen.
149 | ///
150 | private void RenderSourceAsImage()
151 | {
152 | if (Bounds.Width == 0 || Bounds.Height == 0)
153 | return;
154 |
155 | // Check if the control bitmap needs to be recreated (e.g., if size has changed).
156 | if (m_sourceControlBitmap == null || m_sourceControlBitmap.Width != (int)Bounds.Width || m_sourceControlBitmap.Height != (int)Bounds.Height)
157 | {
158 | m_sourceControlBitmap?.Dispose();
159 | m_sourceControlBitmap = new SKBitmap(new SKImageInfo((int)Bounds.Width, (int)Bounds.Height, SKColorType.Rgba8888, SKAlphaType.Premul));
160 | m_blurredControlBitmap?.Dispose();
161 | m_blurredControlBitmap = new SKBitmap(new SKImageInfo((int)Bounds.Width, (int)Bounds.Height, SKImageInfo.PlatformColorType, SKAlphaType.Premul));
162 | m_renderTargetBitmap?.Dispose();
163 | m_renderTargetBitmap = new RenderTargetBitmap(new PixelSize(m_sourceControlBitmap.Width, m_sourceControlBitmap.Height));
164 | }
165 |
166 | // Get the image of the Avalonia source control.
167 | m_renderTargetBitmap.Render(ControlSource);
168 |
169 | // Convert it to an SKBitmap.
170 | m_renderTargetBitmap.CopyPixels(
171 | new PixelRect(0, 0, m_blurredControlBitmap.Width, m_blurredControlBitmap.Height),
172 | m_blurredControlBitmap.GetPixels(),
173 | m_blurredControlBitmap.ByteCount,
174 | m_blurredControlBitmap.RowBytes);
175 |
176 | if (Trails)
177 | {
178 | // Combine image with the previous frame, to add motion blur.
179 | using var paint = new SKPaint();
180 | paint.Color = new SKColor(0xff, 0xff, 0xff, 100);
181 | paint.BlendMode = SKBlendMode.SrcOver;
182 | using var canvas = new SKCanvas(m_sourceControlBitmap);
183 | canvas.DrawBitmap(m_blurredControlBitmap, 0, 0, paint);
184 | }
185 | else
186 | {
187 | using var canvas = new SKCanvas(m_sourceControlBitmap);
188 | canvas.DrawBitmap(m_blurredControlBitmap, 0, 0);
189 | }
190 |
191 | // Set the image to send to the shader for display.
192 | m_visualHandler.SourceBitmap = m_sourceControlBitmap;
193 | }
194 |
195 | private Size GetShaderSize() => m_controlSource?.Bounds.Size ?? new Size(512, 512);
196 |
197 | protected override Size MeasureOverride(Size availableSize) =>
198 | ShaderUri != null ? Stretch.Fill.CalculateSize(availableSize, GetShaderSize()) : new Size();
199 |
200 | protected override Size ArrangeOverride(Size finalSize)
201 | {
202 | var source = ShaderUri;
203 | if (source == null)
204 | return new Size();
205 |
206 | var sourceSize = GetShaderSize();
207 | return Stretch.Fill.CalculateSize(finalSize, sourceSize);
208 | }
209 |
210 | protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
211 | {
212 | base.OnAttachedToVisualTree(e);
213 |
214 | IsHitTestVisible = false;
215 |
216 | var elemVisual = ElementComposition.GetElementVisual(this);
217 | var compositor = elemVisual?.Compositor;
218 | if (compositor is null)
219 | return;
220 |
221 | m_visualHandler = new ShaderVisualHandler(m_uniforms);
222 | m_customVisual = compositor.CreateCustomVisual(m_visualHandler);
223 | ElementComposition.SetElementChildVisual(this, m_customVisual);
224 |
225 | LayoutUpdated += OnLayoutUpdated;
226 |
227 | m_customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
228 |
229 | m_customVisual.SendHandlerMessage(
230 | new ShaderVisualHandler.DrawPayload(
231 | ShaderVisualHandler.Command.Update,
232 | null,
233 | GetShaderSize(),
234 | Bounds.Size));
235 |
236 | Start();
237 | }
238 |
239 | protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
240 | {
241 | base.OnDetachedFromVisualTree(e);
242 | LayoutUpdated -= OnLayoutUpdated;
243 |
244 | Stop();
245 | DisposeImpl();
246 | }
247 |
248 | private void OnLayoutUpdated(object sender, EventArgs e)
249 | {
250 | if (m_customVisual == null)
251 | return;
252 |
253 | m_customVisual.Size = new Vector2((float)Bounds.Size.Width, (float)Bounds.Size.Height);
254 |
255 | m_customVisual.SendHandlerMessage(
256 | new ShaderVisualHandler.DrawPayload(
257 | ShaderVisualHandler.Command.Update,
258 | null,
259 | GetShaderSize(),
260 | Bounds.Size));
261 | }
262 |
263 | private void Start()
264 | {
265 | m_customVisual?.SendHandlerMessage(
266 | new ShaderVisualHandler.DrawPayload(
267 | ShaderVisualHandler.Command.Start,
268 | ShaderUri,
269 | GetShaderSize(),
270 | Bounds.Size));
271 | InvalidateVisual();
272 | }
273 |
274 | private void Stop() =>
275 | m_customVisual?.SendHandlerMessage(new ShaderVisualHandler.DrawPayload(ShaderVisualHandler.Command.Stop));
276 |
277 | private void DisposeImpl() =>
278 | m_customVisual?.SendHandlerMessage(new ShaderVisualHandler.DrawPayload(ShaderVisualHandler.Command.Dispose));
279 |
280 | ///
281 | /// Apply new shader code.
282 | ///
283 | public void SetSksl(string sksl)
284 | {
285 | Stop();
286 | m_visualHandler.ShaderCode = sksl;
287 | Start();
288 | }
289 |
290 | ///
291 | /// Handles custom visual drawing for the shader effect.
292 | ///
293 | private class ShaderVisualHandler : CompositionCustomVisualHandler
294 | {
295 | private readonly object m_sync = new object();
296 | private readonly Dictionary> m_customUniforms;
297 | private Size? m_boundsSize;
298 | private SKRuntimeEffect m_effect;
299 | private bool m_isDisposed;
300 | private bool m_running;
301 | private Size? m_shaderSize;
302 | private SKRuntimeEffectUniforms m_uniforms;
303 |
304 | internal string ShaderCode { get; set; }
305 |
306 | public ShaderVisualHandler(Dictionary> uniforms)
307 | {
308 | m_customUniforms = uniforms;
309 | m_customUniforms["iTime"] = () => new[] { (float)CompositionNow.TotalSeconds };
310 | }
311 |
312 | ///
313 | /// Gets or sets the source bitmap that the shader effect is applied to.
314 | ///
315 | public SKBitmap SourceBitmap { get; set; }
316 |
317 | ///
318 | /// Handles messages sent to the visual handler, such as starting or stopping the shader effect.
319 | ///
320 | public override void OnMessage(object message)
321 | {
322 | if (message is not DrawPayload msg)
323 | return;
324 |
325 | switch (msg)
326 | {
327 | case { Command: Command.Start, ShaderCode: { } uri, ShaderSize: { } shaderSize, Size: { } size }:
328 | {
329 | if (ShaderCode == null)
330 | {
331 | using var stream = AssetLoader.Open(uri);
332 | using var txt = new StreamReader(stream);
333 | ShaderCode = txt.ReadToEnd();
334 | }
335 |
336 | m_effect = SKRuntimeEffect.Create(ShaderCode, out var errorText);
337 | if (m_effect == null)
338 | Console.WriteLine($"Shader compilation error: {errorText}");
339 |
340 | m_shaderSize = shaderSize;
341 | m_running = true;
342 | m_boundsSize = size;
343 | RegisterForNextAnimationFrameUpdate();
344 | break;
345 | }
346 | case { Command: Command.Update, ShaderSize: { } shaderSize, Size: { } size }:
347 | {
348 | m_shaderSize = shaderSize;
349 | m_boundsSize = size;
350 | RegisterForNextAnimationFrameUpdate();
351 | break;
352 | }
353 | case { Command: Command.Stop }:
354 | {
355 | m_running = false;
356 | break;
357 | }
358 | case { Command: Command.Dispose }:
359 | {
360 | DisposeImpl();
361 | break;
362 | }
363 | }
364 | }
365 |
366 | ///
367 | /// Updates the shader effect on each animation frame, and schedules the next frame to be processed.
368 | ///
369 | public override void OnAnimationFrameUpdate()
370 | {
371 | if (!m_running || m_isDisposed)
372 | return;
373 |
374 | Invalidate();
375 | RegisterForNextAnimationFrameUpdate();
376 | }
377 |
378 | ///
379 | /// Draws the shader effect onto the given SkiaSharp canvas.
380 | ///
381 | private void Draw(SKCanvas canvas)
382 | {
383 | if (m_isDisposed || m_effect is null)
384 | return;
385 |
386 | canvas.Save();
387 |
388 | var targetWidth = (float)(m_shaderSize?.Width ?? 0.0);
389 | var targetHeight = (float)(m_shaderSize?.Height ?? 0.0);
390 |
391 | m_uniforms ??= new SKRuntimeEffectUniforms(m_effect);
392 |
393 | m_uniforms["iResolution"] = new[]
394 | {
395 | targetWidth, targetHeight
396 | };
397 |
398 | foreach (var (name, getValue) in m_customUniforms)
399 | m_uniforms[name] = getValue();
400 |
401 | SKRuntimeEffectChildren children = null;
402 | using var imageShader = SourceBitmap?.ToShader();
403 | if (imageShader != null)
404 | {
405 | children = new SKRuntimeEffectChildren(m_effect)
406 | {
407 | ["iImage1"] = imageShader
408 | };
409 | m_uniforms["iImageResolution"] = new float[]
410 | {
411 | SourceBitmap.Width, SourceBitmap.Height
412 | };
413 | }
414 |
415 | using (var paint = new SKPaint())
416 | using (var shader = children != null ? m_effect.ToShader(false, m_uniforms, children) : m_effect.ToShader(false, m_uniforms))
417 | {
418 | paint.Shader = shader;
419 | paint.FilterQuality = SKFilterQuality.Low;
420 | canvas.DrawRect(SKRect.Create(targetWidth, targetHeight), paint);
421 | }
422 |
423 | canvas.Restore();
424 | }
425 |
426 | ///
427 | /// Renders the shader effect within the context of the Avalonia ImmediateDrawingContext.
428 | ///
429 | /// The drawing context.
430 | public override void OnRender(ImmediateDrawingContext context)
431 | {
432 | lock (m_sync)
433 | {
434 | if (m_isDisposed)
435 | return;
436 |
437 | var leaseFeature = context.TryGetFeature();
438 | if (leaseFeature is null)
439 | return;
440 |
441 | var rb = GetRenderBounds();
442 | var size = m_boundsSize ?? rb.Size;
443 | var viewPort = new Rect(rb.Size);
444 | var sourceSize = m_shaderSize!.Value;
445 |
446 | if (sourceSize.Width <= 0 || sourceSize.Height <= 0)
447 | return;
448 |
449 | var scale = Stretch.Fill.CalculateScaling(rb.Size, sourceSize);
450 | var scaledSize = sourceSize * scale;
451 | var destRect = viewPort
452 | .CenterRect(new Rect(scaledSize))
453 | .Intersect(viewPort);
454 | var sourceRect = new Rect(sourceSize)
455 | .CenterRect(new Rect(destRect.Size / scale));
456 |
457 | var bounds = SKRect.Create(new SKPoint(), new SKSize((float)size.Width, (float)size.Height));
458 |
459 | var scaleMatrix = Matrix.CreateScale(
460 | destRect.Width / sourceRect.Width,
461 | destRect.Height / sourceRect.Height);
462 |
463 | var translateMatrix = Matrix.CreateTranslation(
464 | (-sourceRect.X + destRect.X) - bounds.Top,
465 | (-sourceRect.Y + destRect.Y) - bounds.Left);
466 |
467 | using (context.PushClip(destRect))
468 | using (context.PushPostTransform(translateMatrix * scaleMatrix))
469 | {
470 | using var lease = leaseFeature.Lease();
471 | Draw(lease.SkCanvas);
472 | }
473 | }
474 | }
475 |
476 | private void DisposeImpl()
477 | {
478 | lock (m_sync)
479 | {
480 | if (m_isDisposed) return;
481 | m_isDisposed = true;
482 | m_effect?.Dispose();
483 | m_uniforms?.Reset();
484 | m_running = false;
485 | }
486 | }
487 |
488 | ///
489 | /// Enum representing commands sent to the shader visual handler.
490 | ///
491 | public enum Command
492 | {
493 | Start,
494 | Stop,
495 | Update,
496 | Dispose
497 | }
498 |
499 | ///
500 | /// A struct representing the payload for draw commands sent to the shader visual handler.
501 | ///
502 | public record struct DrawPayload(
503 | Command Command,
504 | Uri ShaderCode = default,
505 | Size? ShaderSize = default,
506 | Size? Size = default);
507 | }
508 | }
--------------------------------------------------------------------------------
/CrtTextBox/Assets/Fonts/VGA/LICENSE.TXT:
--------------------------------------------------------------------------------
1 | Attribution-ShareAlike 4.0 International
2 |
3 | =======================================================================
4 |
5 | Creative Commons Corporation ("Creative Commons") is not a law firm and
6 | does not provide legal services or legal advice. Distribution of
7 | Creative Commons public licenses does not create a lawyer-client or
8 | other relationship. Creative Commons makes its licenses and related
9 | information available on an "as-is" basis. Creative Commons gives no
10 | warranties regarding its licenses, any material licensed under their
11 | terms and conditions, or any related information. Creative Commons
12 | disclaims all liability for damages resulting from their use to the
13 | fullest extent possible.
14 |
15 | Using Creative Commons Public Licenses
16 |
17 | Creative Commons public licenses provide a standard set of terms and
18 | conditions that creators and other rights holders may use to share
19 | original works of authorship and other material subject to copyright
20 | and certain other rights specified in the public license below. The
21 | following considerations are for informational purposes only, are not
22 | exhaustive, and do not form part of our licenses.
23 |
24 | Considerations for licensors: Our public licenses are
25 | intended for use by those authorized to give the public
26 | permission to use material in ways otherwise restricted by
27 | copyright and certain other rights. Our licenses are
28 | irrevocable. Licensors should read and understand the terms
29 | and conditions of the license they choose before applying it.
30 | Licensors should also secure all rights necessary before
31 | applying our licenses so that the public can reuse the
32 | material as expected. Licensors should clearly mark any
33 | material not subject to the license. This includes other CC-
34 | licensed material, or material used under an exception or
35 | limitation to copyright. More considerations for licensors:
36 | wiki.creativecommons.org/Considerations_for_licensors
37 |
38 | Considerations for the public: By using one of our public
39 | licenses, a licensor grants the public permission to use the
40 | licensed material under specified terms and conditions. If
41 | the licensor's permission is not necessary for any reason--for
42 | example, because of any applicable exception or limitation to
43 | copyright--then that use is not regulated by the license. Our
44 | licenses grant only permissions under copyright and certain
45 | other rights that a licensor has authority to grant. Use of
46 | the licensed material may still be restricted for other
47 | reasons, including because others have copyright or other
48 | rights in the material. A licensor may make special requests,
49 | such as asking that all changes be marked or described.
50 | Although not required by our licenses, you are encouraged to
51 | respect those requests where reasonable. More_considerations
52 | for the public:
53 | wiki.creativecommons.org/Considerations_for_licensees
54 |
55 | =======================================================================
56 |
57 | Creative Commons Attribution-ShareAlike 4.0 International Public
58 | License
59 |
60 | By exercising the Licensed Rights (defined below), You accept and agree
61 | to be bound by the terms and conditions of this Creative Commons
62 | Attribution-ShareAlike 4.0 International Public License ("Public
63 | License"). To the extent this Public License may be interpreted as a
64 | contract, You are granted the Licensed Rights in consideration of Your
65 | acceptance of these terms and conditions, and the Licensor grants You
66 | such rights in consideration of benefits the Licensor receives from
67 | making the Licensed Material available under these terms and
68 | conditions.
69 |
70 |
71 | Section 1 -- Definitions.
72 |
73 | a. Adapted Material means material subject to Copyright and Similar
74 | Rights that is derived from or based upon the Licensed Material
75 | and in which the Licensed Material is translated, altered,
76 | arranged, transformed, or otherwise modified in a manner requiring
77 | permission under the Copyright and Similar Rights held by the
78 | Licensor. For purposes of this Public License, where the Licensed
79 | Material is a musical work, performance, or sound recording,
80 | Adapted Material is always produced where the Licensed Material is
81 | synched in timed relation with a moving image.
82 |
83 | b. Adapter's License means the license You apply to Your Copyright
84 | and Similar Rights in Your contributions to Adapted Material in
85 | accordance with the terms and conditions of this Public License.
86 |
87 | c. BY-SA Compatible License means a license listed at
88 | creativecommons.org/compatiblelicenses, approved by Creative
89 | Commons as essentially the equivalent of this Public License.
90 |
91 | d. Copyright and Similar Rights means copyright and/or similar rights
92 | closely related to copyright including, without limitation,
93 | performance, broadcast, sound recording, and Sui Generis Database
94 | Rights, without regard to how the rights are labeled or
95 | categorized. For purposes of this Public License, the rights
96 | specified in Section 2(b)(1)-(2) are not Copyright and Similar
97 | Rights.
98 |
99 | e. Effective Technological Measures means those measures that, in the
100 | absence of proper authority, may not be circumvented under laws
101 | fulfilling obligations under Article 11 of the WIPO Copyright
102 | Treaty adopted on December 20, 1996, and/or similar international
103 | agreements.
104 |
105 | f. Exceptions and Limitations means fair use, fair dealing, and/or
106 | any other exception or limitation to Copyright and Similar Rights
107 | that applies to Your use of the Licensed Material.
108 |
109 | g. License Elements means the license attributes listed in the name
110 | of a Creative Commons Public License. The License Elements of this
111 | Public License are Attribution and ShareAlike.
112 |
113 | h. Licensed Material means the artistic or literary work, database,
114 | or other material to which the Licensor applied this Public
115 | License.
116 |
117 | i. Licensed Rights means the rights granted to You subject to the
118 | terms and conditions of this Public License, which are limited to
119 | all Copyright and Similar Rights that apply to Your use of the
120 | Licensed Material and that the Licensor has authority to license.
121 |
122 | j. Licensor means the individual(s) or entity(ies) granting rights
123 | under this Public License.
124 |
125 | k. Share means to provide material to the public by any means or
126 | process that requires permission under the Licensed Rights, such
127 | as reproduction, public display, public performance, distribution,
128 | dissemination, communication, or importation, and to make material
129 | available to the public including in ways that members of the
130 | public may access the material from a place and at a time
131 | individually chosen by them.
132 |
133 | l. Sui Generis Database Rights means rights other than copyright
134 | resulting from Directive 96/9/EC of the European Parliament and of
135 | the Council of 11 March 1996 on the legal protection of databases,
136 | as amended and/or succeeded, as well as other essentially
137 | equivalent rights anywhere in the world.
138 |
139 | m. You means the individual or entity exercising the Licensed Rights
140 | under this Public License. Your has a corresponding meaning.
141 |
142 |
143 | Section 2 -- Scope.
144 |
145 | a. License grant.
146 |
147 | 1. Subject to the terms and conditions of this Public License,
148 | the Licensor hereby grants You a worldwide, royalty-free,
149 | non-sublicensable, non-exclusive, irrevocable license to
150 | exercise the Licensed Rights in the Licensed Material to:
151 |
152 | a. reproduce and Share the Licensed Material, in whole or
153 | in part; and
154 |
155 | b. produce, reproduce, and Share Adapted Material.
156 |
157 | 2. Exceptions and Limitations. For the avoidance of doubt, where
158 | Exceptions and Limitations apply to Your use, this Public
159 | License does not apply, and You do not need to comply with
160 | its terms and conditions.
161 |
162 | 3. Term. The term of this Public License is specified in Section
163 | 6(a).
164 |
165 | 4. Media and formats; technical modifications allowed. The
166 | Licensor authorizes You to exercise the Licensed Rights in
167 | all media and formats whether now known or hereafter created,
168 | and to make technical modifications necessary to do so. The
169 | Licensor waives and/or agrees not to assert any right or
170 | authority to forbid You from making technical modifications
171 | necessary to exercise the Licensed Rights, including
172 | technical modifications necessary to circumvent Effective
173 | Technological Measures. For purposes of this Public License,
174 | simply making modifications authorized by this Section 2(a)
175 | (4) never produces Adapted Material.
176 |
177 | 5. Downstream recipients.
178 |
179 | a. Offer from the Licensor -- Licensed Material. Every
180 | recipient of the Licensed Material automatically
181 | receives an offer from the Licensor to exercise the
182 | Licensed Rights under the terms and conditions of this
183 | Public License.
184 |
185 | b. Additional offer from the Licensor -- Adapted Material.
186 | Every recipient of Adapted Material from You
187 | automatically receives an offer from the Licensor to
188 | exercise the Licensed Rights in the Adapted Material
189 | under the conditions of the Adapter's License You apply.
190 |
191 | c. No downstream restrictions. You may not offer or impose
192 | any additional or different terms or conditions on, or
193 | apply any Effective Technological Measures to, the
194 | Licensed Material if doing so restricts exercise of the
195 | Licensed Rights by any recipient of the Licensed
196 | Material.
197 |
198 | 6. No endorsement. Nothing in this Public License constitutes or
199 | may be construed as permission to assert or imply that You
200 | are, or that Your use of the Licensed Material is, connected
201 | with, or sponsored, endorsed, or granted official status by,
202 | the Licensor or others designated to receive attribution as
203 | provided in Section 3(a)(1)(A)(i).
204 |
205 | b. Other rights.
206 |
207 | 1. Moral rights, such as the right of integrity, are not
208 | licensed under this Public License, nor are publicity,
209 | privacy, and/or other similar personality rights; however, to
210 | the extent possible, the Licensor waives and/or agrees not to
211 | assert any such rights held by the Licensor to the limited
212 | extent necessary to allow You to exercise the Licensed
213 | Rights, but not otherwise.
214 |
215 | 2. Patent and trademark rights are not licensed under this
216 | Public License.
217 |
218 | 3. To the extent possible, the Licensor waives any right to
219 | collect royalties from You for the exercise of the Licensed
220 | Rights, whether directly or through a collecting society
221 | under any voluntary or waivable statutory or compulsory
222 | licensing scheme. In all other cases the Licensor expressly
223 | reserves any right to collect such royalties.
224 |
225 |
226 | Section 3 -- License Conditions.
227 |
228 | Your exercise of the Licensed Rights is expressly made subject to the
229 | following conditions.
230 |
231 | a. Attribution.
232 |
233 | 1. If You Share the Licensed Material (including in modified
234 | form), You must:
235 |
236 | a. retain the following if it is supplied by the Licensor
237 | with the Licensed Material:
238 |
239 | i. identification of the creator(s) of the Licensed
240 | Material and any others designated to receive
241 | attribution, in any reasonable manner requested by
242 | the Licensor (including by pseudonym if
243 | designated);
244 |
245 | ii. a copyright notice;
246 |
247 | iii. a notice that refers to this Public License;
248 |
249 | iv. a notice that refers to the disclaimer of
250 | warranties;
251 |
252 | v. a URI or hyperlink to the Licensed Material to the
253 | extent reasonably practicable;
254 |
255 | b. indicate if You modified the Licensed Material and
256 | retain an indication of any previous modifications; and
257 |
258 | c. indicate the Licensed Material is licensed under this
259 | Public License, and include the text of, or the URI or
260 | hyperlink to, this Public License.
261 |
262 | 2. You may satisfy the conditions in Section 3(a)(1) in any
263 | reasonable manner based on the medium, means, and context in
264 | which You Share the Licensed Material. For example, it may be
265 | reasonable to satisfy the conditions by providing a URI or
266 | hyperlink to a resource that includes the required
267 | information.
268 |
269 | 3. If requested by the Licensor, You must remove any of the
270 | information required by Section 3(a)(1)(A) to the extent
271 | reasonably practicable.
272 |
273 | b. ShareAlike.
274 |
275 | In addition to the conditions in Section 3(a), if You Share
276 | Adapted Material You produce, the following conditions also apply.
277 |
278 | 1. The Adapter's License You apply must be a Creative Commons
279 | license with the same License Elements, this version or
280 | later, or a BY-SA Compatible License.
281 |
282 | 2. You must include the text of, or the URI or hyperlink to, the
283 | Adapter's License You apply. You may satisfy this condition
284 | in any reasonable manner based on the medium, means, and
285 | context in which You Share Adapted Material.
286 |
287 | 3. You may not offer or impose any additional or different terms
288 | or conditions on, or apply any Effective Technological
289 | Measures to, Adapted Material that restrict exercise of the
290 | rights granted under the Adapter's License You apply.
291 |
292 |
293 | Section 4 -- Sui Generis Database Rights.
294 |
295 | Where the Licensed Rights include Sui Generis Database Rights that
296 | apply to Your use of the Licensed Material:
297 |
298 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right
299 | to extract, reuse, reproduce, and Share all or a substantial
300 | portion of the contents of the database;
301 |
302 | b. if You include all or a substantial portion of the database
303 | contents in a database in which You have Sui Generis Database
304 | Rights, then the database in which You have Sui Generis Database
305 | Rights (but not its individual contents) is Adapted Material,
306 |
307 | including for purposes of Section 3(b); and
308 | c. You must comply with the conditions in Section 3(a) if You Share
309 | all or a substantial portion of the contents of the database.
310 |
311 | For the avoidance of doubt, this Section 4 supplements and does not
312 | replace Your obligations under this Public License where the Licensed
313 | Rights include other Copyright and Similar Rights.
314 |
315 |
316 | Section 5 -- Disclaimer of Warranties and Limitation of Liability.
317 |
318 | a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
319 | EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
320 | AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
321 | ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
322 | IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
323 | WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
324 | PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
325 | ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
326 | KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
327 | ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
328 |
329 | b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
330 | TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
331 | NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
332 | INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
333 | COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
334 | USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
335 | ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
336 | DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
337 | IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
338 |
339 | c. The disclaimer of warranties and limitation of liability provided
340 | above shall be interpreted in a manner that, to the extent
341 | possible, most closely approximates an absolute disclaimer and
342 | waiver of all liability.
343 |
344 |
345 | Section 6 -- Term and Termination.
346 |
347 | a. This Public License applies for the term of the Copyright and
348 | Similar Rights licensed here. However, if You fail to comply with
349 | this Public License, then Your rights under this Public License
350 | terminate automatically.
351 |
352 | b. Where Your right to use the Licensed Material has terminated under
353 | Section 6(a), it reinstates:
354 |
355 | 1. automatically as of the date the violation is cured, provided
356 | it is cured within 30 days of Your discovery of the
357 | violation; or
358 |
359 | 2. upon express reinstatement by the Licensor.
360 |
361 | For the avoidance of doubt, this Section 6(b) does not affect any
362 | right the Licensor may have to seek remedies for Your violations
363 | of this Public License.
364 |
365 | c. For the avoidance of doubt, the Licensor may also offer the
366 | Licensed Material under separate terms or conditions or stop
367 | distributing the Licensed Material at any time; however, doing so
368 | will not terminate this Public License.
369 |
370 | d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
371 | License.
372 |
373 |
374 | Section 7 -- Other Terms and Conditions.
375 |
376 | a. The Licensor shall not be bound by any additional or different
377 | terms or conditions communicated by You unless expressly agreed.
378 |
379 | b. Any arrangements, understandings, or agreements regarding the
380 | Licensed Material not stated herein are separate from and
381 | independent of the terms and conditions of this Public License.
382 |
383 |
384 | Section 8 -- Interpretation.
385 |
386 | a. For the avoidance of doubt, this Public License does not, and
387 | shall not be interpreted to, reduce, limit, restrict, or impose
388 | conditions on any use of the Licensed Material that could lawfully
389 | be made without permission under this Public License.
390 |
391 | b. To the extent possible, if any provision of this Public License is
392 | deemed unenforceable, it shall be automatically reformed to the
393 | minimum extent necessary to make it enforceable. If the provision
394 | cannot be reformed, it shall be severed from this Public License
395 | without affecting the enforceability of the remaining terms and
396 | conditions.
397 |
398 | c. No term or condition of this Public License will be waived and no
399 | failure to comply consented to unless expressly agreed to by the
400 | Licensor.
401 |
402 | d. Nothing in this Public License constitutes or may be interpreted
403 | as a limitation upon, or waiver of, any privileges and immunities
404 | that apply to the Licensor or You, including from the legal
405 | processes of any jurisdiction or authority.
406 |
407 |
408 | =======================================================================
409 |
410 | Creative Commons is not a party to its public
411 | licenses. Notwithstanding, Creative Commons may elect to apply one of
412 | its public licenses to material it publishes and in those instances
413 | will be considered the “Licensor.” The text of the Creative Commons
414 | public licenses is dedicated to the public domain under the CC0 Public
415 | Domain Dedication. Except for the limited purpose of indicating that
416 | material is shared under a Creative Commons public license or as
417 | otherwise permitted by the Creative Commons policies published at
418 | creativecommons.org/policies, Creative Commons does not authorize the
419 | use of the trademark "Creative Commons" or any other trademark or logo
420 | of Creative Commons without its prior written consent including,
421 | without limitation, in connection with any unauthorized modifications
422 | to any of its public licenses or any other arrangements,
423 | understandings, or agreements concerning use of licensed material. For
424 | the avoidance of doubt, this paragraph does not form part of the
425 | public licenses.
426 |
427 | Creative Commons may be contacted at creativecommons.org.
428 |
429 |
--------------------------------------------------------------------------------