Simple shadow mapping example

Sorry, but I always use highp. I hate low and medium precision.

I can guess that the problem may be in the sampler mapping via glGetUniformLocation(). Or there might be a GLES2 legacy hiding somewhere, which prevents float samplers from being set correctly. This, by the way, may be indicated by the crash of the build when trying to use float formats other than R32F.

1 Like

I’ve tried to test shadow’s render target render.FORMAT_R32F on my mobile. And it works correct. But the app lags noticeably.


Screenshot from Google Pixel 2XL. (4y.o. model).

Then I replaced render target back to render.FORMAT_RGBA and the app works smooth again. Not sure why.


Screenshot from the same device.

P.s. I use 2048x2048 depth buffer

10 Likes

Hello,
How do you draw debug camera frustum?

Regards

As long as I don’t have guaranteed float render-targets, I make shadows using RGBA texture to record depth.
And here I’ve encountered a strange bug that shows up consistently on all iPhones and iPads (I’ve tested devices from iPhone7 to 12 Pro and several iPads):


It looks as if the RGBA channels are less than 8 bits.

I wasn’t able to find the cause, but I was able to artificially reproduce this error on Android by lowering the storage accuracy of the four RGBA channels, but still leaving the same entire unpacking formula from RGBA to float (i use this formula: Encoding floats to RGBA - the final? · Aras' website)

What solution do you recommend?

4 Likes

Could you share the project with me, or a smaller repro? iPhones having less precision on newer devices doesn’t sound right :thinking: jhonny@defold.se

EDIT: Found the issue with your F32 texture sampling, so you might not need to do the encoding. See https://github.com/defold/defold/issues/6730

3 Likes

I solved this problem by turning off linear texture filtering (yes, there it is again!).
It’s a pity, I wanted to have smoothed shadows, but while filtering on androids is accurate enough, on iPhones it’s not.

Nevertheless, I will prepare and send a project with this error later, perhaps you will be interested to see it.

2 Likes

We are discussing support for adding extensions in some way, so hopefully you can get that in some near ish future :slight_smile: you can do the sampling yourself aswell but it’s a bit expensive for low end I’m afraid

3 Likes

Due to the advent of float RT, I have converted my shadows to R32F format. And discovered the unpleasant thing - for some old (and not so old) smartphones the R16F format is somehow used instead of the R32F format.

If I use RGBA32 and convert the shadow depth to 4 components (R,G,B,A) then everything works correctly on all smartphones and PCs.
While this is a good solution, it is saddening to have to do a dot() for each texture read and normalize the shadow depth to a range of 0…1.

But the unpredictable switching in 16F is a nuisance. Is there anything you can do about it?

Not sure, it’s a pretty classic problem with OpenGL and old devices. But maybe we could expose values from this function glGetShaderPrecisionFormat so you can do the workaround necessary. Alternatively I guess you could split the value over two R16 channels. But usually 16F should be enough for shadows I would think, but I guess it depends on your needs…

2 Likes

Yeah, I jumped to conclusions a bit. :slight_smile:
Indeed, the 16 bit format should be enough.
Indeed, when I tweaked the bias, everything was almost fine.
Moreover, even the position recovery from depth was not affected (well, or it’s imperceptible to the eye). :slight_smile:
SSAO didn’t feel the drop in accuracy from 32 to 16 bit at all, apparently it doesn’t care about such subtleties. :slight_smile:

3 Likes

Good to hear! :+1:

2 Likes

What the hell! When using the R16F directly, the smartphone crashes with error GL 1282. Classic!
So I am forced to always specify R32F, expecting to sometimes get R16F. It’s all right, we’ll get over it somehow.

2 Likes

Hmm on more than one device? You might be facing some strange driver edge case… old android is a minefield of issues like this unfortunately. But if it’s an es3 device you should be able to request 16F, I’ll do some investigation this week but you might want to use the 32F solution for now if it works…

3 Likes

For people reading this now or in the future, do NOT use anything other than point filtering for depth targets if you are testing for differences in depth yourself. I believe that some graphics APIs have a sampler type for shadow mapping that allows for getting some basic PCF running with linear filtering, but I do not believe Defold allows you to access that currently. The reason you do not want to use linear filtering on depth targets is it gives you incorrect depth values (remember this is depth information, not color information) You are basically blurring the depth buffer, which when testing against fragment depth you will get artifacts. It only gets worse when you are using some form of encoding on your depth buffer.

If you want smooth shadows, there are other solutions. One simple solution is PCF, which acts as a form of antialiasing (or really a blur). Combine that with linear filtering in the shader (after you have tested your depth values) and you get decent shadows.

OK, I made a PCSS. It works pretty well on a mobile phone.

12 Likes

CORRECTION: Linear filter should be fine if you are using a standard depth target… If you encode it however, there will be issues.

This looks great! Would you be able to share the code?

2 Likes

Yes, I’ll try to make it quick.

2 Likes