# Complex gradient loop

And playing with the program and I am hallucinating with results. I have obtained this amazing gradient that you can see here:

colorMode( HSB, 360,100,100 );

``````color c = color( random(1,360), 100, 100 );
``````

But sometimes the result is dirtier because the colors of the points art not as closer and organized in the colour wheel:

So how could I relate these points to follow the order of colors in colour wheel, from hue 1 to 360 in HSB color mode? Imagine that randoms colors are 22,45,154, 263,302 and 313, how could I distribute them like this: point 1(22), point 2(45), point 3(154), point 4(263), point 5(302), point 6(313)?

1 Like

In `initControlPoints()`, you could change it to:

``````  for( int i=0; i<N; i++ ) {
float ang = TAU*i/N;
int x = (int)((0.5 + 0.4*cos(ang)) * 65536);
int y = (int)((0.5 + 0.4*sin(ang)) * 65536);
color c = color( 360.0*i/N, 100, 100 );
inputs.pixels[ i ] = (x << 16) | y;
inputs.pixels[ i+N ] = c;
}
``````

If you want some randomness, you would want to randomly generate and store N hue values in an array, sort it, and read them out in order when filling the `input.pixels`.

``````  float[] hues = new float[N];
for( int i=0; i<N; i++ ) hues[i] = random(360);
hues = sort( hues );
for( int i=0; i<N; i++ ) {
float ang = TAU*i/N;
float r = random( 0.2, 0.5 );
int x = (int)((0.5 + r*cos(ang)) * 65536);
int y = (int)((0.5 + r*sin(ang)) * 65536);
color c = color( hues[i], 100, 100 );
inputs.pixels[ i ] = (x << 16) | y;
inputs.pixels[ i+N ] = c;
}
``````
1 Like

Hi

Complex but easy

``````void setup () {
size (600,600);
colorMode(HSB);
}
void draw(){
for(int i= 600; i >0; i=i -1) {
stroke((i/2) + (mouseX/2), 300,300);
rect(0,0,i ,i);
}
}

``````

well, no I am trying to change

size( 1200, 1600, P3D );

and I receive this message:

âThe sketch has been resized from 1200x1600 to 1200x1055 by the operating system.
This happened outside Processing, and may be a limitation of the OS or window manager.â

how could make this image bigger in windows?

1 Like

You can keep `size()` so it fits on your screen, but, in my code above, you can set the size of the `grad` PGraphics to be as large as you want.

So

``````void setup() {
size( 600, 800, P3D );
colorMode( HSB, 1, 1, 1, 1 );
grad = createGraphics( width*2, height*2, P3D );
initControlPoints();
noLoop();
}
``````

and in `draw()`, change `image()` to `image( grad, 0, 0, width, height );` and where I have `save( fileName );` change it to `grad.save( fileName );` so it saves the PGraphics image rather than the screen image.

1 Like

And what If I wanted to choose coordinates and colors of the control points? How could I use, for example, these values?

``````float x1 = 525;
float y1 = 150;
float x2 = 990;
float y2 = 500;
float x3 = 550;
float y3 = 925;
float x4 = 275;
float y4 = 725;
float x5 = 500;
float y5 = 125;
float x6 = 250;
float y6 = 200;

color a = color(179,100,100);
color b = color(68, 100,100);
color c = color(303, 100,100);
color d = color(299, 100,100);
color e = color(276, 100,100);
color f = color(193, 100,100);
``````
1 Like

Put them in an array and read from the array in the loop to fill the `inputs` texture. For instance if you have the coordinates in `x[]` and `y[]` and the colors in `c[]`, then you would use:

``````  for( int i=0; i<N; i++ ) {
int x = (int)(65536 * x[i] / grad.width);
int y = (int)(65536 * y[i] / grad.height);
inputs.pixels[ i ] = (x << 16) | y;
inputs.pixels[ i+N ] = c[i];
}
``````
2 Likes

like this?

``````float[] positions =  new float [12];
float [x1] = 525;
float [y1] = 150;
float [x2] = 990;
float [y2] = 500;
float [x3] = 550;
float [y3] = 925;
float [x4] = 275;
float [y4] = 725;
float [x5] = 500;
float [y5] = 125;
float [x6] = 250;
float [y6] = 200;

color[] colors = new color [];
color [a] = color(179,100,100);
color [b] = color(68, 100,100);
color [c] = color(303, 100,100);
color [d] = color(299, 100,100);
color [e] = color(276, 100,100);
color [f] = color(193, 100,100);

``````

More like this. Itâs easier to make a 2D array of floats for the positions. I wouldnât name an array `color` since thatâs already a Processing function name â could be confusing.

1 Like

Hi

Thanks! And do I receive this message? âNullPointerExceptionâ for this line

``````inputs.pixels[ i ] = (x << 16) | y;
``````
``````PImage inputs;

int N = 9;
float strength = 1.;
boolean bShowPoints = true;
boolean bSaveFrame = false;

void setup() {
size( 750, 1000, P3D );
//fullScreen( P3D, SPAN );
colorMode( HSB, 360,100,100 );
grad = createGraphics( width, height, P3D );
initControlPoints();
noLoop();
}

void initControlPoints() {
float[][] pos = {
{ 525, 150 }, { 990, 500 }, { 550, 925 },
{ 275, 725 }, { 500, 125 }, { 250, 200 }
};
color[] cols = {
color( 179, 100, 100 ), color( 68, 100, 100 ), color( 303, 100, 100 ),
color( 299, 100, 100 ), color( 276, 100, 100 ), color( 193, 100, 100 )
};

for( int i=0; i<N; i++ ) {
int x = (int)(65536 * pos[i][0] / grad.width);
int y = (int)(65536 * pos[i][1] / grad.height);
inputs.pixels[ i ] = (x << 16) | y;
inputs.pixels[ i+N ] = cols[i];
}
//inputs = createImage( N, 2, ARGB );
//float[] hues = new float[N];
// for( int i=0; i<N; i++ ) hues[i] = random(360);
//hues = sort( hues );
//for( int i=0; i<N; i++ ) {
//float ang = TAU*i/N;
// float r = random( 0.2, 0.5 );
// int x = (int)((0.5 + r*cos(ang)) * 65536);
// int y = (int)((0.5 + r*sin(ang)) * 65536);
//color c = color( hues[i], 100, 100 );
//inputs.pixels[ i ] = (x << 16) | y;
//inputs.pixels[ i+N ] = c;
//}
//inputs.updatePixels();
}

void draw() {
image( grad, 0, 0 );
if( bShowPoints )
text( str(N)+"    "+str(strength), 8, 16 );
if( bSaveFrame ) {
String fileName = getClass().getSimpleName() + "-" +
nf(year(),4) + "-" + nf(month(),2) + "-" + nf(day(),2) + "-" +
nf(hour(),2) + "-" + nf(minute(),2) + "-" + nf(second(),2) + ".TIFF";
save( fileName );
println( "saved " + fileName );
bSaveFrame = false;
}
}

void keyPressed() {
if( keyCode == ENTER ) initControlPoints();
else if( keyCode == DOWN ) {
strength /= 1.1;
}
else if( keyCode == UP ) {
strength *= 1.1;
}
else if( keyCode == LEFT ) { N = max(N-1, 1);  initControlPoints(); }
else if( keyCode == RIGHT ) { N++;  initControlPoints(); }
else if( key == ' ' ) bShowPoints = !bShowPoints;
else if( key == '+' ) bSaveFrame = true;
redraw();
}

String[] gradVert = {"""
#version 330
uniform mat4 transformMatrix;
in vec4 position;
void main() {
gl_Position = transformMatrix * position;
}
"""};

String[] gradFrag = {"""
#version 330
precision highp float;
uniform vec2 resolution;
uniform sampler2D inputs;
uniform int N;
uniform bool bShowPoints;
uniform float strength;
out vec4 fragColor;

void main() {
float aspect = resolution.x/resolution.y;
vec2 uv = gl_FragCoord.xy / resolution.y;
vec3 col = vec3(0.);
float totw = 0.;
for( int i=0; i<N; i++ ) {
vec4 posData = texelFetch( inputs, ivec2( i, 0 ), 0 ) * 255.0;
float x = (posData.a * 256 + posData.r)*aspect;
float y = posData.g * 256 + posData.b;
vec2 pos = vec2( x, y ) / 65536.0;
vec3 c = texelFetch( inputs, ivec2( i, 1 ), 0 ).rgb;
float d = length( uv - pos );
float w = exp( -d*d*N*strength );
if( w > 0 ) {
col += c * w;
totw += w;
}
}
if( totw > 0. ) col /= totw;

if( bShowPoints ) {
for( int i=0; i<N; i++ ) {
vec4 posData = texelFetch( inputs, ivec2( i, 0 ), 0 ) * 255.0;
float x = (posData.a * 256 + posData.r)*aspect;
float y = posData.g * 256 + posData.b;
vec2 pos = vec2( x, y ) / 65536.0;
vec3 c = texelFetch( inputs, ivec2( i, 1 ), 0 ).rgb;
float d = length( uv - pos );
if( d < 0.01 ) col = vec3(1.);
if( d < 0.007 ) col = c;
}
}

fragColor = vec4( col, 1. );
}
"""};
``````

You have to keep the rest of the code that creates the PImage. And because you have 6 points, you have to set N to 6 at the top or can set it to `N = pos.length;` after creating the `pos` array as I did in the code below.

``````void initControlPoints() {
float[][] pos = {
{ 525, 150 }, { 990, 500 }, { 550, 925 },
{ 275, 725 }, { 500, 125 }, { 250, 200 }
};
color[] cols = {
color( 179, 100, 100 ), color( 68, 100, 100 ), color( 303, 100, 100 ),
color( 299, 100, 100 ), color( 276, 100, 100 ), color( 193, 100, 100 )
};

N = pos.length;
inputs = createImage( N, 2, ARGB );