Generating transparent image in PlayCanvas

This is the situation

We need to take a screen capture in runtime from playcanvas, and change a specific HEX color of that base64 image we captured to transparent ( HEX : 00FFFFFF ) . and then apply that transparent image as a texture on a material.

Is that possible ?

thanks in advance!

You could probably get the texture and change the pixel data using getSource and setSource

thanks @yaustar , do you know if maybe there’s some example about this to check?

Actually, I’m not sure that does what I thought it does as setSource only accepts HTMLCanvasElement|HTMLImageElement|HTMLVideoElement|HTMLCanvasElement[]|HTMLImageElement[]|HTMLVideoElement[]

I think you would have to apply the screencapture to a DOM element, change the pixel data there and use it as a source for texture.

Alternatively (and might be easier), you could create a shader for the material that does a colorkey / chromo key effect similar to what’s been done here: Big size video lags

I’ve fixed the shader to work with the current engine here https://playcanvas.com/project/768855

thanks @yaustar , the problem with the shader method, is, we have the task to get as an output the transparent texture, so the shader is not an option, because the texture will be use as input in other app, not just for playcanvas, so that’s why we are looking for a method, where we first create a texture, capture the camera viewport and encode as base 64 to use as output, but our current problem is this texture has not transparency, so that’s why we are looking for a way to process this texture (could be before or after pass to base64), to swap a specific color by a transparent one.

Okay, so you need it effectively as an image? In which case, I would go the route of editing the data on the off screen canvas DOM.

Where is the solid colour out of interest? Could you do capture with transparency instead? Or do some post processing on the render before taking the capture?

yes, we need as an image.
It’s possible to capture with transparency directly using the method we are apply?, what we are doing is
creating a texture from the camera viewport, I will explain it here:,

var colorBuffer = new pc.Texture(this.app.graphicsDevice, {
            width: 1024,
            height: 1024,
            format: pc.PIXELFORMAT_R8_G8_B8,
            autoMipmap: true
        });
        colorBuffer.minFilter = pc.FILTER_LINEAR;
        colorBuffer.magFilter = pc.FILTER_LINEAR;
        this.renderTarget = new pc.RenderTarget(this.app.graphicsDevice, colorBuffer, {
            depth: true,
            flipY: true
        });
        var layer = this.app.scene.layers.getLayerByName(this.layerName); //our layer to capture
        layer.renderTarget = this.renderTarget;
        this.framebuffer = this.app.graphicsDevice.gl.createFramebuffer();
        this.pixels = new Uint8Array(colorBuffer.width * colorBuffer.height * 4);
        var cb = this.renderTarget.colorBuffer;
        this.canvas = window.document.createElement('canvas');
        this.context = this.canvas.getContext('2d');
        this.canvas.width = cb.width;
        this.canvas.height = cb.height;
 
     // then we take the screenshot 
takeScreenshot = function () {

    var colorBuffer = this.renderTarget.colorBuffer; 
    var gl = this.app.graphicsDevice.gl;
    var fb = this.framebuffer;

    var pixels = this.pixels;

    gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
    gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorBuffer._glTexture, 0);

    gl.readPixels(0, 0, colorBuffer.width, colorBuffer.height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);   
    var imgData = this.context.createImageData(colorBuffer.width, colorBuffer.height);
    var data = imgData.data; 
    var palette = this.context.getImageData(0, 0, colorBuffer.width, colorBuffer.height); 
    palette.data.set(new Uint8ClampedArray(pixels));   
    this.context.putImageData(palette, 0, 0);
    this.context.drawImage(this.canvas, 0,0);
    this.b64 = this.canvas.toDataURL('image/jpeg', 0.5);
    //console.log(b64); // finally our base64 image!
};

we use this and set different sizes and layers, and every works ok, but the problem is the texture didn’t get transparency, even if we use a camera with clear color, transparent canvas, camera color with alpha = 0,
maybe there’s some parameters to config the new texture, to allow to detect the transparency from the captured camera view?

thanks!!!

The issue is that the texture has PIXELFORMAT_R8_G8_B8 so there’s no alpha channel.

If you change it to PIXELFORMAT_R8_G8_B8_A8, it will give you an alpha channel to capture transparency.

See this thread: Screenshot with transparent BG

great! will check it and let you know! thanks @yaustar