2
\$\begingroup\$

EDIT: Ok so the question here is how to you generate a linear gradient along a vector.

Here is the function i'm looking for:

function CreateGradient(x,y, x1,y1,x2,y2) {
    // x and y are the point in our image we are looking to create the  color for in grayscale
    // x1,y1,x2,y2 is the vector in which the linear gradient should run
    // Can be in any language
}

What I have so far (that doesn't work):

var width = 2.0;
var offset = 0;

var convX = ((x / RES) * width - width/2) - offset;
var convY = ((y / RES) * width - width/2) - offset;

var angle = Math.atan(y1-y2, x1-x2);


var rx = Math.cos(angle);
var ry = Math.sin(angle);

var here = convX * rx + convY * ry;
var start = x1 * rx + y1 * ry;
var end = x2 * rx + y2 * ry;

var lerpValue = (start - here) / (start - end);

var val = lerp(0,255,clamp(lerpValue,0.0,1.0));

RES is the total resolution of the picture. val in the value (0-255) which represents the R G and B values of the pixel

Final Edit: I have it now thanks code for the future:

var x1 = 0;
var y1 = 0;
var x2 = 255;
var y2 = 255;

var dx = x2-x1;
var dy = y2-y1;

var rx = x-x1;
var ry = y-y1;

var t = ((rx*dx) +(ry*dy)) / ((dx*dx) + (dy*dy));


return lerp(0,255,t);
\$\endgroup\$
  • \$\begingroup\$ Ok I'll make it easier then how to you generate a linear gradient between two points (x1,y1,x2,y2) \$\endgroup\$ – Dave3of5 Jul 9 '16 at 16:12
  • \$\begingroup\$ Ok I've updated is this clearer ? \$\endgroup\$ – Dave3of5 Jul 9 '16 at 16:20
3
\$\begingroup\$

It looks an introduction to linear algebra is in order, or more precisely the dot product:

dot(a, b) = |a| |b| cos(Theta)

Why is it helpful? Because of its relation to the scalar/vector projection, the length of projection of vector a onto vector b is

lenPA = |a| cos(theta)

or more practically, derived from dot product definition:

lenPA = (a . b) / |b|

and when you know how far the current coordinate is projected onto the line between gradient's step1 and step2, all you have to do is to normalize it:

t = lenPA / |b|
color = lerp(color1, color2, t)

where a is relative position of fragment xy to the gradient step1 and b is non-normalized gradient (direction) going from step1 to step2.
copy/paste code (for shadertoy):

vec2 step1 = vec2(200, 200);
vec2 step2 = vec2(400, 400);

vec4 color1 = vec4(0.0,0.5,1.0,1.0);
vec4 color2 = vec4(1.0,5.0,0.0,1.0);

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    //----constant, can pre compute------
    vec2 gDrirection = step2 - step1;
    float lenSq = dot(gDrirection, gDrirection);//len(gDrirection)^2
    //-----------------------------------
    vec2 relCoords = fragCoord - step1;
    float t = dot (relCoords, gDrirection) /  lenSq;
    fragColor = mix(color1, color2, t); //mix = lerp
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Hey thanks, I don't understand those wikipedia articles fully. But this is what I'm looking for I just needed to know how to project a point onto a 2d vector I think I can take it from here thanks. \$\endgroup\$ – Dave3of5 Jul 9 '16 at 18:28
  • \$\begingroup\$ @Dave3of5 Just read the glsl code - dot the relative coordinates to first gradient point coords - step1 and the gradient direction step2 - step1 and than divide it by squared length of latter vector: float t = dot (relCoords, gDrirection) / lenSq; <- thats all relevat code. Or are you not sure how do vector operations like subtracting or dot product? Dot product is member-wise (x to x, y to y etc.) multiplication of which products you sum to single number. \$\endgroup\$ – wondra Jul 9 '16 at 18:41
1
\$\begingroup\$

is this what you want ?

    float endPercent = curLength / totalLength;                                                         // Calculates the percent of colour at the ending point of the line to be used in current pixel 
    float startPercent = 1 - (curLength / totalLength);                                                 // Calculates the percent of colour at the starting point of the line to be used in current pixel 

    float a = Math.abs(end.getColour().getAInInt() * endPercent + start.getColour().getAInInt() * startPercent);    //Interpolating alpha
    float r = Math.abs(end.getColour().getRInInt() * endPercent + start.getColour().getRInInt() * startPercent);    //Interpolating red 
    float g = Math.abs(end.getColour().getGInInt() * endPercent + start.getColour().getGInInt() * startPercent);    //Interpolating green 
    float b = Math.abs(end.getColour().getBInInt() * endPercent + start.getColour().getBInInt() * startPercent);    //Interpolating blue 

    return new PixelData(a, b, g, r);                                                                   // returing the intepolated value 

enter image description here

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ hey not quite but thanks so much for responding. \$\endgroup\$ – Dave3of5 Jul 9 '16 at 19:50
  • \$\begingroup\$ @Dave3of5 sorry i could not help much. :) \$\endgroup\$ – A---B Jul 9 '16 at 22:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.