我正在尝试从ThreeJS中的Texturepacker加载Spritesheets,它包含图像和json。图片中包含一堆小精灵,而json定义了图片中小精灵的位置和大小。
我尝试了3种加载方法。
使用多个具有不同偏移量的纹理实例的方法应该可以正常工作,因为我没有复制源图像,但是当我通过切换材质的纹理来运行动画时,它会使用大量的RAM,就像在复制整个源一样将每个精灵表存入内存。如果我更改动画的纹理偏移而不是使用纹理副本,则可以正常工作,但是偏移更改将应用于使用相同源Spritesheet的每个对象。
WebGLRenderTarget方法需要一个摄影机和一个用于裁剪纹理的场景,以及一个添加到场景中的精灵。此输出无法使用,因为它不会生成原始纹理的1:1裁剪,并且加载速度确实很慢。有没有办法在ThreeJS中将纹理1:1渲染到较小的缓冲区?
在我为每个精灵创建一个canvas元素并将精灵表裁剪成每个的情况下,Canvas方法效果最好。这是1:1的质量,但使用Spritesheet的要点是GPU仅具有一个要处理的图像,这需要HTML加载程序。理想情况下,我不想将Spritesheet裁剪为较小的纹理缓冲区。
为什么将相同的大型源图像与多个三个纹理对象一起使用会占用大量内存?我希望它只需要在内存中保留一个纹理,Texture对象将只显示具有不同偏移量的相同纹理。
答案 0 :(得分:1)
我找到了一种可行的方法。
首先,我通过通过ThreeJS ImageLoader加载的Spritesheet图像制作WebGLTexture来加载纹理,该图像存储在_spritesheets [textureID] .texture中。
let texture = this._spritesheets[textureID].texture;
let gl = this._renderer.getContext();
let webGLTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, webGLTexture);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, texture);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
然后,我将纹理对象的webGL纹理参数设置为此,并将其webglInit值设置为true,这样就不会创建新的缓冲区。
let frames = textureJSON.frames;
for (let frameID of Object.keys(frames)) {
let frame = frames[frameID];
let t = new THREE.Texture(texture);
let data = frame.frame;
t.repeat.set(data.w / texture.width, data.h / texture.height);
t.offset.x = data.x / texture.width;
t.offset.y = 1 - data.h / texture.height - data.y / texture.height;
let textureProperties = this._renderer.properties.get(t);
textureProperties.__webglTexture = webGLTexture;
textureProperties.__webglInit = true;
this._textures[frameID] = {};
this._textures[frameID].texture = t;
this._textures[frameID].settings = { wrapS: 1, wrapT: 1, magFilter: THREE.LinearFilter, minFilter: THREE.NearestFilter };
}
spritesheet JSON是通过ThreeJS FileLoader加载的。然后,我通过框架ID将精灵存储在_textures对象中,并将其指定给材质的map属性。