diff --git a/ScreenPlayShader/CMakeLists.txt b/ScreenPlayShader/CMakeLists.txt index 5a694c1a..8f103a62 100644 --- a/ScreenPlayShader/CMakeLists.txt +++ b/ScreenPlayShader/CMakeLists.txt @@ -12,7 +12,11 @@ find_package( COMPONENTS Quick Core ShaderTools REQUIRED) -set(QML src/ShadertoyShader.qml src/TestMain.qml) +set(QML src/ShadertoyShader.qml + src/Beam.qml + src/Wobble.qml + src/Flowmap.qml + src/TestMain.qml) set(QML_PLUGIN_SOURCES src/shaderlibrary.cpp) @@ -22,11 +26,17 @@ set(SHADER shaders/lightning.vert shaders/lightning.frag shaders/wobble.frag + shaders/evnergy_beam.frag + shaders/flowmap.frag shaders/water.frag shaders/water.vert) set(RESOURCES assets/mask_01.png + assets/flowmap.png + assets/water_normal.png + assets/lava.png + assets/displace.png assets/Shadertoy_Bayer.png assets/Shadertoy_Gray_Noise_Medium.png assets/Shadertoy_Lichen.jpg diff --git a/ScreenPlayShader/assets/displace.png b/ScreenPlayShader/assets/displace.png new file mode 100644 index 00000000..70efeed7 Binary files /dev/null and b/ScreenPlayShader/assets/displace.png differ diff --git a/ScreenPlayShader/assets/flowmap.png b/ScreenPlayShader/assets/flowmap.png new file mode 100644 index 00000000..7add4312 Binary files /dev/null and b/ScreenPlayShader/assets/flowmap.png differ diff --git a/ScreenPlayShader/assets/lava.png b/ScreenPlayShader/assets/lava.png new file mode 100644 index 00000000..63544c26 Binary files /dev/null and b/ScreenPlayShader/assets/lava.png differ diff --git a/ScreenPlayShader/assets/water_normal.png b/ScreenPlayShader/assets/water_normal.png new file mode 100644 index 00000000..bc45a1a0 Binary files /dev/null and b/ScreenPlayShader/assets/water_normal.png differ diff --git a/ScreenPlayShader/shaders/evnergy_beam.frag b/ScreenPlayShader/shaders/evnergy_beam.frag new file mode 100644 index 00000000..6282ef69 --- /dev/null +++ b/ScreenPlayShader/shaders/evnergy_beam.frag @@ -0,0 +1,125 @@ + + +/* +Shader from Godot Shaders - the free shader library. +godotshaders.com/shader/energy-beams + +This shader is under CC0 license. Feel free to use, improve and +change this shader according to your needs and consider sharing +the modified result to godotshaders.com. +*/ + +#version 440 + +layout(location = 0) in vec2 coord; +layout(location = 0) out vec4 fragColor; + + +layout(std140, binding = 0) uniform buf { + // MUST BE + mat4 qt_Matrix; + float qt_Opacity; + // INCLUDED HERE + + int beams; // How many beams the energy field should have + float time; + float energy; // How much the beams will travel up and down + int roughness; // How compact the noise texture will be + int frequency; // Amount of "ripples" in the beams + + float speed; // Animation speed + float thickness; // Thickness of the main beam + float outline_thickness ; //Thickness of the outline color + float beam_difference; // The thickness difference between the main beam and the other, if there are more than one beam. The closer to 1 the smaller the thickness difference. + float glow; // Use together with WorldEnvironment's Glow feature + float outline_glow ; + vec4 color ; + vec4 outline_color; + float progress; + float y_offset ; // Position of the beam + float fixed_edge_size; // How close to the edge should the beam be still before the animatino starts + vec2 noise_scale; // If the object (for example the ColorRect or Sprite node) is compressed use this to compensate for the noise texture being compressed. + +}; + +layout(binding = 1) uniform sampler2D source; + +float random(vec2 uv) { + return fract(sin(dot(uv.xy, + vec2(12.9898,78.233))) * + 43758.5453123); +} + +float noise(vec2 uv) { + vec2 uv_index = floor(uv); + vec2 uv_fract = fract(uv); + + // Four corners in 2D of a tile + float a = random(uv_index); + float b = random(uv_index + vec2(1.0, 0.0)); + float c = random(uv_index + vec2(0.0, 1.0)); + float d = random(uv_index + vec2(1.0, 1.0)); + + vec2 blur = smoothstep(0.0, 1.0, uv_fract); + + return mix(a, b, blur.x) + + (c - a) * blur.y * (1.0 - blur.x) + + (d - b) * blur.x * blur.y; +} + +float fbm(vec2 uv, float time) { + int octaves = roughness; + + float amp = 0.01 * energy * progress; + float freq = float(frequency); + float value = 0.0; + + for(int i = 0; i < octaves; i++) { + value += amp * noise(freq * vec2(uv.x, uv.y + time)); + amp *= 0.5; + freq *= 2.0; + } + return value; +} + +vec4 difference(vec4 base, vec4 blend){ + return abs(base - blend); +} + +vec4 bolt(vec2 uv, float time, float i) +{ + // Setup the beam locking to the edges. + float falloff = smoothstep(0.0, fixed_edge_size, uv.x) * smoothstep(0.0, fixed_edge_size, 1.0 - uv.x); + + // Use Fractal Brownian Motion to create a "cloud texture" and use Difference blend mode to make the beam + vec4 clouds = vec4(fbm((uv + vec2(i) ) * noise_scale, time * speed)) * falloff; + vec4 diff_clouds = difference(clouds, vec4(uv.y - 0.5 + y_offset + (uv.y * falloff * 0.02 * energy * progress))); + + // Create a new noise to mask the beams on low "progress" values. To make a "turn-off" effect more visually interesting. + vec4 clouds2 = vec4(fbm((uv * 2.0) * noise_scale, time * 1.)) * 5.0; + diff_clouds += smoothstep(0.0, 0.8, clouds2) * 0.1 * (1.-progress); + + // Set thickness of the beams. First beam is the Thickness size and all following beams are sized with beam_difference + float thickness2 = 1. - ( thickness / (min(i + beam_difference, 1.0) + (1.0-beam_difference))) * progress; + vec4 beam = clamp(smoothstep(thickness2, thickness2 + 0.005 * progress, 1.0 - diff_clouds), vec4(0.0), vec4(1.0)); + + //Set the beam outlines + vec4 beam_outline; + float outline = thickness2 - (outline_thickness * progress); + beam_outline = clamp(smoothstep(outline, outline + 0.04, 1.0 - diff_clouds), 0.0, 1.0); + beam_outline = clamp(beam_outline - beam, 0.0, 1.0); + + // Merge the beam and the outline and return to the fragment function + return (beam * (color + vec4(glow, glow, glow, 0.))) + (beam_outline * (outline_color + vec4(outline_glow, outline_glow, outline_glow, 0.))); +} + + +void main() +{ + vec4 beam = vec4(0.0); + for (int i = 0; i < beams; i++){ + beam = max(beam, bolt(coord, time, float(i))); + } +//vec4 tex = texture(source, coord); + fragColor = beam * qt_Opacity; +} diff --git a/ScreenPlayShader/shaders/flowmap.frag b/ScreenPlayShader/shaders/flowmap.frag new file mode 100644 index 00000000..f66136bc --- /dev/null +++ b/ScreenPlayShader/shaders/flowmap.frag @@ -0,0 +1,149 @@ +/* +Shader from Maujoe +https://github.com/Maujoe/godot-flow-map-shader/blob/master/assets/maujoe.flowmap_shader/shader/basic_flowmap_material.shader + +This shader is under the MIT license. +https://github.com/Maujoe/godot-flow-map-shader/blob/master/LICENSE.md +*/ + +#version 440 + + +layout(location = 0) in vec2 coord; // Godot: UV +layout(location = 0) out vec4 fragColor; + +layout(binding = 1) uniform sampler2D texture_albedo; +layout(binding = 2) uniform sampler2D texture_flow_noise; +layout(binding = 3) uniform sampler2D texture_flow_map; +layout(binding = 4) uniform sampler2D texture_normal; +layout(binding = 6) uniform sampler2D texture_refraction; +layout(binding = 7) uniform sampler2D texture_emission; +layout(binding = 8) uniform sampler2D texture_roughness; +layout(binding = 9) uniform sampler2D texture_metallic; + +layout(std140, binding = 0) uniform buf { + // MUST BE + mat4 qt_Matrix; + float qt_Opacity; + // INCLUDED HERE + + float time; + vec4 albedo; + float specular; + float metallic; + float roughness; + vec4 metallic_texture_channel; + vec4 roughness_texture_channel; + vec4 emission; + float emission_energy; + float refraction; + vec4 refraction_texture_channel; + vec2 uv_scale; + vec2 uv_offset; + float proximity_fade_distance; + float distance_fade_min; + float distance_fade_max; + + float normal_scale; + float flow_normal_influence; + + // Flow / Water uniforms + vec4 flow_map_x_channel; + vec4 flow_map_y_channel; + vec2 channel_flow_direction; + float blend_cycle; + float cycle_speed; + float flow_speed; + + vec4 noise_texture_channel; + vec2 flow_noise_size; + float flow_noise_influence; +} ; + + +void main() +{ + // coord flow calculation + /****************************************************************************************************/ + float half_cycle = blend_cycle * 0.5; + + // Use noise texture for offset to reduce pulsing effect + float offset = 10.0;//dot(texture(texture_flow_noise, coord * flow_noise_size), noise_texture_channel) * flow_noise_influence; + + float phase1 = mod(offset + time * cycle_speed, blend_cycle); + float phase2 = mod(offset + time * cycle_speed + half_cycle, blend_cycle); + vec4 flow_tex = texture(texture_flow_map, coord); + + vec2 flow; + flow.x = dot(flow_tex, flow_map_x_channel) * 2.0 - 1.0; + flow.y = dot(flow_tex, flow_map_y_channel) * 2.0 - 1.0; + flow *= normalize(channel_flow_direction); + + // Make flow incluence on the normalmap strenght adjustable (optional) + //float normal_influence = mix(1.0, dot(abs(flow), vec2(1.0, 1.0)) * 0.5, flow_normal_influence); + + // Blend factor to mix the two layers + float blend_factor = abs(half_cycle - phase1)/half_cycle; + // fragColor = flow_tex * blend_factor * 0.01 ; + // return; + // Offset by halfCycle to improve the animation for color (for normalmap not absolutely necessary) + phase1 -= half_cycle; + phase2 -= half_cycle; + + // Multiply with scale to make flow speed independent from the uv scaling + flow *= flow_speed * uv_scale; + + vec2 layer1 = flow * phase1 + coord; // coord == base_uv ? + vec2 layer2 = flow * phase2 + coord; + /****************************************************************************************************/ + +// Albedo +// Mix animated uv layers + vec4 albedo_tex = mix(texture(texture_albedo, layer1), texture(texture_albedo, layer2), blend_factor); + vec3 ALBEDO = albedo.rgb * albedo_tex.rgb; + + // Metallic / Roughness / Specular + // Mix animated uv layers + //float metallic_tex = mix(dot(texture(texture_metallic, layer1), metallic_texture_channel), dot(texture(texture_metallic, layer2), metallic_texture_channel), blend_factor); + //float METALLIC = metallic_tex * metallic; + //float roughness_tex = mix(dot(texture(texture_roughness, layer1), roughness_texture_channel), dot(texture(texture_roughness, layer2), roughness_texture_channel), blend_factor); + //float ROUGHNESS = roughness_tex * roughness; + //float SPECULAR = specular; + + //// Normalmap + //// Mix animated uv layers + //vec3 NORMALMAP = mix(texture(texture_normal, layer1), texture(texture_normal, layer2), blend_factor).rgb; + //float NORMALMAP_DEPTH = normal_scale * normal_influence; + //vec3 NORMAL = vec3(1,1,1);//?? + //vec3 TANGENT = vec3(1,1,1); //?? + //vec3 BINORMAL = vec3(1,1,1); //?? + //vec2 SCREEN_coord = vec2(1,1); // var screen_coord = get_viewport_transform() * (get_global_transform() * local_pos) + + // Refraction + //vec3 ref_normal = normalize(mix(NORMAL,TANGENT * NORMALMAP.x + BINORMAL * NORMALMAP.y + NORMAL * NORMALMAP.z,NORMALMAP_DEPTH)); + //// Mix animated uv layers + //vec4 ref_tex = mix(texture(texture_refraction, layer1), texture(texture_refraction, layer2), blend_factor); + //vec2 ref_ofs = SCREEN_coord - ref_normal.xy * dot(ref_tex, refraction_texture_channel) * refraction; + //float ref_amount = 1.0 - albedo.a * albedo_tex.a; + //ALBEDO *= 1.0 - ref_amount; + + // Emission + // Mix animated uv layers + //vec2 SCREEN_TEXTURE ; //?? + //vec3 emission_tex = mix(texture(texture_emission, layer1), texture(texture_emission, layer2), blend_factor).rgb; + //vec3 EMISSION = (emission.rgb + emission_tex) * emission_energy; + //EMISSION += textureLod(SCREEN_TEXTURE, ref_ofs, ROUGHNESS * 8.0).rgb * ref_amount; + + // Proximity fade / Distance fade + //float depth_tex = textureLod(DEPTH_TEXTURE,SCREEN_coord, 0.0).r; + //vec4 world_pos = INV_PROJECTION_MATRIX * vec4(SCREEN_coord * 2.0 - 1.0, depth_tex * 2.0 - 1.0, 1.0); + //world_pos.xyz /= world_pos.w; + //vec4 ALPHA = 1.0; + //ALPHA *= clamp(1.0 - smoothstep(world_pos.z + proximity_fade_distance, world_pos.z, VERTEX.z), 0.0, 1.0); + //ALPHA *= clamp(smoothstep(distance_fade_min,distance_fade_max,-VERTEX.z), 0.0, 1.0); + + + fragColor = vec4(ALBEDO,1.0); + //fragColor = texture(texture_albedo, layer1) ; + //fragColor = albedo_tex ; +} diff --git a/ScreenPlayShader/src/Beam.qml b/ScreenPlayShader/src/Beam.qml new file mode 100644 index 00000000..e433c26c --- /dev/null +++ b/ScreenPlayShader/src/Beam.qml @@ -0,0 +1,51 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Controls.Material +import ScreenPlayShader + +Rectangle { + id: img + layer.enabled: true + //source: "qrc:/qml/ScreenPlayShader/assets/test_image_andras-vas-Bd7gNnWJBkU-unsplash.jpg" + layer.effect: ShaderEffect { + property real framerate: 60 + property real updateInterval: Math.round((1000 / framerate) * 10) / 10 + property int beams: 2 // How many beams the energy field should have + property real time + + property real qt_Opacity: 1 + property real energy: 3.0 // How much the beams will travel up and down + property int roughness: 3 // How compact the noise texture will be + property int frequency: 10 // Amount of "ripples" in the beams + + property real speed: 1.0 // Animation speed + property real thickness: 0.006 // Thickness of the main beam + property real outline_thickness: 0.03 //Thickness of the outline color + property real beam_difference: 0.0 // The thickness difference between the main beam and the other, if there are more than one beam. The closer to 1 the smaller the thickness difference. + property real glow: 0.0 // Use together with WorldEnvironment's Glow feature + property real outline_glow: 0.0 + property vector4d color: Qt.vector4d(0.91, 1.0, 1.0, 1.0) + property vector4d outline_color: Qt.vector4d(0.5, 1.0, 0.96, 1.0) + property real progress: 1.0 + property real y_offset: 0.0 // Position of the beam + property real fixed_edge_size: 0.05 // How close to the edge should the beam be still before the animatino starts + property vector2d noise_scale: Qt.vector2d( + 1.0, + 1.0) // If the object (for example the ColorRect or Sprite node) is compressed use this to compensate for the noise texture being compressed. + + Timer { + interval: updateInterval + running: true + repeat: true + onTriggered: { + if (parent.time > 600) { + parent.time = 0 + } + parent.time += 1 + } + } + + fragmentShader: "/shaders/evnergy_beam.frag.qsb" + } +} diff --git a/ScreenPlayShader/src/Flowmap.qml b/ScreenPlayShader/src/Flowmap.qml new file mode 100644 index 00000000..8e645198 --- /dev/null +++ b/ScreenPlayShader/src/Flowmap.qml @@ -0,0 +1,123 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Controls.Material +import ScreenPlayShader + +Rectangle { + color: "gray" + + Image { + id: img_albedo + sourceSize: Qt.size(500,500) + source: "qrc:/qml/ScreenPlayShader/assets/lava.png" + visible: false + + } + Image { + id: img_flow_noise + visible: false + } + Image { + id: img_flow_map + sourceSize: Qt.size(500,500) + source: "qrc:/qml/ScreenPlayShader/assets/flowmap.png" + visible: false + } + Image { + id: img_normal + visible: false + } + Image { + id: img_refraction + visible: false + } + Image { + id: img_emission + visible: false + // source: "qrc:/qml/ScreenPlayShader/assets/test_image_andras-vas-Bd7gNnWJBkU-unsplash.jpg" + + } + Image { + id: img_roughness + visible: false + } + Image { + id: img_metallic + visible: false + } + + + Rectangle { + id: flowmap + width:500 + height:500 + //source: "qrc:/qml/ScreenPlayShader/assets/test_image_andras-vas-Bd7gNnWJBkU-unsplash.jpg" + layer.enabled: true + layer.effect: ShaderEffect { + id:se + blending: false + + property real time: 0 + property real framerate: 60 + property real updateInterval: Math.round( + (1000 / framerate) * 10) / 10 + Timer { + interval: 16 + running: true + repeat: true + onTriggered: { + se.time += 1 + } + } + property variant texture_albedo: img_albedo + property variant texture_flow_noise: img_flow_noise + property variant texture_flow_map: img_flow_map + property variant texture_normal: img_normal + property variant texture_refraction: img_refraction + property variant texture_emission: img_emission + property variant texture_roughness: img_roughness + property variant texture_metallic: img_metallic + property vector4d albedo: Qt.vector4d(1.0, 1.0, + 1.0, 1.0) + + property real specular: 0 + property real metallic: 0 + property real roughness: 1 + property vector4d metallic_texture_channel: Qt.vector4d(1.0, 0.0, + 0.0, 0.0) + property vector4d roughness_texture_channel: Qt.vector4d(1.0, 0.0, + 0.0, 0.0) + property vector4d emission + property real emission_energy: 1 + property real refraction: 0 + property vector4d refraction_texture_channel: Qt.vector4d(1.0, 0.0, + 0.0, 0.0) + property vector2d uv_scale: Qt.vector2d(10.0, 10.0) + property vector2d uv_offset: Qt.vector2d(0.0, 0.0) + property real proximity_fade_distance: 1 + property real distance_fade_min: 1 + property real distance_fade_max: 1 + + property real normal_scale: 10 + property real flow_normal_influence: 0.5 + + // Flow / Water uniforms + property vector4d flow_map_x_channel: Qt.vector4d(1.0,0.0, 0.0, 0.0) + property vector4d flow_map_y_channel: Qt.vector4d(0.0,1.0, 0.0, 0.0) + property vector2d channel_flow_direction: Qt.vector2d(1.0, 1.0) + property real blend_cycle: 1.0 + property real cycle_speed: 1.0 + property real flow_speed: 0.5 + + property vector4d noise_texture_channel: Qt.vector4d(1.0, + 0.0, 0.0, 0.0) + property vector2d flow_noise_size: Qt.vector2d(1.0, 1.0) + property real flow_noise_influence: 0.5 + + + + fragmentShader: "/shaders/flowmap.frag.qsb" + } + } +} diff --git a/ScreenPlayShader/src/TestMain.qml b/ScreenPlayShader/src/TestMain.qml index ce9eeadd..88a5cfd1 100644 --- a/ScreenPlayShader/src/TestMain.qml +++ b/ScreenPlayShader/src/TestMain.qml @@ -11,34 +11,35 @@ Window { visible: true title: qsTr("ScreenPlayShader") - Image { - id: img - anchors.fill: parent - fillMode: Image.PreserveAspectCrop - source: "qrc:/qml/ScreenPlayShader/assets/test_image_andras-vas-Bd7gNnWJBkU-unsplash.jpg" - layer.enabled: true - layer.effect: ShaderEffect { - property real amplitude: 0.04 * .1 - property real frequency: 2 - property real time: 0 - property real framerate: 60 - property real updateInterval: Math.round( - (1000 / framerate) * 10) / 10 - - Timer { - interval: updateInterval - onIntervalChanged: print(updateInterval) - running: true - repeat: true - onTriggered: { - if (parent.time > 600) { - parent.time = 0 - } - parent.time += 1 - } - } - - fragmentShader: "/shaders/wobble.frag.qsb" + TabBar { + id: bar + width: parent.width + TabButton { + text: qsTr("Wobble") + } + TabButton { + text: qsTr("Flowmap") + } + TabButton { + text: qsTr("Beam") } } + + SwipeView { + anchors { + top: bar.bottom + right: parent.right + bottom: parent.bottom + left: parent.left + } + + currentIndex: bar.currentIndex + clip: true + + Flowmap {} + + Wobble {} + + Beam {} + } } diff --git a/ScreenPlayShader/src/Wobble.qml b/ScreenPlayShader/src/Wobble.qml new file mode 100644 index 00000000..4552a67f --- /dev/null +++ b/ScreenPlayShader/src/Wobble.qml @@ -0,0 +1,50 @@ +import QtQuick +import QtQuick.Layouts +import QtQuick.Controls +import QtQuick.Controls.Material +import ScreenPlayShader + +Rectangle { + color: "gray" + + Image { + id: img + anchors.fill: parent + fillMode: Image.PreserveAspectCrop + source: "qrc:/qml/ScreenPlayShader/assets/test_image_andras-vas-Bd7gNnWJBkU-unsplash.jpg" + layer.enabled: true + layer.effect: ShaderEffect { + id: shader + property real amplitude: 0.04 * .1 + property real frequency: 2 + property real time: 0 + property real framerate: 60 + property real updateInterval: Math.round( + (1000 / framerate) * 10) / 10 + + Timer { + interval: updateInterval + running: true + repeat: true + onTriggered: { + if (parent.time > 600) { + parent.time = 0 + } + parent.time += 1 + } + } +// UniformAnimator { +// target: shader +// uniform: "time" +// from: 0 +// to: 600 +// duration: 25 +// running: true +// loops:Animation.Infinite +// } + + fragmentShader: "/shaders/wobble.frag.qsb" + } + + } +}