PBR Terrain Shaders - Basic & Advanced versions

trully, im not familiar with AO maps and im not sure how to do/use them.

my workflow was only albedo/normal/ (metal/roughtness) .

if you could tell me how to use this, and you say it look way better, im interested.

edit: ok im baking AO in blender cycles render, will see how it look

I learned how to utilize each map to its fullest potential by analzying the models on sketchfab using the “Model Inspector” button down at the bottom right of the model preview window. Even if you don’t purchase a model, you can still inspect it to see the individual albedo map, normal map, AO map, etc. - and then also view the final render

I spent alot of time looking at and inspecting models on sketchfab - comparing the ‘final render’ version of a model to what it looks like with only the ‘BaseColor’.

Although I guess that would be getting into a topic of its own, related to making the most of the PBR shader, and how the artist’s approach differs from the Phong workflow

1 Like

right,

anyway in earlier image i just used your terrain shader (it work in IDE because i have ShaderLibs in project)

not sure if AO will change something, but will try

1 Like

Glad to hear that the terrain is working for you now :slightly_smiling_face:

1 Like

hope you will grant us with official cleaned/upgraded version when 3.3 stable :slight_smile:

anyway, great work!

3 Likes

I need a PBR terrain material for a project I’m working on. What’s the status of this project?

The PBR Terrain material should work in its current state for both 3.2 and 3.3, but I have some new improvements coming soon as well. The currently available code is the regular PBR Terrain shader that just has normal/alebdo textures and a roughness/metallic float value for each texture slot. But I have coincidentally been working on the terrain shaders more this past week, so I will update the git-hub files as soon as I have a chance.

I’ve been primarily been working on getting the Advanced PBR Terrain material functional. It is technically finished in the shader, and allows for >16 texture slots and support metallic/roughness/ao maps (all packed into a single texture and single texture read in the shader) for each texture slot as well.

But saving a terrain with a TextureArray only saves the first texture layer of the texture array, so the texture array needs re-created every time the terrain is loaded into the game or an editor. So I still need to improve the TerrainShaderConverter utility for use in the game’s client, and then I will also be releasing my custom editor specifically for its terrain editing functionality.

1 Like

That’s great news.

Any tips on building the project from source? Here’s what I’m seeing:

sgold:~/Git/ext/PBR-Terrain/PBRTerrain$ gradle build

> Task :compileJava FAILED
/home/sgold/Git/ext/PBR-Terrain/PBRTerrain/src/main/java/com/aaaaGames/pbrTerrain/TextureChannelPacker.java:197: error: cannot find symbol
            ImageWriter.fillColor(newPackedImage, new ColorRGBA(1.0f, 1.0f, 1.0f, 0.0f));
            ^
  symbol:   variable ImageWriter
  location: class TextureChannelPacker
/home/sgold/Git/ext/PBR-Terrain/PBRTerrain/src/main/java/com/aaaaGames/pbrTerrain/TextureChannelPacker.java:222: error: cannot find symbol
                ImageIO.write(ImageWriter.getARGB8ImageFrom(metallicRoughnessAoEmissiveMap.getImage()), "png", file);
                              ^
  symbol:   variable ImageWriter
  location: class TextureChannelPacker
/home/sgold/Git/ext/PBR-Terrain/PBRTerrain/src/main/java/com/aaaaGames/pbrTerrain/TextureChannelPacker.java:262: error: cannot find symbol
            ImageWriter.fillColor(newPackedImage, new ColorRGBA(0.0f, 0.0f, 0.0f, 0.5f)); //what default value should parallax (aka alpha channel) be set to, in case of null parallax map
            ^
  symbol:   variable ImageWriter
  location: class TextureChannelPacker
/home/sgold/Git/ext/PBR-Terrain/PBRTerrain/src/main/java/com/aaaaGames/pbrTerrain/TextureChannelPacker.java:280: error: cannot find symbol
                ImageIO.write(ImageWriter.getARGB8ImageFrom(normalParallaxMap.getImage()), "png", file);
                              ^
  symbol:   variable ImageWriter
  location: class TextureChannelPacker
4 errors


FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':compileJava'.
> Compilation failed; see the compiler error output for details.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 0s
1 actionable task: 1 executed
1 Like

It looks like there’s some classes from the texture packer utility missing from my github repository. I uploaded the one causing the problem so it should compile now.

Although it does look like the version of my texture converter utility on github isn’t quite up to date with my local version I’ve been using, and there’s lots of important features missing (pretty much everything but the texture packing utility and shaders is missing right now). It should still compile now since I uploaded the one missing class, but I’m going to work on having an entire new version of the converter utility posted this week.

1 Like

I see there have been many commits. What’s the project status?

I’m setting up a separate branch of the shader for jme 3.2 and 3.3, since it looks like I had both in the master branch before, and overall it was not organized well. I’m actually working on some final touches with the shaders right now as well, primarily making sure the 3.3 version will work, since I’ve been testing on mostly 3.2. Then I’m going to upload them to the 3.2 and 3.3 branches that are currently empty.

I also am migrating all of the code for the shader converter utility to its own project in a separate repository, and the current PBR-Terrain repository will contain just the shader code, and can be used with or without the shader converter utility.

So if you want to use the terrain shader converter or any other utilities like the TexturePacker, they’ll be a part of a utility library for my custom terrain editor, which I’m also uploading to a repository very soon. I think that it may be difficult to set up the version of the shader that uses texture arrays by code (and then it would also not work in the SDK or JMB terrain editors as a result), so I’ve been working to get my editor and its utility library finished enough that I can release it for use. I just need to migrate them from the SDK into gradle projects, and make sure everything still works, then the scene editor and utility libraries will be public as well.

1 Like

That all sounds good. My only concern is that your project might be overkill for my needs. Since I’m taking a break right now, I’m happy to wait for it to settle down before deciding.

Yeah using the converter utility (and especially using the custom scene editor once I release it) may require more time/effort implementing into your workflow than simply using the shaders on their own.

But since the shaders are now going to be alone in their own github repository, I hope it should be fairly easy to create a basic PBR terrain shader (the one without texture arrays) by code the same way you would for JME’s current stock terrain shader. And that should still work in the SDK’s terrain editor since the basic PBR terrain does not use Texture Arrays.

1 Like

also please note that “too many blending textures” cause low performance. Especially in pbr where you might want use more maps.

What i have noted is that if someone want use many textures, its just better have like 4 textures per Chunk, while more chunks allow use more textures. In current JME terrain is set Material for all “terrain chunks”.

I have implemented Texture array, but in this case, it wasnt really needed, and it have disadvantages too, because it require same size textures. (and like you said, it do not work in SDK editor)

I’ve only done a bit of stress testing, but so far I haven’t noticed any major framerate drops. I had to drop parallax map support, because that seemed to be the only thing that was causing a heavy framerate drop, but in the future I might spend more time on that. Although currently its a lower priority, since I just found a way to improve the effects of normal maps and don’t feel as though the extra benefit of parallax would be worth it as much as before.

Surprisingly, my device does not run any slower using the PBR terrain compared to using the stock phong Terrain shader. When I initially created my shader converter, it was with the intention of making my game run faster on older devices. But after comparing both shaders, my device actually runs the older phong terrain shader exactly 1-2 fps slower than my pbr terrain shader when I swap back and forth without changing the camera’s view or position.

The version of the shader that uses texture arrays is also only 1 extra texture read per texture slot, since the metallic/roughness/ao map are all packed together. I’ve only just gotten the shader out of its testing/dev environment and into my game, but on one map I have some terrains with 9 slots, each with 2-3 texture reads per slot, and so far I’m not running into any performance issues, I’ll have to report back if I notice any framerate drops as I implement it more into my game, but so far it seems to run no different than when I used to use the standard phong terrain shader.

1 Like

I mention this in passing because I’ve always meant to try it. I don’t know if it will work but I’ve had good luck with “old school tricks” lately.

In the before time, the long long ago, if we wanted to simulate multiple textures blending together then the trick was to render the mesh with one texture, set the depth test function to equals, and render the mesh again with a different texture+alpha blending.

In modern times, I’ve often wondered if this could be a nice way to mitigate these sorts of stacked fragment problems where the fragment shader is really expensive because it has to handle 8 different texture sets or whatever. Instead, render the mesh with one cheap base pass to fill in the zbuffer and then render single ‘texture’ follow on passes with the different layers and depth test set to “equals”.

In theory, if the fragment shader is aggressively discarding then this could be a win for some number of layers. I don’t know how the numbers break out but the benefits are:

  1. fragment shader is only having to manage one texture (plus normal, bump, etc.) and not looking up texture info it will just ignore.
  2. the expensive per-fragment rendering is guaranteed to only be done for actually visible pixels.

I actually believe that the multiple passes could even be done in one draw call by tricking instancing to think there is more than one instance and writing a clever shader that uses the instance ID to figure out which texture array index to use.

Note: it’s all speculation… but it would be an interesting experiment to see how many layers it takes before that approach works better.

2 Likes

A new version of the standard PBR terrain shader was just uploaded to the github repository, for both 3.2 and 3.3. You can build the shaders from source in your project, or you can directly download the pre compiled assets-jar that I uploaded to the repository.

I fixed the tangents issue with the terrain, and now the normal maps appear with the same depth as the stock pbr shader - so there are no longer any visible differences between a PBR Terrain and standard PBR models.

The shaders for 3.2 can be found here:

The shaders for 3.3 can be found here:
https://github.com/yaRnMcDonuts/PBR-Terrain/tree/3.3

I’m doing some final testing on the AdvancedPBRTerrain.j3md shader (the one using texture arrays and metallic/roughnes/ao maps) to ensure that the final render is still accurate when viewed next to a standard PBR model, but those will be uploaded soon as well.

Quick screen shot of some normal mapping after calculating the tangents in the shader: (previously you could only notice terrains’ normal maps in shiney spots… now they’re more visible in rough areas too)

15 Likes

Looking nice! Might be a good idea to post it to the jmonkeystore as well, so it doesn’t get lost in the forums.

3 Likes

Thank you, @yaRnMcDonuts! Gorgeous screenshot, btw.

As @grizeldi pointed out, posting it to the Store would help spread the word.

Perhaps it could also be available from JCenter. If you’re interested, I can help with that.

2 Likes

Yeah that would be great, I have actually been wondering how to get that quick-link that users can drop into their dependencies list for gradle projects. Do I just make an account on the JCenter website and upload the source code, or the compiled jar file?

I actually made an account on the store page last night, but I noticed most other items on the store page include the quick dependency link thats hosted on places like JCenter, so I wanted to figure that out and then post this to the JMEStore.

1 Like