如何将画布坐标圆转为WebGL坐标,或生成对应顶点数组?
实现WebGL圆顶点数组函数及坐标转换方案
核心逻辑:WebGL与画布坐标的差异
WebGL采用标准化设备坐标(NDC):原点在画布中心,x轴向右、y轴向上,坐标范围为x∈[-1, 1]、y∈[-1, 1]。而普通画布坐标以左上角为原点,x向右、y向下,范围是[0, 画布宽度]、[0, 画布高度]。要避免圆被拉伸,必须根据画布宽高比做适配转换。
可直接用的WebGL圆顶点生成函数
这个函数接收像素半径、画布宽高、精度参数,返回WebGL可直接使用的扁平化顶点数组:
function createWebGLCircleVertices(radius, canvasWidth, canvasHeight, accuracy) { const vertices = []; const aspectRatio = canvasWidth / canvasHeight; // 计算从像素坐标到NDC的缩放因子 const scaleX = 2 * radius / canvasWidth; const scaleY = 2 * radius / canvasHeight; let theta = 0; const dtheta = (2 * Math.PI) / accuracy; for (let i = 0; i < accuracy; i++) { // 先计算中心原点的圆坐标,再转换为适配宽高比的NDC坐标 const x = Math.cos(theta) * scaleX / aspectRatio; const y = Math.sin(theta) * scaleY; vertices.push(x, y); theta += dtheta; } // 追加第一个顶点闭合圆形(按需添加,取决于GL_LINE_LOOP/GL_TRIANGLE_FAN等绘制模式) vertices.push(vertices[0], vertices[1]); return vertices; }
坐标转换关键步骤
- 原点迁移:通过缩放至
[-1,1]范围,将画布左上角原点转为WebGL要求的中心原点。 - 宽高比适配:除以
aspectRatio是为了防止非正方形画布上的圆被拉伸——NDC是正方形,画布宽大于高时,x轴需要额外缩放才能保持圆形比例。 - 顶点格式:WebGL要求扁平化数组(而非嵌套数组),因此直接推入
x,y数值。
原函数的问题修正
你提供的原函数存在三个核心问题:
- 参数使用
diameter而非radius,逻辑不够直观; - 生成的是画布左上角为原点的坐标,未转换到WebGL的中心原点坐标系;
- 未处理宽高比,非正方形画布上圆会变成椭圆。
通用归一化版本(着色器中适配尺寸)
如果想生成不依赖画布尺寸的归一化顶点,可使用这个版本,后续在着色器中做宽高比适配:
function createNormalizedCircleVertices(radius, accuracy) { const vertices = []; let theta = 0; const dtheta = (2 * Math.PI) / accuracy; for (let i = 0; i < accuracy; i++) { // 生成[-1,1]范围内的归一化圆坐标 const x = Math.cos(theta) * radius; const y = Math.sin(theta) * radius; vertices.push(x, y); theta += dtheta; } vertices.push(vertices[0], vertices[1]); return vertices; }
对应顶点着色器代码:
attribute vec2 a_position; uniform float u_aspectRatio; void main() { gl_Position = vec4(a_position.x / u_aspectRatio, a_position.y, 0.0, 1.0); }
内容的提问来源于stack exchange,提问作者Ned August
相关产品推荐
相关产品推荐

