Personal portfolio - Impossible-Box

Hey everyone,

I’m super stoked to share a project that I’ve been working on with three.js.
I’ve put together a 3D portfolio that’s a bit out of the box - quite literally. I used react-three-fiber to craft an impossible box, and each of its faces is a different project I’ve worked on.

And the cherry on top - this project bagged an Honorable Mention on Awwwards!

Check it out here: Impossible Box Link
See the award here: Awwwards Mention Link

I’d really appreciate any feedback you guys might have. If you spot something off, or have suggestions to make it better, do let me know. I’m all ears for ways to improve.


It is beautiful and captivating. If I stay more than 30 seconds watching a showcase, it means I like it. I stayed a few minutes with (or in) your impossible box.

As for glitches, there are some:

  • the asset loading bar is not honest, see where 50% is (sometimes it is 1/3, sometimes it is 1/4 full)
  • the maze has some z-fighting
  • when I enter the house generation room, I cannot exit (tried pressing the close button many times), the exit buttons of other rooms work fine
  • I tried to look under the box or on top of its roof (in case there is some Easter egg), … but there was none

Also, congrats for the honorable mention on Awwwards!

1 Like

Thanks heaps for your feedback on my project! I’ll tackle those unnoticed bugs ASAP. As for the Easter egg on the box top and bottom - love the idea, but it’s tricky with the current setup

1 Like

I’m really scratching my head over this issue as it seems to crop up only on certain devices. Could you please let me know the type of device and browser you used? This info would be super helpful in troubleshooting

It’s a laptop with two cards (integrated and NVidia)

Opera 98.0.4759.39, Edge 113.0.1774.35 → looks good
Firefox 112.0.2, Chrome 113.0.5672.93 → z-figthing

(this is somewhat unexpected, usually Chrome outperforms the other browsers, it might be some setting)

Maybe some more brutal PolygonOffset would be sufficient?

1 Like

Thanks so much for going the extra mile and running these tests, I really appreciate your help.

I tried your fix, but I can’t tell if it worked because I’m not able to reproduce the bug on my end

The issue is strange because the maze is just one plane, so it’s weird that it would have z-fighting with itself. I think it might be a shader issue, but I’m not sure why this would happen on some devices and not others

It appears I’ve set up different browsers to different graphics hardware. Here are snapshots. I’ve marked differences with red arrows:

1 Like

Honestly, this issue has me totally stumped
I’m not even sure where to start fixing this.
But I really appreciate the information - it could come in handy as I continue to troubleshoot

1 Like

It appears it is not related to the browser, but to the graphical system. Works fine with Chrome+UHD, fails with Chrome+NVidia.

Could you make just the maze in CodePen? Some minimal example, without all the logic for maze generation and path finding.

When I have time, and if it is not urgent, I could try to debug it on my machine.

1 Like

Sorry for the delay. I’ve put together a CodeSandbox with everything needed to reproduce the bug. Here’s the link: CodeSandbox Link
Thank you for taking the time to help me try to solve this issue, I really appreciate

In MazeShader.js, when wallHeight is 10 there is z-fighting:

When wallHeight is 11 it looks without fight:

However, the color looks wrong. So, when I look how wallHeight is used, I see direct compare of floating point values. This is dangerous. When I replace a==b with abs(a-b)<0.001, the color looks OK with wallHeight = 10:

1 Like

It turned out to be an easy fix after all!
No more comparing floating-point values for me – I’ve learned my lesson haha
I’ve made the correction on the site, but this time I’m the one with a Z-fighting issue

Capture d'écran 2023-05-14 104951 Capture d'écran 2023-05-14 105054

To resolve it, I removed the polygon offset and adopted this code organization and it seems to work:

const maze = {
    wallHeight: 8,
    pathHeight: 18,
    visitedHeight: 5
const colors = /* glsl */ `
    (vPosition.z > ${maze.pathHeight}.0)
    || (north.x > ${maze.pathHeight}.0)
    || (south.x > ${maze.pathHeight}.0)
    || (east.x > ${maze.pathHeight}.0)
    || (west.x > ${maze.pathHeight}.0)
        diffuseColor.rgb = vec3(0.6,0.0,0.0);
    else if( 
    (vPosition.z > ${maze.wallHeight}.0)
    || (north.x > ${maze.wallHeight}.0 )
    || (south.x > ${maze.wallHeight}.0 )
    || (east.x > ${maze.wallHeight}.0 )
    || (west.x > ${maze.wallHeight}.0 )
        diffuseColor.rgb = vec3(0.05,0.05,0.7);
    else if (
    (vPosition.z == ${maze.visitedHeight}.0 )
    || (north.x == ${maze.visitedHeight}.0)
    || (south.x == ${maze.visitedHeight}.0)
    || (east.x == ${maze.visitedHeight}.0)
    || (west.x == ${maze.visitedHeight}.0)
        diffuseColor.rgb = vec3(1.0,1.0,1.0);
        diffuseColor.rgb = vec3(0.01,0.01,0.01);
1 Like

Imagine vPosition.z fluctuates around wallHeight, e.g. from 9.999999 to 10.000001 … In this case vPosition.z > wallHeight is not sufficient:

1 Like

Ah, I see now. I’ve reinstated your solution. Could you please take a look at the site and let me know if it’s working properly now?

Now both mazes show up well. :+1:

BTW, if you want to use (a > b) and safeguard against turbulence, you can use (a > b-eps), where eps is something small, like 0.001 or even smaller.

I know I’ve said it a hundred times, but thank you again for your help
Your assistance made all the difference! :grin:

1 Like

Very very cool @James_Hall !! Well done :+1:

1 Like

This is seriously cool. Apart from cube itself with the “portals”, the I especially like the house layout generator. Did you use a wave-function collapse method for this?

1 Like

Thank you! No, I don’t even know what that is. I created a 3-dimensional js array where I fill in information like ‘wall’ or ‘staircase’ with algorithms, and then I use that array to generate the three.js geometries

1 Like