I am trying to use material to color a surface based on the the angle between its normal and a given vector representing the vertical (I am computing a slope). I have gotten that to work correctly by creating a simple material with a vertex and fragment shaders, but I am not doing any shading or anything fancy, so its looks, well, flat.
What I would like to do is to add the color computed by my normal material to be added as a semi-transparent color on top of what the Common/MatDefs/Light/Lighting.j3md is providing (shading, etc). So I am looking at getting the rendering of provided by using the Lighting.j3md and then mixing an additional color on top based on some other calculations (here I have started by looking at the slope)
I do not know how to approach this ?
I was thinking of creating a new material by copying the Lighting.j3md and its associated (many) vertex and fragment shaders and adding in the shaders what is required to compute the slope derived color and add it add to the gl_FragColor computed by the Lighting.j3md shaders, but this seems to be not trivial (I am a beginner in shaders).
The tricky part of lighting.j3md is that it does itâs lighting calculations in âview spaceâ in the fragment shader. That means that the interpolated normals, etc. are all in camera-relative space⌠where as it sounds like you would prefer world space.
Something to note is that the PBR material actually is doing lighting in âworld spaceâ. So the normal available in the fragment shader is in world space and its y component then can be used to determine how âupâ something points.
I donât know if this is helpful information. Step 1 is going to be forking a shader and hacking away at it.
Do note: you donât need to necessarily copy/fork all of the vert and frag files as you will likely only be using one set of them. (Single pass versus multipass lighting, etcâŚ)
I did a quick try using the Lighting.j3md (that is the only one that I have in my now very dated version of JME3) and it behaves as you described : the inNormal that is passed to the vertex shader is view dependent. Where is this behaviour defined ? I looked at the material, the vertex and fragment shader and could not figure it out. I will try to import the PBRLighting.jme3 and hack that one, but I am trying to understand why the Lighting.j3md is behaving the way it is.
inNormal is the one defined from the model. The vertex attributes come from the mesh.
The inNormal is then transformed into view space further down. Itâs the âvaryingâ variables you need to look at because thatâs what gets interpolated over all of the fragments.
âŚbut as said, Lighting.j3md is doing everything in view space so youâll have to setup your own varying and transform inNormal to world space and store it in the varying.
This worked as expected and is view independent (i.e. the slope color does not change as the view point is moved around).
I tried to use the same approach and initialized the normal variable at the beginning of the Lighting.vert main function. I then added the fragment code shown above and mixed the resulting color with what computed be Lighting.frag at the very end of the main function.
While I think I could probably fix this by applying the inverse of the g_WorldViewProjectionMatrix to the normal before doing the slope angle calculation, I still do not understand why the interpolation is affecting my normal variable differently in this case. What is making the interpolation behaving differently in my shader and the Lighting one ?
Itâs not really clear to me what your latest problem is and what you want to fix. What is the difference in the output between your simple shader and the patched Lighting shaders?
Why position?
In case you didnât know: The GPU does the interpolation over the fragments automatically. Itâs not in the shader code. It can be disabled with the âflatâ keyword, like flat varying vec3 origNormal.
But interpolation is not whatâs causing view-dependency.
Edit:
Actually, yeah, the PBR shader doesnât need the modification to the vertex shader. The existing âwNormalâ is already in world space and can be used for the calculations. float angle = acos(dot(wNormal, vec3(0, 1, 0)));
And btw: Reduce the PBR Materialâs âMetallicâ paramter to <1.0 to make the color visible.
I actually got the code to work in the modified Lighting vertex and fragment shader and get it to work as I expected. I am not sure what was not working in my previous attempts⌠My code looks very much like yours, but I modified the Lighting.vert and Lighting.frag instead (I could not get the PBRLighting to work in my setup, which is make use of an old version of JME3).
P.S. Why Position ? â position = inPosition; This is a left over from a previous test I was doingâŚ