簡體   English   中英

偽造在畫布的3d球形

[英]Faking a 3d sphere in canvas

我有一個關於在HTML5 / Canvas / Javascript中偽造3D的問題...

基本上,我使用drawImage()<canvas>上繪制了一個2D圖像。
我想做的是繪制圖像,然后將球體上的紋理移動到...... 球體狀 ......

為清晰起見,請參見下圖:

在Javascript中Spherise

有任何想法嗎?

我已經用谷歌搜索了自己近乎死亡,也不能是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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM