<postprocess>, fix tab open/close, fix some URL bugs
236
docs/docs/postprocess.md
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
---
|
||||||
|
sidebar_position: 5
|
||||||
|
---
|
||||||
|
|
||||||
|
# Postprocess
|
||||||
|
|
||||||
|
The `<postprocess>` tag in Gurted allows you to apply real-time visual effects to your entire webpage through GPU-accelerated shaders. These effects are rendered as an overlay on top of your content, not affecting the browser UI.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
The postprocess tag supports three ways to define shader effects:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- Using built-in presets -->
|
||||||
|
<postprocess preset="crt" />
|
||||||
|
|
||||||
|
<!-- Loading external shader files -->
|
||||||
|
<postprocess src="custom-shader.gdshader" />
|
||||||
|
|
||||||
|
<!-- Inline shader code -->
|
||||||
|
<postprocess>
|
||||||
|
shader_type canvas_item;
|
||||||
|
void fragment() {
|
||||||
|
COLOR = texture(SCREEN_TEXTURE, SCREEN_UV);
|
||||||
|
}
|
||||||
|
</postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Shader Tutorial
|
||||||
|
For documentation on how to write GDShader code, see the [Godot Shader Language documentation](https://docs.godotengine.org/en/stable/tutorials/shading/index.html).
|
||||||
|
|
||||||
|
### Parameters
|
||||||
|
|
||||||
|
HTML attributes are automatically converted to shader uniforms with the following supported types:
|
||||||
|
|
||||||
|
#### Numeric Types
|
||||||
|
```html
|
||||||
|
<!-- Float values -->
|
||||||
|
<postprocess preset="vignette" vignette_strength="1.5"></postprocess>
|
||||||
|
|
||||||
|
<!-- Integer values -->
|
||||||
|
<postprocess preset="snowfall" num_of_layers="25"></postprocess>
|
||||||
|
|
||||||
|
<!-- Boolean values -->
|
||||||
|
<postprocess preset="custom" enable_effect="true"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Vector Types
|
||||||
|
```html
|
||||||
|
<!-- Vector2 -->
|
||||||
|
<postprocess preset="rblur" blur_center="Vector2(0.3, 0.7)"></postprocess>
|
||||||
|
<postprocess preset="rblur" blur_center="vec2(0.3, 0.7)"></postprocess>
|
||||||
|
|
||||||
|
<!-- Vector3 -->
|
||||||
|
<postprocess preset="lensflare" tint="Vector3(1.4, 1.2, 1.0)"></postprocess>
|
||||||
|
<postprocess preset="lensflare" tint="vec3(1.4, 1.2, 1.0)"></postprocess>
|
||||||
|
|
||||||
|
<!-- Vector4 -->
|
||||||
|
<postprocess preset="vignette" vignette_color="Vector4(0.0, 0.0, 0.0, 1.0)"></postprocess>
|
||||||
|
<postprocess preset="vignette" vignette_color="vec4(0.0, 0.0, 0.0, 1.0)"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Color Values
|
||||||
|
```html
|
||||||
|
<!-- Hex colors -->
|
||||||
|
<postprocess preset="vignette" vignette_color="#ff0000"></postprocess>
|
||||||
|
|
||||||
|
<!-- Named colors work as strings -->
|
||||||
|
<postprocess preset="snowfall" snow_color="white"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Built-in Preset Shaders
|
||||||
|
|
||||||
|
### CRT Monitor Effect
|
||||||
|
Creates a retro CRT monitor appearance with scanlines, distortion, and screen curvature.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<postprocess preset="crt"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Available Properties:**
|
||||||
|
- `curvature` (0.0-10.0, default: 2.0) - Screen curvature amount
|
||||||
|
- `skip` (0.0-1.0, default: 1.0) - Vertical hold distortion intensity
|
||||||
|
- `image_flicker` (0.0-1.0, default: 1.0) - Image flicker intensity
|
||||||
|
- `vignette_flicker_speed` (0.0-2.0, default: 1.0) - Vignette animation speed
|
||||||
|
- `vignette_strength` (0.0-2.0, default: 1.0) - Dark edge vignette intensity
|
||||||
|
- `small_scanlines_speed` (0.0-10.0, default: 1.0) - Fine scanline animation speed
|
||||||
|
- `small_scanlines_proximity` (0.01-2.0, default: 1.0) - Fine scanline density
|
||||||
|
- `small_scanlines_opacity` (0.01-5.0, default: 1.0) - Fine scanline visibility
|
||||||
|
- `scanlines_opacity` (0.0-2.0, default: 1.0) - Main scanline visibility
|
||||||
|
- `scanlines_speed` (0.0-5.0, default: 1.0) - Main scanline animation speed
|
||||||
|
- `scanline_thickness` (0.0-0.6, default: 0.5) - Scanline thickness
|
||||||
|
- `scanlines_spacing` (0.3-3.0, default: 1.0) - Space between scanlines
|
||||||
|
|
||||||
|
### Film Grain Effect
|
||||||
|
Adds vintage film grain noise to give content an analog film appearance.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<postprocess preset="film"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Available Properties:**
|
||||||
|
- `grain_amount` (0.0-1.0, default: 0.05) - Amount of grain noise added
|
||||||
|
- `grain_size` (0.1-10.0, default: 1.0) - Size/scale of individual grain particles
|
||||||
|
|
||||||
|
### Vignette Effect
|
||||||
|
Creates a darkened border around the screen edges, focusing attention on the center.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<postprocess preset="vignette"></postprocess>
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
**Available Properties:**
|
||||||
|
- `inner_radius` (0.0-1.0, default: 0.1) - Inner edge of the vignette effect
|
||||||
|
- `outer_radius` (0.0-1.0, default: 1.0) - Outer edge where vignette is strongest
|
||||||
|
- `vignette_strength` (0.0-2.0, default: 1.0) - Intensity of the darkening effect
|
||||||
|
- `dither_strength` (0.0-1.0, default: 0.03) - Noise added to prevent banding
|
||||||
|
- `vignette_color` (color, default: black) - Color of the vignette overlay
|
||||||
|
|
||||||
|
### Pencil Effect
|
||||||
|
Converts the webpage into a pencil drawing style with adjustable thresholds for line detection.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<postprocess preset="pencil"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Available Properties:**
|
||||||
|
- `u_bgColorFactor` (0.0-1.0, default: 0.4) - Blend amount of background color
|
||||||
|
- `u_threshold1` (0.0-1.0, default: 0.75) - Brightest areas threshold
|
||||||
|
- `u_threshold2` (0.0-1.0, default: 0.50) - Medium-bright areas threshold
|
||||||
|
- `u_threshold3` (0.0-1.0, default: 0.25) - Medium-dark areas threshold
|
||||||
|
- `u_threshold4` (0.0-1.0, default: 0.05) - Darkest areas threshold
|
||||||
|
- `u_bgTiling` (Vector2, default: vec2(1.0, 1.0)) - Background texture tiling
|
||||||
|
- `u_patternTiling` (Vector2, default: vec2(1.0, 1.0)) - Pattern texture tiling
|
||||||
|
- `u_bgColor` (color, default: white) - Background paper color
|
||||||
|
- `u_patternColor` (color, default: black) - Pencil line color
|
||||||
|
|
||||||
|
### Snowfall Effect
|
||||||
|
Adds animated falling snow particles over the content with customizable layers and physics.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<postprocess preset="snowfall"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Available Properties:**
|
||||||
|
- `spread` (0.0-1.5, default: 0.5) - Horizontal spread of snowflakes
|
||||||
|
- `size` (0.01-5.0, default: 0.5) - Size of individual snowflakes
|
||||||
|
- `snow_color` (color, default: white) - Color of the snow particles
|
||||||
|
- `snow_transparency` (-0.5-1.0, default: 0.2) - Transparency of snow overlay
|
||||||
|
- `speed` (0.0-10.0, default: 0.5) - Falling speed of snowflakes
|
||||||
|
- `wind` (-2.0-2.0, default: 0.0) - Horizontal wind effect
|
||||||
|
- `num_of_layers` (integer, default: 40) - Number of snow layers for depth
|
||||||
|
|
||||||
|
### Chromatic Aberration Effect
|
||||||
|
Simulates lens distortion by separating RGB color channels, creating a retro video glitch effect.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<postprocess preset="chrome"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Available Properties:**
|
||||||
|
- `levels` (integer, default: 3) - Number of color separation levels
|
||||||
|
- `spread` (float, default: 0.01) - Amount of color channel separation
|
||||||
|
|
||||||
|
|
||||||
|
### Radial Blur Effect
|
||||||
|
Creates motion blur radiating from a center point, useful for speed effects or focus attention.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<postprocess preset="rblur"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Available Properties:**
|
||||||
|
- `blur_center` (Vector2, default: vec2(0.5, 0.5)) - Center point of the blur effect
|
||||||
|
- `blur_power` (0.0-1.0, default: 0.01) - Intensity of the blur effect
|
||||||
|
- `sampling_count` (1-64, default: 2) - Quality of the blur (higher = smoother)
|
||||||
|
|
||||||
|
### Lens Flare Effect
|
||||||
|
Adds realistic lens flare effects, simulating light hitting a camera lens.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<postprocess preset="lensflare"></postprocess>
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
**Available Properties:**
|
||||||
|
- `sun_position` (Vector2, default: vec2(400.0, 0.0)) - Position of the light source
|
||||||
|
- `tint` (Vector3, default: vec3(1.4, 1.2, 1.0)) - Color tint of the lens flare
|
||||||
|
|
||||||
|
### Foliage Sway Effect
|
||||||
|
Creates animated wave distortion effects, mimicking vegetation movement or underwater effects.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<postprocess preset="foliage"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
**Available Properties:**
|
||||||
|
- `x_intensity` (float, default: 3.0) - Horizontal sway intensity
|
||||||
|
- `y_intensity` (float, default: 0.5) - Vertical sway intensity
|
||||||
|
- `offset` (float, default: 0.0) - Animation offset for timing
|
||||||
|
- `speed` (0-20, default: 2.0) - Animation speed
|
||||||
|
- `wave_frequency` (0-100, default: 20) - Frequency of wave oscillations
|
||||||
|
- `wave_length` (50-800, default: 200.0) - Length of wave patterns
|
||||||
|
|
||||||
|
### Dithering Effect
|
||||||
|
Applies retro pixel art dithering with color palette reduction for a vintage gaming aesthetic.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<postprocess preset="dither"></postprocess>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
:::note
|
||||||
|
Due to the limitations of GDShader, the dithering effect relies on a `GradientTexture` node internally. This means the colors are hardcoded to be a rusty tint - unchangeable via parameters. A similar effect can be achieved with a custom `<postprocess>` shader without external nodes - however, that's beyond the scope of this preset.
|
||||||
|
:::
|
||||||
|
|
||||||
|
**Available Properties:**
|
||||||
|
- `pixel` (float, default: 1.0) - Pixel size for the dithering pattern
|
||||||
|
|
||||||
|
All postprocess shaders are GPU-accelerated thanks to Godot's shader system.
|
||||||
@@ -31,7 +31,6 @@ const sidebars: SidebarsConfig = {
|
|||||||
items: [
|
items: [
|
||||||
'dns-system',
|
'dns-system',
|
||||||
'flumi-browser',
|
'flumi-browser',
|
||||||
'search-engine'
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -40,6 +39,7 @@ const sidebars: SidebarsConfig = {
|
|||||||
items: [
|
items: [
|
||||||
'html',
|
'html',
|
||||||
'css',
|
'css',
|
||||||
|
'postprocess',
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
BIN
docs/static/img/docs/chrome.png
vendored
Normal file
|
After Width: | Height: | Size: 686 KiB |
BIN
docs/static/img/docs/crt.gif
vendored
Normal file
|
After Width: | Height: | Size: 38 MiB |
BIN
docs/static/img/docs/dither.png
vendored
Normal file
|
After Width: | Height: | Size: 426 KiB |
BIN
docs/static/img/docs/film.png
vendored
Normal file
|
After Width: | Height: | Size: 117 KiB |
BIN
docs/static/img/docs/foliage.gif
vendored
Normal file
|
After Width: | Height: | Size: 13 MiB |
BIN
docs/static/img/docs/lensflare.png
vendored
Normal file
|
After Width: | Height: | Size: 406 KiB |
BIN
docs/static/img/docs/pencil.png
vendored
Normal file
|
After Width: | Height: | Size: 2.1 MiB |
BIN
docs/static/img/docs/rblur.png
vendored
Normal file
|
After Width: | Height: | Size: 438 KiB |
BIN
docs/static/img/docs/snowfall.gif
vendored
Normal file
|
After Width: | Height: | Size: 16 MiB |
BIN
docs/static/img/docs/vignette.png
vendored
Normal file
|
After Width: | Height: | Size: 1.6 MiB |
BIN
flumi/Assets/Textures/bayer8tile4.png
Normal file
|
After Width: | Height: | Size: 327 B |
34
flumi/Assets/Textures/bayer8tile4.png.import
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://c8eervlu44g5e"
|
||||||
|
path="res://.godot/imported/bayer8tile4.png-af05367272eb1e9c5c1494aea351d772.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Textures/bayer8tile4.png"
|
||||||
|
dest_files=["res://.godot/imported/bayer8tile4.png-af05367272eb1e9c5c1494aea351d772.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=0
|
||||||
BIN
flumi/Assets/Textures/blue_noise.png
Normal file
|
After Width: | Height: | Size: 323 KiB |
34
flumi/Assets/Textures/blue_noise.png.import
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bh6ou8qfqhml3"
|
||||||
|
path="res://.godot/imported/blue_noise.png-3429c5fff13cc3510f3a6adb3d9b290a.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Textures/blue_noise.png"
|
||||||
|
dest_files=["res://.godot/imported/blue_noise.png-3429c5fff13cc3510f3a6adb3d9b290a.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
flumi/Assets/Textures/dither_matrix.png
Normal file
|
After Width: | Height: | Size: 616 B |
34
flumi/Assets/Textures/dither_matrix.png.import
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://crdyaxcy0l5fe"
|
||||||
|
path="res://.godot/imported/dither_matrix.png-e5f72ab3b733bd12bb9be69cb29c5303.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Textures/dither_matrix.png"
|
||||||
|
dest_files=["res://.godot/imported/dither_matrix.png-e5f72ab3b733bd12bb9be69cb29c5303.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
flumi/Assets/Textures/parchment.jpg
Normal file
|
After Width: | Height: | Size: 709 KiB |
34
flumi/Assets/Textures/parchment.jpg.import
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://b8x712hkjbsh"
|
||||||
|
path="res://.godot/imported/parchment.jpg-ea29c24066df61d46bc7b0bcc25a86c1.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Textures/parchment.jpg"
|
||||||
|
dest_files=["res://.godot/imported/parchment.jpg-ea29c24066df61d46bc7b0bcc25a86c1.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
BIN
flumi/Assets/Textures/pencil.jpg
Normal file
|
After Width: | Height: | Size: 363 KiB |
34
flumi/Assets/Textures/pencil.jpg.import
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://dnvdbk47n56ej"
|
||||||
|
path="res://.godot/imported/pencil.jpg-3bb1b8082faf74808f54e9dd81d1b7d0.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://Assets/Textures/pencil.jpg"
|
||||||
|
dest_files=["res://.godot/imported/pencil.jpg-3bb1b8082faf74808f54e9dd81d1b7d0.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/high_quality=false
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
||||||
6
flumi/Scenes/Tags/postprocess.tscn
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[gd_scene load_steps=2 format=3 uid="uid://bpn7d4x5qr8vw"]
|
||||||
|
|
||||||
|
[ext_resource type="Script" path="res://Scripts/Tags/postprocess.gd" id="1_postprocess"]
|
||||||
|
|
||||||
|
[node name="postprocess" type="Control"]
|
||||||
|
script = ExtResource("1_postprocess")
|
||||||
@@ -430,6 +430,9 @@ func get_all_images() -> Array[String]:
|
|||||||
func get_all_scripts() -> Array[String]:
|
func get_all_scripts() -> Array[String]:
|
||||||
return get_attribute_values("script", "src")
|
return get_attribute_values("script", "src")
|
||||||
|
|
||||||
|
func get_all_postprocess() -> Array[String]:
|
||||||
|
return get_attribute_values("postprocess", "src")
|
||||||
|
|
||||||
func process_scripts(lua_api: LuaAPI, _lua_vm) -> void:
|
func process_scripts(lua_api: LuaAPI, _lua_vm) -> void:
|
||||||
if not lua_api:
|
if not lua_api:
|
||||||
print("Warning: Lua API not available for script processing")
|
print("Warning: Lua API not available for script processing")
|
||||||
@@ -459,6 +462,14 @@ func process_external_scripts(lua_api: LuaAPI, _lua_vm, base_url: String = "") -
|
|||||||
if not script_content.is_empty():
|
if not script_content.is_empty():
|
||||||
lua_api.execute_lua_script(script_content)
|
lua_api.execute_lua_script(script_content)
|
||||||
|
|
||||||
|
func process_postprocess() -> HTMLParser.HTMLElement:
|
||||||
|
var postprocess_elements = find_all("postprocess")
|
||||||
|
if postprocess_elements.is_empty():
|
||||||
|
return null
|
||||||
|
|
||||||
|
# Return the last postprocess element (last defined wins)
|
||||||
|
return postprocess_elements[-1]
|
||||||
|
|
||||||
func get_all_stylesheets() -> Array[String]:
|
func get_all_stylesheets() -> Array[String]:
|
||||||
return get_attribute_values("style", "src")
|
return get_attribute_values("style", "src")
|
||||||
|
|
||||||
|
|||||||
@@ -672,7 +672,7 @@ func _handle_dom_operation(operation: Dictionary):
|
|||||||
"get_text":
|
"get_text":
|
||||||
_handle_text_getting(operation)
|
_handle_text_getting(operation)
|
||||||
"append_element":
|
"append_element":
|
||||||
LuaDOMUtils.handle_element_append(operation, dom_parser, self)
|
LuaDOMUtils.handle_element_append(operation, dom_parser)
|
||||||
"add_class":
|
"add_class":
|
||||||
LuaClassListUtils.handle_add_class(operation, dom_parser)
|
LuaClassListUtils.handle_add_class(operation, dom_parser)
|
||||||
"remove_class":
|
"remove_class":
|
||||||
@@ -682,7 +682,7 @@ func _handle_dom_operation(operation: Dictionary):
|
|||||||
"remove_element":
|
"remove_element":
|
||||||
LuaDOMUtils.handle_element_remove(operation, dom_parser)
|
LuaDOMUtils.handle_element_remove(operation, dom_parser)
|
||||||
"insert_before":
|
"insert_before":
|
||||||
LuaDOMUtils.handle_insert_before(operation, dom_parser, self)
|
LuaDOMUtils.handle_insert_before(operation, dom_parser)
|
||||||
"insert_after":
|
"insert_after":
|
||||||
LuaDOMUtils.handle_insert_after(operation, dom_parser)
|
LuaDOMUtils.handle_insert_after(operation, dom_parser)
|
||||||
"replace_child":
|
"replace_child":
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ static func is_gurt_domain(url: String) -> bool:
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
if not url.contains("://"):
|
if not url.contains("://"):
|
||||||
var parts = url.split(".")
|
# Extract just the domain part (before any path)
|
||||||
|
var domain = url.split("/")[0]
|
||||||
|
var parts = domain.split(".")
|
||||||
return parts.size() == 2
|
return parts.size() == 2
|
||||||
|
|
||||||
return false
|
return false
|
||||||
|
|||||||
@@ -64,19 +64,33 @@ static func apply_element_styles(node: Control, element: HTMLParser.HTMLElement,
|
|||||||
|
|
||||||
if (width != null or height != null) and not skip_sizing:
|
if (width != null or height != null) and not skip_sizing:
|
||||||
if width != null:
|
if width != null:
|
||||||
if width is String and width == "100%":
|
if width is String and width.ends_with("%"):
|
||||||
|
if width == "100%":
|
||||||
node.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
node.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||||
node.custom_minimum_size.x = 0
|
node.custom_minimum_size.x = 0
|
||||||
|
else:
|
||||||
|
# For other percentages, convert to viewport-relative size
|
||||||
|
var percent = float(width.replace("%", "")) / 100.0
|
||||||
|
var viewport_width = node.get_viewport().get_visible_rect().size.x if node.get_viewport() else 800
|
||||||
|
node.custom_minimum_size.x = viewport_width * percent
|
||||||
node.set_meta("size_flags_set_by_style_manager", true)
|
node.set_meta("size_flags_set_by_style_manager", true)
|
||||||
|
node.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||||
else:
|
else:
|
||||||
node.custom_minimum_size.x = width
|
node.custom_minimum_size.x = width
|
||||||
node.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
node.size_flags_horizontal = Control.SIZE_SHRINK_BEGIN
|
||||||
|
|
||||||
if height != null:
|
if height != null:
|
||||||
if height is String and height == "100%":
|
if height is String and height.ends_with("%"):
|
||||||
|
if height == "100%":
|
||||||
node.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
node.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||||
node.custom_minimum_size.y = 0
|
node.custom_minimum_size.y = 0
|
||||||
|
else:
|
||||||
|
# For other percentages, convert to viewport-relative size
|
||||||
|
var percent = float(height.replace("%", "")) / 100.0
|
||||||
|
var viewport_height = node.get_viewport().get_visible_rect().size.y if node.get_viewport() else 600
|
||||||
|
node.custom_minimum_size.y = viewport_height * percent
|
||||||
node.set_meta("size_flags_set_by_style_manager", true)
|
node.set_meta("size_flags_set_by_style_manager", true)
|
||||||
|
node.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||||
else:
|
else:
|
||||||
node.custom_minimum_size.y = height
|
node.custom_minimum_size.y = height
|
||||||
node.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
node.size_flags_vertical = Control.SIZE_SHRINK_BEGIN
|
||||||
|
|||||||
@@ -210,7 +210,9 @@ func create_tab() -> void:
|
|||||||
var index = tabs.size();
|
var index = tabs.size();
|
||||||
var tab = TAB.instantiate()
|
var tab = TAB.instantiate()
|
||||||
tabs.append(tab)
|
tabs.append(tab)
|
||||||
|
h_box_container.add_child(tab)
|
||||||
tab.tab_pressed.connect(_tab_pressed.bind(index))
|
tab.tab_pressed.connect(_tab_pressed.bind(index))
|
||||||
|
tab.tab_closed.connect(_tab_closed.bind(index))
|
||||||
var viewport_width = get_viewport().get_visible_rect().size.x
|
var viewport_width = get_viewport().get_visible_rect().size.x
|
||||||
var available_width = viewport_width - POPUP_BUTTON_WIDTH - NEW_TAB_BUTTON_WIDTH - OTHER_UI_PADDING
|
var available_width = viewport_width - POPUP_BUTTON_WIDTH - NEW_TAB_BUTTON_WIDTH - OTHER_UI_PADDING
|
||||||
var visible_count = calculate_visible_tab_count(available_width)
|
var visible_count = calculate_visible_tab_count(available_width)
|
||||||
|
|||||||
162
flumi/Scripts/Tags/postprocess.gd
Normal file
@@ -0,0 +1,162 @@
|
|||||||
|
class_name HTMLPostprocess
|
||||||
|
extends Control
|
||||||
|
|
||||||
|
const Network = preload("res://Scripts/Network.gd")
|
||||||
|
|
||||||
|
var element: HTMLParser.HTMLElement
|
||||||
|
var parser: HTMLParser
|
||||||
|
var shader_material: ShaderMaterial
|
||||||
|
var built_in_shaders = {
|
||||||
|
"crt": "res://Shaders/crt.gdshader",
|
||||||
|
"film": "res://Shaders/film.gdshader",
|
||||||
|
"vignette": "res://Shaders/vignette.gdshader",
|
||||||
|
"pencil": "res://Shaders/pencil.gdshader",
|
||||||
|
"snowfall": "res://Shaders/snowfall.gdshader",
|
||||||
|
"chrome": "res://Shaders/chrome.gdshader",
|
||||||
|
"rblur": "res://Shaders/rblur.gdshader",
|
||||||
|
"lensflare": "res://Shaders/lensflare.gdshader",
|
||||||
|
"foliage": "res://Shaders/foliage.gdshader",
|
||||||
|
"dither": "res://Shaders/dither.gdshader"
|
||||||
|
}
|
||||||
|
|
||||||
|
func init(element_: HTMLParser.HTMLElement, parser_: HTMLParser):
|
||||||
|
element = element_
|
||||||
|
parser = parser_
|
||||||
|
|
||||||
|
var preset = element.get_attribute("preset")
|
||||||
|
if preset and built_in_shaders.has(preset):
|
||||||
|
await apply_preset_shader(preset)
|
||||||
|
|
||||||
|
elif element.has_attribute("src"):
|
||||||
|
await load_external_shader()
|
||||||
|
|
||||||
|
elif not element.text_content.is_empty():
|
||||||
|
apply_inline_shader()
|
||||||
|
|
||||||
|
func apply_preset_shader(preset_name: String):
|
||||||
|
var shader_resource = built_in_shaders[preset_name]
|
||||||
|
var shader = load(shader_resource)
|
||||||
|
|
||||||
|
shader_material = ShaderMaterial.new()
|
||||||
|
shader_material.shader = shader
|
||||||
|
|
||||||
|
shader_material.set_shader_parameter("u_bgTexture", load("res://Assets/Textures/parchment.jpg"))
|
||||||
|
shader_material.set_shader_parameter("u_patternTexture", load("res://Assets/Textures/pencil.jpg"))
|
||||||
|
|
||||||
|
var BLUE_NOISE = load("res://Assets/Textures/blue_noise.png")
|
||||||
|
shader_material.set_shader_parameter("uTexBlueNoise", BLUE_NOISE)
|
||||||
|
var gradient_texture = GradientTexture2D.new()
|
||||||
|
var gradient = Gradient.new()
|
||||||
|
gradient.colors = [Color("#8B4513"), Color("#CD853F"), Color("#D2691E"), Color("#B22222"), Color("#A0522D")]
|
||||||
|
gradient_texture.gradient = gradient
|
||||||
|
shader_material.set_shader_parameter("pallete", gradient_texture)
|
||||||
|
|
||||||
|
apply_shader_uniforms()
|
||||||
|
apply_postprocessing_to_viewport()
|
||||||
|
|
||||||
|
func load_external_shader():
|
||||||
|
var src = element.get_attribute("src")
|
||||||
|
|
||||||
|
var main = Engine.get_main_loop().current_scene
|
||||||
|
var resolved_url = URLUtils.resolve_url(main.current_domain, src)
|
||||||
|
|
||||||
|
var network = Network.new()
|
||||||
|
var response = await network.fetch_content(resolved_url)
|
||||||
|
|
||||||
|
if response.success:
|
||||||
|
var shader_code = response.content.get_string_from_utf8()
|
||||||
|
var shader = Shader.new()
|
||||||
|
shader.code = shader_code
|
||||||
|
|
||||||
|
shader_material = ShaderMaterial.new()
|
||||||
|
shader_material.shader = shader
|
||||||
|
|
||||||
|
apply_shader_uniforms()
|
||||||
|
apply_postprocessing_to_viewport()
|
||||||
|
else:
|
||||||
|
print("Failed to load shader from: ", resolved_url)
|
||||||
|
|
||||||
|
func apply_inline_shader():
|
||||||
|
var shader_code = element.text_content.strip_edges()
|
||||||
|
if shader_code.is_empty():
|
||||||
|
return
|
||||||
|
|
||||||
|
var shader = Shader.new()
|
||||||
|
shader.code = shader_code
|
||||||
|
|
||||||
|
shader_material = ShaderMaterial.new()
|
||||||
|
shader_material.shader = shader
|
||||||
|
|
||||||
|
apply_shader_uniforms()
|
||||||
|
apply_postprocessing_to_viewport()
|
||||||
|
|
||||||
|
func apply_shader_uniforms():
|
||||||
|
if not shader_material or not shader_material.shader:
|
||||||
|
return
|
||||||
|
|
||||||
|
for attr_name in element.attributes:
|
||||||
|
if attr_name in ["src", "preset"]:
|
||||||
|
continue
|
||||||
|
|
||||||
|
var attr_value = element.get_attribute(attr_name)
|
||||||
|
var uniform_value = parse_uniform_value(attr_value)
|
||||||
|
|
||||||
|
if uniform_value != null:
|
||||||
|
shader_material.set_shader_parameter(attr_name, uniform_value)
|
||||||
|
|
||||||
|
func parse_uniform_value(value_string: String):
|
||||||
|
if value_string.is_valid_float():
|
||||||
|
return value_string.to_float()
|
||||||
|
|
||||||
|
if value_string.is_valid_int():
|
||||||
|
return value_string.to_int()
|
||||||
|
|
||||||
|
if value_string.to_lower() == "true":
|
||||||
|
return true
|
||||||
|
elif value_string.to_lower() == "false":
|
||||||
|
return false
|
||||||
|
|
||||||
|
if value_string.begins_with("Vector2(") or value_string.begins_with("vec2("):
|
||||||
|
var vec_str = value_string.replace("Vector2(", "").replace("vec2(", "").replace(")", "")
|
||||||
|
var components = vec_str.split(",")
|
||||||
|
if components.size() == 2:
|
||||||
|
return Vector2(components[0].strip_edges().to_float(), components[1].strip_edges().to_float())
|
||||||
|
|
||||||
|
if value_string.begins_with("Vector3(") or value_string.begins_with("vec3("):
|
||||||
|
var vec_str = value_string.replace("Vector3(", "").replace("vec3(", "").replace(")", "")
|
||||||
|
var components = vec_str.split(",")
|
||||||
|
if components.size() == 3:
|
||||||
|
return Vector3(components[0].strip_edges().to_float(), components[1].strip_edges().to_float(), components[2].strip_edges().to_float())
|
||||||
|
|
||||||
|
if value_string.begins_with("Vector4(") or value_string.begins_with("vec4("):
|
||||||
|
var vec_str = value_string.replace("Vector4(", "").replace("vec4(", "").replace(")", "")
|
||||||
|
var components = vec_str.split(",")
|
||||||
|
if components.size() == 4:
|
||||||
|
return Vector4(components[0].strip_edges().to_float(), components[1].strip_edges().to_float(), components[2].strip_edges().to_float(), components[3].strip_edges().to_float())
|
||||||
|
|
||||||
|
if value_string.begins_with("#"):
|
||||||
|
return Color(value_string)
|
||||||
|
|
||||||
|
return value_string
|
||||||
|
|
||||||
|
func apply_postprocessing_to_viewport():
|
||||||
|
if not shader_material:
|
||||||
|
return
|
||||||
|
|
||||||
|
var main_scene = Engine.get_main_loop().current_scene
|
||||||
|
var active_tab = main_scene.get_active_tab()
|
||||||
|
var panel_container = active_tab.background_panel
|
||||||
|
|
||||||
|
var existing_overlay = panel_container.get_node_or_null("PostprocessOverlay")
|
||||||
|
if existing_overlay:
|
||||||
|
existing_overlay.queue_free()
|
||||||
|
|
||||||
|
var overlay_rect = ColorRect.new()
|
||||||
|
overlay_rect.name = "PostprocessOverlay"
|
||||||
|
overlay_rect.material = shader_material
|
||||||
|
overlay_rect.color = Color.WHITE
|
||||||
|
overlay_rect.mouse_filter = Control.MOUSE_FILTER_IGNORE
|
||||||
|
overlay_rect.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||||
|
overlay_rect.z_index = 100
|
||||||
|
|
||||||
|
panel_container.add_child(overlay_rect)
|
||||||
1
flumi/Scripts/Tags/postprocess.gd.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://btm4uqcfr43cm
|
||||||
@@ -95,7 +95,7 @@ static func get_element_last_child_handler(vm: LuauVM, dom_parser: HTMLParser, l
|
|||||||
|
|
||||||
# DOM Manipulation Methods
|
# DOM Manipulation Methods
|
||||||
|
|
||||||
static func handle_element_append(operation: Dictionary, dom_parser: HTMLParser, lua_api) -> void:
|
static func handle_element_append(operation: Dictionary, dom_parser: HTMLParser) -> void:
|
||||||
var parent_id: String = operation.parent_id
|
var parent_id: String = operation.parent_id
|
||||||
var child_id: String = operation.child_id
|
var child_id: String = operation.child_id
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ static func handle_element_remove(operation: Dictionary, dom_parser: HTMLParser)
|
|||||||
if all_elements_index >= 0:
|
if all_elements_index >= 0:
|
||||||
dom_parser.parse_result.all_elements.remove_at(all_elements_index)
|
dom_parser.parse_result.all_elements.remove_at(all_elements_index)
|
||||||
|
|
||||||
static func handle_insert_before(operation: Dictionary, dom_parser: HTMLParser, lua_api) -> void:
|
static func handle_insert_before(operation: Dictionary, dom_parser: HTMLParser) -> void:
|
||||||
var parent_id: String = operation.parent_id
|
var parent_id: String = operation.parent_id
|
||||||
var new_child_id: String = operation.new_child_id
|
var new_child_id: String = operation.new_child_id
|
||||||
var reference_child_id: String = operation.reference_child_id
|
var reference_child_id: String = operation.reference_child_id
|
||||||
|
|||||||
@@ -472,7 +472,9 @@ func _set_interval_handler(vm: LuauVM) -> int:
|
|||||||
func get_current_href() -> String:
|
func get_current_href() -> String:
|
||||||
var main_node = Engine.get_main_loop().current_scene
|
var main_node = Engine.get_main_loop().current_scene
|
||||||
|
|
||||||
|
if main_node:
|
||||||
return main_node.current_domain
|
return main_node.current_domain
|
||||||
|
return ""
|
||||||
|
|
||||||
func _gurt_select_handler(vm: LuauVM) -> int:
|
func _gurt_select_handler(vm: LuauVM) -> int:
|
||||||
var selector: String = vm.luaL_checkstring(1)
|
var selector: String = vm.luaL_checkstring(1)
|
||||||
|
|||||||
@@ -29,15 +29,15 @@ const SELECT = preload("res://Scenes/Tags/select.tscn")
|
|||||||
const TEXTAREA = preload("res://Scenes/Tags/textarea.tscn")
|
const TEXTAREA = preload("res://Scenes/Tags/textarea.tscn")
|
||||||
const DIV = preload("res://Scenes/Tags/div.tscn")
|
const DIV = preload("res://Scenes/Tags/div.tscn")
|
||||||
const AUDIO = preload("res://Scenes/Tags/audio.tscn")
|
const AUDIO = preload("res://Scenes/Tags/audio.tscn")
|
||||||
|
const POSTPROCESS = preload("res://Scenes/Tags/postprocess.tscn")
|
||||||
|
|
||||||
const MIN_SIZE = Vector2i(750, 200)
|
const MIN_SIZE = Vector2i(750, 200)
|
||||||
|
|
||||||
var font_dependent_elements: Array = []
|
var font_dependent_elements: Array = []
|
||||||
|
var current_domain = ""
|
||||||
|
|
||||||
func should_group_as_inline(element: HTMLParser.HTMLElement) -> bool:
|
func should_group_as_inline(element: HTMLParser.HTMLElement) -> bool:
|
||||||
# Don't group inputs unless they're inside a form
|
|
||||||
if element.tag_name == "input":
|
if element.tag_name == "input":
|
||||||
# Check if this element has a form ancestor
|
|
||||||
var parent = element.parent
|
var parent = element.parent
|
||||||
while parent:
|
while parent:
|
||||||
if parent.tag_name == "form":
|
if parent.tag_name == "form":
|
||||||
@@ -60,8 +60,6 @@ func _ready():
|
|||||||
|
|
||||||
call_deferred("render")
|
call_deferred("render")
|
||||||
|
|
||||||
var current_domain = "" # Store current domain for display
|
|
||||||
|
|
||||||
func resolve_url(href: String) -> String:
|
func resolve_url(href: String) -> String:
|
||||||
return URLUtils.resolve_url(current_domain, href)
|
return URLUtils.resolve_url(current_domain, href)
|
||||||
|
|
||||||
@@ -193,6 +191,20 @@ func render_content(html_bytes: PackedByteArray) -> void:
|
|||||||
remove_child(lua_api)
|
remove_child(lua_api)
|
||||||
lua_api.queue_free()
|
lua_api.queue_free()
|
||||||
active_tab.lua_apis.clear()
|
active_tab.lua_apis.clear()
|
||||||
|
|
||||||
|
var existing_postprocess = []
|
||||||
|
for child in get_children():
|
||||||
|
if child is HTMLPostprocess:
|
||||||
|
existing_postprocess.append(child)
|
||||||
|
|
||||||
|
for postprocess in existing_postprocess:
|
||||||
|
remove_child(postprocess)
|
||||||
|
postprocess.queue_free()
|
||||||
|
|
||||||
|
if active_tab.background_panel:
|
||||||
|
var existing_overlay = active_tab.background_panel.get_node_or_null("PostprocessOverlay")
|
||||||
|
if existing_overlay:
|
||||||
|
existing_overlay.queue_free()
|
||||||
else:
|
else:
|
||||||
var existing_lua_apis = []
|
var existing_lua_apis = []
|
||||||
for child in get_children():
|
for child in get_children():
|
||||||
@@ -204,6 +216,20 @@ func render_content(html_bytes: PackedByteArray) -> void:
|
|||||||
remove_child(lua_api)
|
remove_child(lua_api)
|
||||||
lua_api.queue_free()
|
lua_api.queue_free()
|
||||||
|
|
||||||
|
var postprocess_nodes: Array[Node] = []
|
||||||
|
for child in get_children():
|
||||||
|
if child is HTMLPostprocess:
|
||||||
|
postprocess_nodes.append(child)
|
||||||
|
for node in postprocess_nodes:
|
||||||
|
remove_child(node)
|
||||||
|
node.queue_free()
|
||||||
|
|
||||||
|
var default_panel = website_container.get_parent()
|
||||||
|
if default_panel and default_panel.has_method("get_node_or_null"):
|
||||||
|
var existing_overlay = default_panel.get_node_or_null("PostprocessOverlay")
|
||||||
|
if existing_overlay:
|
||||||
|
existing_overlay.queue_free()
|
||||||
|
|
||||||
if target_container.get_parent() and target_container.get_parent().name == "BodyMarginContainer":
|
if target_container.get_parent() and target_container.get_parent().name == "BodyMarginContainer":
|
||||||
var body_margin_container = target_container.get_parent()
|
var body_margin_container = target_container.get_parent()
|
||||||
var scroll_container = body_margin_container.get_parent()
|
var scroll_container = body_margin_container.get_parent()
|
||||||
@@ -320,6 +346,12 @@ func render_content(html_bytes: PackedByteArray) -> void:
|
|||||||
if parse_result.external_scripts and not parse_result.external_scripts.is_empty():
|
if parse_result.external_scripts and not parse_result.external_scripts.is_empty():
|
||||||
await parser.process_external_scripts(lua_api, null, current_domain)
|
await parser.process_external_scripts(lua_api, null, current_domain)
|
||||||
|
|
||||||
|
var postprocess_element = parser.process_postprocess()
|
||||||
|
if postprocess_element:
|
||||||
|
var postprocess_node = POSTPROCESS.instantiate()
|
||||||
|
add_child(postprocess_node)
|
||||||
|
await postprocess_node.init(postprocess_element, parser)
|
||||||
|
|
||||||
active_tab.current_url = current_domain
|
active_tab.current_url = current_domain
|
||||||
active_tab.has_content = true
|
active_tab.has_content = true
|
||||||
|
|
||||||
|
|||||||
29
flumi/Shaders/chrome.gdshader
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// Chromatic Aberration Shader by https://godotshaders.com/shader/chromatic-abberation/
|
||||||
|
// All credits to the original author!!!
|
||||||
|
|
||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
|
||||||
|
|
||||||
|
uniform int levels = 3;
|
||||||
|
uniform float spread = 0.01;
|
||||||
|
|
||||||
|
vec3 chromatic_slice(float t){
|
||||||
|
vec3 res = vec3(1.0-t, 1.0 - abs(t - 1.0), t - 1.0);
|
||||||
|
return max(res, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fragment(){
|
||||||
|
vec3 sum;
|
||||||
|
COLOR.rgb = vec3(0);
|
||||||
|
vec2 offset = (UV - vec2(0.5))*vec2(1,-1);
|
||||||
|
for(int i = 0; i < levels; i++){
|
||||||
|
float t = 2.0*float(i)/float(levels-1); // range 0.0->2.0
|
||||||
|
vec3 slice = vec3(1.0-t, 1.0 - abs(t - 1.0), t - 1.0);
|
||||||
|
slice = max(slice, 0.0);
|
||||||
|
sum += slice;
|
||||||
|
vec2 slice_offset = (t-1.0)*spread*offset;
|
||||||
|
COLOR.rgb += slice * texture(SCREEN_TEXTURE, SCREEN_UV + slice_offset).rgb;
|
||||||
|
}
|
||||||
|
COLOR.rgb /= sum;
|
||||||
|
}
|
||||||
1
flumi/Shaders/chrome.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://dbkni4dqt0ral
|
||||||
90
flumi/Shaders/crt.gdshader
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
/* License CC BY-NC-SA 4.0 Deed */
|
||||||
|
/* https://creativecommons.org/licenses/by-nc-sa/4.0/ */
|
||||||
|
/* Fork of Ryk's VCR distortion shader */
|
||||||
|
/* https://www.shadertoy.com/view/ldjGzV */
|
||||||
|
|
||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform sampler2D screen_texture: hint_screen_texture, filter_linear_mipmap, repeat_disable;
|
||||||
|
|
||||||
|
group_uniforms Image;
|
||||||
|
uniform float curvature: hint_range(0., 10., .01) = 2.;
|
||||||
|
uniform float skip: hint_range(0., 1., .01) = 1.;
|
||||||
|
uniform float image_flicker: hint_range(0., 1., .01) = 1.;
|
||||||
|
|
||||||
|
group_uniforms Vignette;
|
||||||
|
uniform float vignette_flicker_speed: hint_range(0., 2., .01) = 1.;
|
||||||
|
uniform float vignette_strength: hint_range(0., 2., 0.01) = 1.;
|
||||||
|
|
||||||
|
group_uniforms Scanlines;
|
||||||
|
uniform float small_scanlines_speed: hint_range(0., 10., .01) = 1.;
|
||||||
|
uniform float small_scanlines_proximity: hint_range(.01, 2., .01) = 1.;
|
||||||
|
uniform float small_scanlines_opacity: hint_range(0.01, 5., .01) = 1.;
|
||||||
|
uniform float scanlines_opacity: hint_range(0., 2., .01) = 1.;
|
||||||
|
uniform float scanlines_speed: hint_range(0., 5., .01) = 1.;
|
||||||
|
uniform float scanline_thickness: hint_range(0., .6, .01) = 0.5;
|
||||||
|
uniform float scanlines_spacing: hint_range(0.3, 3., .01) = 1.;
|
||||||
|
|
||||||
|
group_uniforms Noise;
|
||||||
|
uniform sampler2D noise_texture: filter_linear_mipmap, repeat_enable;
|
||||||
|
|
||||||
|
float noise(vec2 p, vec2 uv)
|
||||||
|
{
|
||||||
|
float s = texture(noise_texture,vec2(1.*TIME,2.*TIME)*8. + p*1.).x;
|
||||||
|
s *= s;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
float onOff(float a, float b, float c)
|
||||||
|
{
|
||||||
|
return step(c, sin(TIME + a*cos(TIME*b)));
|
||||||
|
}
|
||||||
|
|
||||||
|
float ramp(float y, float start, float end)
|
||||||
|
{
|
||||||
|
float inside = step(start,y) - step(end,y);
|
||||||
|
float fact = (y-start)/(end-start)*inside;
|
||||||
|
return (1.-fact) * inside;
|
||||||
|
}
|
||||||
|
|
||||||
|
float stripes(vec2 uv)
|
||||||
|
{
|
||||||
|
float noi = noise(uv*vec2(0.5,1.) + vec2(1.,3.), uv)*scanlines_opacity;
|
||||||
|
return ramp(mod(uv.y*4.*scanlines_spacing + TIME*scanlines_speed/(2.*scanlines_spacing)+sin(TIME*scanlines_speed + sin(TIME*scanlines_speed*0.63*scanlines_spacing)),1.),scanline_thickness,.6)*noi;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 getVideo(vec2 uv)
|
||||||
|
{
|
||||||
|
vec2 look = uv;
|
||||||
|
float window = 1./(1.+20.*(look.y-mod(TIME/4.,1.))*(look.y-mod(TIME/4.,1.)))*image_flicker;
|
||||||
|
look.x = look.x + sin(look.y*10. + TIME)/50.*onOff(4.,4.,.3)*(1.+cos(TIME*80.))*window;
|
||||||
|
float vShift = 0.4*onOff(2.,3.,.9)*(sin(TIME)*sin(TIME*20.)+(0.5 + 0.1*sin(TIME*200.)*cos(TIME)))*skip;
|
||||||
|
look.y = mod(look.y + vShift, 1.);
|
||||||
|
vec3 video = texture(screen_texture,look).xyz;
|
||||||
|
return video;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 screenDistort(vec2 uv)
|
||||||
|
{
|
||||||
|
uv -= vec2(.5,.5);
|
||||||
|
uv = uv*1.2*(1./1.2+curvature*uv.x*uv.x*uv.y*uv.y);
|
||||||
|
uv += vec2(.5,.5);
|
||||||
|
return uv;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fragment()
|
||||||
|
{
|
||||||
|
vec2 uv = FRAGCOORD.xy / (1.0 / SCREEN_PIXEL_SIZE).xy;
|
||||||
|
uv = screenDistort(uv);
|
||||||
|
vec3 video = getVideo(uv);
|
||||||
|
float vigAmt = 3.+.3*sin(TIME*vignette_flicker_speed+1. + 5.*cos(TIME*5.*vignette_flicker_speed+1.));
|
||||||
|
vigAmt *= vignette_strength;
|
||||||
|
float vignette = (1.-vigAmt*(uv.y-.5)*(uv.y-.5))*(1.-vigAmt*(uv.x-.5)*(uv.x-.5));
|
||||||
|
|
||||||
|
video += stripes(uv);
|
||||||
|
video += noise(uv*2., uv)/2.;
|
||||||
|
video *= vignette;
|
||||||
|
video *= (12./small_scanlines_opacity+mod(uv.y*30.*small_scanlines_proximity+TIME*small_scanlines_speed,1.))/13.*small_scanlines_opacity;
|
||||||
|
|
||||||
|
COLOR = vec4(video,1.0);
|
||||||
|
}
|
||||||
1
flumi/Shaders/crt.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://db3f2xubcujnq
|
||||||
45
flumi/Shaders/dither.gdshader
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
//GODOT 4
|
||||||
|
|
||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform float pixel = 1.0;
|
||||||
|
uniform sampler2D pallete;
|
||||||
|
|
||||||
|
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
|
||||||
|
|
||||||
|
const float bit = 6.0;
|
||||||
|
const mat4 bayer = mat4(
|
||||||
|
vec4(1.0, 9.0, 3.0, 11.0),
|
||||||
|
vec4(13.0, 5.0, 15.0, 7.0),
|
||||||
|
vec4(4.0, 12.0, 2.0, 10.0),
|
||||||
|
vec4(16.0, 8.0, 14.0, 6.0));
|
||||||
|
|
||||||
|
|
||||||
|
float getbayer(int x, int y)
|
||||||
|
{
|
||||||
|
return bayer[x][y];
|
||||||
|
}
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
vec4 original = texture(TEXTURE, UV);
|
||||||
|
|
||||||
|
vec2 FUV = floor(FRAGCOORD.xy / pixel) / floor((1.0 / SCREEN_PIXEL_SIZE) / pixel);
|
||||||
|
|
||||||
|
vec4 _color = texture(SCREEN_TEXTURE, SCREEN_UV);
|
||||||
|
vec4 color = _color * texture(pallete, vec2(_color.r, 1.0));
|
||||||
|
|
||||||
|
|
||||||
|
float b = getbayer(int(FRAGCOORD.x) % 4, int(FRAGCOORD.y) % 4);// * 1.0) / 1.0;
|
||||||
|
vec2 uv = FRAGCOORD.xy / SCREEN_PIXEL_SIZE;
|
||||||
|
vec4 col_noise = color;
|
||||||
|
vec3 noise = vec3(fract(sin(dot(FUV, vec2(12.9898, 78.233))) * 43758.5453));
|
||||||
|
noise *= 0.1;
|
||||||
|
noise.xy *= (b / 16.0) * 1.5;
|
||||||
|
col_noise.rgb += noise; //noise effect
|
||||||
|
|
||||||
|
vec4 post = col_noise * floor(col_noise * 4.0) / 4.0; //noise + post-effect
|
||||||
|
|
||||||
|
COLOR *= post;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
1
flumi/Shaders/dither.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bggtn4uh67v0u
|
||||||
20
flumi/Shaders/film.gdshader
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
// Uniforms
|
||||||
|
uniform sampler2D screen_texture : hint_screen_texture;
|
||||||
|
uniform float grain_amount : hint_range(0.0, 1.0) = 0.05; // Adjust the amount of grain
|
||||||
|
uniform float grain_size : hint_range(0.1, 10.0) = 1.0; // Adjust the size of the grain
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
// Sample the original screen texture
|
||||||
|
vec4 original_color = texture(screen_texture, SCREEN_UV);
|
||||||
|
|
||||||
|
// Generate random noise
|
||||||
|
float noise = (fract(sin(dot(UV, vec2(12.9898, 78.233))) * 43758.5453) - 0.5) * 2.0;
|
||||||
|
|
||||||
|
// Add noise to the original color
|
||||||
|
original_color.rgb += noise * grain_amount * grain_size;
|
||||||
|
|
||||||
|
// Clamp the final color to make sure it stays in the valid range
|
||||||
|
COLOR = clamp(original_color, 0.0, 1.0);
|
||||||
|
}
|
||||||
1
flumi/Shaders/film.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bss3x1xthtaef
|
||||||
32
flumi/Shaders/foliage.gdshader
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
|
||||||
|
|
||||||
|
uniform float x_intensity = 3.0;
|
||||||
|
uniform float y_intensity = 0.5;
|
||||||
|
uniform float offset = 0.0;
|
||||||
|
uniform float speed : hint_range(0, 20) = 2.0;
|
||||||
|
uniform float wave_frequency : hint_range(0, 100) = 20;
|
||||||
|
uniform float wave_length : hint_range(50, 800) = 200.0;
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
vec2 real_uv = UV;
|
||||||
|
|
||||||
|
vec2 vecToBottom = vec2(1, 1) - UV.y;
|
||||||
|
float distToBottom = length(vecToBottom);
|
||||||
|
|
||||||
|
float final_speed = TIME * (speed / 4.0) + offset;
|
||||||
|
|
||||||
|
float time_var = (cos(final_speed) * cos(final_speed * 4.0) * cos(final_speed * 2.0))/(200.0);
|
||||||
|
float time_var2 = (cos(final_speed) * cos(final_speed * 6.0) * cos(final_speed * 2.0))/(200.0);
|
||||||
|
|
||||||
|
float wave_from_x = (cos(real_uv.x * 100.0)/1000.0);
|
||||||
|
float wave_large_from_x = cos(TIME + (real_uv.x * wave_frequency))/wave_length;
|
||||||
|
|
||||||
|
float offset_x = time_var * (distToBottom * x_intensity) + wave_from_x + (wave_large_from_x);
|
||||||
|
float offset_y = time_var2 * (distToBottom * y_intensity);
|
||||||
|
|
||||||
|
vec2 distortion_offset = vec2(offset_x, offset_y);
|
||||||
|
|
||||||
|
COLOR = texture(SCREEN_TEXTURE, SCREEN_UV + distortion_offset);
|
||||||
|
}
|
||||||
1
flumi/Shaders/foliage.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://12ar0h66dukp
|
||||||
1
flumi/Shaders/future.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c8nv7tds2neww
|
||||||
95
flumi/Shaders/lensflare.gdshader
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
// TRANSLATED & MODIFIED FROM: https://www.shadertoy.com/view/4sX3Rs
|
||||||
|
|
||||||
|
shader_type canvas_item;
|
||||||
|
render_mode blend_mix;
|
||||||
|
|
||||||
|
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
|
||||||
|
|
||||||
|
uniform vec2 sun_position = vec2(400.0, 0.0);
|
||||||
|
uniform vec3 tint = vec3(1.4,1.2,1.0);
|
||||||
|
uniform sampler2D noise_texture;
|
||||||
|
|
||||||
|
float noise_float(float t, vec2 texResolution)
|
||||||
|
{
|
||||||
|
return texture(noise_texture,vec2(t,0.0)/texResolution).x;
|
||||||
|
}
|
||||||
|
float noise_vec2(vec2 t, vec2 texResolution)
|
||||||
|
{
|
||||||
|
return texture(noise_texture,t/texResolution).x;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 lensflare(vec2 uv,vec2 pos, vec2 texResolution)
|
||||||
|
{
|
||||||
|
vec2 main = uv-pos;
|
||||||
|
vec2 uvd = uv*(length(uv));
|
||||||
|
|
||||||
|
float ang = atan(main.x,main.y);
|
||||||
|
float dist = length(main);
|
||||||
|
dist = pow(dist,0.1);
|
||||||
|
|
||||||
|
float n = noise_vec2(vec2(ang*16.0,dist*32.0), texResolution);
|
||||||
|
|
||||||
|
// Do not need an artificial sun
|
||||||
|
//float f0 = 1.0/(length(uv-pos)*16.0+1.0);
|
||||||
|
//f0 = f0 + f0*(sin(noise_float(sin(ang*2.+pos.x)*4.0 - cos(ang*3.+pos.y), texResolution)*16.)*.1 + dist*.1 + .8);
|
||||||
|
|
||||||
|
float f1 = max(0.01-pow(length(uv+1.2*pos),1.9),.0)*7.0;
|
||||||
|
|
||||||
|
float f2 = max(1.0/(1.0+32.0*pow(length(uvd+0.8*pos),2.0)),.0)*00.25;
|
||||||
|
float f22 = max(1.0/(1.0+32.0*pow(length(uvd+0.85*pos),2.0)),.0)*00.23;
|
||||||
|
float f23 = max(1.0/(1.0+32.0*pow(length(uvd+0.9*pos),2.0)),.0)*00.21;
|
||||||
|
|
||||||
|
vec2 uvx = mix(uv,uvd,-0.5);
|
||||||
|
|
||||||
|
float f4 = max(0.01-pow(length(uvx+0.4*pos),2.4),.0)*6.0;
|
||||||
|
float f42 = max(0.01-pow(length(uvx+0.45*pos),2.4),.0)*5.0;
|
||||||
|
float f43 = max(0.01-pow(length(uvx+0.5*pos),2.4),.0)*3.0;
|
||||||
|
|
||||||
|
uvx = mix(uv,uvd,-.4);
|
||||||
|
|
||||||
|
float f5 = max(0.01-pow(length(uvx+0.2*pos),5.5),.0)*2.0;
|
||||||
|
float f52 = max(0.01-pow(length(uvx+0.4*pos),5.5),.0)*2.0;
|
||||||
|
float f53 = max(0.01-pow(length(uvx+0.6*pos),5.5),.0)*2.0;
|
||||||
|
|
||||||
|
uvx = mix(uv,uvd,-0.5);
|
||||||
|
|
||||||
|
float f6 = max(0.01-pow(length(uvx-0.3*pos),1.6),.0)*6.0;
|
||||||
|
float f62 = max(0.01-pow(length(uvx-0.325*pos),1.6),.0)*3.0;
|
||||||
|
float f63 = max(0.01-pow(length(uvx-0.35*pos),1.6),.0)*5.0;
|
||||||
|
|
||||||
|
vec3 c = vec3(.0);
|
||||||
|
|
||||||
|
c.r+=f2+f4+f5+f6; c.g+=f22+f42+f52+f62; c.b+=f23+f43+f53+f63;
|
||||||
|
c = c*1.3 - vec3(length(uvd)*.05);
|
||||||
|
|
||||||
|
// Do not need an artificial sun
|
||||||
|
//c+=vec3(f0);
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 cc(vec3 color, float factor,float factor2) // color modifier
|
||||||
|
{
|
||||||
|
float w = color.x+color.y+color.z;
|
||||||
|
return mix(color,vec3(w)*factor,w*factor2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fragment()
|
||||||
|
{
|
||||||
|
vec2 texResolution = 1.0 / TEXTURE_PIXEL_SIZE;
|
||||||
|
vec2 resolution = 1.0 / SCREEN_PIXEL_SIZE;
|
||||||
|
|
||||||
|
vec2 uv = FRAGCOORD.xy / resolution.xy - 0.5;
|
||||||
|
uv.x *= resolution.x/resolution.y; //fix aspect ratio
|
||||||
|
vec2 mouse = (sun_position.xy / resolution.xy) - vec2(0.5, 0.5);
|
||||||
|
mouse.x *= resolution.x / resolution.y; //fix aspect ratio
|
||||||
|
|
||||||
|
vec4 previousColor = texture(SCREEN_TEXTURE, SCREEN_UV);
|
||||||
|
|
||||||
|
vec3 color = previousColor.rgb;
|
||||||
|
|
||||||
|
color += tint * lensflare(uv, mouse.xy, texResolution);
|
||||||
|
color -= noise_vec2(FRAGCOORD.xy, texResolution)*.015;
|
||||||
|
color = cc(color,.5,.1);
|
||||||
|
COLOR = vec4(color,1.0);
|
||||||
|
}
|
||||||
1
flumi/Shaders/lensflare.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c6auxoe0vpq46
|
||||||
58
flumi/Shaders/pencil.gdshader
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
|
||||||
|
uniform vec4 u_bgColor: source_color = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
uniform float u_bgColorFactor: hint_range(0.0, 1.0) = 0.4;
|
||||||
|
uniform vec4 u_patternColor: source_color = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
|
||||||
|
uniform float u_threshold1: hint_range(0.0, 1.0) = 0.75;
|
||||||
|
uniform float u_threshold2: hint_range(0.0, 1.0) = 0.50;
|
||||||
|
uniform float u_threshold3: hint_range(0.0, 1.0) = 0.25;
|
||||||
|
uniform float u_threshold4: hint_range(0.0, 1.0) = 0.05;
|
||||||
|
|
||||||
|
uniform vec2 u_bgTiling = vec2(1.0, 1.0);
|
||||||
|
uniform vec2 u_patternTiling = vec2(1.0, 1.0);
|
||||||
|
|
||||||
|
uniform sampler2D u_bgTexture;
|
||||||
|
uniform sampler2D u_patternTexture;
|
||||||
|
|
||||||
|
const float C2_SQRT2 = 0.707106781;
|
||||||
|
const mat2 ROT_45 = mat2(vec2(C2_SQRT2, -C2_SQRT2), vec2(C2_SQRT2, C2_SQRT2));
|
||||||
|
const vec4 COLOR_WHITE = vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
|
||||||
|
float getIntensity(vec3 color)
|
||||||
|
{
|
||||||
|
return 0.299*color.r + 0.587*color.g + 0.114*color.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 getPatternColor(vec2 uv, float intensity)
|
||||||
|
{
|
||||||
|
vec2 patternUV1 = vec2(-uv.x, uv.y) * u_patternTiling;
|
||||||
|
vec2 patternUV2 = uv * u_patternTiling;
|
||||||
|
vec2 patternUV3 = ROT_45*(uv + vec2(0.2358, 0.9123)) * u_patternTiling;
|
||||||
|
vec2 patternUV4 = (vec2(uv.x, -uv.y) + vec2(0.4123, 0.7218)) * u_patternTiling;
|
||||||
|
vec4 pCol1 = texture(u_patternTexture, patternUV1);
|
||||||
|
vec4 pCol2 = texture(u_patternTexture, patternUV2);
|
||||||
|
vec4 pCol3 = texture(u_patternTexture, patternUV3);
|
||||||
|
vec4 pCol4 = texture(u_patternTexture, patternUV4);
|
||||||
|
|
||||||
|
if(intensity > u_threshold1)
|
||||||
|
return vec4(1.0, 1.0, 1.0, 1.0);
|
||||||
|
if(intensity > u_threshold2)
|
||||||
|
return mix(pCol1, COLOR_WHITE, 0.5);
|
||||||
|
if(intensity > u_threshold3)
|
||||||
|
return mix(pCol1*pCol2, COLOR_WHITE, 0.3);
|
||||||
|
if(intensity > u_threshold4)
|
||||||
|
return mix(pCol1*pCol2*pCol3, COLOR_WHITE, 0.1);
|
||||||
|
return pCol1*pCol2*pCol3*pCol4*0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
void fragment()
|
||||||
|
{
|
||||||
|
vec4 origColor = texture(SCREEN_TEXTURE, SCREEN_UV);
|
||||||
|
float intensity = getIntensity(origColor.rgb);
|
||||||
|
vec4 bgColor = mix(texture(u_bgTexture, UV*u_bgTiling), u_bgColor, u_bgColorFactor);
|
||||||
|
vec4 patternColor = getPatternColor(UV, intensity);
|
||||||
|
vec4 color = mix(u_patternColor, bgColor, getIntensity(patternColor.rgb));
|
||||||
|
COLOR = color;
|
||||||
|
}
|
||||||
1
flumi/Shaders/pencil.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c54knriu0lot8
|
||||||
1
flumi/Shaders/pixelate.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://b4qebk1wtx6pj
|
||||||
27
flumi/Shaders/rblur.gdshader
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
放射状ブラーエフェクト by あるる(きのもと 結衣) @arlez80
|
||||||
|
Radial Blur Effect by Yui Kinomoto
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
*/
|
||||||
|
|
||||||
|
shader_type canvas_item;
|
||||||
|
uniform sampler2D SCREEN_TEXTURE : hint_screen_texture, filter_linear_mipmap;
|
||||||
|
|
||||||
|
// 発射中央部
|
||||||
|
uniform vec2 blur_center = vec2( 0.5, 0.5 );
|
||||||
|
// ブラー強度
|
||||||
|
uniform float blur_power : hint_range( 0.0, 1.0 ) = 0.01;
|
||||||
|
// サンプリング回数
|
||||||
|
uniform int sampling_count : hint_range( 1, 64 ) = 2;
|
||||||
|
|
||||||
|
void fragment( )
|
||||||
|
{
|
||||||
|
vec2 direction = SCREEN_UV - blur_center;
|
||||||
|
vec3 c = vec3( 0.0, 0.0, 0.0 );
|
||||||
|
float f = 1.0 / float( sampling_count );
|
||||||
|
for( int i=0; i < sampling_count; i++ ) {
|
||||||
|
c += texture( SCREEN_TEXTURE, SCREEN_UV - blur_power * direction * float(i) ).rgb * f;
|
||||||
|
}
|
||||||
|
COLOR.rgb = c;
|
||||||
|
}
|
||||||
1
flumi/Shaders/rblur.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://bcwhtc0sjmwr3
|
||||||
1
flumi/Shaders/retro.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://c366ik3prmltu
|
||||||
59
flumi/Shaders/snowfall.gdshader
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
// Modified version of https://godotshaders.com/shader/multilayer-snowfall-shader/
|
||||||
|
// All credits to the original author!!!
|
||||||
|
|
||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform float spread : hint_range(0.0, 1.5) = 0.5;
|
||||||
|
uniform float size : hint_range(0.01, 5.0) = 0.5;
|
||||||
|
uniform vec4 snow_color : source_color = vec4(1.0);
|
||||||
|
uniform float snow_transparency: hint_range(-0.5, 1.0) = 0.2;
|
||||||
|
|
||||||
|
uniform float speed : hint_range(0.0, 10.0) = 0.5;
|
||||||
|
uniform float wind : hint_range(-2.0, 2.0) = 0.0;
|
||||||
|
uniform int num_of_layers = 40;
|
||||||
|
|
||||||
|
const mat3 NOISE_MATRIX = mat3(
|
||||||
|
vec3(13.323122, 23.5112, 21.71123),
|
||||||
|
vec3(21.1212, 28.7312, 11.9312),
|
||||||
|
vec3(21.8112, 14.7212, 61.3934)
|
||||||
|
);
|
||||||
|
|
||||||
|
vec3 generate_snowflake(vec2 coord, float layer_index, float time, float wind_strength) {
|
||||||
|
float layer_scale = 1.0 + layer_index * 0.5 / (max(size, 0.01) * 2.0);
|
||||||
|
vec2 scaled_coord = coord * layer_scale;
|
||||||
|
|
||||||
|
vec2 movement = vec2(
|
||||||
|
scaled_coord.y * (spread * mod(layer_index * 7.238917, 1.0) - spread * 0.5) +
|
||||||
|
(-wind_strength) * speed * time * 0.5,
|
||||||
|
-speed * time / (1.0 + layer_index * 0.5 * 0.03)
|
||||||
|
);
|
||||||
|
vec2 final_coord = scaled_coord + movement;
|
||||||
|
|
||||||
|
vec3 noise_input = vec3(floor(final_coord), 31.189 + layer_index);
|
||||||
|
vec3 noise_val = floor(noise_input) * 0.00001 + fract(noise_input);
|
||||||
|
vec3 random = fract((31415.9 + noise_val) / fract(NOISE_MATRIX * noise_val));
|
||||||
|
|
||||||
|
vec2 shape = abs(mod(final_coord, 1.0) - 0.5 + 0.9 * random.xy - 0.45);
|
||||||
|
shape += 0.01 * abs(2.0 * fract(10.0 * final_coord.yx) - 1.0);
|
||||||
|
|
||||||
|
float depth_offset = 5.0 * sin(time * 0.1);
|
||||||
|
float edge_softness = 0.005 + 0.05 * min(0.5 * abs(layer_index - 5.0 - depth_offset), 1.0);
|
||||||
|
|
||||||
|
float shape_value = 0.6 * max(shape.x - shape.y, shape.x + shape.y) + max(shape.x, shape.y) - 0.01;
|
||||||
|
|
||||||
|
return vec3(smoothstep(edge_softness, -edge_softness, shape_value) *
|
||||||
|
(random.x / (1.0 + 0.02 * layer_index * 0.5)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
vec3 snow_accumulation = vec3(0.0);
|
||||||
|
|
||||||
|
for (int i = 0; i < num_of_layers; i++) {
|
||||||
|
snow_accumulation += generate_snowflake(UV, float(i), TIME, wind);
|
||||||
|
}
|
||||||
|
|
||||||
|
float snow_intensity = clamp(length(snow_accumulation), 0.0, 1.0);
|
||||||
|
vec4 transparency_color = vec4(snow_color.rgb * (1.0 + snow_transparency), snow_intensity);
|
||||||
|
|
||||||
|
COLOR = transparency_color;
|
||||||
|
}
|
||||||
1
flumi/Shaders/snowfall.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://deof0r34dt78d
|
||||||
17
flumi/Shaders/vignette.gdshader
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
shader_type canvas_item;
|
||||||
|
|
||||||
|
uniform float inner_radius = 0.1;
|
||||||
|
uniform float outer_radius = 1;
|
||||||
|
uniform float vignette_strength = 1.0;
|
||||||
|
uniform float dither_strength = 0.03;
|
||||||
|
uniform vec4 vignette_color: source_color;
|
||||||
|
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
float dist = distance(UV, vec2(0.5));
|
||||||
|
|
||||||
|
float vignette = smoothstep(inner_radius, outer_radius, dist) * vignette_strength;
|
||||||
|
float dither = fract(sin(dot(UV, vec2(12.9898, 78.233))) * 43758.5453123) * dither_strength;
|
||||||
|
|
||||||
|
COLOR = vec4(vignette_color.rgb, vignette + dither);
|
||||||
|
}
|
||||||
1
flumi/Shaders/vignette.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://boba7hm3vito8
|
||||||
1
flumi/Shaders/wobbly.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
|||||||
|
uid://186q3n8sc7qw
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
.copy-url-btn { bg-[#8b5cf6] text-white hover:bg-[#7c3aed] }
|
.copy-url-btn { bg-[#8b5cf6] text-white hover:bg-[#7c3aed] }
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<postprocess preset="chrome" />
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
gurt.log('Script started!')
|
gurt.log('Script started!')
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<meta name="description" content="A stylish no-script dashboard">
|
<meta name="description" content="A stylish no-script dashboard">
|
||||||
|
|
||||||
<font name="roboto" src="https://fonts.gstatic.com/s/roboto/v48/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2" />
|
<font name="roboto" src="https://fonts.gstatic.com/s/roboto/v48/KFO7CnqEu92Fr1ME7kSn66aGLdTylUAMa3KUBGEe.woff2" />
|
||||||
|
<postprocess preset="rblur" />
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
h1 { text-[#ffffff] text-3xl font-bold }
|
h1 { text-[#ffffff] text-3xl font-bold }
|
||||||
|
|||||||