Initial Commit
This commit is contained in:
96
tools/README.md
Normal file
96
tools/README.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Shader Dev Guide
|
||||
|
||||
`ShaderCompiler.py` and `ShaderProcessor.py` are from the KDE Shader Wallpaper project
|
||||
|
||||
## Automated Shader Import
|
||||
|
||||
### Prerequisite
|
||||
To compile shaders, you must use QT6's qsb, by default it isn't in your PATH.
|
||||
qsb can be found in `/usr/lib/qt6/bin`
|
||||
add it to your path like this: `export PATH:$PATH:/usr/lib/qt6/bin` and now we can call it from anywhere
|
||||
|
||||
### Processing & Compiling
|
||||
Currently, kde-shader-wallpaper doesn't support shaders that uses buffers
|
||||
|
||||
Place the .frag shaders you want to convert here: `package/contents/ui/Shaders/ConvertMe`
|
||||
|
||||
Run:
|
||||
- `python ShaderProcessor.py` to add the required code to the shader files and process it (!!! it's probably a good idea to manually verify as it's not perfect!!! )
|
||||
- `python ShaderCompiler.py` to compile it to the `Shaders6` folder
|
||||
|
||||
### Install the package
|
||||
- `kpackagetool6 -t Plasma/Wallpaper -i package`
|
||||
|
||||
( You may need to remove the previously installed package first, which can be found here: `~/.local/share/plasma/wallpapers/online.knowmad.shaderwallpaper` )
|
||||
|
||||
|
||||
## Manual Shader Import
|
||||
|
||||
### Processing
|
||||
|
||||
Add this to your shader .frag file:
|
||||
|
||||
```hlsl
|
||||
// add this at the top of the file
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float iTime;
|
||||
float iTimeDelta;
|
||||
float iFrameRate;
|
||||
float iSampleRate;
|
||||
int iFrame;
|
||||
vec4 iDate;
|
||||
vec4 iMouse;
|
||||
vec3 iResolution;
|
||||
float iChannelTime[4];
|
||||
vec3 iChannelResolution[4];
|
||||
} ubuf;
|
||||
|
||||
layout(binding = 1) uniform sampler2D iChannel0;
|
||||
layout(binding = 2) uniform sampler2D iChannel1;
|
||||
layout(binding = 3) uniform sampler2D iChannel2;
|
||||
layout(binding = 4) uniform sampler2D iChannel3;
|
||||
|
||||
vec2 fragCoord = vec2(qt_TexCoord0.x, 1.0 - qt_TexCoord0.y) * ubuf.iResolution.xy;
|
||||
|
||||
// either rename them in the frag or add this (probably costs some performance)
|
||||
|
||||
// int iFrame = ubuf.iFrame;
|
||||
// float iTime = ubuf.iTime;
|
||||
// float iTimeDelta = ubuf.iTimeDelta;
|
||||
// vec3 iResolution = ubuf.iResolution;
|
||||
// vec4 iMouse = ubuf.iMouse;
|
||||
// etc...
|
||||
|
||||
// these must be modified as you cant do that with arrays afaik:
|
||||
// float iChannelTime[4];
|
||||
// vec3 iChannelResolution[4];
|
||||
|
||||
// add this at the end
|
||||
void main() {
|
||||
vec4 color = vec4(0.0);
|
||||
mainImage(color, fragCoord);
|
||||
fragColor = color;
|
||||
}
|
||||
```
|
||||
|
||||
### Compile
|
||||
`qsb --glsl "100 es,120,150" --hlsl 50 --msl 12 -o MYSHADER.frag.qsb MYSHADER.frag`
|
||||
|
||||
|
||||
### Install the package
|
||||
You may need to remove the previously installed package in your `~/.local/share/plasma/wallpapers/online.knowmad.shaderwallpaper`
|
||||
`kpackagetool6 -t Plasma/Wallpaper -i package`
|
||||
|
||||
|
||||
|
||||
## Reference
|
||||
|
||||
- https://doc.qt.io/qt-6/qtshadertools-qsb.html
|
||||
- https://invent.kde.org/plasma/libplasma
|
||||
42
tools/ShaderCompiler.py
Normal file
42
tools/ShaderCompiler.py
Normal file
@@ -0,0 +1,42 @@
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
# If they fail to convert, try only converting for 120,150 or 150 instead of 100 es
|
||||
# otherwise, debug the shader it self
|
||||
|
||||
# Paths
|
||||
source_directory = 'processed'
|
||||
output_directory = 'build'
|
||||
|
||||
# Ensure output directory exists
|
||||
os.makedirs(output_directory, exist_ok=True)
|
||||
|
||||
# THIS WILL DELETE YOUR ORIGINAL FRAG AFTER COMPILING IF SET TO TRUE
|
||||
DELETE_AFTER_COMPILATION = False
|
||||
|
||||
# Iterate over all .frag files in the source directory
|
||||
for root, dirs, files in os.walk(source_directory):
|
||||
for file in files:
|
||||
if file.endswith('.frag'):
|
||||
# Construct the full path to the source file
|
||||
source_file_path = os.path.join(root, file)
|
||||
# Construct the output file path
|
||||
output_file_name = file.replace('.frag', '.frag.qsb')
|
||||
output_file_path = os.path.join(output_directory, output_file_name)
|
||||
# Construct and execute the command
|
||||
cmd = [
|
||||
'qsb', '--glsl', '100 es,120,150', '--hlsl', '50', '--msl', '12',
|
||||
'-o', output_file_path, source_file_path
|
||||
]
|
||||
|
||||
try:
|
||||
subprocess.run(cmd, check=True)
|
||||
# If the command was successful, delete the source file
|
||||
if (DELETE_AFTER_COMPILATION):
|
||||
os.remove(source_file_path)
|
||||
print(f"Successfully converted and deleted: {file}")
|
||||
else:
|
||||
print(f"Successfully converted: {file}")
|
||||
except subprocess.CalledProcessError:
|
||||
# If the command failed, do not delete the source file
|
||||
print(f"Conversion failed for: {file}")
|
||||
82
tools/ShaderProcessor.py
Normal file
82
tools/ShaderProcessor.py
Normal file
@@ -0,0 +1,82 @@
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
|
||||
# Specify the directory where your .frag files are located
|
||||
directory_path = 'src'
|
||||
output_directory = 'processed'
|
||||
|
||||
# List of variables to update
|
||||
variables_to_update = [
|
||||
'iTime', 'iTimeDelta', 'iFrameRate', 'iSampleRate',
|
||||
'iFrame', 'iDate', 'iMouse', 'iResolution',
|
||||
r'iChannelTime', r'iChannelResolution'
|
||||
]
|
||||
|
||||
# Header and footer to append
|
||||
header = '''
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float iTime;
|
||||
float iTimeDelta;
|
||||
float iFrameRate;
|
||||
float iSampleRate;
|
||||
int iFrame;
|
||||
vec4 iDate;
|
||||
vec4 iMouse;
|
||||
vec3 iResolution;
|
||||
float iChannelTime[4];
|
||||
vec3 iChannelResolution[4];
|
||||
} ubuf;
|
||||
|
||||
layout(binding = 1) uniform sampler2D iChannel0;
|
||||
layout(binding = 2) uniform sampler2D iChannel1;
|
||||
layout(binding = 3) uniform sampler2D iChannel2;
|
||||
layout(binding = 4) uniform sampler2D iChannel3;
|
||||
|
||||
vec2 fragCoord = vec2(qt_TexCoord0.x, 1.0 - qt_TexCoord0.y) * ubuf.iResolution.xy;
|
||||
'''
|
||||
|
||||
footer = '''
|
||||
|
||||
void main() {
|
||||
vec4 color = vec4(0.0);
|
||||
mainImage(color, fragCoord);
|
||||
fragColor = color;
|
||||
}
|
||||
'''
|
||||
|
||||
for root, dirs, files in os.walk(directory_path):
|
||||
for file in files:
|
||||
if file.endswith('.frag'):
|
||||
file_path = os.path.join(root, file)
|
||||
|
||||
with open(file_path, 'r', encoding='utf-8') as f:
|
||||
content = f.read()
|
||||
|
||||
# Replace variable names
|
||||
for var in variables_to_update:
|
||||
content = re.sub(r'\b' + re.escape(var) + r'\b', 'ubuf.' + var, content)
|
||||
|
||||
# Insert header after first empty line
|
||||
insert_index = content.find('\n\n') + 1
|
||||
content = content[:insert_index] + header + content[insert_index:]
|
||||
|
||||
# Append footer
|
||||
content += footer
|
||||
|
||||
# Construct new output path
|
||||
relative_path = os.path.relpath(root, directory_path)
|
||||
new_root = os.path.join(output_directory, relative_path)
|
||||
os.makedirs(new_root, exist_ok=True)
|
||||
new_file_path = os.path.join(new_root, file)
|
||||
|
||||
# Write to the new file
|
||||
with open(new_file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(content)
|
||||
141
tools/processed/002-Blue.frag
Normal file
141
tools/processed/002-Blue.frag
Normal file
@@ -0,0 +1,141 @@
|
||||
// https://www.shadertoy.com/view/WldSRn
|
||||
// credits to haquxx
|
||||
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 qt_TexCoord0;
|
||||
layout(location = 0) out vec4 fragColor;
|
||||
|
||||
layout(std140, binding = 0) uniform buf {
|
||||
mat4 qt_Matrix;
|
||||
float qt_Opacity;
|
||||
float iTime;
|
||||
float iTimeDelta;
|
||||
float iFrameRate;
|
||||
float iSampleRate;
|
||||
int iFrame;
|
||||
vec4 iDate;
|
||||
vec4 iMouse;
|
||||
vec3 iResolution;
|
||||
float iChannelTime[4];
|
||||
vec3 iChannelResolution[4];
|
||||
} ubuf;
|
||||
|
||||
layout(binding = 1) uniform sampler2D iChannel0;
|
||||
layout(binding = 2) uniform sampler2D iChannel1;
|
||||
layout(binding = 3) uniform sampler2D iChannel2;
|
||||
layout(binding = 4) uniform sampler2D iChannel3;
|
||||
|
||||
vec2 fragCoord = vec2(qt_TexCoord0.x, 1.0 - qt_TexCoord0.y) * ubuf.iResolution.xy;
|
||||
|
||||
float sdSphere(vec3 pos, float size)
|
||||
{
|
||||
return length(pos) - size;
|
||||
}
|
||||
|
||||
float sdBox(vec3 pos, vec3 size)
|
||||
{
|
||||
pos = abs(pos) - vec3(size);
|
||||
return max(max(pos.x, pos.y), pos.z);
|
||||
}
|
||||
|
||||
float sdOctahedron(vec3 p, float s)
|
||||
{
|
||||
p = abs(p);
|
||||
float m = p.x+p.y+p.z-s;
|
||||
vec3 q;
|
||||
if( 3.0*p.x < m ) q = p.xyz;
|
||||
else if( 3.0*p.y < m ) q = p.yzx;
|
||||
else if( 3.0*p.z < m ) q = p.zxy;
|
||||
else return m*0.57735027;
|
||||
|
||||
float k = clamp(0.5*(q.z-q.y+s),0.0,s);
|
||||
return length(vec3(q.x,q.y-s+k,q.z-k));
|
||||
}
|
||||
|
||||
float sdPlane(vec3 pos)
|
||||
{
|
||||
return pos.y;
|
||||
}
|
||||
|
||||
mat2 rotate(float a)
|
||||
{
|
||||
float s = sin(a);
|
||||
float c = cos(a);
|
||||
return mat2(c, s, -s, c);
|
||||
}
|
||||
|
||||
vec3 repeat(vec3 pos, vec3 span)
|
||||
{
|
||||
return abs(mod(pos, span)) - span * 0.5;
|
||||
}
|
||||
|
||||
float getDistance(vec3 pos, vec2 uv)
|
||||
{
|
||||
vec3 originalPos = pos;
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
pos = abs(pos) - 4.5;
|
||||
pos.xz *= rotate(1.0);
|
||||
pos.yz *= rotate(1.0);
|
||||
}
|
||||
|
||||
pos = repeat(pos, vec3(4.0));
|
||||
|
||||
float d0 = abs(originalPos.x) - 0.1;
|
||||
float d1 = sdBox(pos, vec3(0.8));
|
||||
|
||||
pos.xy *= rotate(mix(1.0, 2.0, abs(sin(ubuf.iTime))));
|
||||
float size = mix(1.1, 1.3, (abs(uv.y) * abs(uv.x)));
|
||||
float d2 = sdSphere(pos, size);
|
||||
float dd2 = sdOctahedron(pos, 1.8);
|
||||
float ddd2 = mix(d2, dd2, abs(sin(ubuf.iTime)));
|
||||
|
||||
return max(max(d1, -ddd2), -d0);
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
vec2 p = (fragCoord.xy * 2.0 - ubuf.iResolution.xy) / min(ubuf.iResolution.x, ubuf.iResolution.y);
|
||||
|
||||
// camera
|
||||
vec3 cameraOrigin = vec3(0.0, 0.0, -10.0 + ubuf.iTime * 4.0);
|
||||
vec3 cameraTarget = vec3(cos(ubuf.iTime) + sin(ubuf.iTime / 2.0) * 10.0, exp(sin(ubuf.iTime)) * 2.0, 3.0 + ubuf.iTime * 4.0);
|
||||
vec3 upDirection = vec3(0.0, 1.0, 0.0);
|
||||
vec3 cameraDir = normalize(cameraTarget - cameraOrigin);
|
||||
vec3 cameraRight = normalize(cross(upDirection, cameraOrigin));
|
||||
vec3 cameraUp = cross(cameraDir, cameraRight);
|
||||
vec3 rayDirection = normalize(cameraRight * p.x + cameraUp * p.y + cameraDir);
|
||||
|
||||
float depth = 0.0;
|
||||
float ac = 0.0;
|
||||
vec3 rayPos = vec3(0.0);
|
||||
float d = 0.0;
|
||||
|
||||
for(int i = 0; i < 80; i++)
|
||||
{
|
||||
rayPos = cameraOrigin + rayDirection * depth;
|
||||
d = getDistance(rayPos, p);
|
||||
|
||||
if(abs(d) < 0.0001)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ac += exp(-d * mix(5.0, 10.0, abs(sin(ubuf.iTime))));
|
||||
depth += d;
|
||||
}
|
||||
|
||||
vec3 col = vec3(0.0, 0.3, 0.7);
|
||||
ac *= 1.2 * (ubuf.iResolution.x/ubuf.iResolution.y - abs(p.x)) ;
|
||||
vec3 finalCol = col * ac * 0.06;
|
||||
fragColor = vec4(finalCol, 1.0);
|
||||
fragColor.w = 1.0 - depth * 0.1;
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 color = vec4(0.0);
|
||||
mainImage(color, fragCoord);
|
||||
fragColor = color;
|
||||
}
|
||||
108
tools/src/002-Blue.frag
Normal file
108
tools/src/002-Blue.frag
Normal file
@@ -0,0 +1,108 @@
|
||||
// https://www.shadertoy.com/view/WldSRn
|
||||
// credits to haquxx
|
||||
|
||||
float sdSphere(vec3 pos, float size)
|
||||
{
|
||||
return length(pos) - size;
|
||||
}
|
||||
|
||||
float sdBox(vec3 pos, vec3 size)
|
||||
{
|
||||
pos = abs(pos) - vec3(size);
|
||||
return max(max(pos.x, pos.y), pos.z);
|
||||
}
|
||||
|
||||
float sdOctahedron(vec3 p, float s)
|
||||
{
|
||||
p = abs(p);
|
||||
float m = p.x+p.y+p.z-s;
|
||||
vec3 q;
|
||||
if( 3.0*p.x < m ) q = p.xyz;
|
||||
else if( 3.0*p.y < m ) q = p.yzx;
|
||||
else if( 3.0*p.z < m ) q = p.zxy;
|
||||
else return m*0.57735027;
|
||||
|
||||
float k = clamp(0.5*(q.z-q.y+s),0.0,s);
|
||||
return length(vec3(q.x,q.y-s+k,q.z-k));
|
||||
}
|
||||
|
||||
float sdPlane(vec3 pos)
|
||||
{
|
||||
return pos.y;
|
||||
}
|
||||
|
||||
mat2 rotate(float a)
|
||||
{
|
||||
float s = sin(a);
|
||||
float c = cos(a);
|
||||
return mat2(c, s, -s, c);
|
||||
}
|
||||
|
||||
vec3 repeat(vec3 pos, vec3 span)
|
||||
{
|
||||
return abs(mod(pos, span)) - span * 0.5;
|
||||
}
|
||||
|
||||
float getDistance(vec3 pos, vec2 uv)
|
||||
{
|
||||
vec3 originalPos = pos;
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
pos = abs(pos) - 4.5;
|
||||
pos.xz *= rotate(1.0);
|
||||
pos.yz *= rotate(1.0);
|
||||
}
|
||||
|
||||
pos = repeat(pos, vec3(4.0));
|
||||
|
||||
float d0 = abs(originalPos.x) - 0.1;
|
||||
float d1 = sdBox(pos, vec3(0.8));
|
||||
|
||||
pos.xy *= rotate(mix(1.0, 2.0, abs(sin(iTime))));
|
||||
float size = mix(1.1, 1.3, (abs(uv.y) * abs(uv.x)));
|
||||
float d2 = sdSphere(pos, size);
|
||||
float dd2 = sdOctahedron(pos, 1.8);
|
||||
float ddd2 = mix(d2, dd2, abs(sin(iTime)));
|
||||
|
||||
return max(max(d1, -ddd2), -d0);
|
||||
}
|
||||
|
||||
void mainImage( out vec4 fragColor, in vec2 fragCoord )
|
||||
{
|
||||
vec2 p = (fragCoord.xy * 2.0 - iResolution.xy) / min(iResolution.x, iResolution.y);
|
||||
|
||||
// camera
|
||||
vec3 cameraOrigin = vec3(0.0, 0.0, -10.0 + iTime * 4.0);
|
||||
vec3 cameraTarget = vec3(cos(iTime) + sin(iTime / 2.0) * 10.0, exp(sin(iTime)) * 2.0, 3.0 + iTime * 4.0);
|
||||
vec3 upDirection = vec3(0.0, 1.0, 0.0);
|
||||
vec3 cameraDir = normalize(cameraTarget - cameraOrigin);
|
||||
vec3 cameraRight = normalize(cross(upDirection, cameraOrigin));
|
||||
vec3 cameraUp = cross(cameraDir, cameraRight);
|
||||
vec3 rayDirection = normalize(cameraRight * p.x + cameraUp * p.y + cameraDir);
|
||||
|
||||
float depth = 0.0;
|
||||
float ac = 0.0;
|
||||
vec3 rayPos = vec3(0.0);
|
||||
float d = 0.0;
|
||||
|
||||
for(int i = 0; i < 80; i++)
|
||||
{
|
||||
rayPos = cameraOrigin + rayDirection * depth;
|
||||
d = getDistance(rayPos, p);
|
||||
|
||||
if(abs(d) < 0.0001)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
ac += exp(-d * mix(5.0, 10.0, abs(sin(iTime))));
|
||||
depth += d;
|
||||
}
|
||||
|
||||
vec3 col = vec3(0.0, 0.3, 0.7);
|
||||
ac *= 1.2 * (iResolution.x/iResolution.y - abs(p.x)) ;
|
||||
vec3 finalCol = col * ac * 0.06;
|
||||
fragColor = vec4(finalCol, 1.0);
|
||||
fragColor.w = 1.0 - depth * 0.1;
|
||||
}
|
||||
Reference in New Issue
Block a user