From a7930760e8a40e4153c861b395346df2682f90ee Mon Sep 17 00:00:00 2001 From: Nova Date: Sun, 25 Jun 2023 10:04:37 -0400 Subject: [PATCH] feat: glsl simula text shaders --- Cargo.lock | 2 +- Cargo.toml | 4 +- src/nodes/drawable/mod.rs | 1 + src/nodes/drawable/shaders.rs | 54 +++++++++++ src/wayland/shaders/mod.rs | 6 ++ src/wayland/shaders/simula.frag | 158 ++++++++++++++++++++++++++++++++ src/wayland/shaders/simula.vert | 7 ++ src/wayland/state.rs | 2 - src/wayland/surface.rs | 13 ++- 9 files changed, 239 insertions(+), 8 deletions(-) create mode 100644 src/nodes/drawable/shaders.rs create mode 100644 src/wayland/shaders/simula.frag create mode 100644 src/wayland/shaders/simula.vert diff --git a/Cargo.lock b/Cargo.lock index 08472dc..86fad70 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1951,7 +1951,7 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smithay" version = "0.3.0" -source = "git+https://github.com/technobaboo/smithay.git#2a03e6c9100a158c6ea30fff76d1c3658bef0c6d" +source = "git+https://github.com/smithay/smithay.git#da5c1b9d4dc21c8fe4037e216a82419cab124a77" dependencies = [ "appendlist", "bitflags 2.3.1", diff --git a/Cargo.toml b/Cargo.toml index 0888fc0..65d0a28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,8 +66,8 @@ features = ["linux-egl"] version = "0.16.7" [dependencies.smithay] -git = "https://github.com/technobaboo/smithay.git" # Until we get stereokit to understand OES samplers and external textures -# git = "https://github.com/smithay/smithay.git" # Until we get stereokit to understand OES samplers and external textures +# git = "https://github.com/technobaboo/smithay.git" # Until we get stereokit to understand OES samplers and external textures +git = "https://github.com/smithay/smithay.git" # Until we get stereokit to understand OES samplers and external textures # path = "../smithay" default-features = false features = ["desktop", "renderer_gl", "wayland_frontend"] diff --git a/src/nodes/drawable/mod.rs b/src/nodes/drawable/mod.rs index b6148e5..6001fe6 100644 --- a/src/nodes/drawable/mod.rs +++ b/src/nodes/drawable/mod.rs @@ -1,5 +1,6 @@ pub mod lines; pub mod model; +pub mod shaders; pub mod text; use self::{ diff --git a/src/nodes/drawable/shaders.rs b/src/nodes/drawable/shaders.rs new file mode 100644 index 0000000..7715517 --- /dev/null +++ b/src/nodes/drawable/shaders.rs @@ -0,0 +1,54 @@ +use std::{ffi::CString, mem::transmute}; + +use smithay::backend::renderer::gles::ffi::{Gles2, FRAGMENT_SHADER, VERTEX_SHADER}; +use stereokit::Shader; + +struct FfiAssetHeader { + asset_type: i32, + asset_state: i32, + id: u64, + index: u64, + refs: i32, +} + +struct FfiSkgShader { + meta: *mut u8, + vertex: u32, + pixel: u32, + program: u32, + compute: u32, +} + +struct FfiShader { + header: FfiAssetHeader, + shader: FfiSkgShader, +} + +unsafe fn load_shader(c: &Gles2, source: &str, stage: u32) -> u32 { + let shader = c.CreateShader(stage); + let shader_source = CString::new(source).unwrap(); + c.ShaderSource(shader, 1, &shader_source.as_ptr(), std::ptr::null()); + c.CompileShader(shader); + shader +} + +unsafe fn link_program(c: &Gles2, vert: u32, frag: u32) -> u32 { + let program = c.CreateProgram(); + c.AttachShader(vert, VERTEX_SHADER); + c.AttachShader(frag, FRAGMENT_SHADER); + c.LinkProgram(program); + program +} + +pub unsafe fn shader_inject(c: &Gles2, sk_shader: &mut Shader, vert_str: &str, frag_str: &str) { + let gl_vert = load_shader(c, vert_str, VERTEX_SHADER); + let gl_frag = load_shader(c, frag_str, FRAGMENT_SHADER); + let gl_prog = link_program(c, gl_vert, gl_frag); + + let shader: *mut FfiShader = transmute(sk_shader.0.as_mut()); + if let Some(shader) = shader.as_mut() { + shader.shader.vertex = gl_vert; + shader.shader.pixel = gl_frag; + shader.shader.program = gl_prog; + } +} diff --git a/src/wayland/shaders/mod.rs b/src/wayland/shaders/mod.rs index 178d192..911cb57 100644 --- a/src/wayland/shaders/mod.rs +++ b/src/wayland/shaders/mod.rs @@ -5,3 +5,9 @@ // Simula shader with fancy lanzcos sampling pub const PANEL_SHADER_BYTES: &[u8] = include_bytes!("shader_unlit_simula.sks"); + +// Simula text shader (fragment) +pub const SIMULA_FRAG_STR: &str = include_str!("simula.frag"); + +// Simula text shader (vertex) +pub const SIMULA_VERT_STR: &str = include_str!("simula.vert"); diff --git a/src/wayland/shaders/simula.frag b/src/wayland/shaders/simula.frag new file mode 100644 index 0000000..d1e0300 --- /dev/null +++ b/src/wayland/shaders/simula.frag @@ -0,0 +1,158 @@ +// #version 320 es +// #extension GL_OES_EGL_image_external : require + +// precision highp float; + +// in vec2 vUV; +// uniform samplerExternalOES diffuse; +// uniform vec4 diffuse_i; +// uniform vec2 uv_scale; +// uniform vec2 uv_offset; +// uniform float fcFactor; +// uniform float ripple; +// uniform float alpha_min; +// uniform float alpha_max; + +// float map(float value, float min1, float max1, float min2, float max2) { +// return min2 + (value - min1) * (max2 - min2) / (max1 - min1); +// } + +// // float gaussian(float x, float t) { +// // float PI = 3.14159265358; +// // return exp(-x*x/(2.0 * t*t))/(sqrt(2.0*PI)*t); +// // } + +// float besselI0(float x) { +// return 1.0 + pow(x, 2.0) * (0.25 + pow(x, 2.0) * (0.015625 + pow(x, 2.0) * (0.000434028 + pow(x, 2.0) * (6.78168e-6 + pow(x, 2.0) * (6.78168e-8 + pow(x, 2.0) * (4.7095e-10 + pow(x, 2.0) * (2.40281e-12 + pow(x, 2.0) * (9.38597e-15 + pow(x, 2.0) * (2.8969e-17 + 7.24226e-20 * pow(x, 2.0)))))))))); +// } + +// float kaiser(float x, float alpha) { +// if (x > 1.0) { +// return 0.0; +// } +// return besselI0(alpha * sqrt(1.0-x*x)); +// } + +// vec4 lowpassFilter(samplerExternalOES tex, samplerExternalOES texSampler, vec2 uv, float alpha) { +// float PI = 3.14159265358; + +// vec4 q = vec4(0.0); + +// vec2 dx_uv = dFdx(uv); +// vec2 dy_uv = dFdy(uv); +// //float width = sqrt(max(dot(dx_uv, dx_uv), dot(dy_uv, dy_uv))); +// vec2 width = abs(vec2(dx_uv.x, dy_uv.y)); + +// vec2 pixelWidth = floor(width * diffuse_i.xy); +// vec2 aspectRatio = normalize(pixelWidth); + +// vec2 xyf = uv * diffuse_i.xy; +// ivec2 xy = ivec2(xyf); + +// pixelWidth = clamp(pixelWidth, vec2(1.0), vec2(2.0)); + +// ivec2 start = xy - ivec2(pixelWidth); +// ivec2 end = xy + ivec2(pixelWidth); + +// vec4 outColor = vec4(0.0); + +// float qSum = 0.0; + +// for (int v = start.y; v <= end.y; v++) { +// for (int u = start.x; u <= end.x; u++) { +// float kx = fcFactor * (xyf.x - float(u))/pixelWidth.x; +// float ky = fcFactor * (xyf.y - float(v))/pixelWidth.y; + +// //float lanczosValue = gaussian(kx, fcx); +// float lanczosValue = kaiser(sqrt(kx*kx + ky*ky), alpha); + +// q += texture2D(tex, (vec2(u, v)+vec2(0.5))/diffuse_i.xy) * lanczosValue; +// // q += tex.Load(int3(u, v, 0)) * lanczosValue; +// qSum += lanczosValue; +// } +// } + +// return q/qSum; +// } + +void main() { + //gl_FragColor = texture2D(diffuse, vec2(1.0 - vUV.x, vUV.y)); //to turn off + gl_FragColor = lowpassFilter(diffuse, vec2(1.0 - vUV.x, vUV.y), ripple); + gl_FragColor.a = map(col.a, 0, 1, alpha_min, alpha_max); +} + +#version 320 es +#extension GL_OES_EGL_image_external : require +precision mediump float; +precision highp int; + +layout(binding = 0, std140) uniform _Global +{ + highp vec4 diffuse_i; + highp vec2 uv_scale; + highp vec2 uv_offset; + highp float fcFactor; + highp float ripple; + highp float alpha_min; + highp float alpha_max; +} uniforms; + +layout(binding = 0) uniform highp samplerExternalOES diffuse; + +layout(location = 0) in highp vec2 fs_uv; +layout(location = 0) out highp vec4 gl_FragColor; + +void main() +{ + highp vec2 dx_uv = dFdx(fs_uv); + highp vec2 dy_uv = dFdy(fs_uv); + highp vec2 width = fs_uv * uniforms.diffuse_i.xy; + ivec2 _475 = ivec2(width); + highp vec2 _477 = clamp(floor(abs(vec2(dx_uv.x, dy_uv.y)) * uniforms.diffuse_i.xy), vec2(1.0), vec2(2.0)); + ivec2 _480 = ivec2(_477); + ivec2 _481 = _475 - _480; + ivec2 _485 = _475 + _480; + int _487 = _481.y; + highp vec4 _671; + highp float _672; + _672 = 0.0; + _671 = vec4(0.0); + highp vec4 _679; + highp float _681; + for (int _670 = _487; _670 <= _485.y; _672 = _681, _671 = _679, _670++) + { + int _496 = _481.x; + _681 = _672; + _679 = _671; + highp vec4 _553; + highp float _556; + for (int _673 = _496; _673 <= _485.x; _681 = _556, _679 = _553, _673++) + { + highp float _509 = float(_673); + highp float _514 = (uniforms.fcFactor * (width.x - _509)) / _477.x; + highp float _520 = float(_670); + highp float _525 = (uniforms.fcFactor * (width.y - _520)) / _477.y; + highp float _533 = sqrt((_514 * _514) + (_525 * _525)); + highp float _675; + do + { + if (_533 > 1.0) + { + _675 = 0.0; + break; + } + highp float _592 = pow(uniforms.ripple * sqrt(1.0 - (_533 * _533)), 2.0); + _675 = 1.0 + (_592 * (0.25 + (_592 * (0.015625 + (_592 * (0.00043402801384218037128448486328125 + (_592 * (6.7816799855791032314300537109375e-06 + (_592 * (6.7816799287356843706220388412476e-08 + (_592 * (4.709500012189948847662890329957e-10 + (_592 * (2.4028099388645474121517509047408e-12 + (_592 * (9.3859703944590075486154034933861e-15 + (_592 * (2.8968999943407451927966655969016e-17 + (7.242260299760125752555485045131e-20 * _592))))))))))))))))))); + break; + } while(false); + _553 = _679 + (texture(diffuse, (vec2(_509, _520) + vec2(0.5)) / uniforms.diffuse_i.xy) * _675); + _556 = _681 + _675; + } + } + highp vec4 _568 = _671 / vec4(_672); + highp vec3 _417 = pow(_568.xyz, vec3(2.2000000476837158203125)); + highp vec4 _669 = vec4(_417.x, _417.y, _417.z, _568.w); + _669.w = uniforms.alpha_min + (_568.w * (uniforms.alpha_max - uniforms.alpha_min)); + gl_FragColor = _669; +} + diff --git a/src/wayland/shaders/simula.vert b/src/wayland/shaders/simula.vert new file mode 100644 index 0000000..f6f0bdd --- /dev/null +++ b/src/wayland/shaders/simula.vert @@ -0,0 +1,7 @@ +#version 320 es +in vec2 UV; +out vec2 vUV; + +void main() { + vUV = UV; +} \ No newline at end of file diff --git a/src/wayland/state.rs b/src/wayland/state.rs index a590961..43db8b8 100644 --- a/src/wayland/state.rs +++ b/src/wayland/state.rs @@ -60,7 +60,6 @@ pub struct WaylandState { pub shm_state: ShmState, pub dmabuf_state: DmabufState, pub dmabuf_global: DmabufGlobal, - pub pending_dmabufs: Vec, pub output: Output, pub seats: FxHashMap>, } @@ -120,7 +119,6 @@ impl WaylandState { shm_state, dmabuf_state, dmabuf_global, - pending_dmabufs: Vec::new(), output, seats: FxHashMap::default(), }) diff --git a/src/wayland/surface.rs b/src/wayland/surface.rs index fb371ea..a25d871 100644 --- a/src/wayland/surface.rs +++ b/src/wayland/surface.rs @@ -1,7 +1,10 @@ -use super::{shaders::PANEL_SHADER_BYTES, state::WaylandState}; +use super::{ + shaders::{PANEL_SHADER_BYTES, SIMULA_FRAG_STR, SIMULA_VERT_STR}, + state::WaylandState, +}; use crate::{ core::{delta::Delta, destroy_queue, registry::Registry}, - nodes::drawable::model::ModelPart, + nodes::drawable::{model::ModelPart, shaders::shader_inject}, }; use mint::Vector2; use once_cell::sync::OnceCell; @@ -95,7 +98,11 @@ impl CoreSurface { SendWrapper::new(sk.tex_create(TextureType::IMAGE_NO_MIPS, TextureFormat::RGBA32)) }); self.sk_mat.get_or_init(|| { - let shader = sk.shader_create_mem(&PANEL_SHADER_BYTES).unwrap(); + let mut shader = sk.shader_create_mem(&PANEL_SHADER_BYTES).unwrap(); + let _ = renderer.with_context(|c| unsafe { + shader_inject(c, &mut shader, SIMULA_VERT_STR, SIMULA_FRAG_STR) + }); + let mat = sk.material_create(&shader); sk.material_set_texture(&mat, "diffuse", sk_tex.as_ref()); sk.material_set_transparency(&mat, Transparency::Blend);