Custom transparent ground that receives shadows, show mirror and use diffuseTexture

Hello guys,

I am facing again a situation I can’t solve on my own. I try to combine several things into one plane material.

The ground should:

  1. … be transparent.
  2. … be able to receive shadows.
  3. … be able to mirror.
  4. … be able to show a diffuseTexture with alpha.

It’s exactly the setup of the default environment (https://www.babylonjs-playground.com/#10D6YT#35) just with transparent ground.

I created a playground here: https://playground.babylonjs.com/#9KLUBA#1

Thank you very much!!

pinging @Evgeni_Popov

You should set useAlphaFromDiffuseTexture to true for the ground material to enable alpha blending:

https://playground.babylonjs.com/#9KLUBA#2

1 Like

Thank you. That works great.

Am I able to easily disable the diffuse texture while keeping shadows and mirror on transparent ground? Or do I have to replace the diffuse texture to imitate a transparent effect?

You have to either use a diffuse texture with transparency or an opacity texture to get transparent effect in your use case.

I tried it with a transparent diffuseTexture. The problem is that the ground gets completely transparent. So the mirror as well as the shadow are not visible anymore.

EDIT:

In my project it’s woks after setting alpha mode to multiply. In playground the ground is still visible though: https://playground.babylonjs.com/#9KLUBA#3

Any chance to keep the mirror if the light is shining on it?

I think what you want is to keep the shadow and the mirror and have everything else transparent?

Maybe this will work for you:

https://playground.babylonjs.com/#9KLUBA#4

If the shadow variable is strictly less than 1 it means the pixel is at least partly in shadow. And the if (color.r != 0.2 || color.g != 0.2 || color.b != 0.3) check is to test against the clear color.

Thanks for your effort. With just the clearColor background it looks transparent but unfortunately it isn’t.
https://playground.babylonjs.com/#9KLUBA#5

My mistake, testing for the clear color is wrong as it is not the color computed in the shader.

One way to do it would be to clear the mirror with an alpha=0 color and use this alpha value as the final alpha value of the shader, except when shadow is < 1:

https://playground.babylonjs.com/#9KLUBA#6

1 Like

We are getting close. I put all codes together and now I am able to show all combinations:

  • gradient
  • gradient, shadow
  • gradient, mirror
  • gradient, shadow, mirror
  • shadow
  • shadow, mirror
  • mirror

I encounter two weird behaviours though:

  • If using the custom material to create the combination “shadow, gradient” the shadow breaks after enabling blur.
  • The mirror is mirrored :grinning: This is only after appending a glb model and adjusting scale and position.

https://playground.babylonjs.com/#9KLUBA#10

It’s because blurScale and/or blurKernel is too high: lower one of them (or both) to correct the problem.

You should enable backface culling on the material of the sphere to get rid of the artifacts:

Thanks again for your help.

Backface culling works fine. But setting the blurScale or blurKernel down corrects the shadow in terms of size but it is not blurry anymore. With blurScale = 4 and blurKernel = 64 it should look like this:

That’s because I set a straight black when in shadow: color = vec4(0., 0., 0., 1.);

Improved PG:

https://playground.babylonjs.com/#9KLUBA#12

1 Like

This is perfect. Thank you!!

1 Like

I am sorry, but I have to come back to this thread.

I noticed two things:

  1. The initial problem with smooth shadow still exists in the mirror reflection of the sphere (https://playground.babylonjs.com/#9KLUBA#13).

  2. It is not possible to combine the shadow of multiple lights (https://playground.babylonjs.com/#9KLUBA#14). I had the same problem before with shadowOnlyMaterial. Earlier you helped me solving this with using backgroundMaterial like this:

     this.ground.material = new BackgroundMaterial("groundMaterial", this.props.scene)
     this.ground.material.alpha = -0.01
     this.ground.material.primaryColor = new Color3(0, 0, 0)
    
     Effect.ShadersStore["backgroundPixelShader"] = 
     Effect.ShadersStore["backgroundPixelShader"].replace(
         /gl_FragColor=color;/g,
         "gl_FragColor=vec4(vPrimaryColor.rgb, (1.0 - clamp(globalShadow, 0., 1.)) * 1.);")
    

Unfortunately that doesn’t work while using mirror as well.

Here’s the best I can do for #1: https://playground.babylonjs.com/#9KLUBA#16

Regarding #2, unfortunately globalShadow does not exist in the standard material. But with a bit of work we can reimplement it:

https://playground.babylonjs.com/#9KLUBA#17

1 Like

Thanks again. That is really helpful.

#1 It couldn’t be better :slight_smile:

#2 This works great. Is there a way to make the shadows stronger similar to this backgroundMaterial shadow? https://playground.babylonjs.com/#9KLUBA#18

#3 Do you know why this happens when shadow blur is disabled? https://playground.babylonjs.com/#9KLUBA#19

Yes, in the line:

color = mix(vec4(0., 0., 0., 1. - globalShadow),
            vec4(color.rgb, reflectionColor.a),
            pow(globalShadow, 0.25));

Raise the value 0.25. Try 2.0 for eg.

It’s the bias value of the shadow generators. Try to lower it:

2 Likes

I am happy. Thank you for your help!