Hi all, sorry for my bad english i’m french
I’ve created a simple shader based on tutorial lightouse3d… It works but i’ve got a problem with the direction of the light who seems to follow my view deplacement. I use a directional light. I’m noob on Jmonkey and Shader and i’m sorry if my question seems to be simple.
This is my .vert file :
[java]uniform mat4 g_WorldViewProjectionMatrix;
uniform mat3 g_NormalMatrix;
uniform mat4 g_WorldViewMatrix;
attribute vec3 inPosition;
attribute vec3 inNormal;
varying vec3 wvPosition;
varying vec3 vNormal;
void main(void)
{
vec4 pos = vec4(inPosition, 1.0);
gl_Position = g_WorldViewProjectionMatrix * pos;
vNormal = normalize(g_NormalMatrix * inNormal);
wvPosition = vec3(g_WorldViewMatrix * pos);
}[/java]
and my .frag file :
[java]varying vec3 vNormal;
varying vec3 lightDir;
varying vec3 wvPosition;
uniform vec4 g_LightPosition;
void main (void)
{
float intensity;
vec4 m_color;
lightDir = normalize(g_LightPosition.xyz - wvPosition) ;
intensity = dot(lightDir,normalize(vNormal));
if (intensity > 0.75)
m_color = vec4(1,1,1,1.0);
else
m_color = vec4(0.1,0.1,0.1,1.0);
gl_FragColor = m_color ;
}[/java]
Can you help me and explain me why i’m so bad
Thank you in advance
I don’t know if the g_LightPosition global uniform is filled if you use a directional light.
i’ll check tonight
You can directly pass the light direction as a uniform instead of computing it in the shader. Directional lights are used to simulate very distant light sources like the sun, so you can assume the direction is the same for every vertex.
On a side note and for good shader practice :
- in your frag shader, your lightDir variable doesn’t have to be a varying. Varying are used to pass variables from the vertex shader to the pixel shader. Your lightDir is local.
- You should compute your lightdir and intensity in the vertex shader. Be aware that the vertex shader is computed once for each vertex and the pixel shader once for each pixel. Since it’s very likely that you’ll have a lot more pixel than vertices in your scene, computing things when you can, in the vertex shader is always faster.
Maybe you’ve already read it but if you are new to both JME and shaders i recommend this reading :
https://wiki.jmonkeyengine.org/legacy/doku.php/jme3:advanced:jme3_shaders
I assume you are doing this toon shader for a training purpose, but if you really need a toon shader for your project i recommend the usage of the CartoonEdgeFilter, and lighting material with correct parameter to achieve toon shading.
See TestCartoonEdge test case for a complete example
French powa dude!
Indeed, it seems that g_LightPosition not filled when it is a directional light.
I’ve noted your advice, thanks. I’m sure already read the tutorial on the shaders and I made this one only for the purpose of my learning.
I think my problem came from my variable vNormal… ?
Thanks Nehon
To use g_LightPosition, you need to specify LightMode Multipass in the material technique (see the Lighting.j3md material)
Okay, thanks all. It works !
I get some code of lighting.vert and specially the lightComputeDir where is the solution for my original problem and i’v add LightMode Multipass in my j3md.
I think i understand who does what… at least in part…
this is my .vert file :
[java]uniform mat4 g_WorldViewProjectionMatrix;
uniform mat3 g_NormalMatrix;
uniform mat4 g_WorldViewMatrix;
uniform mat4 g_ViewMatrix;
attribute vec3 inPosition;
attribute vec3 inNormal;
uniform vec4 g_LightColor;
uniform vec4 g_LightPosition;
varying vec3 wvPosition;
varying vec3 vNormal;
varying vec4 vLightDir;
varying float intensity;
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);
lightDir = vec4(normalize(tempVec), 1.0);
}
void main(void)
{
vec4 pos = vec4(inPosition, 1.0);
gl_Position = g_WorldViewProjectionMatrix * pos;
vNormal = (g_NormalMatrix * inNormal);
wvPosition = g_WorldViewMatrix * pos;
vec4 wvLightPos = (g_ViewMatrix * vec4(g_LightPosition.xyz, g_LightColor.w));
wvLightPos.w = g_LightPosition.w;
lightComputeDir(wvPosition, g_LightColor, wvLightPos, vLightDir);
intensity = dot(vLightDir,normalize(vNormal));
}[/java]
Can you explain to me what is the w (g_LightPosition.w) parameter … :roll:
thx
From the javadoc:
uniform vec4 g_LightColor[numLights];
g_LightColor.rgb is the diffuse/specular color of the light.
g_Lightcolor.a is the type of light, 0 = Directional, 1 = Point, 2 = Spot.
uniform vec4 g_LightPosition[numLights];
g_LightPosition.xyz is the position of the light (for point lights) or the direction of the light (for directional lights).
g_LightPosition.w is the inverse radius (1/r) of the light (for attenuation)