Babylon Projection Texture Support

It is way less expensive to use the projection and I guess it should just work fine with a few of them.

A new mode is definitely the way to go but disabling lighting completely sounds counter intuitive and in this case I think it should be a separate feature.

I guess either we replace the shadow value with the projection and keep it in the light (like a projectionShadowTexture) or if it completely disable lighting maybe we should find smthg else to modulate the output color with the projected shadow.

1 Like

Yes, I think we should add a new feature here, something like a “projector”, that would simply modulate the baseColor / diffuseColor given a projection matrix and a texture and would be independent from lights: we are limited in the number of lights we can use (even if the limit can be raised). Also, we are not using any of the spot light attribute neither (angle, intensity, …).

In fact there is no shadow value because there is no shadow map (shadow=1 in the fragment code).

[EDIT]
Maybe we should have a look at what others do about this (like Unity).
[/EDIT]

1 Like

I like the idea of looking around for this one

@sebavan / @Evgeni_Popov … I dont know where to start here… Do we wanna piggy back off the light and tweak the shader light fragment ?

Or do we wanna create a new class called Projector or something and handle it there ?

We were thinking to first look out how others do and else evaluating the cost in light vs in a new feature.

I did not found anything fully conclusive looking out, so the simplest would be to add new defines in the light code. It could be smthg like a new projectionOnly boolean + another one for projected shadows instead of light.

Yo @Evgeni_Popov or @sebavan any reason why the projected shadow texture would not render on a plane mesh.

I simply replaced the create ground from heightmap to just be a simple plane, but the projected shadow does not show up. Is there a property on the mesh that needs to be setup for the projection to show up ?

Yo @Evgeni_Popov / @sebavan … Did you get a chance to look into why a plane from a gltf vs crating a ground plane via code… The projection texture shadow does not show up on the gltf plane :frowning:

For PBR materials, it’s surfaceAlbedo that should be updated, not baseColor:

Yo @Evgeni_Popov

Thank you very much :slight_smile:

Yo @Evgeni_Popov … Quick question… Does this count against the 4 light max limit ???

Yes, each created light count to the limit. However, you can raise the 4 limit to a higher value (material.maxSimultaneousLights).

Yo @Evgeni_Popov … is there something i have to do to refresh it when i move the spot light projector position… That projected shadow on the ground stays the same spot.

Should i be redrawing something when the spot light moves… My intent was to have the projector above a car racing on a track so the the shadow would be projected on to the track while driving ?

Turns out if you set a new spot light position, that cause the spot light _setPosition override to run which sets _projectionTextureViewLightDirty = true

But if you just update that value, the _setPosition does not run so you gotta manually mark dirty if you manually update the position vector directly. SO that i am only marking it dirty if the that last position is different

        private updateProjectorPosition():void {
            this.m_projectorOffset.set(0, this.projectionHeight, 0);
            UTIL.GetAbsolutePositionToRef(this.transform, this.m_projectorPosition, this.m_projectorOffset);
            if (this.m_lastPosition.x !== this.m_projectorPosition.x || this.m_lastPosition.y !== this.m_projectorPosition.y || this.m_lastPosition.z !== this.m_projectorPosition.z) {
                this.spotLight.position.set(this.m_projectorPosition.x, this.m_projectorPosition.y, this.m_projectorPosition.z);
                (<any>this.spotLight)._projectionTextureViewLightDirty = true;
            }
            this.m_lastPosition.copyFrom(this.m_projectorPosition);
        }

Works great :slight_smile:

Ok @Evgeni_Popov … i got one for you… How would i rotate the spot light and/or its projected texture ?

Can you modify the playground and rotate/spin the projected texture around… since there is no light.rotation.y += 0.1 or something… How would you handle that one ?

Regarding updating the position, instead of:

                (<any>this.spotLight)._projectionTextureViewLightDirty = true;

I would do:

this.spotLight.position = this.spotLight.position;

because _projectionTextureViewLightDirty is a private property and we make no guarantee that this property will exist forever.

You can use the projectionTextureUpDirection property for that, which is used internally to build the view matrix corresponding to the projection matrix:

Yo @Evgeni_Popov … if you back the camera out a bit… there is a bit of Ghosting of the projected shadow. Take a look at this snapshot:

The problem is with mipmapping, which is not full white at the lowest level(s) but grey. You can either create the mipmap chain yourself and make sure the lowest level is a white pixel or simply disable mipmapping for the shadow texture:

https://playground.babylonjs.com/#CQNGRK#512

Thanks so much @Evgeni_Popov … My Spot Light Projector class is working pretty good so far :slight_smile:

Hello, don’t mean to raise a dead thread too much - this is the closest thing I could find searching for how to do a ‘fake’/forced shadow. I want to do something like the original request here, or look at old 8 bit games like Tornado Low Level.

Is there a sort of final / most recent concise explanation or example per chance? I am super new to BabylonJS and modern 3D apis unfortunately.

1 Like

If you want to do the same thing than in TLL, then the easiest way is to simply draw an additional mesh a bit offseted from the main mesh. Else, you can use the latest PG from this thread (https://playground.babylonjs.com/#CQNGRK#512) or even use real shadows.

2 Likes