在片段着色器中绘制椭圆曲线

时间:2018-07-17 15:04:48

标签: webgl shader fragment-shader drawellipse

我想在webgl中获得平滑的曲线,所以我尝试在顶点着色器中绘制一个矩形,并以归一化大小和Size参数(即正方形的实际大小)将位置发送到片段着色器

in  vec2 Position;
in  vec2 Size;

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


}

当大小=正方形的[宽度,高度]并且对于每个顶点和position = [ -1 , -1 , -1 , 1 , 1 , -1 , 1 , 1 , ]相等时 所以我的矩形将以[2 * width,2 * height]绘制,但我可以在片段着色器中使用2 * 2的正方形进行几何操作 但是我想在片段着色器中绘制椭圆(或具有此尺寸的圆)时遇到问题,当我想使用厚度参数制作空心圆时,其水平方向的厚度与垂直方向的厚度不同,我知道这是因为我在水平方向和垂直方向上使用相同的大小(2,2),但在显示中它们是不同的,这就是使this image的厚度不一样的问题。

我想要一个几何公式来计算每个方向的厚度,然后绘制空心椭圆。

先谢谢。 对不起,英语不好

2 个答案:

答案 0 :(得分:0)

如果将大量的数学计算放入片段着色器中,它将很慢。 诀窍可能是使用视觉上可接受的近似值。

您的问题是垂直和水平轴上的厚度不同。 如果当前点的半径大于1且小于 radiusMin ,则需要丢弃碎片。假设 uniWidth uniHeight 为矩形的大小。 *当 y 为空时,在水平轴上, radiusMin = 1.0-BORDER / uniWidth 。 *当 x 为空时,在垂直轴上, radiusMin = 1.0-BORDER / uniHeight

诀窍是使用 mix()函数在这两个半径之间进行插值。 请看下面我的直播示例,以说服您结果还不错。

这是片段着色器进行这样的计算:

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);
}

这是一个实时示例:https://jsfiddle.net/7rh2eog1/5/

答案 1 :(得分:0)

对于x和y有一个隐式公式,它们位于带有厚度参数的空心椭圆的蓝色区域中,因为我们知道了厚度,并且我们拥有视图的大小,所以可以使两个椭圆的大小为size1 = Size-vec2(厚度)和size2 =大小+ vec2(厚度) 然后length(position / size1)<1.0