Elevation lines, Gradients, Smoothed Fractal LODs #358
Replies: 7 comments 10 replies
-
Looks like a great feature. The shader preprocessor was a bit clunky when I wrote the INSERT system. I was thinking of expanding it to offer ending demarcations and replacement blocks. However using the preprocessor is probably a better way to go. It would allow the use of conditionals and be easier to maintain over time. I would accept a PR to strip out the INSERT system and go entirely with the Godot preprocessor. I would accept a PR for these elevation lines.
|
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
at the time of this post, this is the gradients used and the function to sample them: #define STRATA_GRADIENTS_SUPPORT
const int _GRAD_DATA_LEN = 37;
const int TEST_GRAD_OFFSET = 0;
const int TEST_GRAD_LEN = 31;
const int TEST_NORM_GRAD_OFFSET = 31;
const int TEST_NORM_GRAD_LEN = 6;
const int MY_TEST_GRAD_WINDOW_OFFSET = 0;
const int MY_TEST_GRAD_WINDOW_COUNT = 8; // This says there will be 8 portions "windows" defined that mark the indexes necessary to respond to U values between that window's start and stop normalized values (x/total portions -> x+1/total portions)
const int ANOTHER_GRAD_WINDOW_OFFSET = 8;
const int ANOTHER_GRAD_WINDOW_COUNT = 1; // Because this gradient is so short, it's window is just it's start and stop index, ie window count 1
const vec4[_GRAD_DATA_LEN] _GRAD_COLORS = {
vec4( 0.2854815, 0.2786366, 0.2557304, 0.0165 ),
vec4( 0.52393, 0.554962, 0.431105, 0.55 ),
vec4( 0.52393, 0.554962, 0.431105, 0.85 ),
vec4( 0.72, 0.60192, 0.4248, 0.25 ),
vec4( 1., 0.985, 0.7, 0.35 ),
vec4( 0.6, 0.6848, 0.568, 0.625 ),
vec4( 0.449237, 0.472517, 0.409896, 0.75 ),
vec4( 0.501828, 0.492807, 0.347508, 0.85 ),
vec4( 0.1312416, 0.1340626, 0.133792, 0.01 ),
vec4( 0.30297, 0.321987, 0.273123, 0.9 ),
vec4( 0.646057, 0.569328, 0.491916, 1. ),
vec4( 0.3217443, 0.2482282, 0.2073914, 0.57 ),
vec4( 0.0596259, 0.0416335, 0.0218797, 0.90137 ),
vec4( 0.678981, 0.516589, 0.431332, 0.34 ),
vec4( 0.83843, 0.63584, 0.476065, 1. ),
vec4( 1.0, 0.8567344, 0.92304, 0.15 ),
vec4( 0.82, 0.70192, 0.5248, 0.9 ),
vec4( 0.2564323, 0.19531793, 0.12385168, 0.17 ),
vec4( 0.830987, 0.615895, 0.438144, 0.8 ),
vec4( 0.856008, 0.713562, 0.589941, 1. ),
vec4( 0.196, 0.17872, 0.10528, 0.135 ),
vec4( 0.540448, 0.524066, 0.434087, 0.75 ),
vec4( 0.792157, 0.670588, 0.498039, 1. ),
vec4( 0.54369, 0.43421, 0.282027, 0.73 ),
vec4( 0.443975, 0.2609797, 0.0441082, 1. ),
vec4( 0.800305, 0.65918, 0.485817, 1. ),
vec4( 0.831373, 0.615686, 0.439216, 0.8 ),
vec4( 0.802576, 0.656002, 0.482411, 1. ),
vec4( 0.898039, 0.784314, 0.466667, 1. ),
vec4( 0.805077, 0.690615, 0.435805, 0.71 ),
vec4( 0.668368, 0.552822, 0.39042, 1. ),
vec4( 0.501828, 0.692807, 0.347508, 1.0 ),
vec4( 0.501828, 0.692807, 0.347508, 1.0 ),
vec4( 0.564323, 0.9531793, 0.2385168, 1.0 ),
vec4( 0.312416, 0.340626, 0.33792,0.8 ),
vec4( 0.312416, 0.540626, 0.33792, 0.4 ),
vec4( 0.21, 0., 0.26, 0.0 )
};
const ivec2[9] _GRAD_WINDOWS = {
ivec2(0,3),
ivec2(2,8),
ivec2(7,11),
ivec2(10,17),
ivec2(16,22),
ivec2(21,25),
ivec2(24,29),
ivec2(28,30),
ivec2(31,36)
};
const float[_GRAD_DATA_LEN] _GRAD_OFFSETS = {
0.0,
0.0594262,
0.0819672,
0.135295,
0.137295,
0.162651,
0.212851,
0.237705,
0.266393,
0.293033,
0.327869,
0.381148,
0.391393,
0.407787,
0.453815,
0.467213,
0.485656,
0.55123,
0.561475,
0.586066,
0.60041,
0.614943,
0.645594,
0.67418,
0.680328,
0.756148,
0.770492,
0.85041,
0.866803,
0.938525,
1. ,
0.0,
0.25,
0.42,
0.63,
0.88,
1.
};
vec4 SAMPLE_GRAD(int _grad_offset, int _grad_len, float _u) {
vec4 resp = vec4(0.);
ivec2 _window = _GRAD_WINDOWS[_grad_offset + clamp(int(_u*float(_grad_len)),0, _grad_len-1)];
for (int _i = _window.x; _i <_window.y; _i++) {
bool range_valid = _u >= _GRAD_OFFSETS[_i] && _u <= _GRAD_OFFSETS[_i+1];
float _lerpval = (_u - _GRAD_OFFSETS[_i]) / (_GRAD_OFFSETS[_i+1] - _GRAD_OFFSETS[_i]);
resp += mix(vec4(0.), mix(_GRAD_COLORS[_i],_GRAD_COLORS[_i+1],_lerpval), float(range_valid)); }
return resp; } then to take a sample, you pass it the starting index offset of the "window" array, and how many window slices that gradient uses, From that, it looks up a start and finish index of gradient points that might affect the given U coord, iterates through them, and adds their effect to a return value if the current iteration is the valid range. like this: float my_testgrad_u = /* figure out a normalized coord however you do that. should be 0->1 */
vec4 _gradSamp = SAMPLE_GRAD(MY_TEST_GRAD_WINDOW_OFFSET, MY_TEST_GRAD_WINDOW_COUNT, my_testgrad_u); Future versions may wrap these 'start window index / total window count' int pairs in a ivec2 that can be defined constant and passed more easily. |
Beta Was this translation helpful? Give feedback.
-
The 'auto-veg' concept described above In this image I'm letting the veg response kick height up a little bit, but haven't bothered to properly calc normals with that in effect so that's a bit off, but the shadow blobing effect that's built into the gradient it's using is helping a lot also trying out some puddles, key'd off a really tight window to the surface normal versus true-up, the puddles aren't great yet but the idea seems to work ok. I'd like to get some animated rain drops in there. The other non-puddle surfaces pick up some extra spec/shine for a wetness effect. |
Beta Was this translation helpful? Give feedback.
-
I was wondering if I've just gone off the rails off topic here when something occured to me, kinda funny: Plot twist: The plants above are still elevation lines! They always were. Working off the exact same principle, but a gradient instead of a line, only half the gradient is actually used, and the Y is modulated by noise. |
Beta Was this translation helpful? Give feedback.
-
Fractional Octaves -> Smoother transitions original/current:
Becomes:
Didn't want to junk up your PR list with a million edits so here you go, if you want your octaves to blend into each other this seems to do the trick, doesn't appreciably impact performance for me. |
Beta Was this translation helpful? Give feedback.
-
It seems like checking distance and doing a mesh or pixel normal off of that doesn't offer the performance I'd expect it to, and I think that's because since the distance isn't a constant value, the compiler can't optimize that conditional, so it turns into a parallelism issue and the end result not much speed improvement regardless what you set the distance to. So I tried this instead, seems to work much better for me. Instead of testing distance, test against MODEL_MATRIX[0].x where 1 is close and greater values is more distant, since (I believe), that index is the scale.x(?) Pretty sure, couldn't find docs on which index is exactly what but I think [0].x,[1].y,[2].z is basically the scale. Anyways testing against the x being less than 8 seems to work pretty well for me, so it draws the first three stages with mesh normals, than anything farther than that with pixel. And because MODEL_MATRIX is a constant, I can definitely tell the distance optimization is having desired result, the compiler is pruning the branch. edit: confirmed those are the index's for scale. I've always been terrible at matrix math, finally found some reference. |
Beta Was this translation helpful? Give feedback.
-
relevant snippet below. I'm using defines in my fork so you'd want to change that bit around some.
edit: kept messing around with it and have a version that also has a grid overlay, and dark/light mode selection. Here's light mode:
and dark mode, the more colorful option so far:
you can blend the modes (it's lerping their relevant values anyways, by a dark_light_mode float). Here's 85% light mode, it just adds a little color to the lines:
The code got a little crazy and I'm still making it presentable. When it's cleaned up I'll edit this with new code in case you want to try it out.
Beta Was this translation helpful? Give feedback.
All reactions