1
votes

I want an smooth curve in webgl so I tried to draw a rectangle in vertex shader and send positions to fragment shader in normalize size and Size parameter which is the real size of square

in  vec2 Position;
in  vec2 Size;

out vec2 vPosition;
out vec2 vSize;
void main() {
    vSize = Size;
    vPosition = Position
    gl_Position = Position * Size


}

when size = [width, height] of square and is equal for every vertex and position = [ -1 , -1 , -1 , 1 , 1 , -1 , 1 , 1 , ] so my rectangle will be drawn in [2 * width , 2 * height] but I can do geometric operations in fragment shader with a 2 * 2 square which is normalized but I have a problem with drawing ellipse(or circle with this sizes) in fragment shader when I want to make hollow circle with a thickness parameter it's thickness in horizontal direction is not same as vertical direction and I know it's because of that I'm using same size for horizontal and vertical directions(2,2) but in display they are different and this is the problem which make this image as you can see thickness in all of it is not same.

I want a geometry formula to calculate thickness in each direction then I can draw a hollow ellipse.

thanks in advance. sorry for bad English

2

2 Answers

1
votes

If you put heavy mathematical computing in your fragment shader, it will be slow. The trick can be to use an approximation that can be visually acceptable.

Your problem is that the thickness is different on the vertical and the horizontal axis. What you need is discarding fragments if the radius of the current point is greater than 1 and lower than radiusMin. Let uniWidth and uniHeight be the size of your rectangle. * When y is null, on the horizontal axis, radiusMin = 1.0 - BORDER / uniWidth. * When x is null, on the vertical axis, radiusMin = 1.0 - BORDER / uniHeight.

The trick is to interpolate between this two radii using the mix() function. Take a look at my live example below to convince you that the result is not that bad.

Here is the fragment shader to do such a computation:

precision mediump float;
uniform float uniWidth;
uniform float uniHeight;
varying vec2 varCoords;

const float BORDER = 32.0;

void main() {
  float x = varCoords.x;
  float y = varCoords.y;
  float radius = x * x + y * y;
  if( radius > 1.0 ) discard;

  radius = sqrt( radius );

  float radiusH = 1.0 - BORDER / uniWidth;
  float radiusV = 1.0 - BORDER / uniHeight;
  float radiusAverage = (radiusH + radiusV) * 0.5;

  float minRadius = 0.0;
  x = abs( x );
  y = abs( y );
  if( x > y ) {
    minRadius = mix( radiusH, radiusAverage, y / x );
  }
  else {
    minRadius = mix( radiusV, radiusAverage, x / y );
  }

  if( radius < minRadius ) discard;

  gl_FragColor = vec4(1, .5, 0, 1);
}

Here is a live example: https://jsfiddle.net/7rh2eog1/5/

0
votes

There is a implicit formula for x and y which are in the blue area in hollow ellipse with thickness parameter, As we know the thickness and we have the size of our view we can make two ellipse with size1 = Size - vec2(thickness) and size2 = Size + vec2(thickness) and then length(position/size1) < 1.0 < length(position/size2)