Skip to content

Instantly share code, notes, and snippets.

@AndrewRayCode
Created October 1, 2023 17:20
Show Gist options
  • Save AndrewRayCode/945246756b04c8746cd836477b851c61 to your computer and use it in GitHub Desktop.
Save AndrewRayCode/945246756b04c8746cd836477b851c61 to your computer and use it in GitHub Desktop.
Take a screenshot with Playcanvas
const copyUIntToImageData = (data: Uint8Array, imageData: ImageData) => {
for (let i = 0; i < data.length; i += 4) {
let index = data.length - i; // flip how data is read
imageData.data[index] = data[i]; //red
imageData.data[index + 1] = data[i + 1]; //green
imageData.data[index + 2] = data[i + 2]; //blue
imageData.data[index + 3] = data[i + 3]; //alpha
}
};
const takeScreenshotRef = () => {
const screenshotHeight = 400;
const screenshotWidth = 400;
const device = app.graphicsDevice;
// Create a new texture based on the current width and height
const colorBuffer = new pc.Texture(device, {
width: screenshotWidth,
height: screenshotHeight,
format: pc.PIXELFORMAT_R8_G8_B8_A8,
});
const depthBuffer = new pc.Texture(device, {
format: pc.PIXELFORMAT_DEPTHSTENCIL,
width: screenshotWidth,
height: screenshotHeight,
mipmaps: false,
addressU: pc.ADDRESS_CLAMP_TO_EDGE,
addressV: pc.ADDRESS_CLAMP_TO_EDGE,
});
colorBuffer.minFilter = pc.FILTER_LINEAR;
colorBuffer.magFilter = pc.FILTER_LINEAR;
const renderTarget = new pc.RenderTarget({
colorBuffer: colorBuffer,
depthBuffer: depthBuffer,
samples: 4, // Enable anti-alias
});
const camera = new pc.Entity('camera');
camera.addComponent('camera', {
fov: 75,
frustumCulling: true,
clearColor: new pc.Color(0, 0, 0, 0),
});
// Set camera distance to object
const pos = new pc.Vec3(0, 0, 5);
camera.setPosition(pos.x, pos.y, pos.z);
app.root.addChild(camera);
camera.camera!.renderTarget = renderTarget;
const canvas = window.document.createElement('canvas');
const context = canvas.getContext('2d');
if (!context) {
throw new Error('No context');
}
canvas.width = screenshotWidth;
canvas.height = screenshotHeight;
const imageData = context.createImageData(
screenshotWidth,
screenshotHeight
);
const pixels = new Uint8Array(screenshotWidth * screenshotHeight * 4);
app.render();
// @ts-ignore
const gl = app.graphicsDevice.gl;
// @ts-ignore
const fb = app.graphicsDevice.gl.createFramebuffer();
// We are accessing a private property here that has changed between
// Engine v1.51.7 and v1.52.2
const colorGlTexture = colorBuffer.impl
? colorBuffer.impl._glTexture
: // @ts-ignore
colorBuffer._glTexture;
const depthGlTexture = depthBuffer.impl
? depthBuffer.impl._glTexture
: // @ts-ignore
depthBuffer._glTexture;
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(
gl.FRAMEBUFFER,
gl.COLOR_ATTACHMENT0,
gl.TEXTURE_2D,
colorGlTexture,
0
);
gl.framebufferTexture2D(
gl.FRAMEBUFFER,
gl.DEPTH_STENCIL_ATTACHMENT,
gl.TEXTURE_2D,
depthGlTexture,
0
);
gl.readPixels(
0,
0,
screenshotWidth,
screenshotHeight,
gl.RGBA,
gl.UNSIGNED_BYTE,
pixels
);
gl.deleteFramebuffer(fb);
copyUIntToImageData(pixels, imageData);
context.putImageData(imageData, 0, 0);
const data = canvas.toDataURL('image/jpeg', 0.9);
app.root.removeChild(camera);
return data;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment