Detailes about lightComputeDir function Lighting.vert

There is following function:



void lightComputeDir(in vec3 worldPos, in vec4 color, in vec4 position, out vec4 lightDir){

float posLight = step(0.5, color.w);

vec3 tempVec = position.xyz * sign(posLight - 0.5) - (worldPos * posLight);

lightVec = tempVec;

#ifdef ATTENUATION

float dist = length(tempVec);

lightDir.w = clamp(1.0 - position.w * dist * posLight, 0.0, 1.0);

lightDir.xyz = tempVec / vec3(dist);

#else

lightDir = vec4(normalize(tempVec), 1.0);

#endif

}



I’m curious about first and second one lines. What does this computations mean, what exactly is w component of the color vector and is there any documentation about this technique for reading?

its the type of light.



w = 0.0 means its a directional light

w = 1.0 means its a point light

w = 2.0 means its a spotlight.



In the renderer code is the info.





float posLight = step(0.5, color.w);





That becomes 0.0 if its a directional light and 1.0 otherwise.





vec3 tempVec = position.xyz * sign(posLight – 0.5) – (worldPos * posLight);





That gives you the vector between vertex and lightsource. If it’s a directional light, position.xyz is the light direction, because that’s how its set in the renderer.



In case of directional lights the equation is then:



vec3 tempVec = position.xyz * (-1) – (worldPos * 0.0); = -position.xyz



This of course gives you the light direction in world space directed from the vert towards the light, like you want it.



In every other case, you get lightPos - vertPos.

1 Like

It’s some magic to determine the lighting type (point, spot, directional) I think. I don’t know the details exactly.



Regarding w… w is just another element of the vector. The same as .a. GLSL makes no distinction, rgba or xyzw can be used interchangeably.

androlo, thanks a lot, you made very clear description of the color.w magick.



Why does this piece of code uses strange arithmetic with sign function instead of conditional expressions? Is the given approach faster?

On some hardware, step() is faster than branching. Some hardware really hates branching.

In fact, it used to be that you should never use if in a shader. But that is not so true anymore as shaders have come a long way since then.

This question had arisen after studying lighting shaders as examples of shader using in jME. Frag shader use if conditional clause while vert shader respects step() function.

frag shader only recently started using ‘if’ as I understand it. And then at first it was just an if() discard; which is supposedly optimized. It may have picked up more in the mean time.



Old school shader coders try to avoid certain things that modern shader pipelines have no problem with… but eventually things catch up. :wink:

EDIT ^ there you have it.



Tbh I don’t know with new cards branching may be very efficient but it has been a problem, and there are backwards compatibility issues (some early shader versions don’t even support it).

Also there’s a chance it will be more efficient on some cards. For example the Shadow_BorderCheck() function is much faster than its flow control ridden counterpart:

[java]float Shadow_BorderCheck(in vec2 coord){

// Fastest, “hack” method (uses 4-5 instructions)

vec4 t = vec4(coord.xy, 0.0, 1.0);

t = step(t.wwxy, t.xyzz);

return dot(t,t);

}[/java]