Creative coding color study : Gradients
I've been impressed by the sight of the morning glory. Many colors weave complex gradients minutely and capriciously. How can I draw these gradients with my creative coding?
Stacking half-transparent colors
Stacking half-transparent colors in p5.js/Processing generates mixed colors.
I'll use the method of stacking half-transparent colors to make complex gradients.
Now, the 'blendMode()' function gives various effect on the mixed colors.
The 'blendMode(SCREEN)' makes it brighter as you stack the colors. It behaves like light.
The 'blendMode(SUBTRACT)' makes it darker as you stack the colors. It behaves like paints
I think the 'blendMode(BLEND)' (default blend-mode) is easy to stack the half-transparent colors. And I like the difference of mixed colors in the order of stacking.
How can I change the colors smoothly?
I'll try to change the colors by controlling the transparency.
Linear
It's the example that changes transparency in linear.
I feel the vary is rough, especially in the center of the colors.
Sine curve
It's the example that changes transparency in the sine curve.
It seems to change the colors more smoothly than the linear. But I'm concerned the edge seems to end suddenly.
The normal distribution
Is changing the colors with the normal distribution might seem to vary naturally? So I'll try changing colors in the bell curve.
The edge part seems to change smoothly. And I get the bonus I can control the change with the mean and the variance.
The example work of the gradient
It's an example of artwork changing colors in the bell curve.
The colors are half-transparent so the background can be seen through. You can make a composition by the background painting.
I placed the different color rectangles to be vertically arranged this time.
The p5.js example code
/**
* Gradation of Blue.
*
* @author @deconbatch
* @version 0.1
* @license CC0
* p5.js 1.5.0
* created 2022.12.02
*/
function setup() {
createCanvas(640, 1000);
colorMode(HSB, 360, 100, 100, 100);
noSmooth();
noLoop();
blendMode(BLEND);
const yL = 0.7;
// background
fill(220, 90, 30, 100);
rect(0, 0, width, height * yL);
fill(220, 60, 90, 100);
rect(0, height * yL, width, height);
stroke(0, 0, 100, 100);
line(0, height * yL, width, height * yL);
// gradation
gradateY(200, yL, 0.02, 80, createVector(55, 10, 100));
gradateY(200, 0.1, 0.03, 80, createVector(260, 90, 5));
}
/**
* gradateY : draw alpha gradation with the probability distribution function on Y-axis.
* _divNum : divide number.
* _mean : mean value of the probability distribution.
* _vari : variance value of the probability distribution.
* _alpBase : alpha value on the top of the probability distribution curve.
* _color : x = hue, y = saturation, z = brightness
*/
function gradateY(_divNum, _mean, _vari, _alpBase, _color) {
const divW = height / _divNum;
const topV = 1 / sqrt(TWO_PI * _vari);
noStroke();
for (let i = 0; i < _divNum; i++) {
let divRate = map(i, 0, _divNum, 0, 1);
let density = exp(-pow(divRate - _mean, 2) / (2 * _vari)) / sqrt(TWO_PI * _vari);
fill(_color.x, _color.y, _color.z, _alpBase * density / topV);
rect(0, i * divW, width, divW);
}
}
I used 'PVector' to decrease the parameter number of the 'gradateY()' function.
The Processing example code
/**
* Gradation of Blue.
*
* @author @deconbatch
* @version 0.1
* @license CC0
* Processing 3.5.3
* created 2022.12.02
*/
public void setup() {
size(640, 1000);
colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
noSmooth();
noLoop();
blendMode(BLEND);
float yL = 0.7;
// background
fill(220.0, 90.0, 30.0, 100.0);
rect(0.0, 0.0, width, height * yL);
fill(220.0, 60.0, 90.0, 100.0);
rect(0.0, height * yL, width, height);
stroke(0, 0, 100, 100);
line(0, height * yL, width, height * yL);
// gradation
gradateY(200, yL, 0.02, 80.0, new PVector(55.0, 10.0, 100.0));
gradateY(200, 0.1, 0.03, 80.0, new PVector(260.0, 90.0, 5.0));
}
/**
* gradateY : draw alpha gradation with the probability distribution function on Y-axis.
* _divNum : divide number.
* _mean : mean value of the probability distribution.
* _vari : variance value of the probability distribution.
* _alpBase : alpha value on the top of the probability distribution curve.
* _color : x = hue, y = saturation, z = brightness
*/
public void gradateY(int _divNum, float _mean, float _vari, float _alpBase, PVector _color) {
float divW = height * 1.0 / _divNum;
float topV = 1.0 / sqrt(TWO_PI * _vari);
noStroke();
for (int i = 0; i < _divNum; i++) {
float divRate = map(i, 0, _divNum, 0.0, 1.0);
float density = exp(-pow(divRate - _mean, 2) / (2.0 * _vari)) / sqrt(TWO_PI * _vari);
fill(_color.x, _color.y, _color.z, _alpBase * density / topV);
rect(0.0, i * divW, width, divW);
}
}
Final notes
The title drawing is my impression of the dawn I saw on my morning walk.
The example code uses the gradient with Y-axis only. You can enjoy the X-axis, limitation of the gradient area or rotation, etc. Please have fun with devising.