Three.js使用2D纹理\ sprite进行动画制作(planeGeometry)

时间:2013-04-16 04:59:14

标签: javascript html5 three.js webgl

我是html5和three.js的新手。我一直在试验它,基本上我想做的就是有一个Mesh(我正在使用planeGeometry,正如我后面的教程所使用的那样)。网格显示不同的纹理,可以在以后更改。

以下是我的代码:

angelTexture = THREE.ImageUtils.loadTexture("images/textures/chars/angel/angel.png");
angelTexture.offset.x = -0.75;
angelTexture.offset.y = -0.75;

angelMesh = new THREE.Mesh( new THREE.PlaneGeometry(79, 53, 79, 53), new THREE.MeshBasicMaterial( { map: angelTexture, wireframe: false } ));

angelMesh.position.x = 0;
angelMesh.position.y = 0;
scene.add(angelMesh);

问题在于,每当我偏移时,Mesh看起来都足以显示所有其他Sprite(我将纹理用作2D偏移,我将其偏移以对其进行动画处理)。结果是非常灾难性的,我仍然在弄清楚如何控制Mesh的大小,以便它只显示Sprite的一个快照。我所有的尝试似乎只是调整网格和底层纹理的大小,仍然显示所有的精灵。

有人能指出我正确的方向吗?提前谢谢。

...

我的朋友想出了一个解决方案...... 我错过了重复财产。

angelTexture = THREE.ImageUtils.loadTexture("images/textures/chars/angel/angel.png");
angelTexture.offset.x = -0.75; 
angelTexture.offset.y = -0.75;

angelTexture.repeat.x = 0.25;
angelTexture.repeat.y = 0.25;   
scene.add(angelMesh);

希望这有助于其他人遇到同样的问题。

4 个答案:

答案 0 :(得分:19)

前一段时间我有同样的问题,所以我写了一个完整的动画示例,使用spritesheet作为PlaneGeometry的纹理,然后定期更新纹理 - 查看

http://stemkoski.github.io/Three.js/Texture-Animation.html

并查看注释的源代码以获取其他说明。

答案 1 :(得分:1)

我在对Lee Stemkoski的评论中指出,使用较新的THREE.TextureLoader()时,具有多于一行的Spritesheets无法正常工作。

我在测试中使用以下4x4精灵图像。

Image showing quadrant highlighted for each expected tile

假设您有完整的16个图块电子表格,则不对Lee Stemkoski的TextureAnimator函数进行任何修改。

var texture = new THREE.TextureLoader().load('grid-sprite.jpg');
var annie = new TextureAnimator(texture, 4, 4, 16, 150);

动画纹理向后运行。 Codepen Demo

enter image description here

所以我做了自己的,叫做THREE.SpriteSheetTexture

THREE.SpriteSheetTexture = function(imageURL, framesX, framesY, frameDelay, _endFrame) {

    var timer, frameWidth, frameHeight,
            x = 0, y = 0, count = 0, startFrame = 0, 
            endFrame = _endFrame || framesX * framesY,
            CORSProxy = 'https://cors-anywhere.herokuapp.com/',
            canvas = document.createElement('canvas'),
            ctx = canvas.getContext('2d'),
            canvasTexture = new THREE.CanvasTexture(canvas),
            img = new Image();

    img.crossOrigin = "Anonymous"
    img.onload = function(){
        canvas.width = frameWidth = img.width / framesX;
        canvas.height = frameHeight = img.height / framesY;
        timer = setInterval(nextFrame, frameDelay);
    }
    img.src = CORSProxy + imageURL;

    function nextFrame() {
        count++;

        if(count >= endFrame ) {
            count = 0;
        };

        x = (count % framesX) * frameWidth;
        y = ((count / framesX)|0) * frameHeight;

        ctx.clearRect(0, 0, frameWidth, frameHeight);
        ctx.drawImage(img, x, y, frameWidth, frameHeight, 0, 0, frameWidth, frameHeight);

        canvasTexture.needsUpdate = true;
    }

    return canvasTexture;
}

您需要了解的内容 imageURL是您的Spritesheet的网址 framesX是沿x轴(左右)可容纳多少帧 framesY是沿y轴(上下)可容纳多少帧 delay是纹理等待更改到下一帧的时间 _endFrame是可选的-有多少帧(以防不使用整行)

一切看起来像这样

texture = new THREE.SpriteSheetTexture('https://s3-us-west-2.amazonaws.com/s.cdpn.io/68819/grid-sprite.jpg', 4, 4, 100, 16);
var material = new THREE.MeshBasicMaterial({ 
    map: texture
});
geometry = new THREE.BoxGeometry( 200, 200, 200 );
mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );

欢欣鼓舞!!! Codepen Demo Here

答案 2 :(得分:0)

@Cmndo使帧以正确的顺序移动,您只需要更新此内容即可:

texture.offset.y = currentRow / this.tilesVertical;

对此:

texture.offset.y = this.tilesVertical - (currentRow / this.tilesVertical);

在此示例中: https://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/Texture-Animation.html

答案 3 :(得分:0)

要使框架朝正确的方向移动,请使用:

texture.offset.y = (1 - currentRow / _tilesVertical) - (1 / _tilesVertical);

代替

texture.offset.y = currentRow / this.tilesVertical;