Pass light data to custom shader

Something I’ve been working on the last few days (yes, the whole thing is scripted within castle-editor): https://youtu.be/2Q71uhmCs2M

Now for the question :slightly_smiling_face:

I’m at the point where I need to develop a custom lighting engine for the game. Since the environment is 3D while the characters are 2D, the lights need to affect the 2D characters as well. What’s the best way to pass light data to my custom shader?

Nice setup, looks great!

  1. Can you explain in details why do you need it? Maybe this will lead to more optimal advise, simpler than what I say in AD 2 below :slight_smile:

    Note that 2D things can be affected by light the same way as 3D. They can have normal maps etc. I used it long ago in “Orcs and Volcanoes” ( Development: great API for 2D games and UI, our engine in Debian, on the road to OpenGL ES, Orcs and Volcanoes game screenshots | News | Castle Game Engine , unfortunately that game’s cannot be open-source, as assets cannot be public). IOW, nothing forces 2D things to be “unlit”.

    So, what specifically do you want to achieve with custom lighting that isn’t available with current lighting solution + plugs that configure how the end result looks like?

    Note that we include some “plugs” specifically to customize light calculation, A.3. Lights plugs (internal; at vertex or fragment shader) . While they are said to be “internal”, in practice some of them could be declared “official, not internal” easily.

  2. That said, if you really want your own shaders to handle light “from scratch”, the clean way is to :

    • Define uniforms in your shader (whole shader, or shader effect) that get the positions, colors and other parameters of all the light sources). Like my_LightSource%dPosition. Possibly regenerate your shaders based on lights count. Or just limit your lights number and pass the remaining lights as “zero influence”.

    • Each Update, or BeforeRender, scan the world (or maybe only some special TCastleTransform that is guaranteed to hold all the lights) for all the lights, read all lights parameters, and pass the lights’ parameters as uniforms to your shaders (whole shader, or shader effect). Following the examples examples/viewport_and_scenes/shader_effects/ (if you use shader effect to add lighting, which I recommend) or examples/viewport_and_scenes/shader_override.

    I realize this is rather tediuos manual way. If you don’t want this, see AD 1 :slight_smile: I mean, our current lighting calculation tries account for many situations, 2D included, and “plugs” offer further ways to adjust it.

  3. I should note that our internal shader generation code in src/scene/castlerendererinternalshader_light.inc does already pass lighting parameters to uniforms, like castle_LightSource%dPosition. But this is not really useful to you – they are passed following our internal logic, under certain conditions, and to really use them you also need to be aware of some #defines.. like LIGHT%d_TYPE_PUNCTUAL. And these defines are not set on custom shaders… So, you cannot really rely on this information – it is only supposed to be used by our own built-in light shaders.

I hope this is a helpful starting point :slight_smile: If I learn more about “why do you need it” I will likely be able to help better.

P.S. Sorry if you already wrote details about it on Discord – I’m traveling now and will get back to Discord around the end of next week.

Because this is for my own renderer (spine-runtime) which has no access to CGE’s built-in compositing shaders. So I will go with the 2nd option.

1 Like