facebookarchive / react-360

Create amazing 360 and VR content using React
https://facebook.github.io/react-360
Other
8.73k stars 1.23k forks source link

Cannot see Image element through a Sphere with opacity 0 #278

Open 3hpibwalker opened 7 years ago

3hpibwalker commented 7 years ago

Image element within a Sphere of opacity 0 is not displaying

This is a bug. Following code manifests the problem. It is in TSX, but is very close to JSX.

<ReactVR.VrButton
          onClick={() => {
            this._victoryBounce(
              feature.key,
              () => { grabOp(feature.key); }
            );
          }}
          onClickSound={{ wav: ReactVR.asset('success.wav') }}
          onEnterSound={{ wav: ReactVR.asset('hover_item.wav') }}
          style={{
            flexDirection: 'row',
            layoutOrigin: [0.5, 0.5],
            position: 'absolute',
            transform: [{ rotateX: feature.transform.rotateX },
            { rotateY: feature.transform.rotateY },
            { rotateZ: feature.transform.rotateZ },
            { translateX: feature.transform.translateX },
            { translateY: feature.transform.translateY },
            { translateZ: feature.transform.translateZ },
            { scale: feature.transform.scale }]
          }}
          onExit={() => { this._fade(); }}
          billboarding={'on'}
        >
          <ReactVR.Animated.View
            style={{
              // layoutOrigin: [0.5, 0.5],
              opacity: this.state.victoryWiggleAnim.imageOpacity,
              transform: [
                { scale: this.state.sizeAnim },
                { rotateZ: this.state.victoryWiggleAnim.spin },
                {rotateY: spin }
              ],
              position: 'absolute'
            }}
          >
            <ReactVR.Image
              source={ReactVR.asset(feature.icon)}
              style={{
                width: 1.75,
                height: 1.75,
                transform: [
                  {translate: [0, -.85, 0.15]}
                ],
                // layoutOrigin: [0.5, 0.5],
                // position: 'absolute',
              }}
            >
            </ReactVR.Image>
            <ReactVR.Cylinder
              dimHeight={0.25}
              radiusBottom={1}
              radiusTop={1}
              segments={50}
              wireframe={false}
              style={{
                color: '#9400d3',
                transform: [
                  { rotateX: 90 }
                ]
              }}
            />
            <ReactVR.Image
              source={ReactVR.asset(feature.icon)}
              style={{
                width: 1.75,
                height: 1.75,
                opacity: .999,
                transform: [
                  {translate: [0, .85, -0.15]}
                ],
                // layoutOrigin: [0.5, 0.5],
                // position: 'absolute'
              }}
            >
            </ReactVR.Image>
          </ReactVR.Animated.View>

          <ReactVR.Sphere
                  radius={1.35}
                  style={{
                      opacity: 0,
                      position: 'absolute',
                      transform: [{ translate: [0.85, -1.75, 0] }]
                  }}
                  onEnter={() => { this._appear(); }} />
        </ReactVR.VrButton>

Expected behavior

The ReactVR.Sphere encompasses the rotating cylinder-and-image combination. Because the cylinder is narrow and looks like a coin with images on either side, its rotation on the Y axis will make it difficult to interact with by pointing, as its silhouette will be constantly changing. The sphere acts as a collision zone for the coin. The images can be seen on either side of the coin. If a texture could be applied to a single face of the cylinder, the images could be textures instead.

Actual behavior

Everything works as expected, except that the images are not visible when they intersect with the opacity 0 sphere. If the sphere is made to be wireframe, the images are visible, except that the wireframe lines overlay them. sphere in place sphere wireframe

Reproduction

Code above will reproduce. Can deploy a live version of the code with this happening, or provide access to our repository, if necessary.

Solution

Need to be able to see the images if they intersect an opacity 0 element.

Additional Information

mikearmstrong001 commented 7 years ago

If you add the following to the Sphere, this will override the sort and blend handling of that component. I have been debating handling this automatically but there are some tradeoffs in particular there would be two ways to set the same state and this can affect the way the scene will render eg when opaque the Sphere would draw using the zbuffer and correct resolve depth per pixel but when transparent the mode changes to be rendered in the order determined by the distance to the middle of the object. My feeling was that you don't want a flick in state and render method so keeping the states orthogonal is useful.

Interested in opinion

materialParameters: {
  transparent: true
}
3hpibwalker commented 7 years ago

Believe it or not, I actually got down into the three.js Material to try to find a materialParameter setting that would work, but I didn't find "transparent". I did just now by looking and going one level deeper because I knew it had to be somewhere.

I have two thoughts: 1) I can see that there is a difference between opacity and transparency once explained, but this would be a good thing to have documented for those of us coming from outside the VR/3D graphics world. 2) The reason I thought this was a bug was that the opacity of 0 was behaving differently between Images, Views, and the Cylinder. Opacity 0 without transparency being set was allowing the cylinder to show, but not the View/Text nor the Image, and that Cylinder is definitely inside the invisible Sphere.

Mostly, it was the perceived inconsistency that some things were showing and others weren't, and I didn't find any callouts as to how Views/Text/Images would behave when intersecting an opacity 0 shape.

3hpibwalker commented 7 years ago

Upon additional testing, it appears that there are certain angles that the overlapping image disappears. I increased the size of the sphere so that it doesn't intersect with anything, but there appear to be some issue causing the content of the Image control to not show up through the sphere. The image shows up fine if the sphere is wireframe and transparent, or wireframe and non-transparent, but appears and disappears depending on view angle with non-wireframe and transparent.

mikearmstrong001 commented 7 years ago

Sounds like Z fighting, any chance of a small video/animated gif?

3hpibwalker commented 7 years ago

coin-bug

3hpibwalker commented 7 years ago

We have resolved this by using the VrButton height/width. It appears to be doing what we need for now, but this could be an issue if we needed a hitbox around an element.