294 auto *e = ctx.mEngine.get();
306 static constexpr float perlin_period = 2560.0f;
308 e->timings.master_speed = 0.01;
309 e->timings.ratio[0] = 0.1;
310 e->timings.ratio[1] = 0.13;
311 e->timings.ratio[2] = 0.16;
312 e->timings.offset[1] = 10;
313 e->timings.offset[2] = 20;
314 e->timings.offset[3] = 30;
315 e->calculate_oscillators(e->timings);
317 for (
int x = 0;
x < e->num_x;
x++) {
318 for (
int y = 0;
y < e->num_y;
y++) {
320 3 * e->polar_theta[
x][
y] + e->move.radial[0] -
321 e->distance[
x][
y] / 3;
322 e->animation.dist = e->distance[
x][
y];
323 e->animation.scale_z = 0.1;
324 e->animation.scale_y = 0.1;
325 e->animation.scale_x = 0.1;
326 e->animation.offset_x =
fl::fmodf(e->move.linear[0], perlin_period);
327 e->animation.offset_y = 0;
328 e->animation.offset_z = 0;
330 float show1 = e->render_value(e->animation);
333 3 * e->polar_theta[
x][
y] + e->move.radial[1] -
334 e->distance[
x][
y] / 3;
335 e->animation.dist = e->distance[
x][
y];
336 e->animation.offset_x =
fl::fmodf(e->move.linear[1], perlin_period);
337 float show2 = e->render_value(e->animation);
340 3 * e->polar_theta[
x][
y] + e->move.radial[2] -
341 e->distance[
x][
y] / 3;
342 e->animation.dist = e->distance[
x][
y];
343 e->animation.offset_x =
fl::fmodf(e->move.linear[2], perlin_period);
344 float show3 = e->render_value(e->animation);
346 float radius = e->radial_filter_radius;
347 float radial_filter = (radius - e->distance[
x][
y]) / radius;
349 e->pixel.red = 3 * show1 * radial_filter;
350 e->pixel.green = show2 * radial_filter / 2;
351 e->pixel.blue = show3 * radial_filter / 4;
353 e->pixel = e->rgb_sanity_check(e->pixel);
354 e->setPixelColorInternal(
x,
y, e->pixel);
365 const int total_pixels =
setup.total_pixels;
366 const i32 *fade_lut =
setup.fade_lut;
368 const i32 cx_raw =
setup.cx_raw;
369 const i32 cy_raw =
setup.cy_raw;
370 const i32 lin0_raw =
setup.lin0_raw;
371 const i32 lin1_raw =
setup.lin1_raw;
372 const i32 lin2_raw =
setup.lin2_raw;
373 const i32 rad0_raw =
setup.rad0_raw;
374 const i32 rad1_raw =
setup.rad1_raw;
375 const i32 rad2_raw =
setup.rad2_raw;
379 auto noise_channel = [&](
const SinCos32_simd &sc,
int lane,
380 i32 lin_raw, i32 dist_raw) -> i32 {
381 i32 cos_v =
static_cast<i32
>(simd::extract_u32_4(sc.cos_vals, lane));
382 i32 sin_v =
static_cast<i32
>(simd::extract_u32_4(sc.sin_vals, lane));
383 i32 nx = perlinCoord(cos_v, dist_raw, lin_raw + cx_raw);
384 i32 ny = perlinCoord(sin_v, dist_raw, cy_raw);
385 return clampAndScale255(Perlin::pnoise2d_raw(nx, ny, fade_lut, perm));
388 for (
int i = 0; i < total_pixels; i++) {
389 const i32 base_raw =
setup.base_angle[i];
390 const i32 dist_raw =
setup.dist_scaled[i];
394 radiansToA24(base_raw, rad0_raw),
395 radiansToA24(base_raw, rad1_raw),
396 radiansToA24(base_raw, rad2_raw), 0);
399 i32 s0 = noise_channel(sc, 0, lin0_raw, dist_raw);
400 i32 s1 = noise_channel(sc, 1, lin1_raw, dist_raw);
401 i32 s2 = noise_channel(sc, 2, lin2_raw, dist_raw);
403 i32 r = applyRadialFilter(s0,
setup.rf3[i]);
404 i32
g = applyRadialFilter(s1,
setup.rf_half[i]);
405 i32 b = applyRadialFilter(s2,
setup.rf_quarter[i]);
419 const int total_pixels =
setup.total_pixels;
420 const i32 *base_angle =
setup.base_angle;
421 const i32 *dist_scaled =
setup.dist_scaled;
422 const i32 *rf3_arr =
setup.rf3;
423 const i32 *rf_half_arr =
setup.rf_half;
424 const i32 *rf_qtr_arr =
setup.rf_quarter;
425 const u16 *pixel_idx =
setup.pixel_idx;
426 const i32 *fade_lut =
setup.fade_lut;
428 const i32 cx_raw =
setup.cx_raw;
429 const i32 cy_raw =
setup.cy_raw;
430 const i32 lin0_raw =
setup.lin0_raw;
431 const i32 lin1_raw =
setup.lin1_raw;
432 const i32 lin2_raw =
setup.lin2_raw;
433 const i32 rad0_raw =
setup.rad0_raw;
434 const i32 rad1_raw =
setup.rad1_raw;
435 const i32 rad2_raw =
setup.rad2_raw;
440 for (; i + 3 < total_pixels; i += 4) {
442 auto base_vec = loadAligned(base_angle, i);
443 auto dist_vec = loadAligned(dist_scaled, i);
444 auto rf3_vec = loadAligned(rf3_arr, i);
445 auto rf_half_vec = loadAligned(rf_half_arr, i);
446 auto rf_qtr_vec = loadAligned(rf_qtr_arr, i);
448 auto r_vec = simd4_processChannel(
449 base_vec, dist_vec, rad0_raw, lin0_raw, fade_lut, perm, cx_raw, cy_raw, rf3_vec);
450 auto g_vec = simd4_processChannel(
451 base_vec, dist_vec, rad1_raw, lin1_raw, fade_lut, perm, cx_raw, cy_raw, rf_half_vec);
452 auto b_vec = simd4_processChannel(
453 base_vec, dist_vec, rad2_raw, lin2_raw, fade_lut, perm, cx_raw, cy_raw, rf_qtr_vec);
456 scatterPixel(
leds, pixel_idx[i+0], r_vec, g_vec, b_vec, 0);
457 scatterPixel(
leds, pixel_idx[i+1], r_vec, g_vec, b_vec, 1);
458 scatterPixel(
leds, pixel_idx[i+2], r_vec, g_vec, b_vec, 2);
459 scatterPixel(
leds, pixel_idx[i+3], r_vec, g_vec, b_vec, 3);
463 for (; i < total_pixels; i++) {
464 const i32 base_raw = base_angle[i];
465 const i32 dist_raw = dist_scaled[i];
467 auto noise_ch = [&](i32 rad_raw, i32 lin_raw) -> i32 {
468 u32 a24 = radiansToA24(base_raw, rad_raw);
470 i32 nx = perlinCoord(sc.
cos_val, dist_raw, lin_raw + cx_raw);
471 i32 ny = perlinCoord(sc.
sin_val, dist_raw, cy_raw);
472 i32 raw = Perlin::pnoise2d_raw(nx, ny, fade_lut, perm);
473 return clampAndScale255(raw);
476 i32 s0 = noise_ch(rad0_raw, lin0_raw);
477 i32 s1 = noise_ch(rad1_raw, lin1_raw);
478 i32 s2 = noise_ch(rad2_raw, lin2_raw);
480 i32 r = applyRadialFilter(s0, rf3_arr[i]);
481 i32
g = applyRadialFilter(s1, rf_half_arr[i]);
482 i32 b = applyRadialFilter(s2, rf_qtr_arr[i]);
484 leds[pixel_idx[i]] =
CRGB(
static_cast<u8>(r),
static_cast<u8>(
g),
static_cast<u8>(b));