I am in the process of using the TerrainLighting material on a Terrain in my editor.
I came across the SpecularMap property and was wondering, why is this there?
Is the specular map even used on a terrain material?
I took a quick glance at the shader, and it looks like the SpecularMap is not used in the .frag shader at all.
Mg best guess is that it was just left there by mistake when the original author was creating the terrain shader based on the standard Lighting.frag shader.
They probably planned to make 12 SpecularMap params (1 for each terrain texture slot) and then likely never got around to it (possibly intentionally never went back to add it, since a normal map is much more useful than a specular map anyways, and its easy to surpass the texture limit with a terrain so adding them would not be very useful for big. terrains using that shader anyways)
Cool, thanks for the reply. This was exactly my thought.
For my use case, it would be awesome to paint the reflection sports on a terrain by making use of a specular texture map. Similar to how we paint textures on a terrain.
Do you think that would be possible on the TerrainLighting material?
Yeah that should be possible. I don’t use the old lighting anymore (I only use pbr in my current projects) so I hope I am remembering how specular works properly.
But it looks like TerrainLighting already has a uniform shininess param for the entire terrain:
So you could just add code to read a gray-scale SpecularMap and then use that as the final shininess value that gets input into this lighting equation at the end of the shader:
Or, alternatively, you could add a bunch of float uniforms called Shiniess_0, Shininess_1, and so on for all 12 texture slots, and then you can assign a unique shiniess value to each tetxture slot, so that way you wouldn’t have to paint a specular map to match your terrain.
Here’s a quick adjustment to that .frag shader that would use the specular map as a gray-scale reflectivity map: (and it looks like the .j3md already has a Define set for Specular map, so that file should be okay as is)
But in this use case, I think it would no longer be called “specular map” and would instead be called something like a “shininess map”, since Specular color is usually a full rgb color, wheras in this case we are just trying to add reflectivity/shininess.
For simplicity I just made a quick PR with the minimal-necessary adjustments to get it to work how you describe. If anyone else finds this useful and thinks its worth merging the PR, I could work on finalizing it and making it more clean, but this should hopefully atleast do what you described.
I overlooked the fact that the “specularColor” variable is later used in that shader as a static input to the lighting equation.
But it should work if you rename it to something else like “specularMapColor”. I updated the PR to fix it, sorry for the mistake.
I also added a “UseSpecularMapAsReflectivity” define to approach this in a cleaner way, and to allow the specularMap to be used as a standardSpecular color, or for reflectivity if this new define is set to true.
So it should work now, but make sure that you set the useSpecularMapAsShininess true for your use case with a gray-scale shininess map.
I don’t think I ever tried using the shininess param with the standard Lighting shader, so I’m not entirely sure how noticeable it should be.
Maybe it wants values higher than the 0.0 - 1.0 range (which is the range you will get from a grayScale texture), so maybe try multiplying the finalShininess float by 10 or 20 and see what happens.
In this case, it would just be any image where you paint the red, green, and blue channel as the same value, very similar to how an ambientOcclusion texture would look.
This would be what your final grayScale texture would look like, where the black spots indicate no shininess (0.0), and the white spots are max shininess (1.0)
The only thing I can think that could be worth changing is this line here:
It could be better to change it to : finalShininessValue = specularMapColor.a*m_Shininess;
so this change would make it use the the alpha channel as a shiniess multiplier (rather than the red channel which is standard for grayScale textures) and that way you could theoretically still use the red, green, and blue channel as non-gray scale specular color if you want to add colored reflections, or you can leave it as a grascale texture and it will work like it does now.
So specular color would be packed in the RGB channel of the SpecularMap, and the shininess Multiplier would be in the A channel of the SpecularMap. You would just need to update your editor’s terrain painting tool to ensure that you are writing the shininess to the alpha channel instead of the red channel
You should be able to add realistic real-time reflection, I’ve never done that personally, but I think there are some reflection shader examples out there for jme that you could base it on.
But I think that would end up being very resource intensive if it is indeed real-time reflections you are looking for, especially for a big terrain, so that’s usually why PBR is typically considered better for shininess/reflectivity with its “fake” reflections from the light probe, and then real-time reflection shades are used more sparingly for the occasional model that needs clear perfect reflections in real-time (like if you want the player to be able to see their own reflection when they move while looking at things like ice, a mirror, or water).
I know for apps targeting mobile devices, PBR is usually too resource intensive and that is often a reason that jme users choose to use the old phong lighting instead of PBR. So in that case I think implementing reflections into the phong lighting would probably also be too resource intensive as well.
But if you are targeting desktop devices then implementing them into TerrainLighting could potentially be manageable without lowering the framerate too much.
That is unfortunate, I was not aware of that issue with running my pbr terrain shaders on linux, but it looks like it is important to fix and I’ll try to work on it.
Have you confirmed that it doesn’t work on more than 1 linux device (no other jme linux users have used the PBR terrain shader that I’m aware of, so I don’t have any information on whether or not it is affecting all linux users, or f it could potentially be related to your specific GPU).
What are your full OS and device specs?
(I should probably also make another thread about this issue and see if I can get any other jme users to test the shader if they are using linux or a similar GPU as yours).
I’m also curious to know if the AdvancedPBRTerrain also has the same issue for you (I assume it does, but it could still be worthwhile to check in order to rule out a few other potential reasons for the issue, particuarily the fact that I only use the advanced one myslef so I may have been more likely to make a mistake on the older pbr terrain)