你在colorMode(HSB)
渲染彩虹方面已经做得很好了。我会移动嵌套的 for 循环以使其更高效:它会渲染一次并留在那里,因为您没有调用background()
并且rect(0,50,500,500);
低于彩虹渐变。
HSB 实际上比 RGB 更容易使用。这是来自维基百科的图表:
SharkD,CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0,来自维基共享资源
值与亮度相同。色调通常在 0-360 度范围内,因此图片以彩虹圈的形式出现,从红色开始到红色结束。假设你从红色开始,0 度色相,你知道黄色是 60 度色相。直觉上,你会在 30 度时发现介于红色和黄色之间的橙色。事实上,如果您每 60 度转一次,您将通过红色、黄色、绿色、青色、蓝色、品红色,然后在 360/0 时返回红色。
饱和度和亮度通常在 0-100% 之间。请注意,上图中的饱和度远离中心增加:0 饱和度 = 灰色,100% 饱和度 = 全色调。
图中亮度从下到上增加。
您将色调、饱和度和亮度映射到 0-100 范围有点奇怪。也许目的是通过将色调也视为百分比来简化事情。
可以使事情变得更容易的一件事是map()
功能。它将一个数字从一个范围映射到另一个范围。
例如,这段代码试图将 i、j 位置重新映射到色调和饱和度。
i, j
在 0-500、0-50 范围内(x、y 位置)
- 上图显示了具有相同饱和度和亮度的彩虹渐变,因此可以保持不变:
- 简单地
i
从0-499
范围0-100
映射到映射到色调
例如:
void setup() {
size(500, 550);
colorMode(HSB, 100);
for (int i = 0; i < 500; i++) {
for (int j = 0; j < 50; j++) {
// remap i (x -> width) to 0 - 100 range for hue
// since map returns a float, round helps make that an int
int h = round(map(i, 0, 499, 0, 100));
int s = 100;
int b = 100;
stroke(h, s, b);
point(i, j);
}
}
noStroke();
}
void draw() {
fill(map(mouseX, 0, width, 0, 100), map(mouseY, 0, height, 0, 100), 100);
rect(0, 50, 500, 500);
}
在这种特殊情况下,0-500 到 0-50 的范围是微不足道的:500 / 100 = 5,因此:
int h = i / 5;
会得到与 相同的结果int h = round(map(i, 0, 499, 0, 100));
,只是不必过多考虑算术。
在嵌套的 for 循环中,您正在设置 HSB 颜色。对于下一部分,您需要获取/读取 HSB 颜色,幸运的是,Processing 已经为您提供了hue()、saturation()和brightness()。对于颜色选择器,您只需要hue()
.
要获取光标位置下的颜色,您只需调用get(x, y)
它返回那些坐标的颜色。
如果您查看渐变图像,您会注意到:
- 左侧完全饱和,右侧去饱和(灰色):x轴必须映射饱和度
- 顶部是亮的,底部是暗的:y 轴必须映射亮度
如果您阅读了hue()
鼠标单击顶部彩虹渐变时的内容,则可以通过简单地将 x,y 坐标映射到饱和度和亮度来制作更大的渐变波纹管:
float hue;
void setup() {
size(500, 550);
colorMode(HSB, 100);
for (int i = 0; i < 500; i++) {
for (int j = 0; j < 50; j++) {
// remap i (x -> width) to 0 - 100 range for hue
// since map returns a float, round helps make that an int
int h = round(map(i, 0, 499, 0, 100));
int s = 100;
int b = 100;
stroke(h, s, b);
point(i, j);
}
}
noStroke();
}
void draw() {
// pick colour (hue)
if(mousePressed){
// check if the mouse was pressed on the top side only
if((mouseX >= 0 && mouseX <= 500) &&
(mouseY >= 0 && mouseY <= 50)){
hue = hue(get(mouseX, mouseY));
}
}
// render saturation , brightness mapping
for (int i = 0; i < 500; i++) {
for (int j = 50; j < 550; j++) {
int saturation = round(map(i, 0, 500, 100, 0));
// swap output mapping range: brightness goes up when y decreases
int brightness = round(map(j, 50, 550, 100, 0));
stroke(hue, saturation, brightness);
point(i, j);
}
}
}
你会注意到这运行有点慢。使用pixels[]
. 但是有一些曲线球:
- 您需要先调用
loadPixels()
才能读取像素
- 您需要将 x,y 位置转换为一维数组索引:
index = x + y * width
- 您需要
updatePixels()
在设置值后调用pixels[]
以更新
这将运行得更快:
float hue;
void setup() {
size(500, 550);
colorMode(HSB, 100);
for (int i = 0; i < 500; i++) {
for (int j = 0; j < 50; j++) {
// remap i (x -> width) to 0 - 100 range for hue
// since map returns a float, round helps make that an int
int h = round(map(i, 0, 499, 0, 100));
int s = 100;
int b = 100;
stroke(h, s, b);
point(i, j);
}
}
noStroke();
}
void draw() {
// make latest pixels[] data available
loadPixels();
// pick colour (hue)
if(mousePressed){
// check if the mouse was pressed on the top side only
if((mouseX >= 0 && mouseX <= 500) &&
(mouseY >= 0 && mouseY <= 50)){
//hue = hue(get(mouseX, mouseY));
hue = hue(pixels[mouseX + mouseY * width]);
}
}
// render saturation , brightness mapping
for (int i = 0; i < 500; i++) {
for (int j = 50; j < 550; j++) {
int saturation = round(map(i, 0, 500, 100, 0));
// swap output mapping range: brightness goes up when y decreases
int brightness = round(map(j, 50, 550, 100, 0));
//stroke(hue, saturation, brightness);
//point(i, j);
pixels[i + j * width] = color(hue, saturation, brightness);
}
}
// update
updatePixels();
}