Best way to do triplanar projection on landscape master materials?

@Frenetic, @blyxzen
Here is my progress so far. I can say I 100% recommend this tutorial by Visual Tech Art, it looks amazing. Here are some images of the difference and the overall affect:



And here is a weird lighting mishap I am happening with the same texture on a normal (non-enaplanar) material:

It only happened on this one Landscape square, and I am guessing it had to do with the Specular adjustments. I may have to play around with it but it’s not occurring anywhere else so it’s pretty low priority now.

How does it look? This texture is pretty bad but it’s great for demonstration and debugging. I will have to do some work on the seams too.

1 Like

So far so good, but you got seams. :frowning:

Try Alex’s method. It does leverage Temporal Sampling but that thing is here to stay so I say lean into it.

It has a nice blending at does triplanar in 1 sample, so very efficient.

No (Capes!) Seams!

If you wanna get REALLY crunked-up, you can try this guy’s method. Ihave NOT but I am curious as to relative performance. He makes use of a lot of custom nodes.

1 Like

Hmm, interesting, I’ll have to take a look at all of this. I will (I hope) be sticking with the current method but making a decent bit of modifications to it. The most imminent of which being some work on those seams :wink:

1 Like

VisualTechArt actually covers adding dithering to his material for smooth transitions here. I imagine this is the same thing as what Frenetic shared, just implemented in VTA’s material instead of trying to adapt someone else’s.

Screenshot of Dithering Changes

And that’s all there is to it!

I don’t see any of the problems you mentioned having before in the pictures (maybe you fixed them?), but I’ll see about importing that material into an empty project and get back to you.

So far, looking pretty good! My only concern (besides seams) is it looks like your projection might have direction issues. In your second picture, it looks like the “grain” of the texture suddenly travels vertically while the rest is horizontal.

Issue Outlined

I don’t know if this is actually an issue for you (it wasn’t necessary for me, my textures were abstract/non-directional). I double-checked your UVs, but it seems everything is in order. Like I said, I’ll try importing the material and get back to you, but just a heads-up for now. :slight_smile:

EDIT: Still having trouble importing .uasset (even with video). What engine version is your project on? Also, did you create it as a blueprint or C++ project? (So I can create a project matching yours, maybe that will allow the import).

Awesome, probably skipped giving you a few details there :slight_smile: first, thanks for all your support! Second, that stretched portion going vertically is actually an example of the same textures on a non-triplanar material. So I think it’s working!
Third, I do think it’s better now. That clamp you suggested earlier seemed to have helped. I unplugged the material blend and auto material to make sure, there may have been issues there.
Fourth, thanks for the help with the seams! That will make my job much easier. If it’s possible to get help with distance scaling that would be great, I’m not sure what to do with that.
Finally, engine version latest (5.5.4) on a blank Blueprint project. The goal was to make a temporary project to test out some new features and start working on some things for my game (MegaLights will be huge).

1 Like

The best way to apply triplanar projection on landscape master materials is by using world-aligned or triplanar mapping nodes. This method ensures seamless texture blending across different axes, avoiding stretching or distortion, and maintaining consistency on uneven landscape surfaces.

Okay, good :smiley: Glad to hear it’s working.

I was able to import the .uasset with the same engine (5.5.4).

As for distance scaling, there’s a few approaches.

Performant Way
The simplest, most performant method would be to essentially switch on the tile size using the camera distance, like this:

Performant, Hard Line Method

Result:

Note the hard transition line produced in this method. While this is likely the most performant option, I imagine that line is far from desirable.

Quality Way
To get a smooth transition, the only way I’m aware of is to project another set of textures at a larger size, and blend the traditional way. However, since you’ve used the named-reroute nodes, you don’t have to duplicate everything.

Since the only variable you need to change is the tile size, the only steps you need to reproduce are the UVs and DDX/DDY (DDX/DDY is needed because it uses the UVs).

So, produce something like this:

Smooth Transition Method

Then, duplicate your sampling and replace the UV nodes and DDX/DDY nodes with the new macro variants (Note: I made the “Basis X” and “Basis Y” named reroutes from your Normal Correction):

Blend the two Material Attributes together (like you already know):

And Voila:

Smooth blending!

Let me know how it goes, or if you need further help or clarification!

EDITS: Grammar and Conciseness

1 Like

If you are able to mix-up your layer well enough, texture-bombing, stochastic sampling, etc you might not want-for/need a distance texture but if you do you can do this trick. I do it for detail normals but could apply to color, etc.

Take your extra sampler for your detail normal, scale, sample, mix it in, etc and up close it’s a blend w/alpha of 1. Fade it out over distance until it becomes 0. Flip the scaling up, then some distance further out fade it back in for your macro/distance normal. This will still use the one sampler, but scale the UVs based on distance, and the two ranges won’t ever overlap since it’s done per-pixel.

1 Like

Full stop.

That stuff is just to expensive to function.
If you want to prevent tiling like via shader.
Then TarleVFX on youtube are the turorials you want to learn from.

You do stuff on the UV so that the cost can pass off on the GFX via either using a custom uv node or vertexinterpolation node.

Thats just one tutorial. He’s got better ones for uvs.

1 Like

So now I’m curious, what will be the differences between quality and performance in the two methods? And how does having another sampler and blending it not call another sample (correct me if I misinterpreted)?

Yes, all the maths you need to scale, mix, etc can be done in the UVs, up-front and sharable with any of the layers in your landscape. Stochastic-sampling does this quite well IMHO.

To my experience you can do (almost) all your UV manipulation up front and recycle those results across the remainder of your material.

Yes, adding in a detail-normal, distance-blend, etc will invoke another sampler. My suggestion was if you do use one there is a path to get double-duty at least, you could use it for up-close as well as far away, assuming you have a middle-area where neither is applied, else you will have a line when you flip the UVs.

Texture-bombing and other related techniques do require additional samplers, which is why I leapt on Alex’s method Since the triplanar is 1 sample you can then UV-futz to untile and it should still be a single-sample (which it is).

EDIT: I will point out that what works for organic-textures like grass, rock, dirt; one’s that don’t have a lot of regularity doesn’t work for things that tend to tile, like Tharle’s example above. There’s awesome ‘randomize my tiled-floor’ techniques and you can do things like add imperfections here and there to spice things up, but that regularity works against the stone/rock type materials, so you will likely want to learn a mix of techniques depending on what you want in the end.

1 Like

Awesome, thanks for all that! I have implemented the dithering and tiling in the way you laid out, and it normally works great. Here is a good screenshot of the tiling (very exaggerated for this texture, not a great one for the Z-plane :sweat_smile:):


And a screenshot of the dithering (it works very well in the spot where a seam was evident before, but in one area [on the right] I noticed a seam–why???):

Lastly, an issue I presume is coming from the DitherTemporalAA node. I don’t know why it’s happening, there is a weird white line going the opposite direction of the grain of the cliff in multiple places. I tried to make it very evident in this image:

Jeez I need to fix that exposure… lol :slightly_smiling_face:

Here’s the new file:
M_LandscapeMaster.uasset (298.1 KB)

@Frenetic you are probably going to suggest Alex’s method; will that fix the artifact? It uses another sample which is unwanted but I’ll do it if necessary.

1 Like

Oddly enough I can’t import the material again. :confused: Same engine, same project, even a new project… nothing. Perhaps there’s something in the material (like a material function or something) that I don’t have which is preventing me from opening it? Just speculation.

Anyways, your “white lines” issue appears to be a simple blending issue. You can see how the lines disappear on steeper slopes here:

Image

This would indicate your Z axis is blending a lot with the X and Y axes (the steeper the slope, the less the Z axis blends). With a cliff texture like this (directional textures or where a top projection isn’t really desired) the best solution would be to not project on the Z axis entirely (by cranking up the “X-Y Projections Angle” and removing your Z Projection UVs/Z Projection Weight lerp where you sample your textures). This would eliminate the problem entirely.

But, if you need that Z projection, you should be able to tinker with raising the “X-Y Projections Angle” and lowering the “Projection Smoothness”. With directional textures like this one, the result will never be perfect, but you can probably find an acceptable middle-ground.

Now, for your seam issue… I honestly have no idea. :laughing: The fact it only happens at that angle (which can be seen in the other pictures too) is really throwing me off, and without the ability to open the material, I really can’t help that much. I’d say start by looking over your projection weights, where you applied the dithering. Then, if there’s no issues there, trace it backwards, checking your 00 projection axes and 45 projection axes.

I’ll keep trying to open the material and I’ll let you know if I can.

As a final note, the macro-blending uses another 3 samples, so if Frenetic’s solution works for you, it would probably be better (performance wise). Not necessarily, but likely. That said, I’ve tried stochastic-sampling once, and I wasn’t happy with the results. It created a bunch of small seams which were visible when you got close (like a player walking on the ground). But, another grain of salt, it’s possible I followed a bad tutorial. I found a better solution for my case which was more performant and better quality (I did a simple fade to color, since the textures were stylized and lost detail quickly, I could replace it with a simple color).

In the spirit of learning, I’d say follow some tutorials for other anti-tiling methods. Worst case scenario, you learn a little more about materials. Best case scenario, you have a better anti-tiling method than macro-blending. IMHO, macro-blending has been around for a very long time… it’s probably time to upgrade.

Try Witchdev’s solution:

He has two paths, one with a jittered triple-sampling and one with a temporal-single sample. Either can be combined with Alex’s method, and the latter is done via UV’s so can be slotted right in with Alex’s solution to preserve that single sample for a triplanar, untiled single-sample texture.

It’s what drives this: Unreal 5.5.3 - Full Lumen, Nanite, UltraDynamicSky - Album on Imgur (the lightning stuff is all UDS, so worth it..)

Since temporal effects will show up in height/displacement, the single-sample method doesn’t work well for those effects. Either displacement on a landscape or a heightmesh you’ll see the seams all out of shape as the shader flits between two heights. However you can use the first method with the 3 jittered samples and get the same results and without any temporal-seams. Then feed that math to where-ever you need to and the temporal-sample to PBR (ideally). It’s a little more costly but will ensure the bumps match what is painted onto them by the temporal-pass.

2 Likes

Alright, well, it seems to be working! I’ll have to make another post for the other parts of this but the Triplanar is mostly complete. Thank you all so much for your help! @Frenetic and @blyxzen I invite you to take part in the next post, after proving to be very kind and helpful here. I am hoping to go over Nanite Displacement or something similar, Virtual Textures, Procedural Foliage placement based off landscape materials, and a bit more.

I apologize for not being active in this post for a few days, I just didn’t have any time. I switched the texture out for a better one and the results are stunning:




I would greatly appreciate if anyone can recommend any Megascans textures, I need to start building up a good library. Here’s the one I used in the images: Rock Cliff

2 Likes

Your normals look correct; good job. It’s an easy thing to break and sometimes even to a trained eye, you don’t notice it immediate if/when it breaks. Keep an eye on them in case you do break them…

Is the cost exploding yet? I did warn you it’s not cheap to combine all of these things… :smiley:

Lol, it’s not cheap at all :slight_smile:. Honestly, I have no idea. It varies greatly based off position, in those pictures it was consistent 12ms or 90-100 fps (weird) and once I added in the other textures (I fixed them so the naming was right and duplicated the triplanar for all the textures with a static switch for planar) it dipped down to 60-70fps. But then I reloaded the project and it ended up being 9ms looking one way and 10ms looking another way at roughly 90fps. So it’s gonna take some work figuring things out.

On the next topic I’ll share my graph, and ask for some final optimization and condensing tips before moving on to finishing it up. At last, I’m almost done!

You can’t use the editor to mark performance like that.

First of all your scene is empty - the base cost being what it is is pointless.

Second. Its the editor. Doesnt tell you anything at all. Performance on it is based on whatever other windws are open or your pc/engine is doing.

You have to bench the final packaged result of something with the editor closed using fraps or something similar to know what to expect.

After setting up a proper “benchmark” scene.

Idk. Take Superposition as an example. UNIGINE Benchmarks

The idea is you have a set, well made scene, and you test things to know what sort of performance you should get before you make use of whatever it is in your final project.

Or, its also how you easily decide to move to better engines… if unreal cant hack it, it just can’t.
And chanches are it really can’t. Its not built around performance.