基于TensorFlow.js WebGL按心形隐式公式绘制仅显示半幅的问题求解
半幅爱心显示不全的核心原因
- 隐式方程实现错误
参考心形的判定规则为:满足(x²+y²−r²)³−rx²y³ < 0的区域为心形内部。代码中实现的计算项为pow(x²+y²−a²,3.0) - a*x³*y²,将公式中的x²y³项错写为x³y²,直接把原心形旋转90度,轮廓完全错位。 - 坐标轴映射错位
画布坐标系与平面直角坐标系的对应关系为:- 列索引
coords[1](水平方向,从左到右递增)对应x轴 - 行索引
coords[0](垂直方向,从上到下递增)对应y轴
代码中将行索引的偏移量赋值给x、列索引的偏移量赋值给y,等于直接互换了x、y轴。结合前面的公式错误,最终只有半侧区域能满足内部判定条件。
- 列索引
- 坐标偏移尺度不匹配
代码中x、y的计算未结合画布实际宽高做中心对齐,固定a=100的参数没有适配画布400300的尺寸*,容易让心形轮廓超出显示范围。
可直接落地的调整方案
- 修正公式计算项,严格匹配参考规则:将原表达式中的
-a*x3*y2替换为-a*x2*y3 - 重写坐标映射逻辑:
- x轴由列索引计算:
float x = float(coords[1] - ${w} / 2.0),实现水平居中,覆盖范围-w/2 ~ w/2 - y轴由行索引反向计算:
float y = float(${h} / 2.0 - coords[0]),匹配数学坐标系y轴向上为正的规则,覆盖范围h/2 ~ -h/2
- x轴由列索引计算:
- 调整参数a的取值为120,适配当前画布尺寸,保证心形完整落在可视区域内。
- 移除绘制完成后手动修改canvas宽高的逻辑,避免画面拉伸变形。建议将初始背景tensor设置为0值,提升心形与背景的对比度。
修正后的核心代码片段
void main() { ivec3 coords = getOutputCoords(); // 坐标映射修正 float x = float(coords[1] - ${w} / 2.0); float y = float(${h} / 2.0 - coords[0]); float a = 120.0; float x2 = x * x; float y2 = y * y; float y3 = y2 * y; // 严格匹配参考隐式方程判定规则 float val = pow(x2 + y2 - a*a, 3.0) - a * x2 * y3; int r = coords[0]; int c = coords[1]; int d = coords[2]; if(val < 0.0) { setOutput(255.0); // 心形区域输出纯白色 } else { setOutput(getX(r, c, d)); // 非心形区域保留原背景值 } }
补充说明
- 调整心形大小时,仅需修改参数a即可,a值越大心形尺寸越大,建议a值不超过画布短边的0.7倍,避免轮廓被边缘裁切。
- 不需要在绘制后修改canvas宽高,保持canvas尺寸与tensor形状(400*300)一致即可,额外修改宽高会导致画面拉伸模糊。
内容的提问来源于stack exchange,提问作者edkeveked
相关产品推荐
相关产品推荐

