Cloud shadowing on sphere.

Started by
13 comments, last by bluntman 18 years, 5 months ago
I am working on a planet renderer at the moment, which is basically a sphere with various cube maps (texture, height, normal), and (depending on camera distance from the planet) an LOD patch which uses these cube maps, along with its own detail textures. I want to add a cloud layer to my planet, and my best idea for doing this is using another sphere with slightly larger radius than the planet, and cube mapping it with the clouds. This will probably work fine, but I want to have shadows projected from this cloud sphere onto the planets surface, using the sun as directional light source. To do this I would need to apply the cloud texture to the planets surface, but what is the vector math for the cube-map texture coordinates of the cloud shadow, relative to the rest of the textures? Thanks, Bill.
Advertisement
I think you can just trace a line from each vertex on the planet-sphere to the sun, check where this line intersects the cloud-sphere and pick the cloud-sphere tex coords at that point. (This for per-vertex texturing, for per-pixel you would need to do the same for each fragment)

And remember that you only have to do this for the lit half of the planet. You might get strange results at the day/night edge from rounding errors though.
And you are likely to get heavy texture skewing near the edge as well.
I did it like that. It works pretty good and fast.
Computing the cube map tex coords in a vertex shader is absolutely sufficient.
On my homepage, there is also a movie available.

Without taking care, it looks *a bit* strange near the day-night-border, where the shadows "wrap around", but that's not too bad IMO. You can't even see that effect in the screenies.


Wow, what are the chances. I have already been to your homepage and downloaded two of those demo movies about 5 or 6 months ago. They were a large part of my inspiration for making my own LOD planet (along with way too much Frontier: Elite 2 when I was younger). I spent ages trying to find that web site again, and couldn't, and now it gets handed to me! I would love to pick your brains more about planet rendering, unfortunatly I can't understand your website!
I am trying to make my engine completely procedural (except for detail textures, which I intend to take from a standard set). At the moment I have texture, normal, and height all generated from 3D Perlin noise, and all the vertex blending, texturing choices, and material selections are done on the GPU based on the height map, and the camera and sun vectors.

The calculation for the intersection between a line and a sphere needs at least one sqrt, which I definitly couldn't do on a per pixel basis (I would imagine, not sure how much faster the GPU would be at it than the CPU), and would hurt alot on a per point basis in a full res LOD mesh.
I think for the clouds I will try simply adding a portion of the sun vector to my cube map coordinates, based on the height of the atmosphere, and see if that works. If I add a vector which is equivalent to the distance along a tangent from the surface sphere to the cloud sphere. This will mean that at the day night border and the center of the day half the shadows will be perfect, and they will gradualy become warped and un-warped inbetween. I don't know how big the effect would be, because I just did a sketch of it, not any actual math. There must be a compensating factor that can be added to that based on the dot between the texture base coordinate and the light vector.

/edit
Screen shots here


[Edited by - bluntman on November 4, 2005 11:07:57 PM]
Quote:Original post by bluntman
Wow, what are the chances. I have already been to your homepage and downloaded two of those demo movies about 5 or 6 months ago. They were a large part of my inspiration for making my own LOD planet (along with way too much Frontier: Elite 2 when I was younger). I spent ages trying to find that web site again, and couldn't, and now it gets handed to me! I would love to pick your brains more about planet rendering, unfortunatly I can't understand your website!


There is also an English version of my webpage. Just klick on the GB flag with the tea cup.
I don't know why I sent you the German version...

Elite is also my inspiration, together with Ysaneya's journal. Right now, I'm delevoping a
new version of planetary clipmaps that get rid of that annoying global grid without
sacrificing too many advantages. Once it's working properly, I'll put it on my HP.
It's also using the advanced noise functions of libnoise (though they are quite
slow in my eyes).

Quote:
I am trying to make my engine completely procedural (except for detail textures, which I intend to take from a standard set). At the moment I have texture, normal, and height all generated from 3D Perlin noise, and all the vertex blending, texturing choices, and material selections are done on the GPU based on the height map, and the camera and sun vectors.


I intend to make the clipmaps completely independent of the choice procedural/predetermined.
However, this time I also want to make some procedural planets since everyone seems to
do it.

Quote:
The calculation for the intersection between a line and a sphere needs at least one sqrt, which I definitly couldn't do on a per pixel basis (I would imagine, not sure how much faster the GPU would be at it than the CPU), and would hurt alot on a per point basis in a full res LOD mesh.


I don't think a sqrt is that expensive. I think it's comparable to a division but I might be wrong.
Anyway, it's not a bottleneck in my current engine.

Quote:
I think for the clouds I will try simply adding a portion of the sun vector to my cube map coordinates, based on the height of the atmosphere, and see if that works. If I add a vector which is equivalent to the distance along a tangent from the surface sphere to the cloud sphere. This will mean that at the day night border and the center of the day half the shadows will be perfect, and they will gradualy become warped and un-warped inbetween. I don't know how big the effect would be, because I just did a sketch of it, not any actual math. There must be a compensating factor that can be added to that based on the dot between the texture base coordinate and the light vector.


Hey, good idea! I think that will work without a noticable difference (unless your
clouds are 1000km high). You could also try to Taylor-expand the sqrt term for a better
approximation...


Quote:
/edit
Screen shots here



Looks good. You could improve the atmosphere by shading also the planet.
Turns out, after reading up on it, that I am using clipmaps, although I just sort of made it up as I went along, mostly by imagining from your tech demo how you did it. Came up against alot of problems I would never have thought of, but now have a stable system that runs at about 30fps at full LOD (33x33 grid, 10 LODs). The blending between LODs is done using vertex shaders, and the drawing uses tri strips (which I found to be faster than drawing elements). I am currently calculating movement for a particular LOD (i.e. how many columns and rows to move the grid by) using angular distance from the current camera on the planet sphere to the center of the grid, divided by the angle between grid squares.
Whats the global grid you mention? I create a base LOD automatically when my camera is close enuf to the surface but this does not cover the globe.
If your assembly programming is good (unlike mine) you should look into using SSE for generating noise, I have seen 2D Perlin Noise implementations that calculate 4 heights for the price of one. Just needs an extra dimension added, but I don't understand Perlins algorithm well enough to add one to the C let alone the assembly! SSE could also be applied to normal recalculation aswell, more easily than to the Noise, but my tests show that I can calculate 10000000 normalisations in less than a second, but it takes 3550ms to calculate 100000 3D noise calculations.
Put the shadows on aswell, seems to work fine, except now I am running into problems with the granularity of the z-buffer. I am currently doing all rendering in one coordinate frame, but intend to split it up into outerspace coordinates, planet coordinates, and close LOD grid coordinates. How do you handle this in your system? I figure that using a non planetary coordinate system for any of the LOD levels means that one needs to transform all thier coordinates when the local origin moves, which sounds a bit expensive to me. Anyway I am going to try that tonight.
Thanks for the tips, I will check out libnoise, see how it compares with my function.
Quote:Original post by bluntman
Turns out, after reading up on it, that I am using clipmaps, although I just sort of made it up as I went along, mostly by imagining from your tech demo how you did it. Came up against alot of problems I would never have thought of, but now have a stable system that runs at about 30fps at full LOD (33x33 grid, 10 LODs).


That's not quite fast. I have 128x128 grids and 11-12 LODs at 80-120 FPS (RadeOn 9800 Pro).
Did you already implement VBOs? They speed things up quite a bit.

I would love to see how you implemented the clipmaps. I can imagine at least three approaches.
Can you post a screenshot of your grid?

Quote:
Whats the global grid you mention? I create a base LOD automatically when my camera is close enuf to the surface but this does not cover the globe.


Yeah, the problem is that the clipmaps never cover the globe - not even half of the globe in my implementation!. So what do you do when you are far away from the planet? You need some global grid. The global grid is fixed and has nothing to do with the clipmaps! You can see the global grid in the beginning of the tech movie before the little square clipmaps pop up. It's based on a subdivided cube (quite simple).

Quote:
If your assembly programming is good (unlike mine) you should look into using SSE for generating noise, I have seen 2D Perlin Noise implementations that calculate 4 heights for the price of one. Just needs an extra dimension added, but I don't understand Perlins algorithm well enough to add one to the C let alone the assembly! SSE could also be applied to normal recalculation aswell, more easily than to the Noise, but my tests show that I can calculate 10000000 normalisations in less than a second, but it takes 3550ms to calculate 100000 3D noise calculations.


Your 3D noise is about as fast (resp. slow) as libnoise. I do not consider using SSE or something similar for now, because in the moment I want to optimise the look, not the speed. In the end, when everything is ready, I'll optimise for speed.
Don't modern compilers use SSE, anyway?

For now, I'm quite happy with libnoise. I've attached an image of some procedurally generated asteroid (using the turbulence module and ridgedMulti of libnoise, that's all). Try this with Perlin! I think it's worth the effort. There's another one on my homepage.

Quote:
Put the shadows on aswell, seems to work fine, except now I am running into problems with the granularity of the z-buffer. I am currently doing all rendering in one coordinate frame, but intend to split it up into outerspace coordinates, planet coordinates, and close LOD grid coordinates. How do you handle this in your system? I figure that using a non planetary coordinate system for any of the LOD levels means that one needs to transform all thier coordinates when the local origin moves, which sounds a bit expensive to me. Anyway I am going to try that tonight.


The floating point and z-buffer precision are two important problems to solve. You can solve the z-precision problem by adjusting zNear and zFar each frame depending on the distance of the camera to the clipmaps. The floating point precision problem causes vertices to wobble around randomly on Earth when you are in <1000m height. This can be solved by computing the modelview-projection matrix completely in double precision on the CPU and transforming it to single precision in the very end. That's not a big overhead and solves (most of) the problem (I currently get some strange quantization effect which I still don't know the cause of, but it's not visible at speed >50km/h which is common for a star ship ;-).

I think having a special coordinate system for the clipmaps will work, but you'll have to adjust the system once in a while by adding some constant vector to shift it back to zero. You don't have to shift the system each time when the origin moves, that would be too expensive. Just check when the coordinates in the clipmaps are too far off the origin and move them away then. When you indend to stick with a 33x33 grid, this is OK, but with a 128x128 grid or bigger, you'll probably see a noticable jump each time you do this shift.



[Edited by - Lutz on November 10, 2005 7:16:59 AM]
Quote:Original post by bluntman
I have seen 2D Perlin Noise implementations that calculate 4 heights for the price of one. Just needs an extra dimension added, but I don't understand Perlins algorithm well enough to add one to the C let alone the assembly! SSE could also be applied to normal recalculation aswell, more easily than to the Noise, but my tests show that I can calculate 10000000 normalisations in less than a second, but it takes 3550ms to calculate 100000 3D noise calculations.


I think this number is very low.

I just did the same test on my computer. It is a pretty outdated Athlon 2.0 Ghz (not 64 bits).

For the first test (in order to make a relevant comparison), i normalized 10 millions 3D vectors. For this i generated a huge array of 10 millions random 3D vectors, then a big loop which parses this array and renormalizes each of them. It takes approximately 400 milliseconds, which suggests (if you did the same test) that my computer is 2.5 times faster than yours. Remember that number to compare performance of 3D Perlin noise in the next test.

Now, for the second test, i generate 100 000 raw Perlin noise values. The input 3D vector given to the noise function is in the form (i*x,i*y,i*z) where i is the loop counter, and x y z some constants. The result is 22 milliseconds.

Since your computer is 2.5 times slower than mine, the equivalent test on your computer should then be around 55 milliseconds to generate these 100 000 3D noise values. If it's taking 3550 ms, the only conclusion is that my code is 64 times faster than yours. And i got it directly from Perlin's website..

Can you post your noise generation code, and how you tested it ?

Y.
Lutz:
That asteroid is awesome! Really looks like some sort of crystalline formation. I will have to get on with looking at that library (haven't got around to it yet). I am starting to get bored with the look of my planet already.

I got the relative coordinate systems working, now my LOD is displayed at 1000 times the scale of the planet, but the camera is moved 1000 times further away. Also I switched to doubles for the internal calculations and the result is much smoother. I don't think even doubles are enough accuracy for representing a galactic coordinate though, so I will add another coordinate system for interstellar travel, then switch between calculating in this and the other two systems as needed.

Yeah I know 30fps 33x33x11 isn't that fast, but I tried glDrawElements and it is much slower than tri strips, so I can't imagine VBOs would be any faster. I mean the grid changes every frame, and has a dynamic hole in it, so if I need to re-create the data arrays every frame then how can it give me a performance boost? Still when I hide the patch the fps jumps to 60fps (I have vsync on).
Still I will try it, as I already use VBOs for the planet.
My 'global grid' is exactly the same as yours it sounds like, but what could you replace it with? Or you want to stitch the LOD patch into it somehow? I have seem ROAM planet approaches which are just one object.

Ysaneya:
Thanks alot for the comparison numbers! Well when I said Perlin Noise calulations I actually meant fBM calculations, to a depth of 20, so times your figure by 20! Also I know Perlins original noise is quicker than my version, but it also has a bug in it which he admitted. I am using his Java version in which the bug is fixed. Basically if you zoom in real close, and your scale gets real high, then the interpolation breaks down and there are discontinuities everywhere.
As for the normalizations: My vertex normalize is completly standard I think (this is from memory):

float Vector::Length()
{
return(sqrt(x*x + y*y + z*z));
}

void Vector::Normalize()
{
float lenmul = 1.0f/Length();
x *= lenmul; y *= lenmul; z *= lenmul;
}

I will have a look at my code when I am at home. I didn't think anyone would give me comparison times, or I would have been more careful, it could be that I was testing in debug mode, or some other stupid thing. I just wanted the relative timings between normalizations and fBm calculations, not hard figures. I was running Winamp aswell! I will try the test again tonight and get some better figures.
Ah ok, then your numbers are much more in line with what i have. I just remember a small thing that might help, the code posted on Perlin's website is doing at one point a serie of casts from float-to-int, which are extremely slow. Reimplementing them in assembler, i had a speed up of almost 100% of the noise function.

Y.

This topic is closed to new replies.

Advertisement