7 Replies
      Latest reply on Mar 24, 2020 2:47 PM by Bersaelor
      Bersaelor Level 1 Level 1 (0 points)

        Dear Scenekit Experts,

         

        I'm trying to get a material resembling clear glass using PBR. It should be 99% transparent while also very reflective.

         

        Here's some sample code I'm using for my material right now:

         

                lightingModel = .physicallyBased
                metalness.contents = UIColor(white: 1.0, alpha: 1.0)
                diffuse.contents = UIColor(white: 0.2, alpha: 1.0)
                roughness.contents = UIColor(white: CGFloat(0.03), alpha: 1.0)
        
                transparencyMode = .dualLayer
                isDoubleSided = true
                transparency = 0.2

         

         

        The problem is that the amount of reflections seem to be affected by the `transparency`, i.e. if I set `transparency = 0.01` the reflections of the scenes environment map are barely visible anymore.
        If I on the other hand set `transparency = 0.2` I get some nice reflections, but unfortunately now my whole object is visible, i.e. it looks like a piece of tinted glass (depending on which color I set in `diffuse`).

        How can I make it clear , i.e. see-through while still seeing the reflections ?

        • Re: Full transparency while fully reflective (Scenekit material)
          gchiste Apple Staff Apple Staff (320 points)

          Hey there Bersaelor,

           

          Here is a trick that can get you something pretty close to "99% transparent while also very reflective".

           

          1.  Create an SCNPlane

           

          2.  Set it's first material's diffuse contents to UIColor.black

           

          3.  Set it's first material's blendMode to .add

           

          4.  Set it's first material's lightingModel = .physicallyBased

            • Re: Full transparency while fully reflective (Scenekit material)
              Erik Level 1 Level 1 (0 points)

              This will avoid blending the surface color contribution into the render target, but it'll also cause additive blending to be used for the reflections / highlights visible on the transparent surface. That's not ideal for realistic reflections, particularly if bright highlights are possible in your scene.

               

              One (somewhat clunky) option I've used is to set the surface fragment's red, green, and blue components to 0 using a shader modifier. With this approach, you can eliminate the surface color contribution without affecting the subsequent lighting stage. Be sure to specify #pragma transparent if your material properties don't otherwise include transparency.

               

              #pragma arguments
              
              #pragma transparent
              #pragma body
              
              _surface.diffuse.a = 0;
              _surface.diffuse.rgb *= _surface.diffuse.a;

               

              I'd be interested to hear if there's a simpler "correct" way.

                • Re: Full transparency while fully reflective (Scenekit material)
                  gchiste Apple Staff Apple Staff (320 points)

                  Totally agree on the non-realisticness of my previous solution (and the potential for additive blending issues), but OP was asking for "99% transparent while also very reflective", which is not physically realistic.

                   

                  If you want to represent realistic, window pane glass in SceneKit, here is what I recommend:

                   

                  Lighting Model: Physically Based

                   

                  Diffuse Color: Pick something that is mostly white, but with a very slight green/yellow tint (which is what real window pane glass has)

                  *If you want your glass to tint it's reflected light a certain color, pick that color here instead

                   

                  Diffuse Opacity: Somewhere between 8%-15%.  Real glass is not completely, or even 99% transparent.

                   

                  Metalness: Glass is an (imperfect) dielectric, so I suggest a value between 0.1-0.2 (however, if you want to exagerate the reflections on the glass, you can just increase the metalness, again, this would be unrealistic.)

                   

                  Roughness: Real window pane glass is polished, and therefore is pretty smooth, but again, not perfectly smooth.  I suggest a value between 0.05-0.1

                    • Re: Full transparency while fully reflective (Scenekit material)
                      gchiste Apple Staff Apple Staff (320 points)

                      *And set the transparency to Dual Layer

                      • Re: Full transparency while fully reflective (Scenekit material)
                        Erik Level 1 Level 1 (0 points)

                        I imagine the opacity you'd use is dependent on the thickness of the glass, but yeah, some nonzero value does make sense, especially with regard to imparting a tint. I'd been doing it in the output stage, but this sounds like a nicer use of the engine.

                        • Re: Full transparency while fully reflective (Scenekit material)
                          Bersaelor Level 1 Level 1 (0 points)

                          I agree in that glass is never 100% transparent. The problem I found with reflection is If I set the transparency to 0.2 the overall end result alpha channel will be multiplied by that value.
                          This will seems to multiply with 0.2 even those fragments with a very strong specular/highlight reflection.

                          (1) Reality:
                          (a) Strong reflection in glass makes objects behind the glass invisible
                          (b) Normal glass without any reflections, adds a little bit of it's tint, depending on thickness, to the color that is visible behind.


                          Compare an image of a pair of glasses with plexi glass side-protectors from my desk: https://imgur.com/cA5ylB0

                          Where there is a reflection the glas becomes basically opaque.


                          (2) SceneKit:
                          (a) High Opacity: Reflections are beautifully reflecting lights etc, unfortunately one can barely see the object behind the glass.
                          (b) Low Opacity: Great visibility of objects behind the glass, but now all the reflections are very subdued.

                          So, what I ended up doing with this is adjusting the alpha-channel of a fragment by the amount of specular lighing that fragment gets:

                          vec3 light = _lightingContribution.specular;
                          float alpha = reflectivity * min(1.0, 0.33 * light.r + 0.33 * light.g + 0.33 * light.b);
                          _output.color.rgb *= min(1.0, (1.5 + 2 * \(minAlpha)) * alpha);
                          _output.color.a = (0.75 + 0.25 * \(minAlpha)) * alpha;

                          `

                          (We put that shader modifier into our release of https://apps.apple.com/app/id1463380262 in case you want to try yourself)

                          @gchiste I also implemented your tip using `blendMode = .add`, which is a good alternative to the above custom shader in same cases.
                          I agree though that it doesn't work perfectly under varying lighting conditions.