You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用p5.js实现曼德博集合平滑着色的问题求助

曼德博集合着色问题(p5.js实现)

问题说明

用p5.js复刻曼德博集合,已完成基础绘制,但着色存在问题:参照维基伪代码无法实现正确效果,背景呈绿色,想要实现平滑过渡的着色效果但看不懂对应C语言代码。

现有代码

JavaScript部分

let slider;

function setup() {
  createCanvas(400, 400);
  background(51)
  colorMode(HSL, 360, 100, 100)
  slider = createSlider(10, 1000, 500, 1)
}

let k = 0;

function draw() {
  loadPixels()

  for (let i = 0; i < width; i++) {
    for (let j = 0; j < height; j++) {
      let index = (i + j * width) * 4
      let x0 = map(i, 0, width, -2.0, 0.47);
      let y0 = map(j, 0, height, -1.12, 1.12);

      let x = 0;
      let y = 0;

      let iteration = 0;
      let maxIteration = slider.value();

      while (magn(x, y) <= 4 && iteration < maxIteration) {
        let xTemp = x * x - y * y + x0;
        y = 2 * x * y + y0;
        x = xTemp;
        iteration++

      }

      pixels[index + 0] = pow(iteration / maxIteration * 360, 1.5) % 360
      pixels[index + 1] = 50
      pixels[index + 2] = (iteration / maxIteration) * 100

    }
  }
  
  updatePixels()
}

function magn(a, b) {
  return a * a + b * b;
}

HTML部分

<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.8.0/p5.js"></script>

当前效果

当前曼德博集合效果

问题原因与解决方案

核心问题

直接给pixels数组赋值HSL数值是错误的:pixels数组始终采用RGB格式(值范围0-255),colorMode(HSL)仅对color()、fill()等p5.js绘图函数生效,这导致颜色值混乱,出现异常的绿色背景。

另外,直接用原始迭代次数着色会产生明显色带,需要实现平滑着色算法来过渡颜色。

修正后的代码

let slider;

function setup() {
  createCanvas(400, 400);
  colorMode(HSL, 360, 100, 100);
  slider = createSlider(10, 1000, 500, 1);
  noLoop(); // 避免重复绘制,提升性能
}

function draw() {
  background(51);
  loadPixels();
  let maxIteration = slider.value();

  for (let i = 0; i < width; i++) {
    for (let j = 0; j < height; j++) {
      let index = (i + j * width) * 4;
      let x0 = map(i, 0, width, -2.0, 0.47);
      let y0 = map(j, 0, height, -1.12, 1.12);

      let x = 0;
      let y = 0;
      let iteration = 0;

      while (magn(x, y) <= 4 && iteration < maxIteration) {
        let xTemp = x * x - y * y + x0;
        y = 2 * x * y + y0;
        x = xTemp;
        iteration++;
      }

      let col;
      if (iteration === maxIteration) {
        // 曼德博集合内部点,设为黑色
        col = color(0);
      } else {
        // 平滑着色计算,消除色带
        let smoothIter = iteration + 1 - Math.log(Math.log(magn(x, y))) / Math.log(2);
        // 映射平滑迭代值到色相范围,可调整参数改变颜色效果
        let hue = map(smoothIter, 0, maxIteration, 0, 360);
        col = color(hue, 80, 50);
      }

      // 提取RGB值赋值给pixels数组
      pixels[index] = red(col);
      pixels[index + 1] = green(col);
      pixels[index + 2] = blue(col);
      pixels[index + 3] = 255; // 不透明度设为255
    }
  }

  updatePixels();
}

function magn(a, b) {
  return a * a + b * b;
}

// 滑块调整后重新绘制
function mouseReleased() {
  redraw();
}

关键修改点

  1. 颜色赋值修复:用color()函数生成HSL颜色,再提取RGB值给pixels数组,确保颜色格式正确。
  2. 内部点处理:将迭代到最大次数的集合内部点设为黑色,解决背景颜色混乱问题。
  3. 平滑着色:根据维基算法计算平滑迭代次数,消除色带,让颜色过渡更自然。
  4. 性能优化:添加noLoop()避免重复绘制,通过mouseReleased()触发重绘,减少不必要的计算。

效果调整建议

  • 若想要暖色调效果,可修改色相映射范围,比如map(smoothIter, 0, maxIteration, 0, 60)(黄色到红色区间)。
  • 调整color(hue, 80, 50)中的饱和度(80)和亮度(50)参数,可改变颜色的鲜艳度和明暗。
  • 增加maxIteration的值能提升细节,但会增加绘制时间。

内容的提问来源于stack exchange,提问作者Loyown

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 20:24:54