提问人:Loyown 提问时间:11/11/2023 最后编辑:Paul WheelerLoyown 更新时间:11/13/2023 访问量:49
使用p5.js的曼德布洛特套装的平滑颜色
Smooth color for mandelbrot set using p5.js
问:
我和p5.js一起玩,试图重现曼德布洛特的集合。 我已经创建了套装本身,但我在以正确的方式着色方面遇到了问题。
我已经跟进了 wiki 页面中的伪代码,但我无法用正确的颜色着色。
这是我写的p5.js代码:
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;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.8.0/p5.js"></script>
这是生成的图像:
图像本身还不错,但我不明白为什么我得到这种绿色的背景,而且我无法在 wiki 页面中显示颜色。
我想要一个类似于这个家伙的效果,但我无法用 c 代码理解它。
答:
1赞
Paul Wheeler
11/13/2023
#1
在链接到的代码中,着色器(第一个代码片段是 GLSL 而不是 C)根据当前种子点转义所需的最大迭代次数的分数从一维纹理中获取颜色值。因此,在不知道他们如何生成构成该纹理的颜色的情况下,很难推断出他们正在使用的算法。
但是,在您的代码中,存在一些可识别的问题:1) 像素数组始终使用 RGB,无论颜色模式如何,2) 当您使用高 maxIterations 值时,您看到的许多点最终都具有非常相似的低值。这是因为在查看缩小的曼德布洛特集时,许多不是很接近边界的点在经过几次迭代后就会逃逸,因此所有这些点最终都具有非常相似(且非常暗)的颜色。
因此,要解决此问题,您需要手动将所需的 HSV 值转换为 RGB 以在像素数组中使用,并减少默认的 maxIterations 值。
let slider;
function setup() {
createCanvas(400, 400);
pixelDensity(1)
background(51)
// This had no effect
// colorMode(HSL, 360, 100, 100)
// Decreased the default to 80 instead of 500
slider = createSlider(10, 1000, 80, 1)
// Avoid unnecessary re-renders
slider.input(() => {
redraw();
});
noLoop();
}
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++
}
if (iteration < maxIteration) {
let [r, g, b] = hsv2rgb(
pow(iteration / maxIteration * 360, 1.5) % 360,
0.5,
(iteration / maxIteration) * 0.8 + 0.2
);
pixels[index + 0] = r * 255;
pixels[index + 1] = g * 255;
pixels[index + 2] = b * 255;
} else {
pixels[index + 0] = 0;
pixels[index + 1] = 0;
pixels[index + 2] = 0;
}
}
}
updatePixels()
}
function magn(a, b) {
return a * a + b * b;
}
// Source: https://stackoverflow.com/a/54024653/229247
// Author: Kamil Kiełczewski
// CC-BY-SA 4.0
function hsv2rgb(h, s, v) {
function f(n) {
const k = (n + h / 60) % 6;
return v - v * s * Math.max(Math.min(k, 4 - k, 1), 0);
}
return [f(5),f(3),f(1)];
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.8.0/p5.js"></script>
下一个:Pytorch - 向后使用复数
评论
shader() p5.js
。HTH