我有一个关于在HTML5 / Canvas / Javascript中伪造3D的问题......
基本上,我使用<canvas>
在drawImage()
上绘制了一张二维图像。
我想做的是绘制图像,然后将球体上的纹理移动到...... 球状 ...
为清晰起见,请参见下图:
有什么想法吗?
我已经用谷歌搜索了自己近乎死亡的事情,不能成为WebGL,因为它必须在手机上工作......有没有办法做到这一点?
答案 0 :(得分:5)
您可以在此处查看工作原型: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加速。
答案 1 :(得分:0)
你绝对可以做这样的事情。我不确定质量和速度是否足够好,特别是在移动设备上。
你想要getImageData
像素,对它们进行一些我暂时无法想到的数学变换,然后putImageData
它们回来。
它可能看起来有点模糊或像素化(你可以尝试插值,但这只会让你到目前为止)。并且您可能必须大大优化您的JavaScript,以便在合理的时间内在移动设备上完成。
转换可能类似于反方位投影。