提高three.js中动画精灵的性能
Posted
技术标签:
【中文标题】提高three.js中动画精灵的性能【英文标题】:Improving the performance of animated sprites in three.js 【发布时间】:2012-07-02 07:38:25 【问题描述】:现在我正在开发一款在线游戏,出于性能原因,我决定使用 webgl 而不是 html5 的画布。我正在使用three.js 框架,我的目的是让动画精灵移动。精灵本身被放置在精灵表上,我使用 UVOffset 和 UVScale 来使用正确的艺术并在经过的时间切换 Sprite 的艺术。我想知道是否有办法提高这段代码的性能,因为现在它开始变慢,同时场上大约有 300 名“玩家”。
问候
以下是我的代码中最重要的部分:
var image = THREE.ImageUtils.loadTexture( "img/idlew.png" );
function addPlayer()
var mesh = new THREE.Sprite(map:image);//, affectedByDistance: false, useScreenCoordinates: false);
images.push(mesh);
mesh.position.set(Math.floor(Math.random() * 500), Math.floor(Math.random() * 500), 10);
scene.add(mesh);
mesh.uvScale.x = 96/1152;
mesh.scale.x = 0.1;
mesh.scale.y = 0.1;
var imgBackground = new THREE.MeshLambertMaterial(
map:THREE.ImageUtils.loadTexture('img/grass.jpg')
);
var background = new THREE.Mesh(new THREE.PlaneGeometry(1000, 1000),imgBackground);
scene.add(background);
scene.add(camera);
camera.rotation.x = -(Math.PI/2);
scene.add(new THREE.AmbientLight(0xFFFFFF));
addPlayer();
renderer.render(scene, camera);
var moveUp = false;
tick();
var ticker = 0;
var usedOne = 0;
function tick()
ticker++;
if(ticker%10==0)
for (var i = 0; i < images.length; i++)
images[i].uvOffset.x = usedOne * 0.0835;
;
usedOne++;
if(usedOne == 12) usedOne = 0;
addPlayer();
addPlayer();
addPlayer();
console.log(images.length);
requestAnimationFrame( tick );
renderer.render(scene, camera);
【问题讨论】:
欢迎来到 Stack Overflow,很高兴您解决了问题!所以您知道,在下面的答案部分回答您自己的问题并(在短暂的等待期后)将其标记为已接受的答案是完全可以接受的。这有助于将来可能遇到相同问题的其他人更快地找到解决方案。 【参考方案1】:我已经编写了一个显示动画纹理的代码示例,现场示例位于:
http://stemkoski.github.com/Three.js/Texture-Animation.html
来源:
http://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/Texture-Animation.html
有用的部分是我编写的用于自动处理偏移量的函数。函数(摘自上面的链接)如下:
function TextureAnimator(texture, tilesHoriz, tilesVert, numTiles, tileDispDuration)
// note: texture passed by reference, will be updated by the update function.
this.tilesHorizontal = tilesHoriz;
this.tilesVertical = tilesVert;
// how many images does this spritesheet contain?
// usually equals tilesHoriz * tilesVert, but not necessarily,
// if there at blank tiles at the bottom of the spritesheet.
this.numberOfTiles = numTiles;
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;
texture.repeat.set( 1 / this.tilesHorizontal, 1 / this.tilesVertical );
// how long should each image be displayed?
this.tileDisplayDuration = tileDispDuration;
// how long has the current image been displayed?
this.currentDisplayTime = 0;
// which image is currently being displayed?
this.currentTile = 0;
this.update = function( milliSec )
this.currentDisplayTime += milliSec;
while (this.currentDisplayTime > this.tileDisplayDuration)
this.currentDisplayTime -= this.tileDisplayDuration;
this.currentTile++;
if (this.currentTile == this.numberOfTiles)
this.currentTile = 0;
var currentColumn = this.currentTile % this.tilesHorizontal;
texture.offset.x = currentColumn / this.tilesHorizontal;
var currentRow = Math.floor( this.currentTile / this.tilesHorizontal );
texture.offset.y = currentRow / this.tilesVertical;
;
您可以使用(例如)初始化材质:
var runnerTexture = new THREE.ImageUtils.loadTexture( 'images/run.png' );
// a texture with 10 frames arranged horizontally, display each for 75 millisec
annie = new TextureAnimator( runnerTexture, 10, 1, 10, 75 );
var runnerMaterial = new THREE.MeshBasicMaterial( map: runnerTexture );
并在每次渲染之前更新它:
var delta = clock.getDelta();
annie.update(1000 * delta);
希望这会有所帮助!
【讨论】:
绝对是一种自动处理偏移量变化的好方法;但是我真的不明白这如何使渲染更快。现在,我的应用程序的上限为 20fps(即甜蜜点),精灵每帧移动(x 和 y val),动画每 10 次移动(偏移量变化)。渲染重做每一帧的变化。我现在遇到的问题是,当我的场上有太多精灵时,渲染变得太慢了……移动相机时有 100 个精灵移动并改变 UV 偏移量变得非常慢 +1 我用精灵(其中 476 个)填充了我的视口,所有精灵都具有透明度和 8 帧动画。使用这种方法,我仍然获得 30+ fps。谢谢! 嗨。我编写了相同想法的另一个实现,并将其打包为模块。我也使用 uv 偏移,但将所有计算移至着色器。你怎么看? github.com/elephanter/AnimatedSprites 使用imagemagick的标准几何将帧组合成一个单独的spritesheet,需要从左到右,从上到下读取。为了让这个兼容,我修改了update方法中的Y位置:texture.offset.y = 1 - (currentRow / this.tilesVertical) - (1 / this.tilesVertical);
@crowjonah - 是的,我注意到了,您的代码很有用,谢谢。此外,李的爆炸 jpg 文件具有从右下角到左上角的子图像序列,但他的代码期望序列从左下角到右上角运行。生成的动画不流畅。【参考方案2】:
我回答了我自己的问题,意识到通过放置
可以大大改进代码renderer.render(scene, camera);
将代码放在正确的位置,以便仅在需要时调用。
【讨论】:
以上是关于提高three.js中动画精灵的性能的主要内容,如果未能解决你的问题,请参考以下文章