[SOLVED] Cubemap-sources by URL (not as in-.app camera rendertarget.getsources)

"I am on mission, and time is of the essence … " (popquiz answer anyone? :slight_smile: )

Now back to basic, and I recognize that I lack some knowledge-corners in relation to ‘read pixels’ and ‘buffers’ within texture handling etc. (cf Getting pc.rendertarget (as source) from secondary cam to cubemap.rendertarget)

As a second priority (instead of personally using weeks on getting into ‘read pixels/buffers’ etc) I seek a more light weight solution of controlling ‘a user content based rendering of cubemaps’.
This implies for the user, to take a snapshot of 6 cubemap cameras [fx by html-button], and turn them into fully format-written and URL-based images.
From there I need to load the cubemap faces (cf https://developer.playcanvas.com/en/user-manual/assets/cubemaps/ : * face_posx.jpg,* face_negx.jpg etc) one by one, and clamp them into a cubemap assettype that can be set by a: this.app.setSkybox(cubemapAsset);

Additional reference:
A] Getting a snapshot can quite easily be done by this known tutorial: https://developer.playcanvas.com/en/tutorials/capturing-a-screenshot/
{but this only provides a link to a virtual browser-based image-presentation, that can then be dowloaded [this is not a ‘fully format-written and URL-based image’]}

B] @Yaustar has made a parallel example to the ‘capturing-a-screenshot’ tutorial above, where the ‘temporary image’ is being handled by a different method, and closer to a solid FTPlink-presentation of the image; https://playcanvas.com/project/605131/overview/capturing-screenshot-from-camera
… relevant codesnippet from the ‘Camera-To-Texture.js’ file:

 var image = this.canvas.toDataURL('image/png');

    // Thanks https://stackoverflow.com/a/44487883
    var link = document.getElementById('link');
    link.setAttribute('download', filename+'.png');
    link.setAttribute('href', this.canvas.toDataURL("image/png").replace("image/png", "image/octet-stream"));
  • as this prompts a direct download of the image at browser level (as opposed to A] ), you seem (@Yaustar) to have a great understanding of the file-handling.

How can I save the Screencapture-image to my FTP-location? And will there maybe be some sandbox/CORS-limitations?

Honestly, I just found an example online and adopted it :sweat_smile:

For FTP uploads, I would probably use some microservice to provide an API and uploads it to wherever you need to.

The concern here would be security. How will you prevent anyone from uploading any file to your FTP?

Or you can take advantage of cloud storage providers like Dropbox and use their API to upload screenshots to their storage.

hehe … ok :slight_smile:

Hmmm …
{NB: not trying to become ‘too basic’, but I think the oversight got lost a little within my steps and all the references … from Max, Leonidas as well - and I am seldom an ‘Oversight Champ’ myself}

I think I should have restrained myself from using the “FTP-concept” here.
What I should be referring to should be ‘local storage’, which (in essence) only should work by overwriting the local cubemap-files by the same name [this; always, as being a compiled internal function only]. This done by usage of ‘button-input-event’ from the user :


Do you need to use the browsers local storage? Could you keep this image / data in memory instead?

No, not important at all. While trying to keep long story short: I initially found Max’ explanation of (Quote):

" 1. Put camera at the point of cubemap.
2. Make FoV 45 degrees and square viewport (RenderTarget).
3. Rotate camera in direction of each positive and negative axes.
4. Render camera in separate render targets for each face.
5. Create/update cubemap texture providing 6 faces you’ve rendered."

From there I tried to break it up (as best as possible), but the pieces seemed quite scrambled (cf top/start of topic) and ended up here :-/

So if you have a better overview of Textures; as those being held as temporary (non-saved) image-data -> then getting used on a cubemap face (for finally getting used the 6 cubemap sides - this last part should off course be elementary repetition) … you get it, I guess :slight_smile:

You don’t need to have the textures as files to make a cubemap. Once you render to texture, you can use it to set as a for the cubemap using setSource with an array of textures pixel data: https://developer.playcanvas.com/en/api/pc.Texture.html#setSource

Old scripting system but the API is the same: https://playcanvas.com/editor/scene/385269

“So close, yet so far away … (sigh)”

  • or what do you think?


{I tried to publish upload as well [to mitigate any CORS-violations with imgur-image]}

PS: I have been trying both the screenshot.js and the camera-to-texture.js files

my final try: minimized width & height in order to avoid “RangeError: Source is too large
at Uint8ClampedArray.set ()”

Having tried a million things, I honestly don’t think either of;

  • loading camera-based images in realtime (from rendertexture to texture - in the cloud)
  • saving a rendertexture for then to access saved files

… will work in regards to cubemap user-altering.
Its either that, or I will never get convinced, … well only; if a tutorial is made on the topic :slight_smile:
(I am in a lure-mode)

The base libraries might never have been made to handle this kind of usage.
I am now marking as [SOLVED] in that sense, that the concept of a “Snapping a cubemap” by user, will not be done in Playcanvas alone (I will look to Unity and their RenderToPng library,… Unity that actually also has a minor WebGL-JS section that might help me in that regard combined) …

Thx for your dedication anyways @Yaustar :-)))

By the way I got a minor breakthrough in another corner of this topic:

Could you maybe take a look at this @YauStar?
I am trying to merge some scripts here:

var App = pc.createScript('app');

// initialize code called once per entity
App.prototype.initialize = function() {
    var self = this;
         this.app.assets.loadFromUrl('https://upload.wikimedia.org/wikipedia/commons/thumb/b/b3/Wikipedia-logo-v2-en.svg/135px-Wikipedia-logo-v2-en.svg.png', 'texture', function (error, asset) {
        if (error)
            return console.log(error);


        self.app.scene.skyboxMip = 4;
       // self.app.scene.skybox = asset.resource;
        var texHent = self.app.assets.get(asset.resource);
             var cubemap = new pc.Texture(self.app.graphicsDevice, {
                cubemap: true,
                rgbm: true // we're using HDR textures
            // Get the list of texture assets
            var assets = [
            // Load all the assets
            self._loadAssets(assets, function (textures) {
                // set the textures sources into the cubemap
                cubemap.setSource(textures.map(function (texture) {
                    return texture.resource.getSource();
                // set as the skybox
                self.app.scene.skybox = cubemap;
//PS: the following lines are not imp, as they work already:
        var cubeMapAs_MatAccess = self.app.root.findByName('Sphere'); 
        var meshes = cubeMapAs_MatAccess.model.meshInstances;       
            for(var i = 0; i < meshes.length; i++){
                  meshes[i].material.cubeMap = asset.resource;

//EndOf; PS: the following lines are not imp, as they work already ...

    App.prototype._loadAssets = function(assets, callback)      {
            var i = 0;
            var count = 0;
            // called for each asset loaded
            var progress = function () {
                if (count === assets.length) {
            // called when all assets are loaded
            var done = function () {
            // load each asset
            for (i = 0; i < assets.length; i++) {
//!!! This line is failing:

The merge consists (amongst others) of the ‘create_skybox’-script you referenced to above at: https://playcanvas.com/editor/scene/385269

At debug I get this error: “Uncaught TypeError: Cannot read property ‘ready’ of undefined”.
Note!: You referred to the scripting as being outdated? If this is cause, how to rewrite?

Never mind - I got it working … I am afraid this last ‘extra’ thing is sort of classified, as I am, now, trying to get a major semi-comercial project going with this technique (amongst others + have to get bread on the table) -> if one really need to know-how … write me :slight_smile: