You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Babylon JS通过DynamicTexture在球体上绘制圆形出现椭圆变形问题

Fixing Stretched Ellipses When Drawing on a Sphere with DynamicTexture

Hey Carlos, I’ve run into this exact issue before with Babylon.js’s DynamicTexture on spheres—here’s a quick, straightforward fix to get your circle looking round again!

Why This Happens

The problem boils down to how UV mapping works on spheres. Unlike a flat plane, a sphere’s UV coordinates don’t map 1:1 to equal lengths across its surface. The horizontal (longitude) axis spans 360 degrees, while the vertical (latitude) axis only spans 180 degrees. This means the texture gets compressed vertically relative to horizontally when wrapped around the sphere—so a perfect circle drawn on the flat DynamicTexture turns into an ellipse once applied.

Simple Fix: Adjust Your Arc to Counteract UV Stretch

The easiest solution is to draw an intentional ellipse on the DynamicTexture that gets "corrected" into a circle when stretched by the sphere’s UVs. Here’s how to do it:

Example Code for Equator Circle

If you’re placing your circle around the sphere’s equator (the most common case), use a 2:1 aspect ratio for your arc’s vertical radius to offset the UV compression:

// Set up your sphere and DynamicTexture
const sphere = BABYLON.MeshBuilder.CreateSphere("sphere", { diameter: 2 }, scene);
const textureSize = 512;
const dynamicTexture = new BABYLON.DynamicTexture("circleTex", { width: textureSize, height: textureSize }, scene);
const ctx = dynamicTexture.getContext();

// Counteract sphere UV stretch: longitude (360°) vs latitude (180°) = 2:1 ratio
const uvCorrectionRatio = 2;

// Draw an ellipse that becomes a circle on the sphere
ctx.beginPath();
// arc(x, y, radiusX, radiusY, startAngle, endAngle)
ctx.arc(
  textureSize / 2, // Center X
  textureSize / 2, // Center Y
  100,             // Horizontal radius (matches desired circle size)
  100 * uvCorrectionRatio, // Vertical radius (stretched to counter UV compression)
  0,
  Math.PI * 2
);
ctx.strokeStyle = "#ff0000";
ctx.lineWidth = 4;
ctx.stroke();

// Update texture and apply to sphere
dynamicTexture.update();
const mat = new BABYLON.StandardMaterial("sphereMat", scene);
mat.diffuseTexture = dynamicTexture;
sphere.material = mat;

For Circles Near Poles

If you need to draw a circle closer to the poles, the UV stretch changes with latitude. Use the cosine of the latitude angle (in radians) to calculate the correct correction ratio:

// Theta = latitude in radians (0 = equator, Math.PI/2 = north pole)
const theta = Math.PI / 4; // 45° north latitude
// Local stretch ratio: inverse of the parallel circumference at this latitude
const uvCorrectionRatio = 1 / Math.cos(theta);

// Use this ratio in your arc call just like the equator example
ctx.arc(textureSize/2, textureSize/2, 100, 100 * uvCorrectionRatio, 0, Math.PI*2);

How This Works

At any given latitude, the circumference of the sphere’s parallel (the circle around the sphere at that latitude) is smaller than the equator’s circumference by a factor of cos(theta). By stretching the vertical radius of our drawn ellipse by the inverse of that factor, we cancel out the UV compression, resulting in a perfect circle on the sphere’s surface.

内容的提问来源于stack exchange,提问作者Carlos Mendieta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:29:50