From 59bce8fabb0e1d81de108e9859737de59cef0878 Mon Sep 17 00:00:00 2001 From: andrew pliatsikas Date: Sat, 31 Aug 2024 09:55:16 +0100 Subject: [PATCH] Shaderz Update with shade --- metadata/pixdecor.xml | 169 +++-- src/deco-effects.cpp | 406 ++++++++++- src/deco-effects.hpp | 12 +- src/deco-subsurface.cpp | 3 +- src/deco-theme.cpp | 4 +- src/deco-theme.hpp | 4 +- src/effect-shaders.hpp | 1487 +++++++++++++++++++++++++++++++++++++++ src/overlay-shaders.hpp | 412 +++++++++++ src/smoke-shaders.hpp | 1196 +++++++++++++++++++++++++++++++ 9 files changed, 3599 insertions(+), 94 deletions(-) create mode 100644 src/effect-shaders.hpp create mode 100644 src/overlay-shaders.hpp diff --git a/metadata/pixdecor.xml b/metadata/pixdecor.xml index f0fcc26..5f02b54 100644 --- a/metadata/pixdecor.xml +++ b/metadata/pixdecor.xml @@ -92,70 +92,104 @@ + <_short>Effect Type + <_long>Sets the effect type. + none + + none + <_name>None + + + smoke + <_name>Smoke + + + ink + <_name>Ink + + + fumes + <_name>Fumes + + + fast_smoke + <_name>Fast Smoke + + + + clouds + <_name>Clouds + + + halftone + <_name>Halftone + + + pattern + <_name>Pattern + + + lava + <_name>Lava + + + hex + <_name>Hex + + + zebra + <_name>Zebra + + + neural_network + <_name>Neural network + + + hexagon_maze + <_name>Hexagon maze + + + raymarched_truchet + <_name>Raymarched truchet + + + neon_pattern + <_name>Neon pattern + + + neon_rings + <_name>Neon rings + + + deco + <_name>Deco + + + ice + <_name>Ice + + + fire + <_name>Fire + + + flame + <_name>Flame + + + + <_short>Shade diff --git a/src/deco-effects.cpp b/src/deco-effects.cpp index 2d5ff45..24c25a8 100644 --- a/src/deco-effects.cpp +++ b/src/deco-effects.cpp @@ -6,7 +6,7 @@ * Copyright (c) 2024 Ilia Bozhinov * - Awesome optimizations * Copyright (c) 2024 Andrew Pliatsikas - * - Ported effect shaders to compute + * - Fast smoke, fumes, flame and beveled glass * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -31,7 +31,9 @@ #include #include "deco-effects.hpp" +#include "effect-shaders.hpp" #include "smoke-shaders.hpp" +#include "overlay-shaders.hpp" namespace wf @@ -43,6 +45,16 @@ static std::string stitch_smoke_shader(const std::string& source) return smoke_header + source + effect_run_for_region_main; } + +static GLint compile_fragment_effect_program(const std::string& effect_source, const std::string& overlay_source) +{ + std::string full_fragment = + generic_effect_fragment_header + effect_source + overlay_source + generic_effect_fragment_main; + + return OpenGL::compile_program(generic_effect_vertex_shader, full_fragment); +} + + // ported from https://www.shadertoy.com/view/WdXBW4 static const char *render_source_clouds = R"( @@ -183,13 +195,8 @@ void main() { // Mix the cloud color with the background, considering darkness, cover, and alpha vec3 finalColor = mix(skycolour, cloudColor * clouddark, cloudPattern + noiseShape + noiseColor) * (1.0 - cloudCover) + cloudColor * cloudCover; finalColor = mix(skycolour, finalColor, cloudAlpha); - imageStore(out_tex, pos, vec4(finalColor, 1.0)); -} - - - -)"; +})"; // ported from https://github.com/keijiro/ShaderSketches/blob/master/Fragment/Dots3.glsl static const char *render_source_halftone = @@ -1660,6 +1667,151 @@ void main() { } )"; +// ported from https://www.shadertoy.com/view/3djfzy +static const char *render_source_ice = + R"(#version 320 es +precision highp float; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +layout(binding = 0, rgba32f) writeonly uniform highp image2D outputImage; + +layout(location = 5) uniform int width; +layout(location = 6) uniform int height; +layout(location = 9) uniform float current_time; + +float rand(in vec2 _st) { + return fract(sin(dot(_st.xy, vec2(-0.820, -0.840))) * 4757.153); +} + +float noise(in vec2 _st) { + const vec2 d = vec2(0.0, 1.0); + vec2 b = floor(_st), f = smoothstep(vec2(0.0), vec2(0.1, 0.3), fract(_st)); + return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y); +} + +float fbm(in vec2 _st) { + float v = sin(current_time * 0.005) * 0.2; + float a = 0.3; + vec2 shift = vec2(100.0); + // Rotate to reduce axial bias + mat2 rot = mat2(cos(0.5), sin(1.0), -sin(0.5), acos(0.5)); + for (int i = 0; i < 3; ++i) { + v += a * noise(_st); + _st = rot * _st * 2.0 + shift; + a *= 1.5; + } + return v; +} + +void main() { + ivec2 gid = ivec2(gl_GlobalInvocationID.xy); + if (gid.x >= width || gid.y >= height) return; + + vec2 st = (vec2(gid) * 2.0 - vec2(width, height)) / min(float(width), float(height)) * 0.5; + + vec2 coord = st * 0.2; + float len; + for (int i = 0; i < 3; i++) { + len = length(coord); + coord.x += sin(coord.y + current_time * 0.001) * 2.1; + coord.y += cos(coord.x + current_time * 0.001 + cos(len * 1.0)) * 1.0; + } + len -= 3.0; + + vec3 color = vec3(0.0); + + vec2 q = vec2(0.0); + q.x = fbm(st); + q.y = fbm(st + vec2(-0.450, 0.650)); + + vec2 r = vec2(0.0); + r.x = fbm(st + 1.0 * q + vec2(0.570, 0.520) + 0.1 * current_time*0.01); + r.y = fbm(st + 1.0 * q + vec2(0.340, -0.570) + 0.05 * current_time*0.01); + float f = fbm(st + r); + + color = mix(color, cos(len + vec3(0.5, 0.0, -0.1)), 1.0); + color = mix(vec3(0.478, 0.738, 0.760), vec3(0.563, 0.580, 0.667), color); + + vec4 fragColor = vec4((f * f * f + .6 * f * f + .5 * f) * color, 1.0); + + imageStore(outputImage, gid, fragColor); +} + +)"; + + +// ported from https://www.shadertoy.com/view/XsXXRN +static const char *render_source_fire = + R"( + + #version 320 es +precision highp float; + +layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; +layout(binding = 0, rgba32f) writeonly uniform highp image2D outputImage; + +layout(location = 5) uniform int width; +layout(location = 6) uniform int height; +layout(location = 9) uniform float current_time; + +float rand(vec2 n) { + return fract(cos(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); +} + +float noise(vec2 n) { + const vec2 d = vec2(0.0, 1.0); + vec2 b = floor(n), f = smoothstep(vec2(0.0), vec2(1.0), fract(n)); + return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y); +} + +float fbm(vec2 n) { + float total = 0.0, amplitude = 1.0; + for (int i = 0; i < 4; i++) { + total += noise(n) * amplitude; + n += n; + amplitude *= 0.5; + } + return total; +} + +void main() { + ivec2 gid = ivec2(gl_GlobalInvocationID.xy); + if (gid.x >= width || gid.y >= height) return; + + // Only flip the y-coordinate when storing the result + ivec2 storePos = ivec2(gid.x, height - 1 - gid.y); + + const vec3 c1 = vec3(0.5, 0.0, 0.1); + const vec3 c2 = vec3(0.9, 0.0, 0.0); + const vec3 c3 = vec3(0.2, 0.0, 0.0); + const vec3 c4 = vec3(1.0, 0.9, 0.0); + const vec3 c5 = vec3(0.1); + const vec3 c6 = vec3(0.9); + + vec2 speed = vec2(0.7, 0.4); + float shift = 1.0; + float alpha = 1.0; + + // Reduce the effect of current_time by making the change more subtle + float timeEffect = current_time * 0.05; // Slowing down the animation by reducing the current_time factor + + vec2 p = vec2(gid) * 8.0 / float(width); + float q = fbm(p - timeEffect * 0.1); + vec2 r = vec2(fbm(p + q + timeEffect * speed.x - p.x - p.y), fbm(p + q - timeEffect * speed.y)); + vec3 c = mix(c1, c2, fbm(p + r)) + mix(c3, c4, r.x) - mix(c5, c6, r.y); + vec4 fragColor = vec4(c * cos(shift * float(gid.y) / float(height)), alpha); + + // Store the color flipped vertically + imageStore(outputImage, storePos, fragColor); +} + +)"; + + + + + + static const char *rounded_corner_overlay = R"( #version 320 es @@ -1769,7 +1921,7 @@ layout(local_size_x = 16, local_size_y = 16, local_size_z = 1) in; layout(location = 5) uniform int width; layout(location = 6) uniform int height; -layout(location = 7) uniform int radius; +layout(location = 10) uniform int beveled_radius; layout(location = 1) uniform int title_height; layout(location = 2) uniform int border_size; @@ -1811,7 +1963,7 @@ float sin01(float x) { vec4 drawCurveBenzier(vec2 p1, vec2 p2, int setCount) { vec4 col = vec4(0.0); ivec2 storePos = ivec2(gl_GlobalInvocationID.xy); - float curveRadius = float(radius); + float curveRadius = float(beveled_radius/2); // Draw the lines connecting the points vec2 fragCoord = vec2(storePos); @@ -1833,7 +1985,7 @@ vec4 drawCurveBenzier(vec2 p1, vec2 p2, int setCount) { vec4 drawCurve(vec2 p1, vec2 p2, int setCount) { vec4 col = vec4(0.0); ivec2 storePos = ivec2(gl_GlobalInvocationID.xy); - float curveRadius = float(radius + 1); + float curveRadius = float(beveled_radius + 1); vec2 fragCoord = vec2(storePos); float t = clamp(dot(fragCoord - p1, p2 - p1) / dot(p2 - p1, p2 - p1), 0.0, 1.0); @@ -1885,7 +2037,7 @@ void main() { vec2 z1 = vec2(0.0 + THICCNESS + space, 0.0 + THICCNESS); vec2 z2 = vec2(float(width) - THICCNESS - space, 0.0 + THICCNESS); - float curveRadius = float(radius); + float curveRadius = float(beveled_radius); // Draw the lines connecting the points int setwidth = int(width); @@ -1903,7 +2055,7 @@ else { col += drawCurve(x1, x2, setheight); col += drawCurve(y1, y2, setwidth); col += drawCurve(z1, z2, setwidth); - } + } float INNERspace = 0.0; @@ -2148,8 +2300,52 @@ void smoke_t::destroy_programs() void smoke_t::create_programs() { destroy_programs(); - OpenGL::render_begin(); - if ((std::string(effect_type) == "smoke") || (std::string(effect_type) == "ink")) + + + + static std::map fragment_effect_sources = { + {"clouds", effect_clouds_fragment}, + {"halftone", effect_halftone_fragment}, + {"pattern", effect_pattern_fragment}, + {"lava", effect_lava_fragment}, + {"hex", effect_hex_fragment}, + {"zebra", effect_zebra_fragment}, + {"neural_network", effect_neural_network_fragment}, + {"hexagon_maze", effect_hexagon_maze_fragment}, + {"raymarched_truchet", effect_raymarched_truchet_fragment}, + {"neon_pattern", effect_neon_pattern_fragment}, + {"neon_rings", effect_neon_rings_fragment}, + {"deco", effect_deco_fragment}, + {"ice", effect_ice_fragment}, + {"fire", effect_fire_fragment}, + // {"smoke", effect_render_fragment}, + + }; + + static std::map overlay_effect_sources = { + {"none", overlay_no_overlay}, + {"rounded_corners", overlay_rounded_corners}, + {"beveled_glass", overlay_beveled_glass}, + }; + + + if (std::string(compute_fragment_shader) == "fragment_shader"){ + + if (fragment_effect_sources.count(effect_type) && + overlay_effect_sources.count(overlay_engine)) + { + OpenGL::render_begin(); + GLint program = compile_fragment_effect_program( + fragment_effect_sources[effect_type], + overlay_effect_sources[overlay_engine]); + fragment_effect_only_program.set_simple(program); + OpenGL::render_end(); + return; + } +} + + OpenGL::render_begin(); + if ((std::string(effect_type) == "smoke") || (std::string(effect_type) == "ink") ) { setup_shader(&motion_program, motion_source); setup_shader(&diffuse1_program, stitch_smoke_shader(diffuse1_source)); @@ -2163,7 +2359,58 @@ void smoke_t::create_programs() setup_shader(&advect1_program, stitch_smoke_shader(advect1_source)); setup_shader(&advect2_program, stitch_smoke_shader(advect2_source)); setup_shader(&render_program, std::string(render_source) + effect_run_for_region_main); - } else if (std::string(effect_type) == "clouds") + } + else if ((std::string(effect_type) == "fumes")) + { + setup_shader(&motion_program, fumes_motion_source); + setup_shader(&diffuse1_program, stitch_smoke_shader(fumes_diffuse1_source)); +/**/ setup_shader(&diffuse2_program, stitch_smoke_shader(fumes_diffuse2_source)); + setup_shader(&project1_program, stitch_smoke_shader(fumes_project1_source)); + setup_shader(&project2_program, stitch_smoke_shader(fumes_project2_source)); + setup_shader(&project3_program, stitch_smoke_shader(fumes_project3_source)); +/**/ setup_shader(&project4_program, stitch_smoke_shader(fumes_project4_source)); +/**/ setup_shader(&project5_program, stitch_smoke_shader(fumes_project5_source)); +/**/ setup_shader(&project6_program, stitch_smoke_shader(fumes_project6_source)); + setup_shader(&advect1_program, stitch_smoke_shader(fumes_advect1_source)); +/**/ setup_shader(&advect2_program, stitch_smoke_shader(fumes_advect2_source)); + setup_shader(&render_program, std::string(fumes_render_source) + effect_run_for_region_main); + } + else if ((std::string(effect_type) == "fast_smoke")) + { + setup_shader(&motion_program, fast_smoke_motion_source); + setup_shader(&diffuse1_program, stitch_smoke_shader(fast_smoke_diffuse1_source)); +/**/ setup_shader(&diffuse2_program, stitch_smoke_shader(fast_smoke_diffuse2_source)); + setup_shader(&project1_program, stitch_smoke_shader(fast_smoke_project1_source)); + setup_shader(&project2_program, stitch_smoke_shader(fast_smoke_project2_source)); + setup_shader(&project3_program, stitch_smoke_shader(fast_smoke_project3_source)); +/**/ setup_shader(&project4_program, stitch_smoke_shader(fast_smoke_project4_source)); +/**/ setup_shader(&project5_program, stitch_smoke_shader(fast_smoke_project5_source)); +/**/ setup_shader(&project6_program, stitch_smoke_shader(fast_smoke_project6_source)); + setup_shader(&advect1_program, stitch_smoke_shader(fast_smoke_advect1_source)); +/**/ setup_shader(&advect2_program, stitch_smoke_shader(fast_smoke_advect2_source)); + setup_shader(&render_program, std::string(fast_smoke_render_source) + effect_run_for_region_main); + } + + + + else if ((std::string(effect_type) == "flame")) + { + setup_shader(&motion_program, flame_motion_source); + setup_shader(&diffuse1_program, stitch_smoke_shader(flame_diffuse1_source)); +/**/ setup_shader(&diffuse2_program, stitch_smoke_shader(flame_diffuse2_source)); + setup_shader(&project1_program, stitch_smoke_shader(flame_project1_source)); + setup_shader(&project2_program, stitch_smoke_shader(flame_project2_source)); + setup_shader(&project3_program, stitch_smoke_shader(flame_project3_source)); +/**/ setup_shader(&project4_program, stitch_smoke_shader(flame_project4_source)); +/**/ setup_shader(&project5_program, stitch_smoke_shader(flame_project5_source)); +/**/ setup_shader(&project6_program, stitch_smoke_shader(flame_project6_source)); + setup_shader(&advect1_program, stitch_smoke_shader(flame_advect1_source)); +/**/ setup_shader(&advect2_program, stitch_smoke_shader(flame_advect2_source)); + setup_shader(&render_program, std::string(flame_render_source) + effect_run_for_region_main); + } + + + else if (std::string(effect_type) == "clouds") { setup_shader(&render_program, render_source_clouds); } else if (std::string(effect_type) == "halftone") @@ -2200,7 +2447,14 @@ void smoke_t::create_programs() { setup_shader(&render_program, render_source_deco); } - + else if (std::string(effect_type) == "ice") + { + setup_shader(&render_program, render_source_ice); + } + else if (std::string(effect_type) == "fire") + { + setup_shader(&render_program, render_source_fire); + } if (std::string(overlay_engine) == "rounded_corners") { setup_shader(&render_overlay_program, rounded_corner_overlay); @@ -2339,20 +2593,20 @@ void smoke_t::recreate_textures(wf::geometry_t rectangle) destroy_textures(); create_textures(); + GLuint fb; + GL_CALL(glGenFramebuffers(1, &fb)); + GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, fb)); + GL_CALL(glActiveTexture(GL_TEXTURE0 + 0)); GL_CALL(glBindTexture(GL_TEXTURE_2D, texture)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)); GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)); GL_CALL(glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, rectangle.width, rectangle.height)); - if ((std::string(effect_type) != "smoke") && (std::string(effect_type) != "ink")) + if ((std::string(effect_type) != "smoke") && (std::string(effect_type) != "ink")&& (std::string(effect_type) != "fumes") && (std::string(effect_type) != "fast_smoke") && (std::string(effect_type) != "flame")) { return; } - GLuint fb; - GL_CALL(glGenFramebuffers(1, &fb)); - GL_CALL(glBindFramebuffer(GL_FRAMEBUFFER, fb)); - wf::color_t clear_color{0, 0, 0, 0}; GL_CALL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0)); @@ -2414,7 +2668,14 @@ void smoke_t::step_effect(const wf::render_target_t& fb, wf::geometry_t rectangl bool ink, wf::pointf_t p, wf::color_t decor_color, wf::color_t effect_color, int title_height, int border_size, int shadow_radius) { - bool smoke = (std::string(effect_type) == "smoke") || (std::string(effect_type) == "ink"); + last_shadow_radius = shadow_radius; + if (fragment_effect_only_program.get_program_id(wf::TEXTURE_TYPE_RGBA) > 0) + { + // Fragment-only programs are directly rendered and don't need any preparation. + return; + } + + bool smoke = (std::string(effect_type) == "smoke") || (std::string(effect_type) == "ink"|| (std::string(effect_type) == "fumes") || (std::string(effect_type) == "fast_smoke") || (std::string(effect_type) == "flame")); if ((rectangle.width <= 0) || (rectangle.height <= 0)) { return; @@ -2423,6 +2684,14 @@ void smoke_t::step_effect(const wf::render_target_t& fb, wf::geometry_t rectangl int radius = shadow_radius; int diffuse_iterations = 2; + + if (std::string(effect_type) == "fumes") + { + + diffuse_iterations = 10; + } + + OpenGL::render_begin(fb); if ((rectangle.width != saved_width) || (rectangle.height != saved_height)) { @@ -2482,6 +2751,7 @@ void smoke_t::step_effect(const wf::render_target_t& fb, wf::geometry_t rectangl GL_CALL(glBindTexture(GL_TEXTURE_2D, b1d)); GL_CALL(glBindImageTexture(6, b1d, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32F)); + if ((point.x >= radius) && (point.y >= radius)) { GL_CALL(glUseProgram(motion_program)); @@ -2499,6 +2769,16 @@ void smoke_t::step_effect(const wf::render_target_t& fb, wf::geometry_t rectangl GL_CALL(glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT)); } + + + + + + + + + + for (int k = 0; k < diffuse_iterations; k++) { run_shader_region(diffuse1_program, border_region, wf::dimensions(rectangle)); @@ -2549,7 +2829,7 @@ void smoke_t::step_effect(const wf::render_target_t& fb, wf::geometry_t rectangl GL_CALL(glUniform1i(5, rectangle.width)); GL_CALL(glUniform1i(6, rectangle.height)); GL_CALL(glUniform1i(7, radius * 2)); - GL_CALL(glUniform1f(9, effect_animate ? ((wf::get_current_time() / 30) & 0xFF) : 0.0)); + GL_CALL(glUniform1f(9, effect_animate ? (wf::get_current_time() / 30.0) : 0.0)); GL_CALL(glDispatchCompute(rectangle.width / 15, rectangle.height / 15, 1)); GL_CALL(glMemoryBarrier(GL_TEXTURE_FETCH_BARRIER_BIT)); } @@ -2575,8 +2855,16 @@ void smoke_t::step_effect(const wf::render_target_t& fb, wf::geometry_t rectangl GL_CALL(glUniform1i(5, rectangle.width)); GL_CALL(glUniform1i(6, rectangle.height)); GL_CALL(glUniform1i(7, rounded_corner_radius)); + + + if (std::string(overlay_engine) == "beveled_glass") + { + GL_CALL(glUniform1i(10, beveled_radius)); + } + if (std::string(overlay_engine) == "rounded_corners") { + GLfloat shadow_color_f[4] = {GLfloat(wf::color_t(shadow_color).r), GLfloat(wf::color_t(shadow_color).g), GLfloat(wf::color_t(shadow_color).b), GLfloat(wf::color_t(shadow_color).a)}; @@ -2592,9 +2880,79 @@ void smoke_t::step_effect(const wf::render_target_t& fb, wf::geometry_t rectangl OpenGL::render_end(); } +void smoke_t::run_fragment_shader(const wf::render_target_t& fb, + wf::geometry_t rectangle, const wf::region_t& scissor,int border_size, int title_height) +{ + glm::vec4 color; + + fragment_effect_only_program.use(wf::TEXTURE_TYPE_RGBA); + + GLfloat vertexData[] = { + 1.0f * rectangle.x, 1.0f * rectangle.y + rectangle.height, + 1.0f * rectangle.x + rectangle.width, 1.0f * rectangle.y + rectangle.height, + 1.0f * rectangle.x + rectangle.width, 1.0f * rectangle.y, + 1.0f * rectangle.x, 1.0f * rectangle.y, + }; + + + fragment_effect_only_program.attrib_pointer("position", 2, 0, vertexData); + fragment_effect_only_program.uniformMatrix4f("MVP", fb.get_orthographic_projection()); + + fragment_effect_only_program.uniform1f("current_time", wf::get_current_time() / 30.0); + fragment_effect_only_program.uniform1i("border_size", border_size); + fragment_effect_only_program.uniform1i("title_height", title_height); + fragment_effect_only_program.uniform1f("width", rectangle.width); + fragment_effect_only_program.uniform1f("height", rectangle.height); + + if (std::string(overlay_engine) == "rounded_corners") + { + fragment_effect_only_program.uniform1i("shadow_radius", last_shadow_radius * 2); + fragment_effect_only_program.uniform1i("corner_radius", rounded_corner_radius); + fragment_effect_only_program.uniform2f("topLeftCorner", rectangle.x, rectangle.y); + color = glm::vec4(shadow_color.value().r,shadow_color.value().g,shadow_color.value().b,shadow_color.value().a); + fragment_effect_only_program.uniform4f("shadow_color", color); +//testing purposes + // Assuming color is of type glm::vec4 +glm::vec4 black(0.5f, 0.5f, 0.5f, 1.0f); // RGB values for black, A set to 1 for full opacity +glm::vec4 white(1.0f, 1.0f, 1.0f, .8f); // RGB values for white, A set to 1 for full opacity + +// Assuming 'fragment_effect_only_program' is your shader program object +fragment_effect_only_program.uniform4f("decor_color", black); // Set decor_color to black +fragment_effect_only_program.uniform4f("smoke_color", white); // Set smoke_color to white + + } + + else if (std::string(overlay_engine) == "beveled_glass") + { + fragment_effect_only_program.uniform2f("topLeftCorner", rectangle.x, rectangle.y); + fragment_effect_only_program.uniform1i("border_size", border_size); + fragment_effect_only_program.uniform1i("title_height", title_height+border_size); + fragment_effect_only_program.uniform1i("beveled_radius", beveled_radius); + + + } + + + for (auto& box : scissor) + { + fb.logic_scissor(wlr_box_from_pixman_box(box)); + GL_CALL(glDrawArrays(GL_TRIANGLE_FAN, 0, 4)); + } + +} + void smoke_t::render_effect(const wf::render_target_t& fb, wf::geometry_t rectangle, - const wf::region_t& scissor) + const wf::region_t& scissor, int border_size, int title_height) { + + if (fragment_effect_only_program.get_program_id(wf::TEXTURE_TYPE_RGBA) != 0) + { + run_fragment_shader(fb, rectangle, scissor, border_size, title_height); + + return; + } + + OpenGL::render_transformed_texture(wf::texture_t{texture}, rectangle, fb.get_orthographic_projection(), glm::vec4{1}, OpenGL::TEXTURE_TRANSFORM_INVERT_Y | OpenGL::RENDER_FLAG_CACHED); diff --git a/src/deco-effects.hpp b/src/deco-effects.hpp index c92c88c..c8cb601 100644 --- a/src/deco-effects.hpp +++ b/src/deco-effects.hpp @@ -19,26 +19,36 @@ class smoke_t advect1_program, advect2_program, render_program, render_overlay_program, texture, b0u, b0v, b0d, b1u, b1v, b1d, neural_network_tex; + int last_shadow_radius = 0; + + OpenGL::program_t fragment_effect_only_program{}; + int saved_width = -1, saved_height = -1; + wf::option_wrapper_t compute_fragment_shader{"pixdecor/compute_fragment_shader"}; wf::option_wrapper_t effect_type{"pixdecor/effect_type"}; wf::option_wrapper_t overlay_engine{"pixdecor/overlay_engine"}; wf::option_wrapper_t effect_animate{"pixdecor/animate"}; wf::option_wrapper_t rounded_corner_radius{"pixdecor/rounded_corner_radius"}; wf::option_wrapper_t shadow_color{"pixdecor/shadow_color"}; + wf::option_wrapper_t beveled_radius{"pixdecor/beveled_radius"}; + public: smoke_t(); ~smoke_t(); void run_shader(GLuint program, int width, int height, int title_height, int border_size, int radius); + void run_fragment_shader(const wf::render_target_t& fb, + wf::geometry_t rectangle, const wf::region_t& scissor,int border_size, int title_height); + void run_shader_region(GLuint program, const wf::region_t & region, const wf::dimensions_t & size); void dispatch_region(const wf::region_t& region); void step_effect(const wf::render_target_t& fb, wf::geometry_t rectangle, bool ink, wf::pointf_t p, wf::color_t decor_color, wf::color_t effect_color, int title_height, int border_size, int shadow_radius); - void render_effect(const wf::render_target_t& fb, wf::geometry_t rectangle, const wf::region_t& scissor); + void render_effect(const wf::render_target_t& fb, wf::geometry_t rectangle, const wf::region_t& scissor,int border_size,int title_height ); void recreate_textures(wf::geometry_t rectangle); void create_programs(); void destroy_programs(); diff --git a/src/deco-subsurface.cpp b/src/deco-subsurface.cpp index 16b112e..7df554c 100644 --- a/src/deco-subsurface.cpp +++ b/src/deco-subsurface.cpp @@ -148,6 +148,7 @@ class simple_decoration_node_t : public wf::scene::node_t, public wf::pointer_in void render_region(const wf::render_target_t& fb, wf::point_t origin, const wf::region_t& region) { int border = theme.get_border_size(); + int title = theme.get_title_height(); wlr_box geometry{origin.x, origin.y, size.width, size.height}; bool activated = false; @@ -163,7 +164,7 @@ class simple_decoration_node_t : public wf::scene::node_t, public wf::pointer_in OpenGL::render_begin(fb); - theme.render_background(fb, geometry, region, activated, current_cursor_position); + theme.render_background(fb, geometry, region, activated, current_cursor_position,border, title); if (!titlebar_opt) { diff --git a/src/deco-theme.cpp b/src/deco-theme.cpp index d2e1b06..fb89a17 100644 --- a/src/deco-theme.cpp +++ b/src/deco-theme.cpp @@ -112,7 +112,7 @@ void decoration_theme_t::set_maximize(bool state) * @param active Whether to use active or inactive colors */ void decoration_theme_t::render_background(const wf::render_target_t& fb, - wf::geometry_t rectangle, const wf::region_t& scissor, bool active, wf::pointf_t p) + wf::geometry_t rectangle, const wf::region_t& scissor, bool active, wf::pointf_t p,int border_size, int title_height) { if ((std::string(effect_type) == "none") && (std::string(overlay_engine) == "none")) { @@ -123,7 +123,7 @@ void decoration_theme_t::render_background(const wf::render_target_t& fb, } } else { - smoke.render_effect(fb, rectangle, scissor); + smoke.render_effect(fb, rectangle, scissor,border_size, title_height); } } diff --git a/src/deco-theme.hpp b/src/deco-theme.hpp index 3334d48..9cfad81 100644 --- a/src/deco-theme.hpp +++ b/src/deco-theme.hpp @@ -45,8 +45,8 @@ class decoration_theme_t * @param scissor The GL scissor rectangle to use. * @param active Whether to use active or inactive colors */ - void render_background(const wf::render_target_t& fb, - wf::geometry_t rectangle, const wf::region_t& scissor, bool active, wf::pointf_t p); + void render_background(const wf::render_target_t& fb, + wf::geometry_t rectangle, const wf::region_t& scissor, bool active, wf::pointf_t p,int border_size, int title_height); /** * Render the given text on a cairo_surface_t with the given size. diff --git a/src/effect-shaders.hpp b/src/effect-shaders.hpp new file mode 100644 index 0000000..1b72c96 --- /dev/null +++ b/src/effect-shaders.hpp @@ -0,0 +1,1487 @@ +static const char *generic_effect_vertex_shader = R"( +#version 320 es + +in highp vec2 position; +out highp vec2 relativePosition; + +uniform mat4 MVP; +uniform vec2 topLeftCorner; + +void main() { + relativePosition = position.xy - topLeftCorner; + gl_Position = MVP * vec4(position.xy, 0.0, 1.0); +})"; + +static const char *generic_effect_fragment_header = R"( +#version 320 es +precision highp float; +precision highp image2D; + +in highp vec2 relativePosition; +uniform float current_time; +uniform float width; +uniform float height; + + + +out vec4 fragColor; +)"; + +static const char *generic_effect_fragment_main = R"( +void main() +{ + fragColor = overlay_function(relativePosition); +})"; + +// ported from https://www.shadertoy.com/view/WdXBW4 +static const char *effect_clouds_fragment = R"( +float cloudscale=2.1; // Added cloudscale parameter +const mat2 m = mat2(1.6, 1.2, -1.2, 1.6); + +vec2 hash(vec2 p) { + p = vec2(dot(p, vec2(127.1, 311.7)), dot(p, vec2(269.5, 183.3))); + return -1.0 + 2.0 * fract(sin(p) * 43758.5453123); +} + +float noise(vec2 p) { + const float K1 = 0.366025404; // (sqrt(3)-1)/2; + const float K2 = 0.211324865; // (3-sqrt(3))/6; + vec2 i = floor(p + (p.x + p.y) * K1); + vec2 a = p - i + (i.x + i.y) * K2; + vec2 o = (a.x > a.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + vec2 b = a - o + K2; + vec2 c = a - 1.0 + 2.0 * K2; + vec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0); + vec3 n = h * h * h * h * vec3(dot(a, hash(i + 0.0)), dot(b, hash(i + o)), dot(c, hash(i + 1.0))); + return dot(n, vec3(70.0)); +} + +float fbm(vec2 n) { + float total = 0.0, amplitude = 0.1; + for (int i = 0; i < 7; i++) { + total += noise(n) * amplitude; + n = m * n; + amplitude *= 0.4; + } + return total; +} + +vec4 effect_color(vec2 pos) +{ + vec2 uv = pos / vec2(1080, 1920); + + float time = 0.003 * current_time; // Time variable for animation + + float cloudPattern1 = fbm(uv * 10.0 * cloudscale + time); + float cloudPattern2 = fbm(uv * 5.0 * cloudscale + time); + float cloudPattern3 = fbm(uv * 3.0 * cloudscale + time); + + // Combine different cloud patterns with different weights + float cloudPattern = 0.5 * cloudPattern1 + 0.3 * cloudPattern2 + 0.2 * cloudPattern3; + + // Ridge noise shape + float ridgeNoiseShape = 0.0; + uv *= cloudscale * 1.1; // Adjust scale + float weight = 0.8; + for (int i = 0; i < 8; i++) { + ridgeNoiseShape += abs(weight * noise(uv)); + uv = m * uv + time; + weight *= 0.7; + } + + // Noise shape + float noiseShape = 0.0; + uv = vec2(pos) / vec2(1920, 1080); + uv *= cloudscale * 1.1; // Adjust scale + weight = 0.7; + for (int i = 0; i < 8; i++) { + noiseShape += weight * noise(uv); + uv = m * uv + time; + weight *= 0.6; + } + + noiseShape *= ridgeNoiseShape + noiseShape; + + // Noise color + float noiseColor = 0.0; + uv = vec2(pos) / vec2(1920, 1080); + uv *= 2.0 * cloudscale; // Adjust scale + weight = 0.4; + for (int i = 0; i < 7; i++) { + noiseColor += weight * noise(uv); + uv = m * uv + time; + weight *= 0.6; + } + + // Noise ridge color + float noiseRidgeColor = 0.0; + uv = vec2(pos) / vec2(1920, 1080); + uv *= 3.0 * cloudscale; // Adjust scale + weight = 0.4; + for (int i = 0; i < 7; i++) { + noiseRidgeColor += abs(weight * noise(uv)); + uv = m * uv + time; + weight *= 0.6; + } + + noiseColor += noiseRidgeColor; + + // Sky tint + float skytint = 0.5; + vec3 skyColour1 = vec3(0.1, 0.2, 0.3); + vec3 skyColour2 = vec3(0.4, 0.7, 1.0); + vec3 skycolour = mix(skyColour1, skyColour2, smoothstep(0.4, 0.6, uv.y)); + + // Cloud darkness + float clouddark = 0.5; + + // Cloud Cover, Cloud Alpha + float cloudCover = 0.01; + float cloudAlpha = 2.0; + + // Movement effect + uv = uv + time; + + // Use a bright color for clouds + vec3 cloudColor = vec3(1.0, 1.0, 1.0); ; // Bright white color for clouds + + // Mix the cloud color with the background, considering darkness, cover, and alpha + vec3 finalColor = mix(skycolour, cloudColor * clouddark, cloudPattern + noiseShape + noiseColor) * (1.0 - cloudCover) + cloudColor * cloudCover; + finalColor = mix(skycolour, finalColor, cloudAlpha); + + return vec4(finalColor, 1.0); +})"; + +// ported from https://www.shadertoy.com/view/mtyGWy +static const char *effect_neon_pattern_fragment = R"( +vec3 palette(float t) { + vec3 a = vec3(0.5, 0.5, 0.5); + vec3 b = vec3(0.5, 0.5, 0.5); + vec3 c = vec3(1.0, 1.0, 1.0); + vec3 d = vec3(0.263, 0.416, 0.557); + return a + b * cos(6.28318 * (c * t + d)); +} + +vec4 effect_color(vec2 pos) { + vec2 uv = pos / vec2(width, height); + vec2 uv0 = uv; + vec3 finalColor = vec3(0.0); + + for (float i = 0.0; i < 4.0; i++) { + uv = fract(uv * 1.5) - 0.5; + float d = length(uv) * exp(-length(uv0)); + + vec3 col = palette(length(uv0) + i * 0.4 + current_time * 0.000001); + + d = sin(d * 8.0 + current_time * 0.02) / 8.0; + d = abs(d); + d = pow(0.01 / d, 1.2); + finalColor += col * d; + } + + return vec4(finalColor, 1.0); +})"; + +static const char *effect_halftone_fragment = R"( + + + + const vec2 resolution = vec2(1280.0, 720.0); + const float timeFactor = 0.025; + + float rand(vec2 uv) { + return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453); + } + + vec2 rotate(vec2 p, float theta) { + vec2 sncs = vec2(sin(theta), cos(theta)); + return vec2(p.x * sncs.y - p.y * sncs.x, p.x * sncs.x + p.y * sncs.y); + } + + float swirl(vec2 coord, float t) { + float l = length(coord) / resolution.x; + float phi = atan(coord.y, coord.x + 1e-6); + return sin(l * 10.0 + phi - t * 4.0) * 0.5 + 0.5; + } + + float halftone(vec2 coord, float angle, float t, float amp) { + coord -= resolution * 0.5; + float size = resolution.x / (60.0 + sin(current_time * timeFactor * 0.5) * 50.0); + vec2 uv = rotate(coord / size, angle / 180.0 * 3.14159); + vec2 ip = floor(uv); // column, row + vec2 odd = vec2(0.5 * mod(ip.y, 2.0), 0.0); // odd line offset + vec2 cp = floor(uv - odd) + odd; // dot center + float d = length(uv - cp - 0.5) * size; // distance + float r = swirl(cp * size, t) * size * 0.5 * amp; // dot radius + return 1.0 - clamp(d - r, 0.0, 1.0); + } + + +vec4 effect_color(vec2 pos) { + + + + vec3 c1 = 1.0 - vec3(1.0, 0.0, 0.0) * halftone(relativePosition, 0.0, current_time * timeFactor * 1.00, 0.7); + vec3 c2 = 1.0 - vec3(0.0, 1.0, 0.0) * halftone(relativePosition, 30.0, current_time * timeFactor * 1.33, 0.7); + vec3 c3 = 1.0 - vec3(0.0, 0.0, 1.0) * halftone(relativePosition, -30.0, current_time * timeFactor * 1.66, 0.7); + vec3 c4 = 1.0 - vec3(1.0, 1.0, 1.0) * halftone(relativePosition, 60.0, current_time * timeFactor * 2.13, 0.4); + fragColor = vec4(c1 * c2 * c3 * c4, 1.0); + + + + return vec4(fragColor); +} + +)"; + + + + +static const char *effect_zebra_fragment = R"( + +const float resolutionY = 720.0; + + +vec4 effect_color(vec2 pos) { + + const float pi = 3.14159265359; + float size = resolutionY / 10.; // cell size in pixel + + vec2 p1 = gl_FragCoord.xy / size; // normalized pos + vec2 p2 = fract(p1) - 0.5; // relative pos from cell center + + + +// random number + float rnd = dot(floor(p1), vec2(12.9898, 78.233)); + rnd = fract(sin(rnd) * 43758.5453); + + // rotation matrix + float phi = rnd * pi * 2. + current_time/30.0 * 0.4; + mat2 rot = mat2(cos(phi), -sin(phi), sin(phi), cos(phi)); + + vec2 p3 = rot * p2; // apply rotation + p3.y += sin(p3.x * 5. + current_time/30.0 * 2.) * 0.12; // wave + + float rep = fract(rnd * 13.285) * 8. + 2.; // line repetition + float gr = fract(p3.y * rep + current_time/30.0 * 0.8); // repeating gradient + + // make antialiased line by saturating the gradient + float c = clamp((0.25 - abs(0.5 - gr)) * size * 0.75 / rep, 0., 1.); + c *= max(0., 1. - length(p2) * 0.6); // darken corners + + vec2 bd = (0.5 - abs(p2)) * size - 2.; // border lines + c *= clamp(min(bd.x, bd.y), 0., 1.); + + fragColor = vec4(vec3(c), 1.0); + + + + return vec4(fragColor); +} + +)"; + + + +static const char *effect_lava_fragment = R"( + + + + + + +vec3 effect(float speed, vec2 uv, float time, float scale) { + float t = mod(time * 0.005, 6.0); + float rt = 0.00000000000001 * sin(t * 0.45); + + mat2 m1 = mat2(cos(rt), -sin(rt), -sin(rt), cos(rt)); + vec2 uva = uv * m1 * scale; + float irt = 0.005 * cos(t * 0.05); + mat2 m2 = mat2(sin(irt), cos(irt), -cos(irt), sin(irt)); + + for (int i = 1; i < 40; i += 1) { + float it = float(i); + uva *= m2; + uva.y += -1.0 + (0.6 / it) * cos(t + it * uva.x + 0.5 * it) * float(mod(it, 0.5) == 0.0); + uva.x += 1.0 + (0.5 / it) * cos(t + it * uva.y * 0.1 / 5.0 + 0.5 * (it + 15.0)); + } + + float n = 0.5; + float r = n + n * sin(4.0 * uva.x + t); + float gb = n + n * sin(3.0 * uva.y); + return vec3(r, gb * 0.8 * r, gb * r); +} + +vec4 effect_color(vec2 pos) { + + vec2 uv = (gl_FragCoord.xy - 0.5 * vec2(width, height)) / vec2(width, height); + uv *= (10.3 + 0.1 * sin(current_time * 0.01)); + + + + vec3 col = effect(0.001, uv, current_time, 0.5); + + // Set the fragment color + fragColor = vec4(col, 1.0); + + + return vec4(fragColor); +} + +)"; + + + + +static const char *effect_pattern_fragment = R"( + + +float rand(vec2 uv) { + return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453); +} + +vec3 hue2rgb(float h) { + h = fract(h) * 6.0 - 2.0; + return clamp(vec3(abs(h - 1.0) - 1.0, 2.0 - abs(h), 2.0 - abs(h - 2.0)), 0.0, 1.0); +} + +vec3 eyes(vec2 coord, vec2 resolution) { + const float pi = 3.141592; + float t = 0.4 * current_time * 0.05; + float aspectRatio = resolution.x / resolution.y; + float div = 20.0; + float sc = 30.0; + + vec2 p = (coord - resolution / 2.0) / sc - 0.5; + + float dir = floor(rand(floor(p) + floor(t) * 0.11) * 4.0) * pi / 2.0; + vec2 offs = vec2(sin(dir), cos(dir)) * 0.6; + offs *= smoothstep(0.0, 0.1, fract(t)); + offs *= smoothstep(0.4, 0.5, 1.0 - fract(t)); + + float l = length(fract(p) + offs - 0.5); + float rep = sin((rand(floor(p)) * 2.0 + 2.0) * t) * 4.0 + 5.0; + float c = (abs(0.5 - fract(l * rep + 0.5)) - 0.25) * sc / rep; + + vec2 gr = (abs(0.5 - fract(p + 0.5)) - 0.05) * sc; + c = clamp(min(min(c, gr.x), gr.y), 0.0, 1.0); + + return hue2rgb(rand(floor(p) * 0.3231)) * c; +} + + + +vec4 effect_color(vec2 pos) { + + + vec2 resolution = vec2(float(width), float(height)); + pos = gl_FragCoord.xy; + vec3 color = eyes(pos, resolution); + fragColor = vec4(color, 1.0); + + return vec4(fragColor); +} + +)"; + + + + + + +static const char *effect_hex_fragment = R"( + + + +vec2 iResolution; + +float rand(vec2 co) { + return fract(sin(dot(co.xy, vec2(12.9898, 4.1414))) * 43758.5453); +} + +vec4 hexagon(vec2 p) +{ + vec2 q = vec2(p.x * 2.0 * 0.5773503, p.y + p.x * 0.5773503); + + vec2 pi = floor(q); + vec2 pf = fract(q); + + float v = mod(pi.x * 9.0, 0.0); + + float ca = step(1.0, v); + float cb = step(2.0, v); + vec2 ma = step(pf.xy, pf.yx); + + float e = 0.0; + float f = length((fract(p) - 10.5) * vec2(1.0, 0.85)); + + return vec4(pi + ca - cb * ma, e, f); +} + + +vec4 effect_color(vec2 pos) { + + + vec2 resolution = vec2(float(width), float(height)); + pos = (gl_FragCoord.xy - 0.5) / resolution; + pos.y *= resolution.y / resolution.x; + + + vec2 uv = (gl_FragCoord.xy - 0.5) / resolution; + uv = 2.0 * uv - 1.0; + uv *= (10.3 + 0.1 * sin(current_time * 0.01)); + + float randVal = rand(uv); + + vec2 p = (-float(width) + 2.0 * gl_FragCoord.xy) / float(height); + vec4 h = hexagon(40.0 * p + vec2(0.5 * current_time * 0.125)); + + float col = 0.01 + 0.15 * rand(vec2(h.xy)) * 1.0; + col *= 4.3 + 0.15 * sin(10.0 * h.z); + + vec3 shadeColor1 = vec3(0.1, 0.1, 0.1) + 1.1 * col * h.z; + vec3 shadeColor2 = vec3(0.4, 0.4, 0.4) + 1.1 * col; + vec3 shadeColor3 = vec3(0.9, 0.9, 0.9) + 0.1 * col; + + vec3 finalColor = mix(shadeColor1, mix(shadeColor2, shadeColor3, randVal), col); + + fragColor = vec4(finalColor, 1.0); + + return vec4(fragColor); +} +)"; + + + + + + +static const char *effect_neural_network_fragment = R"( + +const vec2 iResolution = vec2(1920.0, 1080.0); + +mat2 rotate2D(float r) { + float c = cos(r); + float s = sin(r); + return mat2(c, -s, s, c); +} + + + +vec4 effect_color(vec2 pos) { + + pos = gl_FragCoord.xy; + + + // Normalized pixel coordinates (from 0 to 1) + vec2 uv = (pos - 0.5 * iResolution) / iResolution.x; + + // Scale the uv coordinates + uv *= 10.00; + + vec3 col = vec3(0); + float t = 0.05 * current_time; + + vec2 n = vec2(0), q; + vec2 N = vec2(0); + vec2 p = uv + sin(t * 0.1) / 10.0; + float S = 10.0; + mat2 m = rotate2D(1.0); + + for (float j = 0.0; j < 30.0; j++) { + p *= m; + n *= m; + q = p * S + j + n + t; + n += sin(q); + N += cos(q) / S; + S *= 1.2; + } + + col = vec3(1, 2, 4) * pow((N.x + N.y + 0.2) + 0.005 / length(N), 2.1); + + fragColor = vec4(col, 1.0); + + return vec4(fragColor); +} +)"; + + + + + + + +static const char *effect_hexagon_maze_fragment = R"( + + + +//vec2 iResolution; + + +const vec2 iResolution = vec2(1920.0, 1080.0); + +// Interlaced variation - Interesting, but patched together in a hurry. +//#define INTERLACING + +// A quick hack to get rid of the winding overlay - in order to show the maze only. +//#define MAZE_ONLY + + + +// Helper vector. If you're doing anything that involves regular triangles or hexagons, the +// 30-60-90 triangle will be involved in some way, which has sides of 1, sqrt(3) and 2. +const vec2 s = vec2(1, 1.7320508); + +// Standard vec2 to float hash - Based on IQ's original. +float hash21(vec2 p){ return fract(sin(dot(p, vec2(141.173, 289.927)))*43758.5453); } + + +// Standard 2D rotation formula. +mat2 r2(in float a){ float c = cos(a), s = sin(a); return mat2(c, -s, s, c); } + +// The 2D hexagonal isosuface function: If you were to render a horizontal line and one that +// slopes at 60 degrees, mirror, then combine them, you'd arrive at the following. +float hex(in vec2 p){ + + p = abs(p); + + // Below is equivalent to: + //return max(p.x*.5 + p.y*.866025, p.x); + + return max(dot(p, s*.5), p.x); // Hexagon. + +} + +// This function returns the hexagonal grid coordinate for the grid cell, and the corresponding +// hexagon cell ID - in the form of the central hexagonal point. That's basically all you need to +// produce a hexagonal grid. +// +// When working with 2D, I guess it's not that important to streamline this particular function. +// However, if you need to raymarch a hexagonal grid, the number of operations tend to matter. +// This one has minimal setup, one "floor" call, a couple of "dot" calls, a ternary operator, etc. +// To use it to raymarch, you'd have to double up on everything - in order to deal with +// overlapping fields from neighboring cells, so the fewer operations the better. +vec4 getHex(vec2 p){ + + // The hexagon centers: Two sets of repeat hexagons are required to fill in the space, and + // the two sets are stored in a "vec4" in order to group some calculations together. The hexagon + // center we'll eventually use will depend upon which is closest to the current point. Since + // the central hexagon point is unique, it doubles as the unique hexagon ID. + vec4 hC = floor(vec4(p, p - vec2(.5, 1))/s.xyxy) + .5; + + // Centering the coordinates with the hexagon centers above. + vec4 h = vec4(p - hC.xy*s, p - (hC.zw + .5)*s); + + // Nearest hexagon center (with respect to p) to the current point. In other words, when + // "h.xy" is zero, we're at the center. We're also returning the corresponding hexagon ID - + // in the form of the hexagonal central point. Note that a random constant has been added to + // "hC.zw" to further distinguish it from "hC.xy." + // + // On a side note, I sometimes compare hex distances, but I noticed that Iomateron compared + // the Euclidian version, which seems neater, so I've adopted that. + return dot(h.xy, h.xy).5) p.y = -p.y; + + + + // Determining the closest of the three arcs to the current point, the keeping a copy + // of the vector used to produce it. That way, you'll know just to render that particular + // decorated arc, lines, etc - instead of all three. + const float r = 1.; + const float th = .2; // Arc thickness. + + // Arc one. + q = p - vec2(0, r)/s; + vec3 da = vec3(q, dfPol(q)); + + // Arc two. "r2" could be hardcoded, but this is a relatively cheap 2D example. + q = r2(3.14159*2./3.)*p - vec2(0, r)/s; + vec3 db = vec3(q, dfPol(q)); + + // Arc three. + q = r2(3.14159*4./3.)*p - vec2(0, r)/s; + vec3 dc = vec3(q, dfPol(q)); + + // Compare distance fields, and return the vector used to produce the closest one. + vec3 q3 = da.z.5 && lRnd.x<.5) hLines2 *= smoothstep(0., .02, ln); + if(lRnd.x>.5) hLines2 *= dMask; + #else + if(rnd>.5) hLines2 *= smoothstep(0., .02, ln); + hLines2 *= dMask; + #endif + bg = mix(bg, vec3(0), hLines2*tr); + + float eDist3 = hex(h3.xy); + float hLines3 = smoothstep(0., .02, eDist3 - .5 + .02); + #ifdef INTERLACING + if(rnd<=.5 && lRnd.x>.5) hLines3 *= smoothstep(0., .02, ln); + if(lRnd.x>.5) hLines3 *= dMask; + #else + if(rnd<=.5) hLines3 *= smoothstep(0., .02, ln); + hLines3 *= dMask; + #endif + bg = mix(bg, vec3(0), hLines3*tr); + + + // Using the two off-centered hex coordinates to give the background a bit of highlighting. + float shade = max(1.25 - dot(h2.xy, h2.xy)*2., 0.); + shade = min(shade, max(dot(h3.xy, h3.xy)*3. + .25, 0.)); + bg = mix(bg, vec3(0), (1.-shade)*.5); + + // I wanted to change the colors of everything at the last minute. It's pretty hacky, so + // when I'm feeling less lazy, I'll tidy it up. :) + vec3 dotCol = bg.zyx*vec3(1.5, .4, .4); + vec3 bCol = mix(bg.zyx, bg.yyy, .25); + bg = mix(bg.yyy, bg.zyx, .25); + + + // Under the random threshold, and we draw the lines under the Truchet pattern. + #ifdef INTERLACING + if(lRnd.x>.5){ + bg = mix(bg, vec3(0), (1. - smoothstep(0., .015, lnBord))); + bg = mix(bg, bCol, (1. - smoothstep(0., .015, ln))); + // Center lines. + bg = mix(bg, vec3(0), smoothstep(0., .02, eDist3 - .5 + .02)*tr); + } + #else + bg = mix(bg, vec3(0), (1. - smoothstep(0., .015, lnBord))); + bg = mix(bg, bCol, (1. - smoothstep(0., .015, ln))); + #endif + + + + // Apply the Truchet shadow to the background. + bg = mix(bg, vec3(0), (1. - smoothstep(0., .07, d))*.5); + + + // Place the Truchet field to the background, with some additional shading to give it a + // slightly rounded, raised feel. + //vec3 col = mix(bg, vec3(1)*max(-d*3. + .7, 0.), (1. - dMask)*.65); + // Huttarl suggest slightly more shading on the snake-like pattern edges, so I added just a touch. + vec3 col = mix(bg, vec3(1)*max(-d*9. + .4, 0.), (1. - dMask)*.65); + + + + // Apply the moving dot pattern to the Truchet. + //dotCol = mix(dotCol, dotCol.xzy, dot(sin(u*3.14159*2. - cos(u.yx*3.14159*2.)*3.14159), vec2(.25)) + .5); + col = mix(col, vec3(0), (1. - dMask)*(1. - smoothstep(0., .02, d2))); + col = mix(col, dotCol, (1. - dMask)*(1. - smoothstep(0., .02, d2 + .125))); + + // Truchet border. + col = mix(col, vec3(0), 1. - smoothstep(0., .015, dBord)); + + #ifdef INTERLACING + // Over the random threshold, and we draw the lines over the Truchet. + if(lRnd.x<=.5){ + col = mix(col, vec3(0), (1. - smoothstep(0., .015, lnBord))); + col = mix(col, bCol, (1. - smoothstep(0., .015, ln))); + // Center lines. + col = mix(col, vec3(0), smoothstep(0., .02, eDist2 - .5 + .02)*tr); + } + #endif + + + + + // Using the offset hex values for a bit of fake 3D highlighting. + //if(rnd>.5) h3.y = -h3.y; // All raised edges. Spoils the mild 3D illusion. + #ifdef INTERLACING + float trSn = max(dMask, 1. - smoothstep(0., .015, lnBord))*.75 + .25; + #else + float trSn = dMask*.75 + .25; + #endif + col = mix(col, vec3(0), trSn*(1. - hex(s/2.+h2.xy))); + col = mix(col, vec3(0), trSn*(1. - hex(s/2.-h3.xy))); + + + // Using the edge distance to produce some repeat contour lines. Standard stuff. + //if (rnd>.5) h.xy = -h.yx; + //float cont = clamp(cos(hex(h.xy)*6.283*12.)*1.5 + 1.25, 0., 1.); + //col = mix(col, vec3(0), (1. - smoothstep(0., .015, ln))*(smoothstep(0., .015, d))*(1.-cont)*.5); + + + // Very basic hatch line effect. + float gr = dot(col, vec3(.299, .587, .114)); + float hatch = (gr<.45)? clamp(sin((sc.x - sc.y)*3.14159*40.)*2. + 1.5, 0., 1.) : 1.; + float hatch2 = (gr<.25)? clamp(sin((sc.x + sc.y)*3.14159*40.)*2. + 1.5, 0., 1.) : 1.; + + col *= min(hatch, hatch2)*.5 + .5; + col *= clamp(sin((sc.x - sc.y)*3.14159*80.)*1.5 + .75, 0., 1.)*.25 + 1.; + + + // Subtle vignette. + u = fragCoord/iResolution.xy; + col *= pow(16.*u.x*u.y*(1. - u.x)*(1. - u.y) , .125) + .25; + // Colored variation. + //col = mix(pow(min(vec3(1.5, 1, 1)*col, 1.), vec3(1, 3, 16)), col, + //pow(16.*u.x*u.y*(1. - u.x)*(1. - u.y) , .25)*.75 + .25); + + + + // Rough gamma correction. + fragColor = vec4(sqrt(max(col, 0.)), 1); + return vec4(fragColor); +} +)"; + + + + + + + + + + +static const char *effect_raymarched_truchet_fragment = R"( + +float heightMap(in vec2 p) { + p *= 3.0; + vec2 h = vec2(p.x + p.y * 0.57735, p.y * 1.1547); + vec2 f = fract(h); + h -= f; + float c = fract((h.x + h.y) / 3.0); + h = c < 0.666 ? (c < 0.333 ? h : h + 1.0) : h + step(f.yx, f); + p -= vec2(h.x - h.y * 0.5, h.y * 0.8660254); + c = fract(cos(dot(h, vec2(41, 289))) * 43758.5453); + p -= p * step(c, 0.5) * 2.0; + p -= vec2(-1, 0); + c = dot(p, p); + p -= vec2(1.5, 0.8660254); + c = min(c, dot(p, p)); + p -= vec2(0, -1.73205); + c = min(c, dot(p, p)); + return sqrt(c); +} + +float map(vec3 p) { + float c = heightMap(p.xy); + c = cos(c * 6.283 * 1.0) + cos(c * 6.283 * 2.0); + c = clamp(c * 0.6 + 0.5, 0.0, 1.0); + return 1.0 - p.z - c * 0.025; +} + +vec3 getNormal(vec3 p, inout float edge, inout float crv) { + vec2 e = vec2(0.01, 0); + float d1 = map(p + e.xyy), d2 = map(p - e.xyy); + float d3 = map(p + e.yxy), d4 = map(p - e.yxy); + float d5 = map(p + e.yyx), d6 = map(p - e.yyx); + float d = map(p) * 2.0; + edge = abs(d1 + d2 - d) + abs(d3 + d4 - d) + abs(d5 + d6 - d); + edge = smoothstep(0.0, 1.0, sqrt(edge / e.x * 2.0)); + crv = clamp((d1 + d2 + d3 + d4 + d5 + d6 - d * 3.0) * 32.0 + 0.6, 0.0, 1.0); + e = vec2(0.0025, 0); + d1 = map(p + e.xyy); d2 = map(p - e.xyy); + d3 = map(p + e.yxy); d4 = map(p - e.yxy); + d5 = map(p + e.yyx); d6 = map(p - e.yyx); + return normalize(vec3(d1 - d2, d3 - d4, d5 - d6)); +} + +float calculateAO(in vec3 p, in vec3 n) { + float sca = 2.0, occ = 0.0; + for (float i = 0.0; i < 5.0; i++) { + float hr = 0.01 + i * 0.5 / 4.0; + float dd = map(n * hr + p); + occ += (hr - dd) * sca; + sca *= 0.7; + } + return clamp(1.0 - occ, 0.0, 1.0); +} + +float n3D(vec3 p) { + const vec3 s = vec3(7, 157, 113); + vec3 ip = floor(p); p -= ip; + vec4 h = vec4(0.0, s.yz, s.y + s.z) + dot(ip, s); + p = p * p * (3.0 - 2.0 * p); + h = mix(fract(sin(h) * 43758.5453), fract(sin(h + s.x) * 43758.5453), p.x); + h.xy = mix(h.xz, h.yw, p.y); + return mix(h.x, h.y, p.z); +} + +vec3 envMap(vec3 rd, vec3 sn) { + vec3 sRd = rd; + rd.xy -= current_time/100.0 * 0.25; + rd *= 3.0; + float c = n3D(rd) * 0.57 + n3D(rd * 2.0) * 0.28 + n3D(rd * 4.0) * 0.15; + c = smoothstep(0.4, 1.0, c); + vec3 col = vec3(c, c * c, c * c * c * c); + return mix(col, col.yzx, sRd * 0.25 + 0.25); +} + + + +vec2 hash22(vec2 p) { + float n = sin(dot(p, vec2(41.0, 289.0))); // Use floating point literals for constants + return fract(vec2(262144.0, 32768.0) * n) * 0.75 + 0.25; // Make sure all numbers are floats +} + +float Voronoi(in vec2 p) { + vec2 g = floor(p), o; p -= g; + vec3 d = vec3(1); + for (int y = -1; y <= 1; y++) { + for (int x = -1; x <= 1; x++) { + o = vec2(x, y); + o += hash22(g + o) - p; + d.z = dot(o, o); + d.y = max(d.x, min(d.y, d.z)); + d.x = min(d.x, d.z); + } + } + return max(d.y / 1.2 - d.x * 1.0, 0.0) / 1.2; +} + +const vec2 iResolution = vec2(1920.0, 1080.0); + + +vec4 effect_color(vec2 pos) { + + + + vec2 fragCoord = gl_FragCoord.xy; + vec3 rd = normalize(vec3(2.0 * fragCoord - iResolution, iResolution.y)); + float tm = current_time / 100.0; + vec2 a = sin(vec2(1.570796, 0.0) + sin(tm / 4.0) * 0.3); + rd.xy = mat2(a, -a.y, a.x) * rd.xy; + vec3 ro = vec3(tm, cos(tm / 4.0), 0.0); + vec3 lp = ro + vec3(cos(tm / 2.0) * 0.5, sin(tm / 2.0) * 0.5, -0.5); + + float d = 0.0; + float t = 0.0; + + + for (int j = 0; j < 32; j++) { + d = map(ro + rd * t); + t += d * 0.7; + if (d < 0.001) break; + } + float edge, crv; + vec3 sp = ro + rd * t; + vec3 sn = getNormal(sp, edge, crv); + vec3 ld = lp - sp; + float c = heightMap(sp.xy); + vec3 fold = cos(vec3(1, 2, 4) * c * 6.283); + float c2 = heightMap((sp.xy + sp.z * 0.025) * 6.); + c2 = cos(c2 * 6.283 * 3.); + c2 = (clamp(c2 + 0.5, 0.0, 1.0)); + vec3 oC = vec3(1); + if (fold.x > 0.) oC = vec3(1, 0.05, 0.1) * c2; + if (fold.x < 0.05 && fold.y < 0.) oC = vec3(1, 0.7, 0.45) * (c2 * 0.25 + 0.75); + else if (fold.x < 0.) oC = vec3(1, 0.8, 0.4) * c2; + float lDist = max(length(ld), 0.001); + float atten = 1.0 / (1.0 + lDist * 0.125); + ld /= lDist; + float diff = max(dot(ld, sn), 0.0); + float spec = pow(max(dot(reflect(-ld, sn), -rd), 0.0), 16.0); + float fre = pow(clamp(dot(sn, rd) + 1.0, 0.0, 1.0), 3.0); + crv = crv * 0.9 + 0.1; + float ao = calculateAO(sp, sn); + vec3 col = oC * (diff + 0.5) + vec3(1.0, 0.7, 0.4) * spec * 2.0 + vec3(0.4, 0.7, 1.0) * fre; + col += (oC * 0.5 + 0.5) * envMap(reflect(rd, sn), sn) * 6.0; + col *= 1.0 - edge * 0.85; + col *= atten * crv * ao; + fragColor = vec4(sqrt(clamp(col, 0.0, 1.0)), 1.0); + + + return vec4(fragColor); +} + + +)"; + + + + + + + + +static const char *effect_neon_rings_fragment = R"( + +#define PI 3.14159265358979323846 +#define TWO_PI 6.28318530717958647692 + +const vec2 iResolution = vec2(1920.0, 1080.0); + +mat2 rotate2D(float r) { + float c = cos(r); + float s = sin(r); + return mat2(c, -s, s, c); +} + +vec4 effect_color(vec2 pos) { + + + // Use gl_FragCoord as the pixel position +// pos = ivec2(gl_FragCoord.xy); + + // pos = ivec2(gl_FragCoord.xy); + // int x = pos.x; + // int y = pos.y; + + // Number of circles + int numCircles = 5; + + // Initialize final color + vec3 finalColor = vec3(0.0); + + for (int i = 0; i < numCircles; ++i) { + // Calculate UV coordinates for each circle +// vec2 uv = vec2(pos) / vec2(width / 3, height / 3); + vec2 uv = vec2(pos) / vec2(width*0.3333333333333, height*0.3333333333333); + + // Calculate polar coordinates + float a = atan(uv.y, uv.x); + float r = length(uv) * (0.2 + 0.1 * float(i)); + + // Map polar coordinates to UV + uv = vec2(a / TWO_PI, r); + + // Apply horizontal movement based on time for each circle + float xOffset = sin(current_time * 0.02 + float(i)) * 0.2; + uv.x += xOffset; + + // Time-dependent color + float xCol = (uv.x - (current_time / 300000.0)) * 3.0; + xCol = mod(xCol, 3.0); + vec3 horColour = vec3(0.25, 0.25, 0.25); + + if (xCol < 1.0) { + horColour.r += 1.0 - xCol; + horColour.g += xCol; + } else if (xCol < 2.0) { + xCol -= 1.0; + horColour.g += 1.0 - xCol; + horColour.b += xCol; + } else { + xCol -= 2.0; + horColour.b += 1.0 - xCol; + horColour.r += xCol; + } + + // Draw color beam + uv = (2.0 * uv) - 1.0; + float beamWidth = (0.7 + 0.5 * cos(uv.x * 1.0 * TWO_PI * 0.15 * clamp(floor(5.0 + 1.0 * cos(current_time)), 0.0, 1.0))) * abs(1.0 / (30.0 * uv.y)); + vec3 horBeam = vec3(beamWidth); + + // Add the color for the current circle to the final color + finalColor += ((horBeam) * horColour); + } + + // Output the final color + fragColor = vec4(finalColor, 1.0); + + + return vec4(fragColor); +} +)"; + + + + +static const char *effect_deco_fragment = R"( + +vec3 effect(float speed, vec2 uv, float time, float scale) { + float t = mod(time * 0.005, 6.0); + float rt = 0.00000000000001 * sin(t * 0.45); + + mat2 m1 = mat2(cos(rt), -sin(rt), -sin(rt), cos(rt)); + vec2 uva = uv * m1 * scale; + float irt = 0.005 * cos(t * 0.05); + mat2 m2 = mat2(sin(irt), cos(irt), -cos(irt), sin(irt)); + + for (int i = 1; i < 400; i += 1) { + float it = float(i); + uva *= m2; + uva.y += -1.0 + (0.6 / it) * cos(t + it * uva.x + 0.5 * it) * float(mod(it, 0.5) == 0.0); + uva.x += 1.0 + (0.5 / it) * cos(t + it * uva.y * 0.1 / 5.0 + 0.5 * (it + 15.0)); + } + + float n = 0.5; + float r = n + n * sin(4.0 * uva.x + t); + float gb = n + n * sin(3.0 * uva.y); + return vec3(r, gb * 0.8 * r, gb * r); +} + +vec4 effect_color(vec2 pos) { + + vec2 uv = (gl_FragCoord.xy - 0.5 * vec2(width, height)) / vec2(width, height); + uv *= (10.3 + 0.1 * sin(current_time * 0.01)); + + + + vec3 col = effect(0.001, uv, current_time, 0.5); + + // Set the fragment color + fragColor = vec4(col, 1.0); + + + return vec4(fragColor); +} + +)"; + + + + + + + + + +// ported from https://www.shadertoy.com/view/3djfzy +static const char *effect_ice_fragment = + R"( + +vec3 effect(float speed, vec2 uv, float time, float scale) { + float t = mod(time * 0.005, 6.0); + float rt = 0.00000000000001 * sin(t * 0.45); + + mat2 m1 = mat2(cos(rt), -sin(rt), -sin(rt), cos(rt)); + vec2 uva = uv * m1 * scale; + float irt = 0.005 * cos(t * 0.05); + mat2 m2 = mat2(sin(irt), cos(irt), -cos(irt), sin(irt)); + + for (int i = 1; i < 400; i += 1) { + float it = float(i); + uva *= m2; + uva.y += -1.0 + (0.6 / it) * cos(t + it * uva.x + 0.5 * it) * float(mod(it, 0.5) == 0.0); + uva.x += 1.0 + (0.5 / it) * cos(t + it * uva.y * 0.1 / 5.0 + 0.5 * (it + 15.0)); + } + + float n = 0.5; + float r = n + n * sin(4.0 * uva.x + t); + float gb = n + n * sin(3.0 * uva.y); + return vec3(r, gb * 0.8 * r, gb * r); +} + + + + + + + + +float rand(in vec2 _st) { + return fract(sin(dot(_st.xy, vec2(-0.820, -0.840))) * 4757.153); +} + +float noise(in vec2 _st) { + const vec2 d = vec2(0.0, 1.0); + vec2 b = floor(_st), f = smoothstep(vec2(0.0), vec2(0.1, 0.3), fract(_st)); + return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y); +} + +float fbm(in vec2 _st) { + float v = sin(current_time * 0.005) * 0.2; + float a = 0.3; + vec2 shift = vec2(100.0); + mat2 rot = mat2(cos(0.5), sin(1.0), -sin(0.5), acos(0.5)); + for (int i = 0; i < 3; ++i) { + v += a * noise(_st); + _st = rot * _st * 2.0 + shift; + a *= 1.5; + } + return v; +} + +vec4 effect_color(vec2 pos) { + + + + + + vec2 st = (gl_FragCoord.xy * 2.0 - vec2(width, height)) / min(float(width), float(height)) * 0.5; + + vec2 coord = st * 0.2; + float len; + for (int i = 0; i < 3; i++) { + len = length(coord); + coord.x += sin(coord.y + current_time * 0.001) * 2.1; + coord.y += cos(coord.x + current_time * 0.001 + cos(len * 1.0)) * 1.0; + } + len -= 3.0; + + vec3 color = vec3(0.0); + + vec2 q = vec2(0.0); + q.x = fbm(st); + q.y = fbm(st + vec2(-0.450, 0.650)); + + vec2 r = vec2(0.0); + r.x = fbm(st + 1.0 * q + vec2(0.570, 0.520) + 0.1 * current_time * 0.01); + r.y = fbm(st + 1.0 * q + vec2(0.340, -0.570) + 0.05 * current_time * 0.01); + float f = fbm(st + r); + + color = mix(color, cos(len + vec3(0.5, 0.0, -0.1)), 1.0); + color = mix(vec3(0.478, 0.738, 0.760), vec3(0.563, 0.580, 0.667), color); + + fragColor = vec4((f * f * f + .6 * f * f + .5 * f) * color, 1.0); + + + return vec4(fragColor); +} +)"; + + + + + +static const char *effect_fire_fragment = R"( + +vec3 effect(float speed, vec2 uv, float time, float scale) { + + + + + float t = mod(time * 0.005, 6.0); + float rt = 0.00000000000001 * sin(t * 0.45); + + mat2 m1 = mat2(cos(rt), -sin(rt), -sin(rt), cos(rt)); + vec2 uva = uv * m1 * scale; + float irt = 0.005 * cos(t * 0.05); + mat2 m2 = mat2(sin(irt), cos(irt), -cos(irt), sin(irt)); + + for (int i = 1; i < 400; i += 1) { + float it = float(i); + uva *= m2; + uva.y += -1.0 + (0.6 / it) * cos(t + it * uva.x + 0.5 * it) * float(mod(it, 0.5) == 0.0); + uva.x += 1.0 + (0.5 / it) * cos(t + it * uva.y * 0.1 / 5.0 + 0.5 * (it + 15.0)); + } + + float n = 0.5; + float r = n + n * sin(4.0 * uva.x + t); + float gb = n + n * sin(3.0 * uva.y); + return vec3(r, gb * 0.8 * r, gb * r); +} + + +float rand(vec2 n) { + return fract(cos(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); +} + +float noise(vec2 n) { + const vec2 d = vec2(0.0, 1.0); + vec2 b = floor(n), f = smoothstep(vec2(0.0), vec2(1.0), fract(n)); + return mix(mix(rand(b), rand(b + d.yx), f.x), mix(rand(b + d.xy), rand(b + d.yy), f.x), f.y); +} + +float fbm(vec2 n) { + float total = 0.0, amplitude = 1.0; + for (int i = 0; i < 4; i++) { + total += noise(n) * amplitude; + n += n; + amplitude *= 0.5; + } + return total; +} +vec4 effect_color(vec2 pos) { + + vec2 gid = gl_FragCoord.xy; + vec2 normalizedCoords = gid / vec2(width, height); // Normalize the coordinates + + const vec3 c1 = vec3(0.5, 0.0, 0.1); + const vec3 c2 = vec3(0.9, 0.0, 0.0); + const vec3 c3 = vec3(0.2, 0.0, 0.0); + const vec3 c4 = vec3(1.0, 0.9, 0.0); + const vec3 c5 = vec3(0.1); + const vec3 c6 = vec3(0.9); + + vec2 speed = vec2(0.7, 0.4); + float shift = 1.0; + float alpha = 1.0; + + float timeEffect = current_time * 0.05; // Slowing down the animation by reducing the current_time factor + + vec2 p = normalizedCoords * 8.0; + float q = fbm(p - timeEffect * 0.1); + vec2 r = vec2(fbm(p + q + timeEffect * speed.x - p.x - p.y), fbm(p + q - timeEffect * speed.y)); + vec3 c = mix(c1, c2, fbm(p + r)) + mix(c3, c4, r.x) - mix(c5, c6, r.y); + fragColor = vec4(c * cos(shift * normalizedCoords.y), alpha); + + + return vec4(fragColor); +} + +)"; + + + + +static const char *effect_render_fragment = R"( + +precision lowp float; +precision lowp sampler2D; + +uniform sampler2D in_b0d; +uniform bool ink; +uniform vec4 smoke_color; +uniform vec4 decor_color; +//uniform int regionInfo[20]; // This will likely go unused in this shader. + +//out vec4 fragColor; + +vec4 effect_color(vec2 pos) { + + vec2 texCoord = gl_FragCoord.xy; + float c, a; + vec3 color; + + vec4 s = texture(in_b0d, texCoord); + c = s.x * 800.0; + if (c > 255.0) + c = 255.0; + a = c / 255.0; // Normalize alpha to the range 0.0 to 1.0 + if (ink) + { + if (c > 2.0) + color = mix(decor_color.rgb, smoke_color.rgb, clamp(a, 0.0, 1.0)); + else + color = mix(decor_color.rgb, vec3(0.0, 0.0, 0.0), clamp(a, 0.0, 1.0)); + + if (c > 1.5) + fragColor = vec4(color, 1.0); + else + fragColor = decor_color; + return vec4(fragColor); + } + + else + { + color = mix(decor_color.rgb, smoke_color.rgb, clamp(a, 0.0, 1.0)); + + + fragColor = vec4(color, decor_color.a); +return vec4(fragColor); + + + + } + + fragColor = vec4(color, decor_color.a); +return vec4(fragColor); + +} + + + +)"; + + + + + + diff --git a/src/overlay-shaders.hpp b/src/overlay-shaders.hpp new file mode 100644 index 0000000..1fc936a --- /dev/null +++ b/src/overlay-shaders.hpp @@ -0,0 +1,412 @@ +static const char *overlay_no_overlay = R"( +vec4 overlay_function(vec2 position) +{ + return effect_color(position); +})"; + +static const char *overlay_rounded_corners = R"( +uniform int corner_radius; +uniform int shadow_radius; +uniform vec4 shadow_color; + +vec4 overlay_function(vec2 pos) +{ + vec4 c = shadow_color; + vec4 m = vec4(0.0); + float diffuse = 1.0 / max(float(shadow_radius / 2), 1.0); + + float distanceToEdgeX = ceil(min(pos.x, width - pos.x)); + float distanceToEdgeY = ceil(min(pos.y, height - pos.y)); + + float radii_sum = float(shadow_radius) + float(corner_radius); + + // We have a corner + if ((distanceToEdgeX <= radii_sum) && (distanceToEdgeY <= radii_sum)) + { + float d = distance(vec2(distanceToEdgeX, distanceToEdgeY), vec2(radii_sum)) - float(corner_radius); + vec4 s = mix(c, m, 1.0 - exp(-pow(d * diffuse, 2.0))); + + vec4 eff_color = effect_color(pos); + return mix(eff_color, s, clamp(d, 0.0, 1.0)); + } + + bool closeToX = ceil(distanceToEdgeX) < float(shadow_radius); + bool closeToY = ceil(distanceToEdgeY) < float(shadow_radius); + + if (!closeToX && !closeToY) + { + return effect_color(pos); + } + + // Edges + float d = float(shadow_radius) - (closeToX ? distanceToEdgeX : distanceToEdgeY); + return mix(c, m, 1.0 - exp(-pow(d * diffuse, 2.0))); +})"; + + + + +static const char *overlay_beveled_glass = R"( + + +#define MARKER_RADIUS 12.5 +#define THICCNESS 2.0 + +uniform int beveled_radius; +uniform int title_height; +uniform int border_size; + + + +bool isInsideTriangle(vec2 p, vec2 a, vec2 b, vec2 c) { + vec2 v0 = b - a; + vec2 v1 = c - a; + vec2 v2 = p - a; + + float dot00 = dot(v0, v0); + float dot01 = dot(v0, v1); + float dot02 = dot(v0, v2); + float dot11 = dot(v1, v1); + float dot12 = dot(v1, v2); + + float invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01); + float u = (dot11 * dot02 - dot01 * dot12) * invDenom; + float v = (dot00 * dot12 - dot01 * dot02) * invDenom; + + return (u >= 0.0) && (v >= 0.0) && (u + v <= 1.0); +} + + +vec4 toBezier(float delta, int i, vec4 P0, vec4 P1, vec4 P2, vec4 P3) +{ + float t = delta * float(i); + float t2 = t * t; + float one_minus_t = 1.0 - t; + float one_minus_t2 = one_minus_t * one_minus_t; + return (P0 * one_minus_t2 * one_minus_t + P1 * 3.0 * t * one_minus_t2 + P2 * 3.0 * t2 * one_minus_t + P3 * t2 * t); +} + +float sin01(float x) { + return (sin(x) + 1.0) / 2.0; +} + + + + + +vec4 drawCurveBenzier(vec2 p1, vec2 p2, int setCount) { + vec4 col = vec4(0.0); + vec2 fragCoord = gl_FragCoord.xy; + float curveRadius = float(beveled_radius/2); + + for (int i = 0; i <= setCount; ++i) { + vec4 bezierPoint = toBezier(1.0 / float(setCount), i, vec4(p1, 0.0, 1.0), vec4(p1 + (p2 - p1) * 0.5, 0.0, 1.0), vec4(p1 + (p2 - p1) * 0.5, 0.0, 1.0), vec4(p2, 0.0, 1.0)); + vec2 curvePoint = bezierPoint.xy / bezierPoint.w; + float distance = length(fragCoord - curvePoint); + float curveIntensity = smoothstep(0.0, THICCNESS, curveRadius - distance); + col.rgb += vec3(0.1, 0.1, 0.1) * curveIntensity; + col.a = max(col.a, curveIntensity); + } + + return col; +} + + + +vec4 drawCurve(vec2 p1, vec2 p2, int setCount) { + vec4 col = vec4(0.0); + ivec2 storePos = ivec2(gl_FragCoord.xy); + + float curveRadius = float(beveled_radius + 1); + vec2 fragCoord = vec2(storePos); + + float t = clamp(dot(fragCoord - p1, p2 - p1) / dot(p2 - p1, p2 - p1), 0.0, 1.0); + vec2 curvePoint = mix(p1, p2, t); + + float distance = length(fragCoord - curvePoint); + float curveIntensity = smoothstep(0.0, curveRadius, curveRadius - distance); + + // Calculate gradient along the line with grey to white to grey + vec3 gradientColor; + + if (t < 0.5) { + gradientColor = mix(vec3(0.7), vec3(1.0), t * 2.0); + } else { + gradientColor = mix(vec3(1.0), vec3(0.7), (t - 0.5) * 2.0); + } + + // Use the curveIntensity to interpolate between gradient colors + col.rgb = gradientColor * curveIntensity; + col.a = max(col.a, curveIntensity); + + return col; +} + + + + +vec4 overlay_function(vec2 pos) +{ + + + +vec2 fragCoord = gl_FragCoord.xy; + + + + + + vec4 col = vec4(0.0); + float space = 15.0; + + vec2 p1 = vec2(0.0 + THICCNESS, float(height) - THICCNESS - space); + vec2 p2 = vec2(0.0 + THICCNESS, 0.0 + THICCNESS + space); + + vec2 x1 = vec2(float(width) - THICCNESS, float(height) - THICCNESS - space); + vec2 x2 = vec2(float(width) - THICCNESS, 0.0 + THICCNESS + space); + + vec2 y1 = vec2(0.0 + THICCNESS + space, float(height) - THICCNESS); + vec2 y2 = vec2(float(width) - THICCNESS - space, float(height) - THICCNESS); + + vec2 z1 = vec2(0.0 + THICCNESS + space, 0.0 + THICCNESS); + vec2 z2 = vec2(float(width) - THICCNESS - space, 0.0 + THICCNESS); + + + float curveRadius = float(beveled_radius); +// Draw the lines connecting the points + +int setwidth = int(width); +int setheight = int(height); + + +if (setwidth<=400 && setheight<=300 ){ + col += drawCurveBenzier(p1, p2, setheight); + col += drawCurveBenzier(x1, x2, setheight); + col += drawCurveBenzier(y1, y2, setwidth); + col += drawCurveBenzier(z1, z2, setwidth); +} +else { + col += drawCurve(p1, p2, setheight); + col += drawCurve(x1, x2, setheight); + col += drawCurve(y1, y2, setwidth); + col += drawCurve(z1, z2, setwidth); + } + + +float INNERspace = 0.0; + + + + +//left + vec2 INNERp1 = vec2(0.0 - THICCNESS+ float(border_size), float(height) + THICCNESS -float(title_height) ); + vec2 INNERp2 = vec2(0.0 - THICCNESS+ float(border_size),0.0 - THICCNESS + INNERspace+float(border_size)); +//right + vec2 INNERx1 = vec2(float(width) + THICCNESS-float(border_size), float(height) + THICCNESS -float(title_height)); + vec2 INNERx2 = vec2(float(width) + THICCNESS-float(border_size),0.0 - THICCNESS + INNERspace+float(border_size)); + + +//top + vec2 INNERy1 = vec2(0.0 + THICCNESS + INNERspace+float(border_size), float(height) + THICCNESS -float(title_height)); + vec2 INNERy2 = vec2(float(width) - THICCNESS - INNERspace-float(border_size), float(height) + THICCNESS-float(title_height)); + +//bottom + vec2 INNERz1 = vec2(0.0 +INNERspace+float(border_size), 0.0 - THICCNESS + INNERspace+float(border_size)); + vec2 INNERz2 = vec2(float(width) - THICCNESS - INNERspace-float(border_size) ,0.0 - THICCNESS + INNERspace+float(border_size) ); + + + + + +if (setwidth<=400 && setheight<=300 ){ + col += drawCurveBenzier(INNERp1, INNERp2, setheight); + col += drawCurveBenzier(INNERx1, INNERx2, setheight); + col += drawCurveBenzier(INNERy1, INNERy2, setwidth); + col += drawCurveBenzier(INNERz1, INNERz2, setwidth); +} +else{ + col += drawCurve(INNERp1, INNERp2, setheight); + col += drawCurve(INNERx1, INNERx2, setheight); + col += drawCurve(INNERy1, INNERy2, setwidth); + col += drawCurve(INNERz1, INNERz2, setwidth); + } + + + vec2 p3 = fragCoord; + vec2 p12 = p2 - p1; + vec2 p13 = p3 - p1; + + vec2 x3 = fragCoord; + vec2 x12 = x2 - x1; + vec2 x13 = x3 - x1; + + vec2 y3 = fragCoord; + vec2 y12 = y2 - y1; + vec2 y13 = y3 - y1; + + vec2 z3 = fragCoord; + vec2 z12 = z2 - z1; + vec2 z13 = z3 - z1; + + float d = dot(p12, p13) / length(p12); // = length(p13) * cos(angle) + float dx = dot(x12, x13) / length(x12); + float dy = dot(y12, y13) / length(y12); + float dz = dot(z12, z13) / length(z12); + + vec2 p4 = p1 + normalize(p12) * d; + vec2 x4 = x1 + normalize(x12) * dx; + vec2 y4 = y1 + normalize(y12) * dy; + vec2 z4 = z1 + normalize(z12) * dz; + + + if (((length(p4 - p3) < THICCNESS && length(p4 - p1) <= length(p12) && length(p4 - p2) <= length(p12)) || + (length(x4 - x3) < THICCNESS && length(x4 - x1) <= length(x12) && length(x4 - x2) <= length(x12))) || + (length(y4 - y3) < THICCNESS && length(y4 - y1) <= length(y12) && length(y4 - y2) <= length(y12)) || + (length(z4 - z3) < THICCNESS && length(z4 - z1) <= length(z12) && length(z4 - z2) <= length(z12))) { + col = vec4(0.1, 0.1, 0.1, 1.0); + } + + + + vec2 INNERp3 = fragCoord; + vec2 INNERp12 = INNERp2 - INNERp1; + vec2 INNERp13 = INNERp3 - INNERp1; + + vec2 INNERx3 = fragCoord; + vec2 INNERx12 = INNERx2 - INNERx1; + vec2 INNERx13 = INNERx3 - INNERx1; + + vec2 INNERy3 = fragCoord; + vec2 INNERy12 = INNERy2 - INNERy1; + vec2 INNERy13 = INNERy3 - INNERy1; + + vec2 INNERz3 = fragCoord; + vec2 INNERz12 = INNERz2 - INNERz1; + vec2 INNERz13 = INNERz3 - INNERz1; + + float INNERd = dot(INNERp12, INNERp13) / length(INNERp12); // = length(p13) * cos(angle) + float INNERdx = dot(INNERx12, INNERx13) / length(INNERx12); + float INNERdy = dot(INNERy12, INNERy13) / length(INNERy12); + float INNERdz = dot(INNERz12, INNERz13) / length(INNERz12); + + vec2 INNERp4 = INNERp1 + normalize(INNERp12) * INNERd; + vec2 INNERx4 = INNERx1 + normalize(INNERx12) * INNERdx; + vec2 INNERy4 = INNERy1 + normalize(INNERy12) * INNERdy; + vec2 INNERz4 = INNERz1 + normalize(INNERz12) * INNERdz; + + if (((length(INNERp4 - INNERp3) < THICCNESS && length(INNERp4 - INNERp1) <= length(INNERp12) && length(INNERp4 - INNERp2) <= length(INNERp12)) || + (length(INNERx4 - INNERx3) < THICCNESS && length(INNERx4 - INNERx1) <= length(INNERx12) && length(INNERx4 - INNERx2) <= length(INNERx12))) || + (length(INNERy4 - INNERy3) < THICCNESS && length(INNERy4 - INNERy1) <= length(INNERy12) && length(INNERy4 - INNERy2) <= length(INNERy12)) || + (length(INNERz4 - INNERz3) < THICCNESS && length(INNERz4 - INNERz1) <= length(INNERz12) && length(INNERz4 - INNERz2) <= length(INNERz12))) { + col = vec4(0.1, 0.1, 0.1, 1.0); + } + + + // Draw the lines connecting the points + // Calculate the line segment connecting p1 and y1 + vec2 dir = normalize(y1 - p1); + vec2 relPoint = fragCoord - p1; + float alongLine = dot(relPoint, dir); + float distance = length(relPoint - alongLine * dir); + + // Draw the line connecting p1 and y1 + if (distance < THICCNESS && alongLine > 0.0 && alongLine < length(y1 - p1)) { + col = vec4(0.1, 0.1, 0.1, 1.0); + } + + + + dir = normalize(y2 - x1); + relPoint = fragCoord - x1; + alongLine = dot(relPoint, dir); + distance = length(relPoint - alongLine * dir); + + if (distance < THICCNESS && alongLine > 0.0 && alongLine < length(x1 - y2)) { + col = vec4(0.1, 0.1, 0.1, 1.0); + } + + + dir = normalize(p2 - z1); + relPoint = fragCoord - z1; + alongLine = dot(relPoint, dir); + distance = length(relPoint - alongLine * dir); + + if (distance < THICCNESS && alongLine > 0.0 && alongLine < length(z1 - p2)) { + col = vec4(0.1, 0.1, 0.1, 1.0); + } + + + + dir = normalize(x2 - z2); + relPoint = fragCoord - z2; + alongLine = dot(relPoint, dir); + distance = length(relPoint - alongLine * dir); + + if (distance < THICCNESS && alongLine > 0.0 && alongLine < length(x2 - z2)) { + col = vec4(0.1, 0.1, 0.1, 1.0); + } + // Draw other lines... + + vec2 t1 = vec2(0.0, float(height)); + vec2 t2 = vec2(float(width), float(height)); + vec2 t3 = vec2(-0.5, -0.5); + vec2 t4 = vec2(float(width), -0.5); + + + +vec4 combine_col= col+effect_color(pos); + + + + + +int shadow_radius=-0; +int corner_radius=15; + + +vec4 c = vec4(1.0); +vec4 m = vec4(0.0, 0.0, 0.0, 0.0); // Transparent for the cut corners +float diffuse = 1.0 / max(float(shadow_radius / 2), 1.0); + +float distanceToEdgeX = ceil(min(pos.x, width - pos.x)); +float distanceToEdgeY = ceil(min(pos.y, height - pos.y)); + +float radii_sum = float(shadow_radius) + float(corner_radius); + +// Check for 45-degree cut corners +if ((distanceToEdgeX <= radii_sum) && (distanceToEdgeY <= radii_sum)) +{ + // Calculate if within the 45-degree triangle area + float diagonalDistance = distanceToEdgeX + distanceToEdgeY; + if (diagonalDistance <= radii_sum) { + // Inside the cut corner area, make it fully transparent + return m; // Return transparent color + } +} + +/* +bool closeToX = distanceToEdgeX < float(shadow_radius); +bool closeToY = distanceToEdgeY < float(shadow_radius); + +if (!closeToX && !closeToY) +{ + // return effect_color(pos); +} + +// Handle shadow along edges +float shadow_d = float(shadow_radius) - (closeToX ? distanceToEdgeX : distanceToEdgeY); +vec4 edgeShadow = mix(c, m, 1.0 - exp(-pow(shadow_d * diffuse, 2.0))); +vec4 shadow = vec4(edgeShadow.rgb, edgeShadow.a * clamp(1.0 - shadow_d / float(shadow_radius), 0.0, 1.0)); // Adjust alpha to fade shadow +*/ + + return combine_col; + +})"; + + + + + + + + diff --git a/src/smoke-shaders.hpp b/src/smoke-shaders.hpp index 5956ca1..f94ff80 100644 --- a/src/smoke-shaders.hpp +++ b/src/smoke-shaders.hpp @@ -443,3 +443,1199 @@ void run_pixel(int x, int y) } imageStore(out_tex, ivec2(x, y), vec4(color, decor_color.a)); })"; + +/*/////////////////////////////////////////////// + ______ _ _ __ __ ______ _____ + | ____|| | | || \/ || ____| / ____| + | |__ | | | || \ / || |__ | (___ + | __| | | | || |\/| || __| \___ \ + | | | |__| || | | || |____ ____) | + |_| \____/ |_| |_||______| |_____/ + +*//////////////////////////////////////////////// + +static const char *fumes_motion_source = + R"( +#version 320 es + +precision lowp image2D; + +layout (binding = 1, r32f) uniform readonly image2D in_b0u; +layout (binding = 1, r32f) uniform writeonly image2D out_b0u; +layout (binding = 2, r32f) uniform readonly image2D in_b0v; +layout (binding = 2, r32f) uniform writeonly image2D out_b0v; +layout (binding = 3, r32f) uniform readonly image2D in_b0d; +layout (binding = 3, r32f) uniform writeonly image2D out_b0d; +layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(location = 1) uniform int title_height; +layout(location = 2) uniform int border_size; +layout(location = 3) uniform int px; +layout(location = 4) uniform int py; +layout(location = 5) uniform int width; +layout(location = 6) uniform int height; +layout(location = 7) uniform int rand1; +layout(location = 8) uniform int rand2; +layout(location = 9) uniform int radius; + +void motion(int x, int y) +{ + int i, i0, i1, j, j0, j1, d = 2; + + if (x - d < 1) + i0 = 1; + else + i0 = x - d; + if (i0 + 2 * d > width - 1) + i1 = width - 1; + else + i1 = i0 + 2 * d; + + if (y - d < 1) + j0 = 1; + else + j0 = y - d; + if (j0 + 2 * d > height - 1) + j1 = height - 1; + else + j1 = j0 + 2 * d; + + for (i = i0; i < i1; i++) + { + for (j = j0; j < j1; j++) { + if (i < radius || j < radius || i > (width - 1) - radius || j > (height - 1) - radius || (i > border_size && i < (width - 1) - border_size && j > (title_height - 1) && j < (height - 1) - border_size)) + { + continue; + } + vec4 b0u = imageLoad(in_b0u, ivec2(i, j)); + vec4 b0v = imageLoad(in_b0u, ivec2(i, j)); + vec4 b0d = imageLoad(in_b0u, ivec2(i, j)); + float u = b0u.x; + float v = b0v.x; + float d = b0d.x; + imageStore(out_b0u, ivec2(i, j), vec4(u + float(256*15 - (rand1 & 512*15)), 0.0, 0.0, 0.0)); + imageStore(out_b0v, ivec2(i, j), vec4(v + float(256*15 - (rand2 & 512*15)), 0.0, 0.0, 0.0)); + // imageStore(out_b0d, ivec2(i, j), vec4(0.0, 0.0, 0.0, 0.0)); + } + } + } + +void main() +{ + motion(px, py); +} +)"; + +static const char *fumes_diffuse1_source = + R"( +void run_pixel(int x, int y) +{ + int k; + float t = 0.0002; + float a = 0.002; + vec4 s = imageLoad(in_b0u, ivec2(x, y)); + vec4 d1 = imageLoad(in_b1u, ivec2(x - 1, y)); + vec4 d2 = imageLoad(in_b1u, ivec2(x + 1, y)); + vec4 d3 = imageLoad(in_b1u, ivec2(x, y - 1)); + vec4 d4 = imageLoad(in_b1u, ivec2(x, y + 1)); + float sx = s.x; + float du1 = d1.x; + float du2 = d2.x; + float du3 = d3.x; + float du4 = d4.x; + float t1 = du1 + du2 + du3 + du4; + s = imageLoad(in_b0v, ivec2(x, y)); + d1 = imageLoad(in_b1v, ivec2(x - 1, y)); + d2 = imageLoad(in_b1v, ivec2(x + 1, y)); + d3 = imageLoad(in_b1v, ivec2(x, y - 1)); + d4 = imageLoad(in_b1v, ivec2(x, y + 1)); + float sy = s.x; + du1 = d1.x; + du2 = d2.x; + du3 = d3.x; + du4 = d4.x; + float t2 = du1 + du2 + du3 + du4; + imageStore(out_b1u, ivec2(x, y), vec4((sx + a * t1) / (1.0 + 4.0 * a) * 0.9999999999999999999999995, 0.0, 0.0, 0.0)); + imageStore(out_b1v, ivec2(x, y), vec4((sy + a * t2) / (1.0 + 4.0 * a) * 0.9999999999999999999999995, 0.0, 0.0, 0.0)); + + +} +)"; + +static const char *fumes_project1_source = + R"( +void run_pixel(int x, int y) { + int k, l, s; + float h; + + h = 1.0 / float(width); +// s = width; + + vec4 s1 = imageLoad(in_b1u, ivec2(x - 1, y)); + vec4 s2 = imageLoad(in_b1u, ivec2(x + 1, y)); + vec4 s3 = imageLoad(in_b1v, ivec2(x, y - 1)); + vec4 s4 = imageLoad(in_b1v, ivec2(x, y + 1)); + float u1 = s1.x; + float u2 = s2.x; + float v1 = s3.x; + float v2 = s4.x; + imageStore(out_b0u, ivec2(x, y), vec4(0.0, 0.0, 0.0, 0.0)); + imageStore(out_b0v, ivec2(x, y), vec4(-0.5 * h * (u2 - u1 + v2 - v1), 0.0, 0.0, 0.0)); +} +)"; + +static const char *fumes_project2_source = + R"( +void run_pixel(int x, int y) +{ + int k, l, s; + float h; + + h = 1.0 / float(width); + s = width; + + vec4 s0 = imageLoad(in_b0v, ivec2(x, y)); + vec4 s1 = imageLoad(in_b0u, ivec2(x - 1, y)); + vec4 s2 = imageLoad(in_b0u, ivec2(x + 1, y)); + vec4 s3 = imageLoad(in_b0u, ivec2(x, y - 1)); + vec4 s4 = imageLoad(in_b0u, ivec2(x, y + 1)); + float u1 = s1.x; + float u2 = s2.x; + float u3 = s3.x; + float u4 = s4.x; + + imageStore(out_b0u, ivec2(x, y), vec4((s0.x + u1 + u2 + u3 + u4) / 4.0, 0.0, 0.0, 0.0)); +})"; + +static const char *fumes_project3_source = + R"( +void run_pixel(int x, int y) +{ + int k, l, s; + float h; + + h = 1.0 / float(width); + s = width; + + vec4 s0x = imageLoad(in_b1u, ivec2(x, y)); + vec4 s1 = imageLoad(in_b0u, ivec2(x - 1, y)); + vec4 s2 = imageLoad(in_b0u, ivec2(x + 1, y)); + vec4 s0y = imageLoad(in_b1v, ivec2(x, y)); + vec4 s3 = imageLoad(in_b0u, ivec2(x, y - 1)); + vec4 s4 = imageLoad(in_b0u, ivec2(x, y + 1)); + float su = s0x.x; + float u1 = s1.x; + float u2 = s2.x; + float sv = s0y.x; + float u3 = s3.x; + float u4 = s4.x; + imageStore(out_b1u, ivec2(x, y), vec4(su - 0.5 * (u2 - u1) / h, 0.0, 0.0, 0.0)); + imageStore(out_b1v, ivec2(x, y), vec4(sv - 0.5 * (u4 - u3) / h, 0.0, 0.0, 0.0)); +})"; + +static const char *fumes_advect1_source = + R"( + +void run_pixel(int x, int y) /* b1.u, b1.v, b1.u, b0.u */ +{ + int stride; + int i, j; + float fx, fy; + stride = width; + + vec4 sx = imageLoad(in_b1u, ivec2(x, y)); + vec4 sy = imageLoad(in_b1v, ivec2(x, y)); + float ix = float(x) - sx.x; + float iy = float(y) - sy.x; + + + ix = clamp(ix, 0.5, float(width) - 1.5); + iy = clamp(iy, 0.5, float(height) - 1.5); + + i = int(ix); + j = int(iy); + fx = ix - float(i); + fy = iy - float(j); + + // Process u component + vec4 s0x = imageLoad(in_b1u, ivec2(i, j)); + vec4 s1x = imageLoad(in_b1u, ivec2(i + 1, j)); + vec4 s2x = imageLoad(in_b1u, ivec2(i, j + 1)); + vec4 s3x = imageLoad(in_b1u, ivec2(i + 1, j + 1)); + float p1 = (s0x.x * (1.0 - fx) + s1x.x * fx) * (1.0 - fy) + (s2x.x * (1.0 - fx) + s3x.x * fx) * fy; + imageStore(out_b0u, ivec2(x, y), vec4(p1, 0.0, 0.0, 0.0)); + + ix = float(x) - sx.x; + iy = float(y) - sy.x; + + ix = clamp(ix, 0.5, float(width) - 1.5); + iy = clamp(iy, 0.5, float(height) - 1.5); + + i = int(ix); + j = int(iy); + fx = ix - float(i); + fy = iy - float(j); + + // Process v component + vec4 s0y = imageLoad(in_b1v, ivec2(i, j)); + vec4 s1y = imageLoad(in_b1v, ivec2(i + 1, j)); + vec4 s2y = imageLoad(in_b1v, ivec2(i, j + 1)); + vec4 s3y = imageLoad(in_b1v, ivec2(i + 1, j + 1)); + float p2 = (s0y.x * (1.0 - fx) + s1y.x * fx) * (1.0 - fy) + (s2y.x * (1.0 - fx) + s3y.x * fx) * fy; + imageStore(out_b0v, ivec2(x, y), vec4(p2, 0.0, 0.0, 0.0)); +})"; + +static const char *fumes_project4_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *fumes_project5_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *fumes_project6_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *fumes_diffuse2_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *fumes_advect2_source = + R"( +void run_pixel(int x, int y) +{ + +})"; + +//math from https://inria.hal.science/inria-00596050/document +static const char *fumes_render_source = + R"( +#version 320 es + +precision lowp image2D; + +layout (binding = 0, rgba32f) uniform writeonly image2D out_tex; +layout (binding = 1, r32f) uniform readonly image2D in_b0u; +layout (binding = 3, r32f) uniform readonly image2D in_b0d; +layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +layout(location = 4) uniform bool ink; +layout(location = 8) uniform vec4 smoke_color; +layout(location = 9) uniform vec4 decor_color; +layout(location = 10) uniform int regionInfo[20]; + + +const float K = 1000.0; +const float v = 0.0000000000005; // Viscosity +const vec2 Step = vec2(0.005, 0.005); // Texture step for resolution +const vec4 ExternalForces = vec4(-0.0, 0.0, 10.0, 0.0); +const float dt = -0.2; // Constant small time step + +bool IsBoundary(vec2 UV) { + // Implement your boundary condition check here + return false; +} + +float rand(vec2 uv) { + return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453); +} + + +void run_pixel(int x, int y) +{ + + + ivec2 coords = ivec2(x, y); + vec2 UV = (vec2(coords) + 0.5) / vec2(imageSize(in_b0d)); + + + + float CScale = 1.0 / 2.0; + float S = K / dt; + + vec4 FC = imageLoad(in_b0d, ivec2(x, y)); + vec4 FR = imageLoad(in_b0d, ivec2(x + 1, y)); + vec4 FL = imageLoad(in_b0d, ivec2(x - 1, y)); + vec4 FT = imageLoad(in_b0d, ivec2(x, y + 1)); + vec4 FD = imageLoad(in_b0d, ivec2(x, y - 1)); + + + mat4 FieldMat = mat4(FR, FL, FT, FD); + // du/dx, du/dy + vec3 UdX = (FieldMat[0].xyz - FieldMat[1].xyz) * CScale; + vec3 UdY = (FieldMat[2].xyz - FieldMat[3].xyz) * CScale; + float Udiv = UdX.x + UdY.y; + vec2 DdX = vec2(UdX.z, UdY.z); + // Solve for density. + FC.z -= dt * dot(vec3(DdX, Udiv), FC.xyz); + // Related to stability. + FC.z = clamp(FC.z, 0.5, 3.0); + // Solve for Velocity. + vec2 PdX = S * DdX; + vec2 Laplacian = vec2(1.0) * dot(vec4(1.0), vec4(FieldMat)) - 4.0 * FC.xy; + vec2 ViscosityForce = v * Laplacian; + // Semi-lagrangian advection. + // Assuming you want to change the direction along the x-axis: +// Adjust the texture coordinates accordingly to change the direction of advection + +// Update the texture coordinates for advection +vec2 Was = UV - dt * FC.xy * Step; + +// Modify the texture coordinates based on the desired direction +// For example, to change the direction along the y-axis: + Was.y = UV.y - dt * FC.y * Step.y; +Was.x = UV.x + dt * FC.x * Step.x; +// Convert Was to texture coordinates +Was = Was * vec2(imageSize(in_b0u)); + +// Sample the velocity texture using the updated coordinates +vec2 newVelocity = imageLoad(in_b0u, ivec2(Was)).xy; + +// Update FC.xy with the new velocity +FC.xy = newVelocity; + + + FC.xy = imageLoad(in_b0u, ivec2(Was)).xy; + FC.xy += dt * (ViscosityForce - PdX + ExternalForces.xy); + + // Output + // imageStore(out_tex, coords, FC* 1.0); + +// Calculate the density value +float density = FC.x; + +// Define a threshold to determine the blend factor +float threshold = 0.02; + + +//vec4 blendedColor = mix(vec4(1.0,0.0,0.0,FC*-10.0), vec4(0.0,0.0,0.0,FC*1.0), smoothstep(0.0, 1.0, density / threshold)); + +// Blend between the two colors based on the density value +//vec4 blendedColor = mix(vec4(1.0,0.0,0.0,FC*-10.0), vec4(1.0,1.0,1.0,FC*1.0), smoothstep(0.0, 1.0, density / threshold)); +//vec4 blendedColor = mix(vec4(1.0,1.0,1.0,FC*-10.0), vec4(0.0,0.0,0.0,FC*1.0), smoothstep(0.0, 1.0, density / threshold)); + + + // Inside the pixel processing loop + vec2 seed = vec2(34.0, 78.0); // Initial seed values + + // Inside the pixel processing loop + vec2 seed2 = vec2(14.0, 98.0); // Initial seed values + // Inside the pixel processing loop + vec2 seed3 = vec2(49.0, 178.0); // Initial seed values + + +// Generate pseudo-random numbers based on the pixel coordinates (x, y) +float randomValueR = rand(UV + seed); +float randomValueG = rand(UV + 2.0 * seed2); // Use a different seed for green to ensure variety +float randomValueB = rand(UV + 3.0 * seed3); // Use another different seed for blue + +// Create a random color using the random values for each component +vec4 randomColor = vec4(randomValueR, randomValueG, randomValueB, smoothstep(0.0, 1.0, density / threshold)); + + // Add the random color to the smoke color + vec4 smokeWithRandomColor = smoke_color; + + + + +vec4 blendedColor = mix(vec4(vec4(smokeWithRandomColor.r*.5,smokeWithRandomColor.g*.5,smokeWithRandomColor.b*-0.5,FC*-10.0)), vec4(smokeWithRandomColor.r,smokeWithRandomColor.g,smokeWithRandomColor.b,FC*1.0), smoothstep(0.0, 1.0, density / threshold)); + +// Output the blended color +//imageStore(out_tex, coords, blendedColor); + +// Blend the decor color with the blended smoke color +vec4 finalColor = mix(decor_color, blendedColor, blendedColor.a); + +// Output the final color +imageStore(out_tex, coords, finalColor); +})"; + + + + +/*/////////////////////////////////////////////// + _____ + / ____| + | (___ + fast \ ___ \ moke + ____) | + |_____/ + +*//////////////////////////////////////////////// + +static const char *fast_smoke_motion_source = + R"( +#version 320 es + +precision lowp image2D; + +layout (binding = 1, r32f) uniform readonly image2D in_b0u; +layout (binding = 1, r32f) uniform writeonly image2D out_b0u; +layout (binding = 2, r32f) uniform readonly image2D in_b0v; +layout (binding = 2, r32f) uniform writeonly image2D out_b0v; +layout (binding = 3, r32f) uniform readonly image2D in_b0d; +layout (binding = 3, r32f) uniform writeonly image2D out_b0d; +layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(location = 1) uniform int title_height; +layout(location = 2) uniform int border_size; +layout(location = 3) uniform int px; +layout(location = 4) uniform int py; +layout(location = 5) uniform int width; +layout(location = 6) uniform int height; +layout(location = 7) uniform int rand1; +layout(location = 8) uniform int rand2; +layout(location = 9) uniform int radius; + +void motion(int x, int y) +{ + int i, i0, i1, j, j0, j1, d = 2; + + if (x - d < 1) + i0 = 1; + else + i0 = x - d; + if (i0 + 2 * d > width - 1) + i1 = width - 1; + else + i1 = i0 + 2 * d; + + if (y - d < 1) + j0 = 1; + else + j0 = y - d; + if (j0 + 2 * d > height - 1) + j1 = height - 1; + else + j1 = j0 + 2 * d; + + for (i = i0; i < i1; i++) + { + for (j = j0; j < j1; j++) { + if (i < radius || j < radius || i > (width - 1) - radius || j > (height - 1) - radius || (i > border_size && i < (width - 1) - border_size && j > (title_height - 1) && j < (height - 1) - border_size)) + { + continue; + } + vec4 b0u = imageLoad(in_b0u, ivec2(i, j)); + vec4 b0v = imageLoad(in_b0u, ivec2(i, j)); + vec4 b0d = imageLoad(in_b0u, ivec2(i, j)); + float u = b0u.x; + float v = b0v.x; + float d = b0d.x; + imageStore(out_b0u, ivec2(i, j), vec4(u + float(256*1 - (rand1 & 512*1)), 0.0, 0.0, 0.0)); + imageStore(out_b0v, ivec2(i, j), vec4(v + float(256*1 - (rand2 & 512*1)), 0.0, 0.0, 0.0)); + // imageStore(out_b0d, ivec2(i, j), vec4(0.0, 0.0, 0.0, 0.0)); + } + } + } + +void main() +{ + motion(px, py); +} +)"; + +static const char *fast_smoke_diffuse1_source = + R"( +void run_pixel(int x, int y) +{ + int k; + float t = 0.0002; + float a = 0.002; + vec4 s = imageLoad(in_b0u, ivec2(x, y)); + vec4 d1 = imageLoad(in_b1u, ivec2(x - 1, y)); + vec4 d2 = imageLoad(in_b1u, ivec2(x + 1, y)); + vec4 d3 = imageLoad(in_b1u, ivec2(x, y - 1)); + vec4 d4 = imageLoad(in_b1u, ivec2(x, y + 1)); + float sx = s.x; + float du1 = d1.x; + float du2 = d2.x; + float du3 = d3.x; + float du4 = d4.x; + float t1 = du1 + du2 + du3 + du4; + s = imageLoad(in_b0v, ivec2(x, y)); + d1 = imageLoad(in_b1v, ivec2(x - 1, y)); + d2 = imageLoad(in_b1v, ivec2(x + 1, y)); + d3 = imageLoad(in_b1v, ivec2(x, y - 1)); + d4 = imageLoad(in_b1v, ivec2(x, y + 1)); + float sy = s.x; + du1 = d1.x; + du2 = d2.x; + du3 = d3.x; + du4 = d4.x; + float t2 = du1 + du2 + du3 + du4; + imageStore(out_b1u, ivec2(x, y), vec4((sx + a * t1) / (1.0 + 4.0 * a) * 0.9999999999999999999999999999999999999999995, 0.0, 0.0, 0.0)); + imageStore(out_b1v, ivec2(x, y), vec4((sy + a * t2) / (1.0 + 4.0 * a) * 0.9999999999999999999999999999999999999999995, 0.0, 0.0, 0.0)); + + +} +)"; + +static const char *fast_smoke_project1_source = + R"( +void run_pixel(int x, int y) { + int k, l, s; + float h; + + h = 1.0 / float(width); +// s = width; + + vec4 s1 = imageLoad(in_b1u, ivec2(x - 1, y)); + vec4 s2 = imageLoad(in_b1u, ivec2(x + 1, y)); + vec4 s3 = imageLoad(in_b1v, ivec2(x, y - 1)); + vec4 s4 = imageLoad(in_b1v, ivec2(x, y + 1)); + float u1 = s1.x; + float u2 = s2.x; + float v1 = s3.x; + float v2 = s4.x; + imageStore(out_b0u, ivec2(x, y), vec4(0.0, 0.0, 0.0, 0.0)); + imageStore(out_b0v, ivec2(x, y), vec4(-0.5 * h * (u2 - u1 + v2 - v1), 0.0, 0.0, 0.0)); +} +)"; + +static const char *fast_smoke_project2_source = + R"( +void run_pixel(int x, int y) +{ + int k, l, s; + float h; + + h = 1.0 / float(width); + s = width; + + vec4 s0 = imageLoad(in_b0v, ivec2(x, y)); + vec4 s1 = imageLoad(in_b0u, ivec2(x - 1, y)); + vec4 s2 = imageLoad(in_b0u, ivec2(x + 1, y)); + vec4 s3 = imageLoad(in_b0u, ivec2(x, y - 1)); + vec4 s4 = imageLoad(in_b0u, ivec2(x, y + 1)); + float u1 = s1.x; + float u2 = s2.x; + float u3 = s3.x; + float u4 = s4.x; + + imageStore(out_b0u, ivec2(x, y), vec4((s0.x + u1 + u2 + u3 + u4) / 4.0, 0.0, 0.0, 0.0)); +})"; + +static const char *fast_smoke_project3_source = + R"( +void run_pixel(int x, int y) +{ + int k, l, s; + float h; + + h = 1.0 / float(width); + s = width; + + vec4 s0x = imageLoad(in_b1u, ivec2(x, y)); + vec4 s1 = imageLoad(in_b0u, ivec2(x - 1, y)); + vec4 s2 = imageLoad(in_b0u, ivec2(x + 1, y)); + vec4 s0y = imageLoad(in_b1v, ivec2(x, y)); + vec4 s3 = imageLoad(in_b0u, ivec2(x, y - 1)); + vec4 s4 = imageLoad(in_b0u, ivec2(x, y + 1)); + float su = s0x.x; + float u1 = s1.x; + float u2 = s2.x; + float sv = s0y.x; + float u3 = s3.x; + float u4 = s4.x; + imageStore(out_b1u, ivec2(x, y), vec4(su - 0.5 * (u2 - u1) / h, 0.0, 0.0, 0.0)); + imageStore(out_b1v, ivec2(x, y), vec4(sv - 0.5 * (u4 - u3) / h, 0.0, 0.0, 0.0)); +})"; + +static const char *fast_smoke_advect1_source = + R"( + +void run_pixel(int x, int y) /* b1.u, b1.v, b1.u, b0.u */ +{ + int stride; + int i, j; + float fx, fy; + stride = width; + + vec4 sx = imageLoad(in_b1u, ivec2(x, y)); + vec4 sy = imageLoad(in_b1v, ivec2(x, y)); + float ix = float(x) - sx.x; + float iy = float(y) - sy.x; + + + ix = clamp(ix, 0.5, float(width) - 1.5); + iy = clamp(iy, 0.5, float(height) - 1.5); + + i = int(ix); + j = int(iy); + fx = ix - float(i); + fy = iy - float(j); + + // Process u component + vec4 s0x = imageLoad(in_b1u, ivec2(i, j)); + vec4 s1x = imageLoad(in_b1u, ivec2(i + 1, j)); + vec4 s2x = imageLoad(in_b1u, ivec2(i, j + 1)); + vec4 s3x = imageLoad(in_b1u, ivec2(i + 1, j + 1)); + float p1 = (s0x.x * (1.0 - fx) + s1x.x * fx) * (1.0 - fy) + (s2x.x * (1.0 - fx) + s3x.x * fx) * fy; + imageStore(out_b0u, ivec2(x, y), vec4(p1, 0.0, 0.0, 0.0)); + + ix = float(x) - sx.x; + iy = float(y) - sy.x; + + ix = clamp(ix, 0.5, float(width) - 1.5); + iy = clamp(iy, 0.5, float(height) - 1.5); + + i = int(ix); + j = int(iy); + fx = ix - float(i); + fy = iy - float(j); + + // Process v component + vec4 s0y = imageLoad(in_b1v, ivec2(i, j)); + vec4 s1y = imageLoad(in_b1v, ivec2(i + 1, j)); + vec4 s2y = imageLoad(in_b1v, ivec2(i, j + 1)); + vec4 s3y = imageLoad(in_b1v, ivec2(i + 1, j + 1)); + float p2 = (s0y.x * (1.0 - fx) + s1y.x * fx) * (1.0 - fy) + (s2y.x * (1.0 - fx) + s3y.x * fx) * fy; + imageStore(out_b0v, ivec2(x, y), vec4(p2, 0.0, 0.0, 0.0)); +})"; + +static const char *fast_smoke_project4_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *fast_smoke_project5_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *fast_smoke_project6_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *fast_smoke_diffuse2_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *fast_smoke_advect2_source = + R"( +void run_pixel(int x, int y) +{ + +})"; + +//math from https://inria.hal.science/inria-00596050/document +static const char *fast_smoke_render_source = + R"( +#version 320 es + +precision lowp image2D; + +layout (binding = 0, rgba32f) uniform writeonly image2D out_tex; +layout (binding = 1, r32f) uniform readonly image2D in_b0u; +layout (binding = 3, r32f) uniform readonly image2D in_b0d; +layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +layout(location = 4) uniform bool ink; +layout(location = 8) uniform vec4 smoke_color; +layout(location = 9) uniform vec4 decor_color; +layout(location = 10) uniform int regionInfo[20]; + + +const float K = 1.0; +const float v = 0.0005; // Viscosity +const vec2 Step = vec2(0.005, 0.005); // Texture step for resolution +const vec4 ExternalForces = vec4(-0.0, 0.0, 10.0, 0.0); +const float dt = 0.2; // Constant small time step +const float k = 0.1; // Or replace with the appropriate diffusion coefficient value + + +bool IsBoundary(vec2 UV) { + // Implement your boundary condition check here + return false; +} + + +void run_pixel(int x, int y) +{ + + + ivec2 coords = ivec2(x, y); + vec2 UV = (vec2(coords) + 0.5) / vec2(imageSize(in_b0d)); + + + float CScale = 1.0 / 2.0; + float S = K / dt; + + vec4 FC = imageLoad(in_b0d, ivec2(x, y)); + vec4 FR = imageLoad(in_b0d, ivec2(x + 1, y)); + vec4 FL = imageLoad(in_b0d, ivec2(x - 1, y)); + vec4 FT = imageLoad(in_b0d, ivec2(x, y + 1)); + vec4 FD = imageLoad(in_b0d, ivec2(x, y - 1)); + + + mat4 FieldMat = mat4(FR, FL, FT, FD); + // du/dx, du/dy + vec3 UdX = (FieldMat[0].xyz - FieldMat[1].xyz) * CScale; + vec3 UdY = (FieldMat[2].xyz - FieldMat[3].xyz) * CScale; + float Udiv = UdX.x + UdY.y; + vec2 DdX = vec2(UdX.z, UdY.z); + // Solve for density. + FC.z -= dt * dot(vec3(DdX, Udiv), FC.xyz); + // Related to stability. + FC.z = clamp(FC.z, 0.5, 3.0); + // Solve for Velocity. + vec2 PdX = S * DdX; + vec2 Laplacian = vec2(1.0) * dot(vec4(0.0), vec4(FieldMat)) - 4000000.0 * FC.xy; + vec2 ViscosityForce = v * Laplacian; + // Semi-lagrangian advection. + // Assuming you want to change the direction along the x-axis: +// Adjust the texture coordinates accordingly to change the direction of advection + +// Update the texture coordinates for advection +vec2 Was = UV - dt * FC.xy * Step; + +// Modify the texture coordinates based on the desired direction +// For example, to change the direction along the y-axis: +// Was.y = UV.y - dt * FC.y * Step.y; +//Was.x = UV.x + dt * FC.x * Step.x; +// Convert Was to texture coordinates +Was = Was * vec2(imageSize(in_b0u)); + +// Sample the velocity texture using the updated coordinates +vec2 newVelocity = imageLoad(in_b0u, ivec2(Was)).xy; + +// Update FC.xy with the new velocity +FC.xy = newVelocity; + + + FC.xy = imageLoad(in_b0u, ivec2(Was)).xy; + FC.xy += dt * (ViscosityForce - PdX + ExternalForces.xy); + + // Output + // imageStore(out_tex, coords, FC* 1.0); + +// Calculate the density value +float density = FC.x; + +// Define a threshold to determine the blend factor +float threshold = 0.02; + + + /// Semi-Lagrangian advection +vec2 advectionOffset = newVelocity * dt; +vec2 advectedCoords = UV - advectionOffset; +advectedCoords = clamp(advectedCoords, vec2(0.0), vec2(1.0)); + +// Convert the floating-point texture coordinates to integer indices +ivec2 texCoords = ivec2(clamp(advectedCoords * vec2(imageSize(in_b0u)), vec2(0.0), vec2(imageSize(in_b0u)) - 1.0)); + +// Sample the velocity texture using the updated integer indices + newVelocity = imageLoad(in_b0u, texCoords).xy; + + + + +UdX = (FR.xyz - FL.xyz) * (1.0 / 2.0); + UdY = (FT.xyz - FD.xyz) * (1.0 / 2.0); +Udiv = UdX.x - UdX.y + UdY.x - UdY.y; // Divergence of the velocity field + +float laplacian = dot(vec4(1.0), vec4(FC.z, FC.z, FC.z, FC.z)) - 4.0 * FC.z; +FC.z += dt * k * laplacian; + + + // FC.xy = newVelocity; + + + // Calculate the final density value + density = FC.x; + + + + +vec4 blendedColor = mix(vec4(smoke_color.r,smoke_color.g,smoke_color.b,FC*-10.0), vec4(smoke_color.r,smoke_color.g,smoke_color.b,FC*10.0), smoothstep(0.0, 1.0, density*FC.z*10.0 / threshold)); + +//vec4 blendedColor = mix(vec4(smoke_color.r,smoke_color.g,smoke_color.b,FC*-10.0), vec4(smoke_color.r,smoke_color.g,smoke_color.b,1.0), smoothstep(0.0, 1.0, density*FC.z / threshold)); + + + + + +// Output the blended color +//imageStore(out_tex, coords, blendedColor); + +// Blend the decor color with the blended smoke color +vec4 finalColor = mix(decor_color, blendedColor, blendedColor.a); + + + // Apply threshold and blend colors +// blendedColor = mix(vec4(smoke_color.r, smoke_color.g, smoke_color.b, FC.z * -10.0), vec4(smoke_color.r, smoke_color.g, smoke_color.b, FC.z * 1.0), smoothstep(0.0, 1.0, density / threshold)); + + + +// Output the final color +imageStore(out_tex, coords, finalColor); +})"; + + + +/*/////////////////////////////////////////////// + ______ _ ____ ______ + | ____|| | | __ \ | ____| + | |__ | | | |__\ | | |____ + | __| | | | ___ | | ____| + | | | | | | \ \ | |____ + |_| |_| |_| |_| |______| + +*//////////////////////////////////////////////// + + +static const char *flame_motion_source = + R"( +#version 320 es + +precision lowp image2D; + +layout (binding = 1, r32f) uniform readonly image2D in_b0u; +layout (binding = 1, r32f) uniform writeonly image2D out_b0u; +layout (binding = 2, r32f) uniform readonly image2D in_b0v; +layout (binding = 2, r32f) uniform writeonly image2D out_b0v; +layout (binding = 3, r32f) uniform readonly image2D in_b0d; +layout (binding = 3, r32f) uniform writeonly image2D out_b0d; +layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in; + +layout(location = 1) uniform int title_height; +layout(location = 2) uniform int border_size; +layout(location = 3) uniform int px; +layout(location = 4) uniform int py; +layout(location = 5) uniform int width; +layout(location = 6) uniform int height; +layout(location = 7) uniform int rand1; +layout(location = 8) uniform int rand2; +layout(location = 9) uniform int radius; + +void motion(int x, int y) +{ + int i, i0, i1, j, j0, j1, d = 2; + + if (x - d < 1) + i0 = 1; + else + i0 = x - d; + if (i0 + 2 * d > width - 1) + i1 = width - 1; + else + i1 = i0 + 2 * d; + + if (y - d < 1) + j0 = 1; + else + j0 = y - d; + if (j0 + 2 * d > height - 1) + j1 = height - 1; + else + j1 = j0 + 2 * d; + + for (i = i0; i < i1; i++) + { + for (j = j0; j < j1; j++) { + if (i < radius || j < radius || i > (width - 1) - radius || j > (height - 1) - radius || (i > border_size && i < (width - 1) - border_size && j > (title_height - 1) && j < (height - 1) - border_size)) + { + continue; + } + vec4 b0u = imageLoad(in_b0u, ivec2(i, j)); + vec4 b0v = imageLoad(in_b0u, ivec2(i, j)); + vec4 b0d = imageLoad(in_b0u, ivec2(i, j)); + float u = b0u.x; + float v = b0v.x; + float d = b0d.x; + imageStore(out_b0u, ivec2(i, j), vec4(u + float(256*4 - (rand1 & 512*4)), 0.0, 0.0, 0.0)); + imageStore(out_b0v, ivec2(i, j), vec4(v + float(256*4 - (rand2 & 512*4)), 0.0, 0.0, 0.0)); + // imageStore(out_b0d, ivec2(i, j), vec4(0.0, 0.0, 0.0, 0.0)); + } + } + } + +void main() +{ + motion(px, py); +} +)"; + +static const char *flame_diffuse1_source = + R"( +void run_pixel(int x, int y) +{ + int k; + float t = 0.0002; + float a = 0.002; + vec4 s = imageLoad(in_b0u, ivec2(x, y)); + vec4 d1 = imageLoad(in_b1u, ivec2(x - 1, y)); + vec4 d2 = imageLoad(in_b1u, ivec2(x + 1, y)); + vec4 d3 = imageLoad(in_b1u, ivec2(x, y - 1)); + vec4 d4 = imageLoad(in_b1u, ivec2(x, y + 1)); + float sx = s.x; + float du1 = d1.x; + float du2 = d2.x; + float du3 = d3.x; + float du4 = d4.x; + float t1 = du1 + du2 + du3 + du4; + s = imageLoad(in_b0v, ivec2(x, y)); + d1 = imageLoad(in_b1v, ivec2(x - 1, y)); + d2 = imageLoad(in_b1v, ivec2(x + 1, y)); + d3 = imageLoad(in_b1v, ivec2(x, y - 1)); + d4 = imageLoad(in_b1v, ivec2(x, y + 1)); + float sy = s.x; + du1 = d1.x; + du2 = d2.x; + du3 = d3.x; + du4 = d4.x; + float t2 = du1 + du2 + du3 + du4; + imageStore(out_b1u, ivec2(x, y), vec4((sx + a * t1) / (1.0 + 4.0 * a) * 0.9999999999999999999999999999999999999999995, 0.0, 0.0, 0.0)); + imageStore(out_b1v, ivec2(x, y), vec4((sy + a * t2) / (1.0 + 4.0 * a) * 0.9999999999999999999999999999999999999999995, 0.0, 0.0, 0.0)); + + +} +)"; + +static const char *flame_project1_source = + R"( +void run_pixel(int x, int y) { + int k, l, s; + float h; + + h = 1.0 / float(width); +// s = width; + + vec4 s1 = imageLoad(in_b1u, ivec2(x - 1, y)); + vec4 s2 = imageLoad(in_b1u, ivec2(x + 1, y)); + vec4 s3 = imageLoad(in_b1v, ivec2(x, y - 1)); + vec4 s4 = imageLoad(in_b1v, ivec2(x, y + 1)); + float u1 = s1.x; + float u2 = s2.x; + float v1 = s3.x; + float v2 = s4.x; + imageStore(out_b0u, ivec2(x, y), vec4(0.0, 0.0, 0.0, 0.0)); + imageStore(out_b0v, ivec2(x, y), vec4(-0.5 * h * (u2 - u1 + v2 - v1), 0.0, 0.0, 0.0)); +} +)"; + +static const char *flame_project2_source = + R"( +void run_pixel(int x, int y) +{ + int k, l, s; + float h; + + h = 1.0 / float(width); + s = width; + + vec4 s0 = imageLoad(in_b0v, ivec2(x, y)); + vec4 s1 = imageLoad(in_b0u, ivec2(x - 1, y)); + vec4 s2 = imageLoad(in_b0u, ivec2(x + 1, y)); + vec4 s3 = imageLoad(in_b0u, ivec2(x, y - 1)); + vec4 s4 = imageLoad(in_b0u, ivec2(x, y + 1)); + float u1 = s1.x; + float u2 = s2.x; + float u3 = s3.x; + float u4 = s4.x; + + imageStore(out_b0u, ivec2(x, y), vec4((s0.x + u1 + u2 + u3 + u4) / 4.0, 0.0, 0.0, 0.0)); +})"; + +static const char *flame_project3_source = + R"( +void run_pixel(int x, int y) +{ + int k, l, s; + float h; + + h = 1.0 / float(width); + s = width; + + vec4 s0x = imageLoad(in_b1u, ivec2(x, y)); + vec4 s1 = imageLoad(in_b0u, ivec2(x - 1, y)); + vec4 s2 = imageLoad(in_b0u, ivec2(x + 1, y)); + vec4 s0y = imageLoad(in_b1v, ivec2(x, y)); + vec4 s3 = imageLoad(in_b0u, ivec2(x, y - 1)); + vec4 s4 = imageLoad(in_b0u, ivec2(x, y + 1)); + float su = s0x.x; + float u1 = s1.x; + float u2 = s2.x; + float sv = s0y.x; + float u3 = s3.x; + float u4 = s4.x; + imageStore(out_b1u, ivec2(x, y), vec4(su - 0.5 * (u2 - u1) / h, 0.0, 0.0, 0.0)); + imageStore(out_b1v, ivec2(x, y), vec4(sv - 0.5 * (u4 - u3) / h, 0.0, 0.0, 0.0)); +})"; + +static const char *flame_advect1_source = + R"( + +void run_pixel(int x, int y) /* b1.u, b1.v, b1.u, b0.u */ +{ + int stride; + int i, j; + float fx, fy; + stride = width; + + vec4 sx = imageLoad(in_b1u, ivec2(x, y)); + vec4 sy = imageLoad(in_b1v, ivec2(x, y)); + float ix = float(x) - sx.x; + float iy = float(y) - sy.x; + + + ix = clamp(ix, 0.5, float(width) - 1.5); + iy = clamp(iy, 0.5, float(height) - 1.5); + + i = int(ix); + j = int(iy); + fx = ix - float(i); + fy = iy - float(j); + + // Process u component + vec4 s0x = imageLoad(in_b1u, ivec2(i, j)); + vec4 s1x = imageLoad(in_b1u, ivec2(i + 1, j)); + vec4 s2x = imageLoad(in_b1u, ivec2(i, j + 1)); + vec4 s3x = imageLoad(in_b1u, ivec2(i + 1, j + 1)); + float p1 = (s0x.x * (1.0 - fx) + s1x.x * fx) * (1.0 - fy) + (s2x.x * (1.0 - fx) + s3x.x * fx) * fy; + imageStore(out_b0u, ivec2(x, y), vec4(p1, 0.0, 0.0, 0.0)); + + ix = float(x) - sx.x; + iy = float(y) - sy.x; + + ix = clamp(ix, 0.5, float(width) - 1.5); + iy = clamp(iy, 0.5, float(height) - 1.5); + + i = int(ix); + j = int(iy); + fx = ix - float(i); + fy = iy - float(j); + + // Process v component + vec4 s0y = imageLoad(in_b1v, ivec2(i, j)); + vec4 s1y = imageLoad(in_b1v, ivec2(i + 1, j)); + vec4 s2y = imageLoad(in_b1v, ivec2(i, j + 1)); + vec4 s3y = imageLoad(in_b1v, ivec2(i + 1, j + 1)); + float p2 = (s0y.x * (1.0 - fx) + s1y.x * fx) * (1.0 - fy) + (s2y.x * (1.0 - fx) + s3y.x * fx) * fy; + imageStore(out_b0v, ivec2(x, y), vec4(p2, 0.0, 0.0, 0.0)); +})"; + +static const char *flame_project4_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *flame_project5_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *flame_project6_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *flame_diffuse2_source = + R"( +void run_pixel(int x, int y) +{ +})"; + +static const char *flame_advect2_source = + R"( +void run_pixel(int x, int y) +{ + +})"; + +static const char *flame_render_source = +R"( +#version 320 es + +precision lowp image2D; + +layout (binding = 0, rgba32f) uniform writeonly image2D out_tex; +layout (binding = 1, r32f) uniform readonly image2D in_b0u; +layout (binding = 3, r32f) uniform readonly image2D in_b0d; +layout (local_size_x = 16, local_size_y = 16, local_size_z = 1) in; + +layout(location = 4) uniform bool ink; +layout(location = 8) uniform vec4 smoke_color; +layout(location = 9) uniform vec4 decor_color; +layout(location = 10) uniform int regionInfo[20]; + +const float K = 10000.0; +const float v = 0.0000000000005; // Viscosity +const vec2 Step = vec2(0.5, 0.5); // Texture step for resolution +const vec4 ExternalForces = vec4(-0.0, 0.0, 10.0, 0.0); +const float dt = -0.2; // Constant small time step + +bool IsBoundary(vec2 UV) { + // Implement your boundary condition check here + return false; +} + +float rand(vec2 uv) { + return fract(sin(dot(uv, vec2(12.9898, 78.233))) * 43758.5453); +} + +void run_pixel(int x, int y) +{ + ivec2 coords = ivec2(x, y); + + // Calculate UV coordinates + vec2 UV = (vec2(coords) + 0.5) / vec2(imageSize(in_b0d)); + + // Load neighboring pixels + vec4 FR = imageLoad(in_b0d, coords + ivec2(1, 0)); + vec4 FL = imageLoad(in_b0d, coords + ivec2(-1, 0)); + vec4 FT = imageLoad(in_b0d, coords + ivec2(0, 1)); + vec4 FD = imageLoad(in_b0d, coords + ivec2(0, -1)); + + // Calculate gradients + vec3 UdX = (FR.xyz - FL.xyz) * 0.5; + vec3 UdY = (FT.xyz - FD.xyz) * 0.5; + float Udiv = UdX.x + UdY.y; + vec2 DdX = vec2(UdX.z, UdY.z); + + // Update density + vec4 FC = imageLoad(in_b0d, coords); + FC.z -= dt * dot(vec3(DdX, Udiv), FC.xyz) + K * dot(DdX, DdX) - 5.0; // Updated density equation + FC.z = clamp(FC.z, 0.5, 3.0); + + // Update velocity + vec2 Was = UV - dt * FC.xy * Step; + Was.y = UV.y - dt * FC.y * Step.y; + Was.x = UV.x + dt * FC.x * Step.x; + Was = Was * vec2(imageSize(in_b0u)); + vec2 newVelocity = imageLoad(in_b0u, ivec2(Was)).xy; + FC.xy = newVelocity; + FC.xy += dt * (v * ((FR.x + FL.x + FT.x + FD.x) / 100.0) - DdX ); + + // Calculate density value + float density = FC.x; + + // Calculate blended color + vec4 blendedColor = mix(vec4(0.5 * FC.x, 0.05 * FC.x, -0.05 * FC.x, -10.0 * FC.x), vec4(0.1 * FC.x,0.1 * FC.x,0.5 * FC.x, FC.x), smoothstep(0.0, 1.0, density / 10.02)); + + // Blend decor color with smoke color +// vec4 finalColor = mix(decor_color, blendedColor, blendedColor.a * -FC.z*10.0); + vec4 finalColor = mix(vec4(0.0,0.0,0.0,1.0), blendedColor, blendedColor.a * -FC.z*10.0); + // Output the final color + imageStore(out_tex, coords, finalColor); +} +)";