Dynamic Cubemaps / Reflection Probes / Render To Texture in 2020

  1. Where would I do this then? When I disable the camera(s) after this part in the code:
        // add the camera as a child entity
        this.entity.addChild(e);

        // set up its rotation
        e.setRotation(cameraRotations[i]);             

the material which uses the cubeMap simply turns black.

  1. So basically what’s done here is rendering the same Cubemap several times in several sizes and then calling pc.reprojectTexture to … kinda combine them , correct?
  1. I added this to render-to-cubemap example to execute after inside app.on(“update” …, to stop cubemaps from updating. But make sure this is done on the second frame, as first one needs to render it. The cubemap at that time continues to be rendered on the sphere.
    This disables 6 child cameras that render individual faces.
                shinyBall.children.forEach(function(child) {
                    if (child.camera) {
                        child.camera.enabled = false;
                    }
                })
  1. from the viewer code, this block is relevant: " // generate prefiltered lighting data"
    it uses single loaded cubemap, and renders it with varying levels of blur into a set of cubemaps, which are then used as a skydome.
3 Likes

I came up with the following solution: use a setTimeout with a short delay and then disable the cameras. However, in the short period of time where the cameras are enabled, every camera throws an error from launch.js seemingly every frame:

Trying to bind current color buffer as a texture

If I don’t disable them at all, this error gets thrown continously. Any idea what I may have done wrong? I mostly just copied the code from above with the minor adjustment that I made it so it could be applied to a model and have the camera as a seperate entity.

Demo is here: https://playcanvas.com/editor/scene/1037157

1 Like

I would say that an object you put cubemap on is getting rendered into cubemap … and you cannot use cubemap both for read and write at the same time. In the example I did, the sphere with cubemap is on excluded layer, so it does not render into cubemap.

2 Likes

also, set timeout is not ideal … it can render few times, or not at all, depending on system’s performance.
Just have some boolean variable, flip it in the update, and use it inside next update to disable cameras.

2 Likes

After a lot of trial and error with the correct way of prefiltering the cubemap, it works fine now. Thanks, @mvaligursky

Here’s the Demo if anyone is interested:
https://playcanvas.com/editor/scene/1037157

3 Likes

nice! glad all that worked.

After a full day of debugging, I came to the conclusion that it doesn’t really work, after all.
In my simple test scene I tried to render a CubeMap and project it to a hollow cube (room-wall-floor-thingy) but the projection doesn’t look right at all. The most glaring issue is the blue cone which is facing to the right instead to the left where it should be facing.
What am I doing wrong this time?

This is not a solution, but it might help. In Playcanvas cubemaps that are downloaded are x-axes flipped compared to those that are realtime rendered. At the moment we have flag on the texture (cubemap). This is automatically set when you render to texture using RenderTarget, but I guess not when we reproject cubemap to another cubemap. So for now, for your 6 or so cubemaps you generate, try to set this on them:

cubemapTexture._isRenderTarget = true;

I’m not quite sure where in the code the texture could actually be accessed, seeing that there are 6 renderTargets created in a loop and then immediately the texture is rendered to the cubeMap, which is the only pc.Texture in the code.

    // set up rendering for all 6 faces
    for (var i = 0; i < 6; i++) {

        // render target, connected to cubemap texture face
        var renderTarget = new pc.RenderTarget(this.app.graphicsDevice, this.cubeMap, {
            depth: this.depth,
            face: i
        });

        // create a child entity with the camera for this face
        var e = new pc.Entity("CubeMapCamera_" + i);
        e.addComponent('camera', {
            aspectRatio: 1,
            fov: 90,

            // cubemap will render all layers as setup on Entity's camera
            layers: camera.layers,

            // priority
            priority: camera.priority,

            // copy other camera properties
            clearColor: camera.clearColor,
            clearColorBuffer: camera.clearColorBuffer,
            clearDepthBuffer: camera.clearDepthBuffer,
            clearStencilBuffer: camera.clearStencilBuffer,
            farClip: camera.farClip,
            nearClip: camera.nearClip,
            frustumCulling: camera.frustumCulling,

            // this camera renders into texture target
            renderTarget: renderTarget
        });
        
        // add the camera as a child entity
        this.cameraEntity.addChild(e);

        // set up its rotation
        e.setRotation(cameraRotations[i]);  
    }
};

I’ve tried it with renderTarget._isRenderTarget = true, I tried setting the cubeMap Texture to _isRenderTarget = true and I tried setting it in the prefilter function, to no avail.
Is there another method to x-flip rendered cubemaps?

those cubemaps created for the reprojection should have that flag set, so the code you based on this creates those textures

I tried setting the flag like you described but it didn’t change anything. Upon further inspection, I noticed that the flag had already be set to true by default, even without me setting it:

how about changing the flag to false on those?
if that doesnt work I’m not sure what the problem is, but as mentioned, it’s on my list to work on this and create some simple API to use this in a way you’re trying to.

I tried that and this is the result:

Guess I’ll be patient, then, and wait for the API rework. Thanks anyways for your time

1 Like

@twe We have identified a bug in the Cubemap box projection from this thread: Cubemaps / Box projection is not working property

A fix is currently in the works which may help your issue

1 Like

The fix has been deployed:

Unfortunately, the fix didn’t solve my issue.
Anyways, thank you for notifying me :wink:

2 Likes

how do i use the that cubemap? it seems not working if i call app.scene.setSkybox(). and if i set it to a material. it just ignore the glossiness value. I tried using pc.prefilterCubemap(options); and get a new texture singleFilteredFixed from options. but it doesn’t help either

see the example here with the source code:
http://playcanvas.github.io/#graphics/render-to-cubemap.html

to use it on the material, you need this:

        // use cubemap which is generated by cubemapRenderer instead of global skybox cubemap
        shinyMat.useSkybox = false;
        shinyMat.cubeMap = shinyBall.script.cubemapRenderer.cubeMap;

regarding the prefiiltering of the skydome, see the post above regarding how do viewer does it. It’s still on our list to make a lot simpler, but unfortunately it has not been done yet.

1 Like

A new example is here:

This needs yet unreleased engine, but that should be coming out shortly as well.

6 Likes