我有一个关于在 HTML5/Canvas/Javascript 中伪造 3d 的问题...
<canvas>
基本上,我在using上绘制了一个 2d 图像drawImage()
。
我想做的是绘制图像,然后置换球体上的纹理以看起来......类似球体......
为了清楚起见,请参见下图:
有任何想法吗?
我已经在谷歌上搜索到自己濒临死亡,它也不能是 WebGL,因为它必须在手机上工作......有没有办法做到这一点?
我有一个关于在 HTML5/Canvas/Javascript 中伪造 3d 的问题...
<canvas>
基本上,我在using上绘制了一个 2d 图像drawImage()
。
我想做的是绘制图像,然后置换球体上的纹理以看起来......类似球体......
为了清楚起见,请参见下图:
有任何想法吗?
我已经在谷歌上搜索到自己濒临死亡,它也不能是 WebGL,因为它必须在手机上工作......有没有办法做到这一点?
您可以在此处检查工作原型:http: //jsbin.com/ipaliq/edit
我敢打赌,优化和更好/更快的算法还有很多空间,但我希望这个概念证明能为您指明正确的方向。
基本算法遍历原始图像的每个像素,如果它受到球面变形,则计算其新位置。
结果如下:
代码:
var w = 150, h = 150;
var canvas=document.getElementById("myCanvas");
var ctx=canvas.getContext("2d");
ctx.fillStyle="red";
ctx.fillRect(0,0,w,h);
//-- Init Canvas
var initCanvas = function()
{
var imgData=ctx.getImageData(0,0,w,h);
for (i=0; i<imgData.width*imgData.height*4;i+=4)
{
imgData.data[i]=i%150*1.5;
imgData.data[i+1]=i%150*1.5;
imgData.data[i+2]=(i/imgData.width)%150*1.5;
imgData.data[i+3]=255;
}
ctx.putImageData(imgData,0,0);
};
initCanvas();
var doSpherize = function()
{
var refractionIndex = 0.5; // [0..1]
//refraction index of the sphere
var radius = 75;
var radius2 = radius * radius;
var centerX = 75;
var centerY = 75;
//center of the sphere
var origX = 0;
var origY = 0;
for (x=0; x<w;x+=1)
for (y=0; y<h;y+=1)
{
var distX = x - centerX;
var distY = y - centerY;
var r2 = distX * distX + distY * distY;
origX = x;
origY = y;
if ( r2 > 0.0 && r2 < radius2 )
{
// distance
var z2 = radius2 - r2;
var z = Math.sqrt(z2);
// refraction
var xa = Math.asin( distX / Math.sqrt( distX * distX + z2 ) );
var xb = xa - xa * refractionIndex;
var ya = Math.asin( distY / Math.sqrt( distY * distY + z2 ) );
var yb = ya - ya * refractionIndex;
// displacement
origX = origX - z * Math.tan( xb );
origY = origY - z * Math.tan( yb );
}
// read
var imgData=ctx.getImageData(origX,origY,1,1);
// write
ctx.putImageData(imgData,x+w,y+h);
}
};
doSpherize();
笔记
我建议不要在没有 webGL 像素着色器的情况下由前端处理如此密集的操作。这些都非常优化,将能够利用 GPU 加速。
你绝对可以做这样的事情。我不确定质量和速度是否足够好,尤其是在移动设备上。
你会想要getImageData
像素,对它们执行一些我目前无法想到的数学变换,然后将putImageData
它们返回。
它可能看起来有点模糊或像素化(你可以尝试插值,但这只会让你到目前为止)。而且您可能必须大幅优化您的 javascript 才能在合理的时间内在移动设备上完成它。
转换可能类似于逆方位角投影。