BrushCue Example: Desert Mirage Filter Animation¶

Open In Colab

You can use this tool online at https://www.brushcue.com/tools/desert-mirage-filter

In [ ]:
!pip install brushcue
In [1]:
import brushcue
import io

input_image_1 = brushcue.composition_monet_women_with_parasol() # insert your own image here
time_2 = brushcue.float_passthrough(0.0)
looping_shader_body_3 = brushcue.string_constant("    let size = vec2f(textureDimensions(input_texture));\n    let uv = vec2f(position) / size;\n\n    // Normalize time over the 3-second duration (0 → 1) then to radians\n    // Integer multiples of 2π ensure every wave returns to zero at t=3.0\n    let t = (time % 3.0) / 3.0;\n    let t1 = t * 6.283185 * 2.0;\n    let t2 = t * 6.283185 * 3.0;\n    let t3 = t * 6.283185 * 1.0;\n\n    // Mirage heat distortion — layered sine waves rising from the bottom\n    let heat_influence = pow(1.0 - uv.y, 2.5);\n    let wave1 = sin(uv.x * 18.0 + uv.y * 6.0 + t1) * 0.007;\n    let wave2 = sin(uv.x * 31.0 - uv.y * 9.0 + 1.3 + t2) * 0.004;\n    let wave3 = sin(uv.x * 9.0 + uv.y * 22.0 + 2.7 + t3) * 0.005;\n    let distort = (wave1 + wave2 + wave3) * heat_influence * intensity;\n\n    // Chromatic aberration for trippy fringe\n    let offset = distort * 1.8;\n    let uv_r = uv + vec2f(distort + offset * 0.5, distort * 0.6);\n    let uv_g = uv + vec2f(distort, distort * 0.8);\n    let uv_b = uv + vec2f(distort - offset * 0.4, distort);\n\n    let r = sample(input_texture, clamp(uv_r, vec2f(0.0), vec2f(1.0))).r;\n    let g = sample(input_texture, clamp(uv_g, vec2f(0.0), vec2f(1.0))).g;\n    let b = sample(input_texture, clamp(uv_b, vec2f(0.0), vec2f(1.0))).b;\n    let a = sample(input_texture, clamp(uv_g, vec2f(0.0), vec2f(1.0))).a;\n\n    return vec4f(r, g, b, a);")
empty_helpers_4 = brushcue.string_constant("")
srgb_profile_5 = brushcue.color_profile_s_r_g_b()
bool_constant_6 = brushcue.bool_constant(True)
string_constant_7 = brushcue.string_constant("time")
shader_inputs_8 = brushcue.dictionary_create()
string_constant_9 = brushcue.string_constant("intensity")
intensity_10 = brushcue.float_passthrough(0.25)
float_multiply_11 = brushcue.float_multiply(0.15, intensity_10)
float_multiply_12 = brushcue.float_multiply(0.08, intensity_10)
float_multiply_13 = brushcue.float_multiply(0.04, intensity_10)
add_intensity_to_shader_14 = brushcue.float_add_to_dictionary(shader_inputs_8, string_constant_9, intensity_10)
float_add_15 = brushcue.float_add(1.0, float_multiply_11)
float_multiply_16 = brushcue.float_multiply(0.6, intensity_10)
vector_2_float_from_components_17 = brushcue.vector2f_from_components(float_multiply_12, float_multiply_13)
add_time_to_shader_18 = brushcue.float_add_to_dictionary(add_intensity_to_shader_14, string_constant_7, time_2)
float_add_19 = brushcue.float_add(1.0, float_multiply_16)
warm_chroma_shift_20 = brushcue.composition_chroma_offset(input_image_1, vector_2_float_from_components_17)
brighten_for_desert_sun_21 = brushcue.composition_brightness_adjust(warm_chroma_shift_20, float_add_15)
boost_saturation_22 = brushcue.composition_saturation_adjust(brighten_for_desert_sun_21, float_add_19)
mirage_heat_distortion_23 = brushcue.composition_custom_transformer_shader(boost_saturation_22, looping_shader_body_3, empty_helpers_4, srgb_profile_5, srgb_profile_5, add_time_to_shader_18, bool_constant_6)
sequence_graph_24 = brushcue.sequence_graph(6.0, time_2, mirage_heat_distortion_23)

ctx = brushcue.Context()
result = sequence_graph_24.execute(ctx)
result = result.as_sequence()
# You can render the result to an video file