LightColor in shader definition?

Hello,

concerning lights in shader

I try to use the Attr.LightColor but as I tested its value (outColor=LightColor) it seems to flicker and give random results depending on the camera movements instead of a uniform value

in UniforBinding.java, it says “The light color when rendering in multi pass mode”, so there is a pass for each light ?
how does it work, how can I tell witch light is used in the fragment shader ?

I saw in the repository LightColor is used as a material parameter, but I wanted to get the real color of each light
[edit : just noticed I had the same issue with Attr.AmbientLightColor]
any help ?
thanks

You have to set your technique as multipass if you want to have those values filled for you by the engine.

Multi pass lighting is the only way to have lighting in 3.0. It indeed does one pass for each light.
Your technique should contain this :

Technique {
        LightMode MultiPass
...
...
}

Note that int 3.1 we enhanced the way this work and you’ll be able to use more efficient way to render several lights.

And by the way, those parameters are actually World Material Parameters and not Attributes.
you have to user WorldParam.LightColor and WorldParam.AmbientLightColor

ok, thanks a lot for the infos

but the compiler cannot find LightColor, LightPosition nor AmbientLightColor in WorldParam
they should be available as uniforms…

in the repository, shaders use “uniform vec4 g_LightPosition;” but no j3dm file define LightPosition
I dont get it

Caused by: com.jme3.material.plugins.MatParseException: Error On line 29 : lightPosition=WorldParam.LightPosition.xyz
->Could not find a World Parameter named LightPosition

here is the definition :

 Technique {
        LightMode MultiPass

        WorldParameters {
            LightPosition
            LightColor
            AmbientLightColor
        }
        VertexShaderNodes {
            ShaderNode WaterVert
            {
                Definition : WaterVert : Shaders/Water/WaterVert.j3sn
                InputMappings
                {
                    lightPosition=WorldParam.LightPosition.xyz
                   ....
                }

also I am quiet confused about multipass…

  • how can I detecting the genre of light (point, directional…) for dir light, there is not light pos
  • how can I get the number of lights, cos if I blend them all I need to use some factor that sums to 1.0 in the end, or I just use an alpha factor for each pass and let it add up even if it saturates…?

If you want to make your own lighting shader, tbh I don’t recommend Shader nodes yet.
There might be issues with light data (it looks like from your post), and there is still a lot to do to make them a usabel solution.

You’d better make your own shader, and look how the lighting shader is done.

In multi pass mode, your shader is called once per light/per object rendered (actually for each vertex and for each pixel).
Light data is encoded and passed to the shader in Material.java here
There is a lot of legacy in this code that makes it inconsistent, but I won’t go into the details of why.
For directional lights, the direction is passed as the LigthPosition parameter (in the shader you have to declare it a g_LightPosition “g_” for global).
Pointlight has a position passed as LightPosition and the w component contains the inverse radius of the light.
LightDirection is set to 0.
Spot light had both LightPosition (with inv range like inv radius for point light in w component) and LightDirection with the spot angle cos encoded in the w component. see lighting.frag to see how to decode it.

Light type is encoded in the w component of the LightColor.

We are thinking of ways to enhance the rationale of all this for future versions of JME. Also we want to make it more flexible.

ok , well worst case scenario, I send lights infos to shader with material params

thanks

sorry to dig this up ,

but after having set the multipass in technique

MaterialDef Simple {
    MaterialParameters {
        Color Color
    }
    Technique {
        LightMode MultiPass
...

this frag code

vec3 L = normalize(g_LightPosition[0].xyz - v);   

gives error
error:0(20) : error C1008: undefined variable “g_LightPosition”

so I am not sure if it is becos it is not implemented yet for shader nodes or something I missed

g_LightPosition is not an array. it’s a vec4.
Multipass does one render pass per geometry and per light, so in that mode you only have one light sent to the GPU.

ok my bad
but it stil dont find it (even if I remove the subscript)

Gonna look into it. Aren’t you getting used to that answer :wink:

yes but I now what it’s like to have a mountain of work to do, so I understand
my concern would be to be able to update the platform so it has the latest bug fixes
but without having regression on other parts of jme

Well it’s a bit complicated right now.
The changes I did were on several separate files in the engine, so you can’t just take the Generator class and hope for the best.

IMO the best way to do it is to pull the 3.0 branch and cherry pick the fixes from master.

I think I get what’s the issue.
You need to declare g_LightPosition in the shader node source as an uniform.


uniform vec4 g_LightPosition;  //<-- that's what I mean     
void main(){
      ...
      vec3 L = normalize(g_LightPosition.xyz - v);
      ...
}

if I use this, I get a black object (so g_LightPosition is 0,0,0) (I got 2 directional lights in my scene)

//-------------------------- vert shader
uniform vec4 g_LightPosition; // hack
void main(){
    lightDir = g_LightPosition.xyz;
...
//--------------------------- frag shader
void main(){
outColor = vec4(lightDir,1);

mhh, I’m almost certain I made this work not a long time ago, let me check, I’ll get back to you.

maybe I need to set the shader technique to multipass ?

Oh yes you do

but how do you figure out in the shader if you deal with a directional light or a point light?

The value of the light’s alpha represents the type of light.

0 = Directional
1 = Point
2 = Spot

There is a trick…we actually don’t know.
we pass the light type in the 4th channel of the lightColor. ( as @Paul_Culkin said)
if you look in lighting.frag the is a lightComputeDir function (maybe in the vert file actually)
this funciton does some math tricks to compute the light dirrection and attenuation. Attenuation just resolves to 0 if it’s a directional light or a spot light.
Then in the lighting.frag, we compute the spotfalloff for the spot light. The angle cosines are packed into the 4th channel of the lightDirection. The spot falloff also resolves to 0 for a directional light.
So basically we compute everything for any types of light. That’s a lot faster in a shader than doing branching to check the light type.