[英]Faking a 3d sphere in canvas
我有一個關於在HTML5 / Canvas / Javascript中偽造3D的問題...
基本上,我使用drawImage()
在<canvas>
上繪制了一個2D圖像。
我想做的是繪制圖像,然后將球體上的紋理移動到...... 球體狀 ......
為清晰起見,請參見下圖:
有任何想法嗎?
我已經用谷歌搜索了自己近乎死亡,也不能是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才能在合理的時間內在移動設備上完成它。
轉換可能類似於反方位投影。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.