Raymarching domain repetiton randomness with each repetition
category: code [glöplog]
Hi guys, I'd like to ask you how can I get some "instance ID" of mod repeated stuff in raymarching. Let's imagine a case, where I want to make a skyscraper, so I've modeled a "skyscraper base", where the skyscraper base is just a box, with a window cutouts. I want these bases to stack on eachother in every repetition, but, once with heigh 3 bases, once 5, once just the base and so on...also, how can I achieve different scaling and/or rotation for each repetition if possible?
Something like id = (maxId * rand(x % sizebuilding, y % sizebuilding)) % 1 ?
Here I made heavy use of noise-based "instance IDs" for domain-repeated cubes:
shadertoy prototype (for educational purposes)
the intro
shadertoy prototype (for educational purposes)
the intro
xTr1m: nice to see that you have used shadertoy only for prototyping. Out of curiosity, what kind of enhancement you put on top of it in the final intro, so that it looks so much better? I can see noise texture and motion blur (I guess?), anything else?
xTr1m, could you please point out on which lines I shall look at, because I have a bit problem reading non-verbose code. Also mate, I saw it live @ Revision, it was badass :)
You can get an id by simply flooring the current position like vec3 ids = floor(p/your_mod_value). based on these IDs (3 for one position) you can easily calculate a random number.
hahaaaa, great will try! :) thank you guys!
Example, line 76: vec3 id = floor(p/SPREAD);
Cupe covers this in his NVScene talk: https://youtu.be/s8nFqwOho-s?t=16m30s
ha! He didn't told this one on Revision seminar...never mind, I've got this now, hope Cupe and the Mercury guys won't get mad if I "borrow" the pMod function. And if we are here, can somebody tell me how can I get those pretty isolines as he has in the scenes the whole time, showing distance function evaluations?
no buddy. now its your turn :P
*rolling up sleeves*
*turns on eye of the tiger* I can do this!
Yay! nah, please borrow it and everything else. And play around and improve on it because I'm sure we haven't done it in the best way possible by far.
Yeah, I didn't show how to do this in the seminar, but the pattern is straightforward:
The noise does not have to be smooth, so a cheaper function (e.g. LFSR-based) can be used.
We'll tidy up and release most of that stuff soon[tm], I hope to have something online after next weekend. But please don't wait for it and roll your own version anyway. I'd like to see variants and improvements instead of people just using it :)
Yeah, I didn't show how to do this in the seminar, but the pattern is straightforward:
Code:
float cell = pMod1(p,1);
someProperty = favouriteNoiseFunction(cell);
The noise does not have to be smooth, so a cheaper function (e.g. LFSR-based) can be used.
We'll tidy up and release most of that stuff soon[tm], I hope to have something online after next weekend. But please don't wait for it and roll your own version anyway. I'd like to see variants and improvements instead of people just using it :)
Well now that there's a thread might as well bring it up. I tried something similar over a month ago, and got pretty bad results. This was with my own modulus function. Decided to try again with Mercury's, and the results are the same.
My code is basically:
Where the texture is a noise texture (shadertoy), I haven't noticed the noise function to make any difference. This is the general result:
It "works", but obviously there are horrible discontinuities caused by the failing distance estimation, apparently because the modulus id's don't "align" with the repetition, if that makes sense. I really can't figure out the fix though, since the repetition should be correct. With certain parameters it does align though and look sort of ok, except for the horrible shadow banding that still persists*:
(*some of it especially in the foreground is caused by something else, not sure what but it's a more minor issue, if you have an idea what causes that I'm also all ears.)
My code is basically:
Code:
vec3 q = pos;
vec2 id = repeat2(q.xz, vec2(1.0+3.0*iMouse.xy/iResolution.xy));
float height = 0.8+texture2D(iChannel0, i).x;
float body = box(q, vec3(0.25, height, 0.25));
Where the texture is a noise texture (shadertoy), I haven't noticed the noise function to make any difference. This is the general result:
It "works", but obviously there are horrible discontinuities caused by the failing distance estimation, apparently because the modulus id's don't "align" with the repetition, if that makes sense. I really can't figure out the fix though, since the repetition should be correct. With certain parameters it does align though and look sort of ok, except for the horrible shadow banding that still persists*:
(*some of it especially in the foreground is caused by something else, not sure what but it's a more minor issue, if you have an idea what causes that I'm also all ears.)
(The sampling coordinates should of course be "id" as well in the paste, that's just a typo.)
Quote:
xTr1m: nice to see that you have used shadertoy only for prototyping. Out of curiosity, what kind of enhancement you put on top of it in the final intro, so that it looks so much better? I can see noise texture and motion blur (I guess?), anything else?
Just a proper raymarching loop, and a different material/lighting model. The motion blur is just in the rendered video (60FPS with 8 motion blur samples each. Took a whole night to render). The intro itself runs without motion blur.
Quote:
xTr1m, could you please point out on which lines I shall look at, because I have a bit problem reading non-verbose code. Also mate, I saw it live @ Revision, it was badass :)
Line 220.
noby: the problem is, at the boundary of a "cell" you cannot possibly know how close is something in a neighboring cell. I guess one way to fix it is to take 4 cells (not just one) into account and calculate proper DF, but I also just started playing with it (some very simple experiment with artifacts), so there could be a faster way/some hack.
xTr1m: thanks for info!
xTr1m: thanks for info!
tomkh: yeah that I already figured, but not the solution. Didn't quite understand what you meant with the four cells.
Neat visualizer though. I tried something similar to what I was trying to achieve. Clearly shows how the distance estimation fails around the borders of the cells. Does some sort of a "smooth modulus" exist that interpolates between the boundaries so that the Lipschitz continuity remains? I'm pretty much a novice so I'm mostly just guessing.
Neat visualizer though. I tried something similar to what I was trying to achieve. Clearly shows how the distance estimation fails around the borders of the cells. Does some sort of a "smooth modulus" exist that interpolates between the boundaries so that the Lipschitz continuity remains? I'm pretty much a novice so I'm mostly just guessing.
Code:
// +-----+-----+
// | | |
// | A | B |
// | p| |
// +-----+-----+
// | | |
// | C | D |
// | | |
// +-----+-----+
I mean, when you estimate DF(p) and p happens to be in cell A, you should in fact evalulate all 4 cells A, B, C, D.
Hmm and in fact @xTr1m shader suffers from the same problem, just replace line 203 with:
Code:
p.y -= phase * 0.9 - 0.2; index = 5;
Hmm right, if you evaluate the neighboring cells as well it well account for the discontinuity between the borders. Of course ideally you should evaluate the whole grid (i.e. not use a modulus at all...), but including the nearest neighbors ought to remove most of the artifacts.
I still feel like there's a less obvious more clever solution to it though...
I still feel like there's a less obvious more clever solution to it though...
noby: yeah, I will have more time over the weekend to play with it, would be nice to find better solution. Just one more obvious thing to do would be to just do rough estimation for neighboring cells (like just a bounding box or few bounding spheres or whatever).
Turns out I had some time this evening, so here you can find proof of concept with exact/correct distance field (I believe).
So the basic idea is to combine evaluation of 4 neighboring cells with "frame" concept.
A frame is bounding area of everything outside those 4 cells, where you have to assume min/max height - that's the limitation of course, as you cannot exceed this min/max height.
So the basic idea is to combine evaluation of 4 neighboring cells with "frame" concept.
A frame is bounding area of everything outside those 4 cells, where you have to assume min/max height - that's the limitation of course, as you cannot exceed this min/max height.
whoa guys, you are awesome! Cupe, thanks for the permission, much appreciated. Now let's learn something, because I haven't checked my thread yesterday :)