首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在JavaScript中渲染灯太慢了。有什么想法吗?

在JavaScript中渲染灯太慢了。有什么想法吗?
EN

Stack Overflow用户
提问于 2015-03-15 12:03:34
回答 1查看 131关注 0票数 1

我有一个用JavaScript编写的光线渲染方法,它可以设置每个物体的亮度.如果我在主循环中用这个过滤器调用呈现对象,它将非常慢(8-10 fps)。这对JavaScript来说是太大了,还是仅仅是一个未优化的解决方案?

如果我在主循环之外调用它,那么它就可以了。

下面是Animator类,它有我写过的方法。您应该使用renderImage开关调用brightness方法。

代码语言:javascript
复制
Animator: { // Animator class 
  renderImage: function(ImageObject,imageX,imageY,filterData = []) {
  /*
    filterData [] =
    0 -> type
    1 -> value for filtering
  */
  switch( filterData[0] )
  {
    case 'none':
      engComponents.ctx.drawImage(ImageObject,imageX,imageY);
      break;

    case 'brightness':
      engComponents.ctx.drawImage(ImageObject,imageX,imageY);
      pixels = engComponents.ctx.getImageData(imageX,imageY,imageX+50,imageY+50);
      data = pixels.data;
      for (var i=0; i<data.length; i+=4) {
        data[i] += filterData[1];
        data[i+1] += filterData[1];
        data[i+2] += filterData[1];
      }
      engComponents.ctx.putImageData(pixels,imageX,imageY);
      break;
  }

谢谢你的帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-15 14:24:44

get/putImageData是相当慢的操作。如果您还需要对每个对象执行此操作,那么期望实时更新性能可能有点太高了。编译后的代码和直接访问显示卡是完全可能的,但是使用JavaScript和画布(包括它附带的所有故障保险箱),我们不得不停留在欺骗中。

你可以(可能应该)做的一件事就是在游戏开始前缓存出有问题的图像/对象的变体。定义一些关键亮度值,并生成其中的精灵页。然后使用亮度索引,而不是实际亮度,因此,您只需绘制单元格与预期的亮度屏幕,而不是计算在每帧。

以这家伙为例:

现在生成一个具有不同亮度值的sprite工作表-在Photoshop中或在代码中动态地这样做(后者在下面的演示中显示):

代码语言:javascript
复制
var sctx = document.getElementById("sprite").getContext("2d"),
    ctx = document.getElementById("main").getContext("2d"),
    img = new Image;
    
img.crossOrigin = "";
img.onload = genSprite;
img.src = "http://i.imgur.com/RV2a28T.png";  // 106x120

function genSprite() {

  sctx.canvas.width = 5 * this.width;          // set sprite size: image width x cells
  sctx.canvas.height = this.width;
  sctx.drawImage(this, 0, 0);                  // draw in image to brighten
  
  
  // generate some brightness cells
  var bStep = 25,                              // brightness step per cell
      max = 5,                                 // max sprites
      idata = sctx.getImageData(0, 0, this.width, this.height), // get once only
      data = idata.data,                       
      len = data.length;
  
  for(var i = 0; i < max; i++) {               // iterate to increase values
    for(var p = 0; p < len; p++) {
      data[p++] += bStep;
      data[p++] += bStep;
      data[p++] += bStep;
    }
    sctx.putImageData(idata, this.width * i, 0); // update at cell pos. with new values
  }
  
  // now we have our sprite-sheet, release the Kraken!
  game();
}

/*==========================================================
This part is just to demonstrate you can draw many instances
with varying brightness without suffer from low frame-rate
==========================================================*/

function game() {

  var dudes = [], // holds Dude objects
      max = 70,   // num. of dudes
      i = 0;
  
  // create game dudes
  while(i++ < max) dudes.push(new Dude(sctx.canvas, ctx));
  
  // animate
  (function loop() {
    ctx.clearRect(0, 0, 500, 500);
    var i = 0;
    while(dude = dudes[i++]) dude.update();  // update dude
    requestAnimationFrame(loop)
  })();
  
}

function Dude(sprite, ctx) {
  var b = (4 * Math.random())|0,   // brightness index (fractional is ok)
      db = 0.25,                   // step for brightness, we round it to integer later
      w = ctx.canvas.width,        // cache some values
      h = ctx.canvas.height,
      x = w * 0.5,                 // center of canvas
      y = h * 0.5,
      v = 1 + 4 * Math.random(),   // random velocity
      a = Math.PI*2*Math.random(), // random angle
      dx = Math.cos(a) * v,        // steps based on angle
      dy = Math.sin(a) * v;
  
  // updates position and brightness cell
  this.update = function() {
    
    // position:
    x += dx;
    y += dy;
    if (x < -106 || x > w || y < -120 || y > h) {
      x = w * 0.5;
      y = h * 0.5;
    }
    
    // brightness:
    b += db;
    if (b <= 0 || b >= 4) db = -db;

    // clip the cell from sprite-sheet and draw to main canvas
    // Note the 106*(b|0) - (b|0) will force integer number which we need.
    ctx.drawImage(sprite, 106*(b|0), 0, 102, sprite.height,  x, y, 106, sprite.height);
  };
}
代码语言:javascript
复制
#sprite {border:1px solid #000;margin-bottom:4px;}
代码语言:javascript
复制
<canvas id="sprite"></canvas><br>
<canvas id="main" width=500 height=500></canvas>

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29060373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档