Skip to content

Perlinscape FX (2D) in the user_fx usermod#5587

Open
BobLoeffler68 wants to merge 8 commits intowled:mainfrom
BobLoeffler68:pr-perlinscape-user-fx
Open

Perlinscape FX (2D) in the user_fx usermod#5587
BobLoeffler68 wants to merge 8 commits intowled:mainfrom
BobLoeffler68:pr-perlinscape-user-fx

Conversation

@BobLoeffler68
Copy link
Copy Markdown
Contributor

@BobLoeffler68 BobLoeffler68 commented May 10, 2026

This PR adds the 2D Perlinscape effect into the new user_fx usermod instead of FX.cpp

  • a Perlin noise landscape animation
  • Created by stepko as part of Stepko Land on soulmatelights.com
  • Adapted to WLED by Bob Loeffler (with explicit permission), and additional features added (and help from Claude)
  • First slider is the speed
  • Second slider is the X multiplier
  • Third slider is the Y multiplier
  • First checkbox will use palettes that are selected by the user
  • Second checkbox will rotate the image
  • Third checkbox will randomize the horizontal and vertical directions

Example videos:

80007897461__00E4D193-7401-4ED9-9F74-DBF3C8C172A7.mov

^-- Default settings and Rotation

IMG_6838.mov

^-- Using the Hult 64 palette

Untitled.1.mp4

^-- Hult 64 palette and mirrored X

Untitled.mp4

^-- Candy palette and Rotation

Summary by CodeRabbit

  • New Features
    • Added a new "Perlinscape" 2D visual effect that renders procedurally generated Perlin-noise landscapes on matrix displays. Supports palette and raw RGB output, optional continuous rotation, randomized X/Y flips, and adjustable zoom, intensity, and X/Y scaling via UI controls.

Review Change Stack

@softhack007 softhack007 added usermod usermod related AI Partly generated by an AI. Make sure that the contributor fully understands the code! effect labels May 10, 2026
@softhack007
Copy link
Copy Markdown
Member

@BobLoeffler68 I see "0 files changed" - is this expected?

image

@softhack007 softhack007 added the waiting for feedback addition information needed to better understand the issue label May 10, 2026
@BobLoeffler68
Copy link
Copy Markdown
Contributor Author

@BobLoeffler68 I see "0 files changed" - is this expected?

Hmmmmm... I'm not sure what is happening. I can't even compile it anymore as it says platform_wled_default doesn't exist in the [common] section of platformio.ini Something strange is happening.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 10, 2026

Walkthrough

A new 2D "Perlinscape" user FX effect was added. It renders a Perlin-noise landscape on a 2D LED matrix with configurable palette or RGB output, zoom/intensity and XY multipliers, optional rotation, and optional randomized X/Y direction flips.

Changes

2D Perlinscape Effect

Layer / File(s) Summary
Effect Implementation and Metadata
usermods/user_fx/user_fx.cpp
mode_2D_perlinscape allocates per-effect scratch data (offsets, steps, previous time), advances time/offsets, optionally applies rotation and random direction flips, evaluates Perlin noise per pixel with zoom/intensity and XY multipliers, and renders via palette or raw RGB. Adds _data_FX_MODE_2D_PERLINSCAPE PROGMEM metadata.
Effect Registration
usermods/user_fx/user_fx.cpp
Registers mode_2D_perlinscape in UserFxUsermod::setup() using the new metadata string, making it available as a user FX mode.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • wled/WLED#5360: Adds a Perlin-based 2D effect in usermods/user_fx/user_fx.cpp with similar per-effect state and registration changes.
  • wled/WLED#5251: Adds a new FX mode in usermods/user_fx/user_fx.cpp and updates UserFxUsermod::setup() to register it.
  • wled/WLED#5252: Adds user FX effects in usermods/user_fx/user_fx.cpp and modifies setup registration.

Suggested reviewers

  • DedeHai
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title 'Perlinscape FX (2D) in the user_fx usermod' accurately summarizes the main change: adding a new 2D Perlinscape effect to the user_fx usermod.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
usermods/user_fx/user_fx.cpp (2)

1335-1336: 💤 Low value

Consider uint_fast8_t for hot-path loop counters.

The nested per-pixel loops use byte (uint8_t). For hot-path performance, the coding guidelines suggest uint_fast8_t / uint_fast16_t for loop counters, though effect functions have diverse contributor styles.

♻️ Optional refactor
-  for (byte x = 0; x < width; x++) {
-    for (byte y = 0; y < height; y++) {
+  for (uint_fast8_t x = 0; x < width; x++) {
+    for (uint_fast8_t y = 0; y < height; y++) {

As per coding guidelines: Use uint_fast16_t / uint_fast8_t in hot-path code (per-frame/per-pixel loops).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@usermods/user_fx/user_fx.cpp` around lines 1335 - 1336, The per-pixel nested
loops use the typedef byte (uint8_t) for counters x and y which can be
suboptimal in hot-path rendering; change the loop counter types from byte to
uint_fast8_t (or uint_fast16_t if width/height can exceed 255) for the loops
that iterate over width and height (the variables x and y in the nested for
loops) to follow the coding guideline for per-frame/per-pixel hot-path
performance, ensuring any dependent uses/overloads accept the updated integer
type.

1261-1354: 💤 Low value

Add AI-generated code markers if applicable.

The PR description mentions "additional features (and help from Claude)" and the code comment references "help from Claude", but there are no // AI: / // AI: end markers in the code. If any contiguous blocks were AI-generated, please mark them per the coding guidelines.

Example format:

// AI: below section was generated by an AI
... AI-generated code ...
// AI: end

As per coding guidelines: Mark AI-generated code blocks with // AI: below section was generated by an AI / // AI: end comments.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@usermods/user_fx/user_fx.cpp` around lines 1261 - 1354, The function
mode_2D_perlinscape and its top comment reference “help from Claude”; if any
contiguous portion of this function or surrounding blocks was AI-generated, wrap
that exact contiguous block with the required markers (add a line "// AI: below
section was generated by an AI" before the block and "// AI: end" after it); if
no part of mode_2D_perlinscape or its comments was AI-generated, add a brief
single-line clarifying comment near the top (e.g., immediately above the
function comment) stating that no AI-generated code was used; locate code by the
symbol mode_2D_perlinscape and the header comment mentioning Claude to apply the
change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@usermods/user_fx/user_fx.cpp`:
- Around line 1329-1330: Replace the standard library calls
cosf(angle)/sinf(angle) with the project's approximations: call
cos_approx(angle) to assign cosA and sin_approx(angle) to assign sinA; update
the expressions where cosA and sinA are set (look for the assignments to cosA
and sinA that currently use cosf/sinf with the variable angle) so they use
cos_approx(angle) and sin_approx(angle) respectively to comply with the WLED C++
coding guideline.
- Line 1277: The allocation is oversized because only five floats (offX, offY,
stepX, stepY, prevT) are used: update the SEGENV.allocateData call to allocate
exactly 5 * sizeof(float) bytes (remove the + width * height), and ensure no
other code in this scope relies on the removed buffer; locate the call to
SEGENV.allocateData and the subsequent accesses to offX/offY/stepX/stepY/prevT
to verify they're unchanged.

---

Nitpick comments:
In `@usermods/user_fx/user_fx.cpp`:
- Around line 1335-1336: The per-pixel nested loops use the typedef byte
(uint8_t) for counters x and y which can be suboptimal in hot-path rendering;
change the loop counter types from byte to uint_fast8_t (or uint_fast16_t if
width/height can exceed 255) for the loops that iterate over width and height
(the variables x and y in the nested for loops) to follow the coding guideline
for per-frame/per-pixel hot-path performance, ensuring any dependent
uses/overloads accept the updated integer type.
- Around line 1261-1354: The function mode_2D_perlinscape and its top comment
reference “help from Claude”; if any contiguous portion of this function or
surrounding blocks was AI-generated, wrap that exact contiguous block with the
required markers (add a line "// AI: below section was generated by an AI"
before the block and "// AI: end" after it); if no part of mode_2D_perlinscape
or its comments was AI-generated, add a brief single-line clarifying comment
near the top (e.g., immediately above the function comment) stating that no
AI-generated code was used; locate code by the symbol mode_2D_perlinscape and
the header comment mentioning Claude to apply the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 71a00cb6-14af-4164-b12e-ec1652c75822

📥 Commits

Reviewing files that changed from the base of the PR and between 37623ed and 8d8e107.

📒 Files selected for processing (1)
  • usermods/user_fx/user_fx.cpp

Comment thread usermods/user_fx/user_fx.cpp Outdated
Comment thread usermods/user_fx/user_fx.cpp Outdated
…- use cos_approx() and sin_approx() instead of cosf and sinf
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
usermods/user_fx/user_fx.cpp (2)

1337-1338: ⚡ Quick win

Consider using uint16_t for loop variables to support larger matrices.

The loop variables x and y are declared as byte (uint8_t), which limits them to 0-255. While typical WLED matrices are smaller, using uint16_t would future-proof the code for larger matrices and match the return types of SEG_W and SEG_H.

🔧 Proposed fix
-  for (byte x = 0; x < width; x++) {
-    for (byte y = 0; y < height; y++) {
+  for (uint16_t x = 0; x < width; x++) {
+    for (uint16_t y = 0; y < height; y++) {
       float rx = cosA * (x - cx) - sinA * (y - cy) + cx;
       float ry = sinA * (x - cx) + cosA * (y - cy) + cy;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@usermods/user_fx/user_fx.cpp` around lines 1337 - 1338, Loop indices x and y
are declared as byte (uint8_t), which restricts matrix sizes; change their types
to uint16_t in the nested loops that iterate over SEG_W and SEG_H (replace the
declarations of x and y in the for loops) so they match the larger return types
and support bigger matrices, and update any nearby usages/expressions that
assume byte to prevent implicit truncation.

1277-1277: 💤 Low value

Remove commented-out old code.

Lines 1277, 1329, and 1330 contain the old buggy code that has been fixed. These commented lines should be removed to keep the codebase clean.

🧹 Proposed cleanup
  const uint16_t width = SEG_W;
  const uint16_t height = SEG_H;
-//  if (!SEGENV.allocateData(5 * sizeof(float) + width * height)) FX_FALLBACK_STATIC;
  if (!SEGENV.allocateData(5 * sizeof(float))) FX_FALLBACK_STATIC;
  if (SEGMENT.check2) {
    float angle = strip.now / 5000.0f;
-//    cosA = cosf(angle);
-//    sinA = sinf(angle);
    cosA = cos_approx(angle);
    sinA = sin_approx(angle);
  }

Also applies to: 1329-1330

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@usermods/user_fx/user_fx.cpp` at line 1277, Remove the leftover commented-out
old code that calls SEGENV.allocateData and uses FX_FALLBACK_STATIC; locate
occurrences of the commented line containing "SEGENV.allocateData(5 *
sizeof(float) + width * height)) FX_FALLBACK_STATIC" and the related commented
lines and delete them so the fixed implementation remains clean and no obsolete
code is left in user_fx.cpp (search for SEGENV.allocateData and
FX_FALLBACK_STATIC to find all instances).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@usermods/user_fx/user_fx.cpp`:
- Around line 1337-1338: Loop indices x and y are declared as byte (uint8_t),
which restricts matrix sizes; change their types to uint16_t in the nested loops
that iterate over SEG_W and SEG_H (replace the declarations of x and y in the
for loops) so they match the larger return types and support bigger matrices,
and update any nearby usages/expressions that assume byte to prevent implicit
truncation.
- Line 1277: Remove the leftover commented-out old code that calls
SEGENV.allocateData and uses FX_FALLBACK_STATIC; locate occurrences of the
commented line containing "SEGENV.allocateData(5 * sizeof(float) + width *
height)) FX_FALLBACK_STATIC" and the related commented lines and delete them so
the fixed implementation remains clean and no obsolete code is left in
user_fx.cpp (search for SEGENV.allocateData and FX_FALLBACK_STATIC to find all
instances).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 61a0d9c7-5bb0-44d1-843b-e4ee11aef293

📥 Commits

Reviewing files that changed from the base of the PR and between 8d8e107 and 0dcdbaa.

📒 Files selected for processing (1)
  • usermods/user_fx/user_fx.cpp

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Partly generated by an AI. Make sure that the contributor fully understands the code! effect usermod usermod related waiting for feedback addition information needed to better understand the issue

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants