smcameron / gaseous-giganticus

This program procedurally generates gas giant cubemap textures for the game Space Nerds In Space. https://www.patreon.com/smcameron

Home Page:https://smcameron.github.io/space-nerds-in-space/gaseous-giganticus-slides/slideshow.html#1

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[Enhancement] Output velocity field as a flow map

Gameslinx opened this issue · comments

In some shaders, a flow map can be used to animate a texture. These are commonly used for liquids and, more importantly, gas giants.

From my understanding, the velocity field dictates the direction in which a particle will be moved in. It would be useful if the velocity field could be output as a texture along with the texture that is normally saved. This would allow for a shader that can utilize a flowmap to shine with this program.

A flowmap without movement defaults to grey (0.5, 0.5, 0.5). Movement in the X direction is indicated by a change in red pixel intensity. Movement in the Y direction is indicated by a change in green pixel intensity. The blue channel is unused.

I feel as if this would be a useful addition to the program.

Good idea!

Hmm, so the velocity field is actually a 3D field of vectors that are constrained to be tangent to the surface of a sphere. I suppose I could transform to tangent space, similar to how normal maps work?

That should hopefully work - A flow map only needs an X and a Y direction so transforming to tangent space would allow for this.
This is a flow map which indicates a vortex around the centre of the image:
image
There are no examples of a gas giant flow map that I could find, but the output should look similar to that above

Thanks for the example image, had done some google image searches for flow maps, but wasn't sure what I was looking at. Now just have to remember/relearn about tangent space, ha. (May take a little while.)

Looky what I made:

flow-field-sphere

I can't believe that worked the first time. Zero debugging. Which probably means that it didn't actually work and there's something wrong with it, but I don't really know how to tell if it's right. It looks plausible that it's right (except for the lack of any need to debug anything.)

I'll commit this, and you can see if you can do anything with it, or if the field is all wrong in some way.

Committed as:

  • f5c1299 Allow exporting velocity field as flow-field png files

To use it, just add command line flag "--dump-flow-field filename-prefix"

It will dump out six png files named "filename-prefix-X.png" where X is 0 thru 5.

Let me know if it works for you, and if you do something cool with it, I wouldn't mind seeing it.

Hmm, the way those bands shift from red to green on opposite sides of the sphere make me think maybe something's subtly wrong. There are counter rotating bands, which makes me think that it should look more like alternating red and green bands, not alternating half-red, half-green bands. But... not really sure.

Added another commit to at least warn that the flow field is not calculated correctly, and comments indicating why I think it's wrong.

I think calculating the flow field is a bit of a hard problem (at least it is for me.)

I knew that quick first seeming success was way too easy.

I generated a gas giant and previewed it with the flow map shader and the current results aren't amazing. I may have a solution, though. Here's what the result looked like:
https://www.youtube.com/watch?v=dEv7s45-c0I

My solution may be simpler:

1. Get position of the current particle (I believe this is stored in the Pos variable)
2. Get position of the particle after it has moved (Pos_1)
3. Directional 2D vector "Vec" = ((Pos_1.x - Pos.x), (Pos_1.y - Pos.y))
4. Normalize this by dividing Vec.x and Vec.y by the magnitude of the vector (sqrt(Vec.x^2 + Vec.y^2)) to get the X and Y values between -1 and 1
5. Red colour (X direction) is (127 + (127 * X)): range from 0 to 255
6. Green colour (Y direction) is (127 + (127 * y)): range from 0 to 255

This should produce a map that lines up correctly with the Gaseous Giganticus output. Hopefully, it is also easier to calculate and does not require a transformation into tangent space if you calculate the vectors from pixel coordinates

Thanks. That might work. Can't get to it today. Hopefully within a week or so I can give it a try though.

Ok, I made another attempt... but it doesn't seem to be working. Not sure why not.

If you want to try it, apply the following patches.

I don't think your step 4 above is correct (normalizing the 2d velocity vectors). You want the flowmap to contain velocities that are not 1.0, and zero velocity areas (centers of vortices) would end up with NaNs.) You do want to scale the velocities. What I tried was finding the max velocity, and dividing by that. However, there were some very large velocities that ended up scaling almost everything to zero. So I tried ignoring large velocities to get a reasonable scaling factor... still the output doesn't look right at all. So... something's screwy, but I don't know what.

I think many of the high velocities are coming from particles that traverse from one face of the cubemap to another. Such particles should be handled specially (e.g. ignored is the easiest special handling. I don't know what "correct" special handling would be.) There are other problems besides that though.

I don't think your step 4 above is correct (normalizing the 2d velocity vectors). You want the flowmap to contain velocities that are not 1.0, and zero velocity areas (centers of vortices) would end up with NaNs.)

Normalizing the vectors is necessary, as a vector (1,0) indicates movement only in the X axis which will correlate to RGB(255, 127, 0). The vector (1, -1) would be RGB(255, -255, 0) which is a movement in the positive X and negative Y direction. If a pixel moves (4, 6) and this value is not normalized, the RGB value would be out of bounds.

In the shader, the map is multiplied by a scalar to get the maximum displacement from the flow map. Normalizing the vector is required for this, and it could be why the map doesn't look right.

I'll need to try this, as I have not yet. Will update the issue once I get it working

Edit: Getting "segmentation fault" error when running the command ./gaseous-giganticus --input input/input01.png --dump-flowmap filename-prefix

Normalizing the vectors is necessary,

I don't agree with this. This would mean every vector has a magnitude of exactly 1.0.

I do agree the vectors need to be scaled. But not normalized.

There are going to be parts of the vector field where things are slow (i.e. magnitude much less than 1.0.) My idea is scan through all the vectors, find the biggest one, and compute a global scale factor such that that biggest vector gets scaled to magnitude 1.0. (First problem with this is vectors spanning edges got huge velocities, causing everything else to get scaled to effectively 0. But solved that for the time being by ignoring such big vectors. Still other problems remain.)

My mistake, you're right - They should be scaled instead of being normalized

Other problems...

flowmap1

There are some weird artifacts near the edges, and the poles seem to have disappeared, so maybe there's something wrong with my cubemap indexing, I dunno.

flowmap2

Zooming in, there's this weird every-other-line thing. Maybe some png related thing... or I dunno.

Ok, fixed a couple bugs... was using vfdim instead of DIM when calling xyz_to_fij_float(), which was the cause of the every-other-line thing, and also the missing poles. Had some crude max velocity checks instead of checking explicitly for cubemap face transitions, which was the cause of some of the larger edge artifacts.

flowmap3

Still some problems, but getting closer.

Ok, I'm going to commit this for now. I have a feeling that the strong edge artifacts at the cubemap corners may be due to the projection of sphere to cube. That is to say, if you have a velocity that is (0.9, 0.1, 0.0) and you project this onto the x-y plane, you get (0.9, 0.1) but if you project onto y-z plane, you get (0.1, 0) -- so you're going to get abrupt speed changes at the cubemap edges.

  • Revert erroneous flowmap calculation b7ffdc2
  • Clean up memory allocations b587e14
  • Make another attempt at flowmap calculation 3986703

Oh, also it outputs RGBA images rather than RGB, because... I dunno, some PNG nonsense, when I took out the alpha channel the images got mangled.

I was able to address some of the missing pixels at the edge due to particles traversing cubemap face boundaries by calculating subsequent particle positions on the same face even if they go out of bounds for purposes of the flow map.

  • Address some edge artifacts of flowmap 5ae8f44

flowmap4

There are still abrupt velocity changes at the cubemap face edges... oh well. (I think the fix is, these vectors need to be in tangent space.)

Getting "segmentation fault"

Hmm, haven't seen that. (But I have generally not been letting it run for very long). If you can duplicate it, you can do

ulimit -c unlimited
./gaseous-giganticus blah blah blah

and it should leave a core file, then you can run gdb on it and get a backtrace.

gdb -c core
....
> bt

and it should show you something interesting.

Possible it's running out of memory, and overcommit is making this manifest as a core dump. Or it's possible some of my memory cleanup code is busted and I never hit it because I always hit ctrl-c before it terminates.

Edit: Just ran it to completion without any seg fault.

Ok, fixed a couple bugs... was using vfdim instead of DIM when calling xyz_to_fij_float(),

I could imagine the above could have triggered a segfault, so maybe that fixed it?

I am now attempting to convert the velocity field to tangent space, but with a new program, ggvf_to_flowmap. It doesn't work yet, but it is here: https://github.com/smcameron/ggvf_to_flowmap

Ok, I've got ggvf_to_flowmap to the point that it will produce output, and it looks promising, but it's not right yet.

flowmap5

Obviously not right.... I've tried the obvious things to rectify it without success. At least it doesn't have the little black speckles that relying on the particles to paint everything produces.

I am starting to think that the code in mesh_sample_spherical_cubemap_tangent_and_bitangent() here: https://github.com/smcameron/ggvf_to_flowmap/blob/master/mesh.c#L633 is not quite correct.

Hmm, I've now tried this three different ways, and none of them worked out.

Not looking too good for this feature.

You may be right. I've been doing some testing on the cubemaps that GG has been exporting and while they do look interesting, they're not creating swirls or moving bands as expected. That said, thank you for looking into this! I've found it really interesting

I'm not going to close this because I think it should work... I think we're just missing some little piece of the puzzle conceptually. It's almost there. It feels like there's just some little piece that's missing. But until that piece is found... well, I guess it's useless. So we leave it hanging for now. Can't force finding the missing piece.

commented

Oh I just wanting to fiddle with this as I can use this in vector displacement in Terragen to further influence the gas giant. However when I run the command --dump-flowmap or --dump-velocity-field GG just spits out the help stuff and doesn't run.

Oops never mind, wasn't specifying filename. I figured it'd just do what it does with other images and give it a suffix.

Well, as you can see from this bug, I never did get this to work correctly.

commented

Was just seeing if the state has changed at all. It doesn't work anyway even as the topic suggests here (partially), even if you set a filename at all. Probably should be removed until it does work, as it just causes a segmentation fault.

I feel like a lot of the issues of converting could easily be solved by using quaternions.

Is there a branch or commit with the latest work on this issue?

Everything is in the main branch already, or here: https://github.com/smcameron/ggvf_to_flowmap

"using quaternions..." Already am using quaternions.

knock yourself out, send me a patch.