GPU.js绘制曼德博集合时CPU与GPU模式计算结果不一致
问题:GPU.js绘制曼德博集合时CPU与GPU模式计算结果不一致
尝试用GPU.js绘制曼德博集合,CPU模式下每个像素的iters值符合预期,但GPU模式下iters始终为0。核心代码如下:
function inlineTestPoint(initialReal, initialImag, maxIterations) { let currentReal = initialReal; let currentImag = initialImag; let i = 0; for (;i < maxIterations; i++) { const curRealSq = (currentReal * currentReal); const curImagSq = (currentImag * currentImag); if (curRealSq + curImagSq <= 4) { currentImag = (2 * currentReal * currentImag) + initialImag; currentReal = (curRealSq - curImagSq) + initialReal; } else { break; } } return i; } function mapRange(n, sourceMin, sourceMax, targetMin, targetMax) { const sourceRatio = (n - sourceMin) / (sourceMax - sourceMin); return (sourceRatio * (targetMax - targetMin)) + targetMin; } const canvasWidth = 1000; const canvasHeight = 1000; const gpu = new GPU({mode: "gpu"}); gpu.addFunction(mapRange, {argumentTypes: ['Float', 'Float', 'Float', 'Float', 'Float'], returnType: 'Float'}); gpu.addFunction(inlineTestPoint, {source: inlineTestPoint, argumentTypes: ['Float', 'Float', 'Float'], returnType: 'Integer'}); const kernel = gpu.createKernel(function(canvasWidth,canvasHeight) { const canvasX = this.thread.x; const canvasY = this.thread.y; const real = mapRange(canvasX, 0, canvasWidth, -2, 2); const imag = mapRange(canvasY, 0, canvasHeight, -2, 2); const iters = inlineTestPoint(real, imag, 200); this.color(iters / 50, iters / 100, iters / 200); //return [real, imag, iters]; }) .setGraphical(true) .setLoopMaxIterations(200) .setOutput([canvasWidth, canvasHeight]); kernel(canvasWidth, canvasHeight);
原因与解决方案
核心问题1:参数类型不匹配
inlineTestPoint的第三个参数maxIterations被声明为Float类型,但实际传入的是整数200。GPU的GLSL对类型匹配要求严格,浮点数与整数的比较逻辑可能导致循环未正确执行。
核心问题2:let变量声明的兼容性
GPU.js会将JavaScript函数转换为GLSL代码,而GLSL中没有let关键字,部分GPU驱动对转换后的代码兼容性不佳,导致变量初始化或循环逻辑出错。
修复步骤:
- 修正参数类型:将
inlineTestPoint的参数类型数组中第三个元素从'Float'改为'Integer':gpu.addFunction(inlineTestPoint, {source: inlineTestPoint, argumentTypes: ['Float', 'Float', 'Integer'], returnType: 'Integer'}); - 替换
let为var:修改inlineTestPoint内部的变量声明,确保GLSL转换正常:function inlineTestPoint(initialReal, initialImag, maxIterations) { var currentReal = initialReal; var currentImag = initialImag; var i = 0; for (;i < maxIterations; i++) { const curRealSq = (currentReal * currentReal); const curImagSq = (currentImag * currentImag); if (curRealSq + curImagSq <= 4) { currentImag = (2 * currentReal * currentImag) + initialImag; currentReal = (curRealSq - curImagSq) + initialReal; } else { break; } } return i; }
完成上述修改后,GPU模式下的计算结果应与CPU模式一致,正常渲染曼德博集合。
内容的提问来源于stack exchange,提问作者Carcigenicate
相关产品推荐
相关产品推荐

