使用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(); }
关键修改点
- 颜色赋值修复:用
color()函数生成HSL颜色,再提取RGB值给pixels数组,确保颜色格式正确。 - 内部点处理:将迭代到最大次数的集合内部点设为黑色,解决背景颜色混乱问题。
- 平滑着色:根据维基算法计算平滑迭代次数,消除色带,让颜色过渡更自然。
- 性能优化:添加
noLoop()避免重复绘制,通过mouseReleased()触发重绘,减少不必要的计算。
效果调整建议
- 若想要暖色调效果,可修改色相映射范围,比如
map(smoothIter, 0, maxIteration, 0, 60)(黄色到红色区间)。 - 调整
color(hue, 80, 50)中的饱和度(80)和亮度(50)参数,可改变颜色的鲜艳度和明暗。 - 增加
maxIteration的值能提升细节,但会增加绘制时间。
内容的提问来源于stack exchange,提问作者Loyown
相关产品推荐
相关产品推荐

