当您的显示器屏幕分辨率不是正方形时,如何画一个圆而不是椭圆?

How to draw a circle instead of an ellipse when your monitor screen resolution isn't square?

我正在使用 WebGL,我试图剪掉我正在绘制的内容以绘制一个圆,但目前它正在绘制一个椭圆。这是我的片段着色器:

void main() {
  vec4 c = vec4((u_matrix * vec3(u_center, 1)).xy, 0, 1); // center

  float r = .25; // radius

  bool withinRadius = pow(v_pos.x - c.x, 2.) + pow(v_pos.y - c.y, 2.) < r * r;

  if (!withinRadius) { discard; }

  gl_FragColor = vec4(1, 1, 1, 1);
}

认为 问题是因为我的屏幕尺寸是 1920x1200,从 -1.0 到 +1.0 的水平剪辑 space 比垂直剪辑宽space 从 -1.0 到 +1.0。我认为解决方案可能涉及以某种方式对 clip-space 进行标准化,使其呈正方形,但我不确定该怎么做或推荐的处理方法是什么。你通常如何处理这种情况?

您必须从圆心到片段缩放矢量的 x 或 y 分量。向片段着色器添加一个不规则变量或常量,它保​​持纵横比 (aspect = width/height) 或 canvas 的分辨率,并按 缩放向量的 x 分量方面:

uniform vec2 u_resolution;

void main()
{
    float aspect = u_resolution.x / u_resolution.y;

    vec4 c = vec4((u_matrix * vec3(u_center, 1)).xy, 0, 1); // center
    float r = .25; // radius

    vec2 dist_vec = (v_pos.xy - c.xy) * vec2(aspect, 1.0);
    if (dot(dist_vec, dist_vec) > r*r)
        discard;

    gl_FragColor = vec4(1, 1, 1, 1); 
}

注意,我使用了 Dot product to compute the square of the Euclidean distance:

dot(va, vb) == va.x*vb.x + va.y*vb.y

fragCoord - 屏幕上像素的系统常数

(https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/gl_FragCoord.xhtml)

iResolution - 您必须自己调的屏幕分辨率

中心 - (0.5)

vec2 uv = fragCoord/iResolution.xy;

// fixe
    uv.x -= center;
    uv.x *= iResolution.x / iResolution.y;
    uv.x += center;
//

float color = length(uv-vec2(0.5));

color = smoothstep(0.46,0.47,color);