mrdoob / three.js

JavaScript 3D Library.
https://threejs.org/
MIT License
100.8k stars 35.22k forks source link

CubeTexture orientation #16328

Closed fabienrohrer closed 5 months ago

fabienrohrer commented 5 years ago

In my app, I would like to rotate the CubeTexture that defines the scene background and the environment map reflections by 180ยฐ along the vertical y-axis. My rotation is defined by the VRML and X3D specifications about the background fields.

I tried to modify several parameters like the mapping, flipY and rotation Texture fields. However I didn't found any good way to do so.

mrdoob commented 5 years ago

You mean being able to rotate scene.background? If so... yes, definitely interested.

We probably need a new API though...

scene.background = new THREE.Background( cubeTexture );`
scene.background.rotation.y = Math.PI / 2;
looeee commented 5 years ago

I'm struggling with exactly this right now. Trying to get baked ground shadows to match up to the sun direction from a cubemap. It seems like somewhere along the way my cubemap is being flipped 180 degrees. It would be great if I could just fix that here rather than re-rendering my cubemap multiple times and trying to figure out where that's happening.

WestLangley commented 5 years ago

@fabienrohrer Try

scene.rotation.y = Math.PI;

If that is not working, please provide a live example to demonstrate exactly what you are doing.

mrdoob commented 5 years ago

Oh, that works? ๐Ÿ˜ฎ The camera must be a child of the scene though?

WestLangley commented 5 years ago

The camera must be a child of the scene though?

I don't think that matters.

fabienrohrer commented 5 years ago

@mrdoob this is exactly what I need too :-)

@WestLangley:

Rotating the overall scene is overkilled and may cause many side effects in my app.

I would like to be able to rotate the background only, and for sure, the environment maps should work the same way.

A live demo is not possible to do, because the API is missing. It's a matter to take any example having a background cubemap (like https://threejs.org/examples/#webgl_materials_cubemap) and be able to rotate only the background around the y-axis. Or more generally, to apply any rotation to the background.

Being able to apply a custom rotation matrix / quaternion to any cubemap seems to be the most generic solution for me.

WestLangley commented 5 years ago

three.js is careful to ensure that material reflections are consistent with the material envMap, which is defined in the world space coordinate system. Allowing users to rotate the scene background would result in a background that is inconsistent with material reflections.

Why don't you create the correct world-space cube map in your app?

mrdoob commented 5 years ago

The camera must be a child of the scene though?

I don't think that matters.

I tried doing scene.rotation.y ++ in the console in webgl_materials_standard and the gun rotates. Then I tried doing scene.add( camera ) and then if I do scene.rotation.y ++ it does what we're after, but then the camera controls get messes up ๐Ÿ˜

If we introduce a THREE.Background object, we could add API to handle this, plus in the renderer we can also introduce the idea of:

var envMap = material.envMap;
if ( scene.background && scene.background.isBackground && envMap === null ) {
    envMap = scene.background.texture;
}
WestLangley commented 5 years ago

I said

Try scene.rotation.y = Math.PI; If that is not working,...

That means it may not work. :-)

It depends on the use-case. I tried with OrbitControls and it worked fine.

unrelated: the webgl_materials_standard example should be using orbit controls, anyway IMO.

looeee commented 5 years ago

You mean being able to rotate scene.background? If so... yes, definitely interested.

It makes more sense to do this at the texture level, otherwise any IBL lighting will not match the background, I assume.

We allow rotation of normal textures, is there any reason why we wouldn't want to do the same for cube textures? Is it too complex to implement?

Why don't you create the correct world-space cube map in your app?

This is very time consuming. I've been working on generating cube maps over the last couple of days, and making changes then re-rendering the cube map takes me about 15-20 minutes for each change.

Another potential interesting use case for this is that you could change the direction of environmental lighting in real time. I'm currently combining a PMREM environment map with a directional light for real-time shadows, and using the map as a skybox, which gives a fairly decent daylight effect. Obviously there's a limit to what you could do without changing the color of the environment map, but you could simulate at least a couple of hours of daylight passing by rotating the map in sync with the directional light while adjusting the .envMapIntensity.

fabienrohrer commented 5 years ago

My concern is also about performance. Currently I implemented a hack about to rotate the top and bottom texture and swap the other ones. It takes about 10ms to rotate a 1024x1024 texture in JS.

omichel commented 5 years ago

Alternatively, could it be possible to have only two options for the CubeTexture orientation, the one you currently have and another one (with the 180 degree rotation) that would be friendly with the other standard largely used in 3D formats (X3D, VRML, etc.). We could probably easily adapt the consistency with material reflections to handle both formats?

makc commented 5 years ago

This sounds familiar #11103

fabienrohrer commented 5 years ago

If I would implement CubeMap.rotation = matrix3, would you merge in r105?

WestLangley commented 5 years ago

My concern is also about performance. Currently I implemented a hack about to rotate the top and bottom texture and swap the other ones. It takes about 10ms to rotate a 1024x1024 texture in JS.

And how often are you doing this in your app?

fabienrohrer commented 5 years ago

@WestLangley I just give you a detailed answer here: https://github.com/mrdoob/three.js/pull/16507#discussion_r286337864

And how often are you doing this in your app?

Not much. Once at loading per client, and once each time the background is changed (very rare case). A DEFINE would also do the job.

WestLangley commented 5 years ago

My concern is also about performance ... It takes about 10ms.

And how often are you doing this in your app?

Not much. Once at loading per client, and once each time the background is changed (very rare case).

Sorry, I am not following the logic of that.

fabienrohrer commented 5 years ago

Unfortunately, @WestLangley doesn't want to merge my modification about the CubeTexture.rotation because of the runtime overhead (a supplementary mat3 multiplication). In this case, I'm running out of ideas to solve this cleanly in threejs. If threejs contributors won't solve this, please close this issue.

FishOrBear commented 4 years ago

I wait for the implementation of this feature.

fabienrohrer commented 4 years ago

@FishOrBear Unfortunately, the threejs maintainers decided to not implement this. You could apply this unmerged patch in a fork, if you would like to have this in your project:

https://github.com/mrdoob/three.js/pull/16507

Mugen87 commented 4 years ago

@mrdoob Maybe we can reconsider this feature requests in #18157?

FishOrBear commented 4 years ago

I am using threejs to make an application similar to AutoCAD, so we use xy to sit as a plane.

The current CubeTexture conflicts a bit with ours.

Mugen87 commented 4 years ago

BTW: With Babylon.js, it is at least possible to rotate a skybox around the y-axis:

https://www.babylonjs-playground.com/#UU7RQ#447

The engine supports this by transforming the reflection vector in the fragment shader. So exactly the approach which was not accepted in #16507. Code from Babylon.js fragment shader:

https://github.com/BabylonJS/Babylon.js/blob/1c4627141f83c08fe4a7e30e2621c916b4e6c9c9/src/Shaders/ShadersInclude/reflectionFunction.fx#L114-L117

Mugen87 commented 4 years ago

@mrdoob I think we should implement this feature. There is another request in the forum:

https://discourse.threejs.org/t/rotate-a-scenes-background-skybox-texture/12199

I doubt that a single additional matrix/vector multiplication per fragment will noticeably affect the performance.

fabienrohrer commented 4 years ago

I still have the same issue in my app, and the hack to solve it is ugly and so costly... I also recommend to accept this improvement.

looeee commented 4 years ago

I also would love to see this feature added.

It seems like the blocker is potential decrease in performance, but that should be easy to test. We can try adding it, and if there's an unnaceptable performance drop we can remove it again.

DavidPeicho commented 3 years ago

Same here, could use this feature instead of re-implementing my background rendering :)

I am not sure to follow on the performance issue. Nothing prevents us to generate the ray direction directly in the vertex shader? Then it would cost as much as any other modelMatrix transform.

capnmidnight commented 3 years ago

In my case, I could use this feature because I'm rendering cubemaps captured by cameras and uploaded by users. The photos aren't always oriented to north correctly, so they need a manual correction after upload.

One way that I've done this is to store the rotation as a variable, apply it to the scene just before rendering, and then resetting the scenes' rotation to the identity quat just after rendering.

This causes two unnecessary updates to all my scene objects' world matrices. It also means I can't do any position updates in onBeforeRender. But it keeps the scene in a normal state otherwise.

wmcmurray commented 3 years ago

Btw (since no one mentioned it), it seems to be possible to make a "classic" skybox that rotates using an array of 6 materials.

something like this :

const urls = [
  '/assets/skybox/right.png',
  '/assets/skybox/left.png',
  '/assets/skybox/top.png',
  '/assets/skybox/bottom.png',
  '/assets/skybox/front.png',
  '/assets/skybox/back.png',
];

const materials = urls.map((url) => {
  const texture = new THREE.TextureLoader().load(url);

  return new THREE.MeshBasicMaterial({
    map: texture,
    side: THREE.BackSide,
    fog: false,
    depthWrite: false,
  });
});

const skybox = new THREE.Mesh( new THREE.BoxBufferGeometry(10000, 10000, 10000), materials );
scene.add(skybox);

skybox.rotation.y = Math.PI / 2;

As demonstrated here : https://woodenraft.games/demos/skybox-rotation-threejs.html

capnmidnight commented 3 years ago

@wmcmurray You'll have to move this skybox with the camera to make it work right, and you'll have to make sure that your box dimension X < Math.sqrt(0.75 camera.far camera.far) so the corners always fit in the view, but that seems easier than my hack of rotating/unrotating the scene.

DavidPeicho commented 3 years ago

Should we re-open a PR for that? There are two use cases and if we don't want to affect performance we can use a shader define:

In order to prevent the user with use case 1 to be affected by the matrix multiplication, maybe we can simply add a flag like:

renderer.dynamicBackground = true;

and compile the background shader accordingly?

In the meantime

As @wmcmurray and @capnmidnight pointed, you can basically re-code your own background rendering and it's not that difficult. Just be extra careful with the viewing plane (near and far values).

Instead of using MeshBasicMaterial, you can also directly create your own shader extending ShaderMaterial and sample the cubemap.

wmcmurray commented 3 years ago

Just to add on top of my previous comment, the method proposed will generate 6 draw calls per frame (1 per material) this is not very good... along with specificities mentioned here. ๐Ÿ˜•

I ended up solving all those issues ๐Ÿ˜ with this approach :

  1. I took all my skyboxes composed of arrays of materials, (I actually have many, one for the sky, one for stars, one for clouds, etc) and I put all of them in a different scene.
  2. I then create a WebGLCubeRenderTarget along with a CubeCamera that renders into this target. Then I add this camera into the scene with my skyboxes.
  3. I then set the background of my original scene to the texture property of this render target.

From there, I can just call CubeCamera.update() to generate a cube texture of the whole scene with skyboxes, this texture will be used as the background of my game scene, it will be rotated properly and it will be rendered with only 1 draw call per frame ! ๐Ÿ‘๐Ÿผ You don't even have to move the skybox with the camera since the CubeCamera is fixed in the skybox scene.

You can also pass that texture to a PMREMGenerator to generate a scene.environment texture, this will give you dynamic envMap reflections on all PBR materials, for "free" ! ๐Ÿคฏ

This method works very great when you just want to generate your background once, but it also works with a dynamic background that moves over time ! In my case, the sky rotates slowly so I can get away with updating the skybox scene texture about 8 times per seconds and it still seems fluid enough ๐Ÿ™‚ It's also super easy to tweak the texture resolution to reduce the work load.

sdraper69 commented 1 year ago

I have noticed that sketchfab and playcanvas have this function available, are we (and by that I mean someone cleverer than me) not able to see how they do it?

AlansCodeLog commented 1 year ago

Any news on this, at least for the case of changing it once like when when the coordinate system is different? I looked in several places and did not really find anything that worked. Some people say they found a workaround but then never reply with a solution. @wmcmurray solution works but I would like to just be able to load a single image.

I dug around a bit in the source code and saw that a CubeCamera is used to project/capture the texture and wondered if it might be possible to rotate it. First I monkeypatched WebGLCubeRenderTarget.fromEquirectangularTexture to rotate the cube camera, this works but broke when I set background blurriness and reflections were still off (am new to threejs so still getting the hang of how all this texture stuff works).

I wondered though why CubeCamera did not respect Object3D.DEFAULT_UP.set(0, 0, 1), and it seems that when it creates the perspective cameras the up vector is set directly. Is there any way it could be made to respect default up or would that break other things?

Anyways after much fiddling, I arrived at this workaround. Now reading some of the comments again in this and other issues I see this was suggested, but I did not really understand what they were talking about.

    const hdrLoader = new RGBELoader()
    hdrLoader.load(hdrUrl, function(texture: Texture) {
        texture.mapping = EquirectangularReflectionMapping
        texture.encoding = sRGBEncoding

        scene.background = texture
        scene.environment = texture

        // Toggle visibility of nodes in scene
        // otherwise they cause artifacts in the background if any objects are loaded
        scene.traverse(node => {
            if (node instanceof Mesh) {
                (node as any)._visibleWas = node.visible
                node.visible = false
            }
        })

        const cubeRenderTarget = new WebGLCubeRenderTarget(256)
        cubeRenderTarget.texture.type = HalfFloatType
        const cubeCamera = new CubeCamera(NEAR_CLIP, FAR_CLIP, cubeRenderTarget)
        // the magic assuming Object3D.DEFAULT_UP.set(0, 0, 1) was set
        cubeCamera.rotation.set(degToRad(-90), 0, 0)
        cubeCamera.update(renderer, scene)

        // Toggle visibility back
        scene.traverse(node => {
            if (node instanceof Mesh) {
                node.visible = (node as any)._visibleWas
                delete (node as any)._visibleWas
            }
        })

        scene.background = cubeCamera.renderTarget.texture
        scene.environment = cubeCamera.renderTarget.texture
    })
nkallen commented 1 year ago

I have a question -- I would very much like to be able to rotate HDRIs in the shader -- not just to deal with the camera y-up / z-up issue (which I'm also facing). I have a 3d modeling application named Plasticity and it would be super useful for people to evaluate the forms of their objects. I am willing to pay a bounty to get this PR landed. If I'm not mistaken, something like @fabienrohrer 's solution would work well for me (behind a #define)

makc commented 1 year ago

@nkallen you are supposedly should be able to use that approach via material.onBeforeCompile route, or at least by patching shader chunks - without waiting for three.js team to do anything. and it is not like you can pay them to include the code you want - unless maybe you would pay a very substantial amount ๐Ÿ˜…

Mugen87 commented 1 year ago

Unfortunately, from today's perspective #16507 was incomplete. After evaluating this issue more deeply I've come to the conclusion that:

a) cubeUV and equirect(*) has to be supported as well. b) the orientation has to be defined on Texture level. c) rotation has to work for env maps and the scene's background. d) the type of the new property should not be Matrix3 but Euler.

It is inconsistent if rotating an env map works for cube maps but not for equirectangular maps or PMREMs. So the new property has to work with all env map types. Hence, it can't be a property of CubeTexture.

Just being able to rotate Scene.background is also insufficient since the background would potentially mismatch with the reflections on 3D objects. Yes, it is true that the background's blurriness can be configured independently however this a different use case. The blurriness can be considered as a DOF effect that should emphasize whatever 3D object is in focus. The directions of the reflections are still correct though.

The new property can't be of type Matrix3 since it would be complicated for users to configure a rotation with its API. Ideally, we use Euler and internally convert it to a 3x3 matrix (which is eventually used in the shader).

And to clarify, it is fine to transform the env map in the shader and not once when loading the map. The computational overhead is so minor that I doubt you see a difference in FPS.

(*) Equirectangular environment maps are internally converted to the cube map format and not directly supported in GLSL. The texture the user loads on app level is an ordinary texture and configured with THREE.EquirectangularReflectionMapping.

nkallen commented 1 year ago

That all sounds great to me. I just want to reiterate that - if itโ€™s any motivation, I will be happy to pay to get this code written. I think it would be useful to the broader community.

Mugen87 commented 1 year ago

@WestLangley Implementing the rotation for cube maps in the shader is clear (by transforming the reflection vector). E.g. the background shader would be:

vec4 texColor = textureCube( envMap, reflectionMatrix * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );

The question is: When using textureCubeUV(), can we transform the sample direction in the same manner? Or is there something else to be aware of when using PMREMs? I have not tested it so far but if we could do the following, the feature should be straightforward to implement:

vec4 texColor = textureCubeUV( envMap, reflectionMatrix * vWorldDirection, backgroundBlurriness );
WestLangley commented 1 year ago

See https://github.com/mrdoob/three.js/pull/24722. I would have preferred to merge it so users would have an option.

For an alternate approach using NodeMaterial, see https://threejs.org/examples/webgpu_cubemap_adjustments.html. (Currently WebGPU-only).

Mugen87 commented 1 year ago

I've noticed the PR but I would not like to see users working with render targets again.

Mugen87 commented 1 year ago

If @mrdoob approves, I can implement a property based approach e.g. Texture.envMapRotation or something similar.

For an alternate approach using NodeMaterial

The node material approach is fine but I think there should be an option for users of WebGLRenderer.

VanderSP commented 6 months ago

actually im using a hack lol, but my hack is pre fixed value, maybe if i know how to feed uniforms onBeforeCompile... maybe ask gpt, at least my hacked fragment rotates correctly by 3 axis, after so much attempts that used to distort before.

PeteMatterfield commented 6 months ago

This is quite an old, but fundamental, feature of rendering. It's been punted over the years to the next revision but some of us need the feature for various upcoming deliverables. Happy to put up some serious sponsorship cash, immediately, to fast track its implementation. Or, for someone to at least post the working shader code so we can implement it locally.

VanderSP commented 6 months ago

@PeteMatterfield paste this in any part of your js: but this is without using pmrem... pmrem u need to change other file... anyway im not into pmrem... now i dunno if it was because in the past when i changed pmrem file, i was doing distorted one and i was thinkin was a pmrem problem.. maybe one day i test, but i think they will implement it soon :)


ShaderChunk['cube_uv_reflection_fragment'] = `
#ifdef ENVMAP_TYPE_CUBE_UV

    #define cubeUV_minMipLevel 4.0
    #define cubeUV_minTileSize 16.0

    // These shader functions convert between the UV coordinates of a single face of
    // a cubemap, the 0-5 integer index of a cube face, and the direction vector for
    // sampling a textureCube (not generally normalized ).
    float getFace( vec3 direction ) {
        vec3 absDirection = abs( direction );

        float face = - 1.0;

        if ( absDirection.x > absDirection.z ) {

            if ( absDirection.x > absDirection.y )

                face = direction.x > 0.0 ? 0.0 : 3.0;

            else

                face = direction.y > 0.0 ? 1.0 : 4.0;

        } else {

            if ( absDirection.z > absDirection.y )

                face = direction.z > 0.0 ? 2.0 : 5.0;

            else

                face = direction.y > 0.0 ? 1.0 : 4.0;

        }

            return face;

    }

    // RH coordinate system; PMREM face-indexing convention
    vec2 getUV( vec3 direction, float face ) {

        vec2 uv;

        if ( face == 0.0 ) {

            uv = vec2( direction.z, direction.y ) / abs( direction.x ); // pos x

        } else if ( face == 1.0 ) {

            uv = vec2( - direction.x, - direction.z ) / abs( direction.y ); // pos y

        } else if ( face == 2.0 ) {

            uv = vec2( - direction.x, direction.y ) / abs( direction.z ); // pos z

        } else if ( face == 3.0 ) {

            uv = vec2( - direction.z, direction.y ) / abs( direction.x ); // neg x

        } else if ( face == 4.0 ) {

            uv = vec2( - direction.x, direction.z ) / abs( direction.y ); // neg y

        } else {

            uv = vec2( direction.x, direction.y ) / abs( direction.z ); // neg z

        }

        return 0.5 * ( uv + 1.0 );

    }

    vec3 bilinearCubeUV( sampler2D envMap, vec3 direction, float mipInt ) {

        float face = getFace( direction );

        float filterInt = max( cubeUV_minMipLevel - mipInt, 0.0 );

        mipInt = max( mipInt, cubeUV_minMipLevel );

        float faceSize = exp2( mipInt );

        highp vec2 uv = getUV( direction, face ) * ( faceSize - 2.0 ) + 1.0; // #25071

        if ( face > 2.0 ) {

            uv.y += faceSize;

            face -= 3.0;

        }

        uv.x += face * faceSize;

        uv.x += filterInt * 3.0 * cubeUV_minTileSize;

        uv.y += 4.0 * ( exp2( CUBEUV_MAX_MIP ) - faceSize );

        uv.x *= CUBEUV_TEXEL_WIDTH;
        uv.y *= CUBEUV_TEXEL_HEIGHT;

        #ifdef texture2DGradEXT

            return texture2DGradEXT( envMap, uv, vec2( 0.0 ), vec2( 0.0 ) ).rgb; // disable anisotropic filtering

        #else

            return texture2D( envMap, uv ).rgb;

        #endif

    }

    // These defines must match with PMREMGenerator

    #define cubeUV_r0 1.0
    #define cubeUV_v0 0.339
    #define cubeUV_m0 - 2.0
    #define cubeUV_r1 0.8
    #define cubeUV_v1 0.276
    #define cubeUV_m1 - 1.0
    #define cubeUV_r4 0.4
    #define cubeUV_v4 0.046
    #define cubeUV_m4 2.0
    #define cubeUV_r5 0.305
    #define cubeUV_v5 0.016
    #define cubeUV_m5 3.0
    #define cubeUV_r6 0.21
    #define cubeUV_v6 0.0038
    #define cubeUV_m6 4.0

    float roughnessToMip( float roughness ) {

        float mip = 0.0;

        if ( roughness >= cubeUV_r1 ) {

            mip = ( cubeUV_r0 - roughness ) * ( cubeUV_m1 - cubeUV_m0 ) / ( cubeUV_r0 - cubeUV_r1 ) + cubeUV_m0;

        } else if ( roughness >= cubeUV_r4 ) {

            mip = ( cubeUV_r1 - roughness ) * ( cubeUV_m4 - cubeUV_m1 ) / ( cubeUV_r1 - cubeUV_r4 ) + cubeUV_m1;

        } else if ( roughness >= cubeUV_r5 ) {

            mip = ( cubeUV_r4 - roughness ) * ( cubeUV_m5 - cubeUV_m4 ) / ( cubeUV_r4 - cubeUV_r5 ) + cubeUV_m4;

        } else if ( roughness >= cubeUV_r6 ) {

            mip = ( cubeUV_r5 - roughness ) * ( cubeUV_m6 - cubeUV_m5 ) / ( cubeUV_r5 - cubeUV_r6 ) + cubeUV_m5;

        } else {

            mip = - 2.0 * log2( 1.16 * roughness ); // 1.16 = 1.79^0.25
        }

        return mip;

    }

    vec3 rotateVectorX(vec3 v, float angle) {
        float s = sin(angle);
        float c = cos(angle);
        return vec3(v.x, c * v.y - s * v.z, s * v.y + c * v.z);
    }

    vec3 rotateVectorY(vec3 v, float angle) {
        float s = sin(angle);
        float c = cos(angle);
        return vec3(c * v.x - s * v.z, v.y, s * v.x + c * v.z);
    }

    vec3 rotateVectorZ(vec3 v, float angle) {
        float s = sin(angle);
        float c = cos(angle);
        return vec3(c * v.x - s * v.y, s * v.x + c * v.y, v.z);
    }

    vec4 textureCubeUV( sampler2D envMap, vec3 sampleDir, float roughness ) {

        float mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP );

        float mipF = fract( mip );

        float mipInt = floor( mip );

    sampleDir = rotateVectorZ(sampleDir, -0.1);

    sampleDir = rotateVectorY(sampleDir, -0.8);

    sampleDir = rotateVectorX(sampleDir, -0.8);

        vec3 color0 = bilinearCubeUV( envMap, sampleDir, mipInt );

        if ( mipF == 0.0 ) {

            return vec4( color0, 1.0 );

        } else {

            vec3 color1 = bilinearCubeUV( envMap, sampleDir, mipInt + 1.0 );

            return vec4( mix( color0, color1, mipF ), 1.0 );

        }

    }

#endif
`

im hardcoding these: sampleDir = rotateVectorZ(sampleDir, -0.1); sampleDir = rotateVectorY(sampleDir, -0.8); sampleDir = rotateVectorX(sampleDir, -0.8);

but i suppose it can feed via some uniforms in onbeforecompile, gpt said something about that, but i not tested, so can realtime update... because i think they will implement it soon...

PeteMatterfield commented 6 months ago

@PeteMatterfield paste this in any part of your js: but this is without using pmrem... pmrem u need to change other file... anyway im not into pmrem... now i dunno if it was because in the past when i changed pmrem file, i was doing distorted one and i was thinkin was a pmrem problem.. maybe one day i test, but i think they will implement it soon :)

Thanks @VanderSP but I'll wait for pmrem support as that's what is being used by default.

Mugen87 commented 6 months ago

I've added an experimental Scene.backgroundRotation property to test a potential change with cube, equirectangular and cubeUV maps. You can use the following two links and enable rotation with the GUI:

https://rawcdn.githack.com/Mugen87/three.js/053bbee3597e55b88e1da5be44dd0b1e81b70cce/examples/webgl_materials_envmaps.html https://rawcdn.githack.com/Mugen87/three.js/053bbee3597e55b88e1da5be44dd0b1e81b70cce/examples/webgl_tonemapping.html

webgl_tonemapping uses PMREM when the background blurriness is greater than 0.

@VanderSP @PeteMatterfield Does this look correct to you?

Like mentioned earlier in the discussion, it would be good to have this feature for environment maps with normal meshes (not just the background skybox) as well.

VanderSP commented 6 months ago

Looks like it rotates... but i neve use back just envmap reflections, my manual solution works, not tested with the pmrem file but probably its possible, as i tried before but with wrong rot calculations, now i just need to ask gpt how to feed uniform values on onbeforecompile so i can change in realtime, but yes actually im overriding the shader variable fragment

PeteMatterfield commented 5 months ago

@Mugen87 Yes, this looks good so far!

joezappie commented 5 months ago

@VanderSP, I'm trying to figure out rotating my scene.enviornment as I have a Z up scene. Does your code work for that? I tried to use it, but I get Fragment shader is not compiled. Never done shader stuff before, so I'm a bit confused. I tried to run renderer.compile(scene, camera) after creating them.