3

Using regl, I am trying to draw a triangle with WebGL where I can define a color at some reference point inside the triangle, and have the color of the other pixels be a function of their distance to this point.

So far, it only works when this reference point is one of the corner :

gradient from corner

This was done using the following Vert and Frag shaders :

  vert: `
  precision mediump float;
  uniform float scale;
  attribute vec2 position;
  attribute vec3 color;
  varying vec3 fcolor;
  void main () {
    fcolor = color;
    gl_Position = vec4(scale * position, 0, 1);
  }
  `,

  frag: `
  precision mediump float;
  varying vec3 fcolor;
  void main () {
    gl_FragColor = vec4(sqrt(fcolor), 1);
  }
  `,

  attributes: {
    position: [
      [1, 0],
      [0, 1],
      [-1, -1]
    ],

    color: [
      [1, 0, 0],
      [0, 1, 0],
      [0, 0, 1]
    ]
  },

  uniforms: {
    scale: regl.prop('scale')
  }

The reference points here are [1,0], [0,1] and [-1,-1]. With the same triangle, how do I put another reference point at [0,0] with color white for instance ? (that would give an "island" of white inside the triangle)

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Ren
  • 35
  • 4

1 Answers1

3

You have to define 2 uniform variables One for the coordinates of the reference point and one for the color of the reference point:

uniforms: {
    scale: regl.prop('scale'),
    refPoint: [0, 0],
    refColor: [1, 1, 1]
}

Pass the vertex coordinate from the vertex shader to the fragment shader by a varying variable:

precision mediump float;

uniform float scale;

attribute vec2 position;
attribute vec3 color;

varying vec2 fpos;
varying vec3 fcolor;

void main()
{
    fpos        = position;
    fcolor      = color;
    gl_Position = vec4(scale * position, 0, 1);
}

Calculate the distance from the reference point to the interpolated position in the fragment shader, by distance:

float dist = distance(refPoint, fpos);

Interpolate the colors dependent on the distance, by mix:

vec3 micColor = mix(refColor, fcolor, dist);

Fragment shader:

precision mediump float;

uniform vec2 refPoint;
uniform vec3 refColor;

varying vec2 fpos;
varying vec3 fcolor;

void main()
{
    float dist    = distance(refPoint, fpos);
    vec3 micColor = mix(refColor, fcolor, dist);
    gl_FragColor  = vec4(sqrt(micColor), 1);
}

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
  • Thanks for the answer ! Is there any reason to calculate the interpolation in the Frag shader rather than in the Vertex one (and then passing it to the Frag) ? – Ren Mar 06 '19 at 08:40
  • @Ren Yes, because the interpolated color depends on the distance to the position which is associated to the fragment. This distance has to be calculated in the fragment shader. If you would calculate this in the vertex than this would be calculated 3 times per vertex. So if for example the point is in the center of the triangle, then the distance to the 3 corner points is the same and the interpolation on the fragments will give the same result for each fragment. – Rabbid76 Mar 06 '19 at 09:21
  • Thanks a lot :) Have a great day ! – Ren Mar 06 '19 at 11:18