Created
October 1, 2023 17:20
-
-
Save AndrewRayCode/945246756b04c8746cd836477b851c61 to your computer and use it in GitHub Desktop.
Take a screenshot with Playcanvas
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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