Directional Mask / Mask by 'heading'.

Started by Tangled-Universe, February 11, 2021, 05:50:34 PM

Previous topic - Next topic


Here's a way to construct a directional mask.
Instead of sharing a .tgd I thought of sharing a screen capture with the explanations on how and why.
From experience I think this is a better learning method than giving the solution right away as it takes away the incentive to investigate how it works.
Better understanding of how and why also allows for trouble-shooting it yourself, should it behave unexpectedly.

1) Heading = constant scalar = angle of choice in degrees (0-360). In this example 90 degrees.
2) Degrees to radians = degrees to radians scalar = convert scalar value to radians
3) Sin/Cos scalar = we take the sine of the radian for X and the cosine of the radian for Z
4) Build vector = construct actual vector of inputs
5)Dot product = output is scalar, thus also known as "scalar product".
Expected output range is from -1 to 1.
Output is value 1 when a surface faces the user defined angle exactly (90 degrees here).
Surfaces facing opposite to the user defined angle have a value of -1. (the left part of the sphere has negative values, thus black)
6) Adjust coverage = multiply scalar = expands selection using the 'Adjust Coverage Factor', which is set to 5 in this example.
7) Remap 0-1 = colour adjust shader = remapping the dot product output range (-1 to +1) to the 0-1 range.
For this set Black point to -1 and White point to 1.

Lastly there's a gamma adjust = colour adjust shader = which, in conjunction with the adjust coverage factor, allows some control over the falloff of your mask.

If there's a huge need for the .tgd then I could upload it, but I hope the explanations are clear enough so that this would only take 5-10 minutes to set up and see for yourself. Cheers!


Since @WAS tagged me for potentially knowing a solution to this I felt a bit ambiguous.
Some may feel the experienced here sail through all aspects of creating scenes and what have you not, but for me that's surely not the case.
Yes I'm around here for a while and know a thing or two, but the thing is... I'm totally inept with math. Really.
I know zero, nada, njet, niks, nothing about math. Some say I am because I can do calculations from the top of my head pretty well, but that's 'arithmetics' to me and not math.

Anyway...just to let anyone who's reading this know: we all struggle, and it's normal. Here's my little story on how I got to this solution:

I noticed the method which is currently circulating, by BigBen, was a bit heavy on nodes and it made me start some Google searches on vector math.
From there I quickly learned that for these type of calculations you do not calculate with degrees, but with radians.
So I knew the first step needed to be a conversion of my heading value (in degrees) into radians.

Then a simple Google search for "convert radians to vector" gave me the result mentioned in bullet 3.
It showed me which mathematical steps I needed to take to go from radians to a vector.
I was not interested in the Y vector, because adding that in is basically already present in the surface layer/distribution shader, as the slope function.
So I only wanted to build the function for X and Z and the info in the link told me to use sin(X) and cos(Z).

With my vector built from the Heading input I knew I had to "compare" it with the vector from the surface.
A little bit of vague prior knowledge told me I needed either cross or dot product and the Wiki gave me the answer:
The dot product of our manually created vector and the vector from the surface as derived from the 'Get normal 01' gives us the scalar value which we can use for the mask.

After this I noticed my mask was faint and I had trouble understanding what was going on. Despite the solution being obvious if I would have read the Wiki more closely.
Angles perpendicular are 0 and angles in the same directions approach values of 1.
Eventually Matt told me to simply multiply the function with a constant to increase the brightness/coverage of the mask.

From there on everything else was common tricks many of us already know and use...


Great share, thanks. This totally makes sense from a logic approach and I'm glad you shared cause me trying to derive vectors, and pick them apart with addition/multiplication and normalizing and crap was not working well. Lol

Edit: Not sure how I got passed the "There was a post before you" warning, but thanks for the further explanation. In general, this allows a dynamic masking system for  directional slopes without needing to load in individual directions. Really really handy.


Welcome man, my pleasure!

With 'dynamic masking' you meant you're planning to replace the Heading input with another function or fractal or...?
I haven't tried that myself, but right now I don't see a reason why it would not work. Interesting!


Well, no I just meant more it's whatever heading you set in as apposed to loading in hard set directions. Though I do wonder what the results would be utilizing noises. Could be something interesting.


This setup can be simplified, see screendump. The one color adjust is enough to clamp to 0-1 ánd use BP, WP and gamma to strengthen or weaken the mask. And the degrees to radians is not needed.

As with the other methods it's still a problem to get an angle mask over big areas, say a whole hillside, without the small patches of other angles within that hillside. Smoothing the hill works, but only if it's really smoothed, i.e. added in the main line, not on a 'sidetrack'.


Thanks Ulco.

It seems the biggest change you made is leaving out the degree to radians convert node.
I'm not sure if I understand why without the convert it still works if you consider the background information I found on how to get a vector from heading scalar.
There must be a reason why people calculate with radians instead of degrees. Yet yours seems to work, puzzling.

The other thing you changed is leaving out the multiplication and I believe that that's actually the fix to the problem you just described.


If get normal could be fed a terrain as its scalar we could easily feed it a smoothed terrain to derive all its data from, or perhaps a way to use another method instead to create a hard mask in a direction from 0,0,0 or another translated location.


I don't know either, but I have a habit of eliminating nodes and see if something changes ;)  The less nodes the better. The factors you feed in the multiply would sort of do the same as sliding up/down the WP in the sole color adjust, at least that's what I saw happening.

Jordan; yes, I tried that, but it needs the main line to compute anything for that main line. There might be a way, but it needs experimenting!


I'm pretty sure you should adhere to at least multiplying the function to increase the coverage of your selection, e.g. expand your selection to neighbouring degrees of your degrees set.
It might also not work anymore, since you also removed the degree to radian converter and the second colour adjust to tighten/feather the selection. So perhaps it's a 1 + 1 thing going on here. What you describe does not happen in my intact setup.


Coming back to this nice function, I wanted to share a usage I have used a few times now. Basically you have the same heading and coverage setting as before, but there is the addition of an offset. This offsets the heading you have chosen in either direction, so your output mask is now a larger area defined by the offsets. For example, offsetting by 45 degrees gives you a whole half of your mountains and such, similar to combining the NSWE masks.