Global Light Info in Custom Shader, similar to the Lights Node

What would be the best way to get all the lights in the scenes contributions in a custom shader?

I have sneaking suspicion its a couple steps.

You can do it like that:

	// Lighting
	vec3 diffuseBase = vec3(0., 0., 0.);
	lightingInfo info;
#ifdef SPECULARTERM
	vec3 specularBase = vec3(0., 0., 0.);
#endif
	float shadow = 1.;

#ifdef LIGHTMAP
	vec3 lightmapColor = texture2D(lightmapSampler, vLightmapUV + uvOffset).rgb * vLightmapInfos.y;
#endif

#include<lightFragment>[0..maxSimultaneousLights]

It’s a copy/paste from the fragment shader of the standard material.

After this block of code, you get the light contributions in diffuseBase and specularBase and the shadow level in shadow (1 meaning not in shadow).

You will need some includes too (lightFragmentDeclaration, lightsFragmentFunctions, …).

Note also that the code in those includes (including lightFragment) is expecting some variables to be defined (like viewDirectionW, normalW, …) so you need to setup them first before this code will work. You can also rename a variable when including a file in your shader with this syntax:

#include<lightsFragmentFunctions>(vPositionW,myWorldPos)

Which will replace all occurrences of the string vPositionW by myWorldPos when including the content of the file lightsFragmentFunctions. You can give more parameters if you need more replacing to take place:

#include<lightsFragmentFunctions>(vPositionW,myWorldPos,char2,replacechar2,char3,replacechar3)

All in all you should look at the code of default.fragment.fx for a better view of the process. Or use the node material editor and export the shader code :wink:

1 Like

Awesome! Now I can really do volumetric particles, my limitation was having to worry about all the lights and only really having directional light as an option.

@Evgeni_Popov I’m trying to get lighting information into my shader as well. I’ve used your hints as a starting point and had a look at default.fragment.fx. One can immediately see in the lightFragment.fx that no light contribution is computed if the light is not defined (#ifdef LIGHT{X}). So I had a look where this is defined and it seems to be done in MaterialHelper.PrepareDefinesForLight(). What I don’t see is that this would ever be called for a ShaderMaterial. So how is the lighting info passed on the CPU side to the shader in a ShaderMaterial?

Yes, it’s a bit involved, see #include directives in shader code output from Node Material Editor - #2 by Evgeni_Popov for more information.

The ShaderMaterial is not meant to be interfaced with lights. You should better use either a custom material, a node material or a material plugin (new in 5.0: Material Plugins | Babylon.js Documentation).

1 Like