There is no clone() method on pc.Texture. Check the docs on that class on how to fill a texture with data:
// Create a 8x8x24-bit texture
var texture = new pc.Texture(graphicsDevice, {
width: 8,
height: 8,
format: pc.PIXELFORMAT_R8_G8_B8
});
// Fill the texture with a gradient
var pixels = texture.lock();
var count = 0;
for (var i = 0; i < 8; i++) {
for (var j = 0; j < 8; j++) {
pixels[count++] = i * 32;
pixels[count++] = j * 32;
pixels[count++] = 255;
}
}
texture.unlock();
I think his question is how to access that array buffer if a texture was added via attributes, rather than proceduarally generated. I am actually not sure myself. I tried the following:
Script.attributes.add('tex', { type: 'asset', assetType: 'texture' });
Script.prototype.initialize = function() {
var texture = new pc.Texture(this.app.graphicsDevice, {
width: 8,
height: 8,
format: pc.PIXELFORMAT_R8_G8_B8
});
var texture2 = this.tex.resource;
var pixels = texture.lock();
var pixels2 = texture2.lock();
console.log(pixels);
console.log(pixels2);
};
Hmm good question, you will have to use gl.readPixels() directly on the texture colorbuffer (beware this would be super slow if you do it per frame, it stalls the GPU):
Otherwise there are some external decoders for specific formats, like this one for PNG that returns a typed array given a PNG image:
There is an issue on the repository to implement the ImageBitmap API at some point, that might help when it’s in the engine:
I will try copy texture by simple shader and use colorbuffer to create texture and rewrite copy function to shader. I think, this is much faster and easier. But not today.
var Script = pc.createScript('script');
Script.attributes.add('tex', { type: 'asset', assetType: 'texture' });
Script.prototype.initialize = function() {
var plane = this.app.root.findByName('Plane');
var device = this.app.graphicsDevice;
var asset = this.tex.resource;
// get pixel data from the asset added via attributes
var pixelData = this.readPixels(asset);
//
// you can modify pixel data here, before assigning it to the texture
//
// generate texture
var texture = new pc.Texture(device, {
width: 1024,
height: 1024,
format: pc.PIXELFORMAT_R8_G8_B8_A8,
// autoMipmap: true, // adjust mip level if needed
// minFilter: pc.FILTER_LINEAR,
// magFilter: pc.FILTER_LINEAR,
});
// get array buffer of the generated texture
var pixels = texture.lock();
// copy pixel data to our texture
for (var i = 0; i < pixels.length; i++) {
pixels[i] = pixelData[i];
}
// send to VRAM
texture.unlock();
// create a standard material with the generated texture
var material = new pc.StandardMaterial();
material.diffuseMap = texture;
material.update();
// assign the material to the Plane model
plane.model.material = material;
};
Script.prototype.readPixels = function(texture) {
var target = new pc.RenderTarget({ colorBuffer: texture, depth: false});
var data = new Uint8Array(texture.width * texture.height * 4);
var device = texture.device;
device.setFramebuffer(target._glFrameBuffer);
device.initRenderTarget(target);
device.gl.readPixels(0, 0, texture.width, texture.height, device.gl.RGBA, device.gl.UNSIGNED_BYTE, data);
return data;
};
As Leonidas mentioned, this method is not really suitable for per-frame rendering, as it is slow. If you ever get to make it to copy in shader, feel free to share.