Intel sponsors gamedev.net search:   
Journal of YsaneyaBy Ysaneya      
Main project:

Infinity, a space-based MMOG

Forums

Monday, July 23, 2007
Planetary engine

The interfaces and rewritting of shaders in GLSL is progressing quite well, I'm pretty much ready to jump on the re-implementation of texturing, and improving water.

I got ride of the seams in some detail textures that were caused by multiplying the texture coordinates by a scale constant in the shaders ( in order to tile the texture a lot of times on the terrain ). It's a bit tricky to explain, but it was easy to implement, so I'll come back on the technique later ( if I don't forget ).

Rings / asteroid fields

I spent most of my week end refining the rendering and tweaking the asteroid fields.

Ring lighting

I introduced lighting of the rings ( yeah, it was missing in the previous update ). My natural approach was to compute a standard diffuse lighting term ( N^L with N being the ring normal, and L the sun direction ) and to add a bit of ambient on the unlit side of the ring, but to my surprise it didn't seem to work that way in reality. Apparently, the rings can range from very dark to very lit when seen from their unlit side, depending on the thickness of the ring. So instead, my lighting uses this formula:

float color = pow(gl_Color.x, 1.0 + (1.0 - diffuse.w) * 3.0);


With gl_Color.x being the vertex-to-sun angle ( ranging from 0.0, for unlit angle, to 1.0 for totally lit angle ), and diffuse.w being the opacity, taken from the ring texture.

Another aspect of ring lighting is that I didn't want to render the ring geometry twice with backface culling, but only once without backface culling; so depending on where the camera is, relative to the ring plane, the coefficient for lighting is adjusted ( typically, coef = +- N^L, with +- being the sign of the distance from the camera to the plane ).



Ring texturing

I was previously using a static texture ( Saturn's, to be more precise ). The ring texture is now procedurally generated. Nothing very advanced technically: a set of 3 main colors are chosen, and given some probabilities. Then, bands of colors are added together in the ring texture ( for the opacity in the alpha channel, they can be removed too ). The algorithm is running in 3 passes where the width of those bands of colors are varying.



Dust lighting

The dust particles are now looking up the correct color in the ring texture, so the texture and the dust particles all match together. I've also introduced alpha-blending for them, which makes them look much nicer than raw points. They are also fading in/out with distance instead of popping up suddenly.



Shadowing

Remember, the planet is still missing in the screenshots ( I can't add it before fixing some issues with the cascading Z frustums, to allow for correct Z-Buffer sorting ).

The shadowing of the planet is computed in the pixel shader by finding the distance between the pixel and the line passing through the planet center, with the sun direction. If this distance is lower than the planet radius, the pixel is in shadow.

The penumbra is also calculated ( at the moment with a constant, but later, will match the average thickness of the atmosphere ).



Precision issues

Last but not least, I had to fix many precision issues ( 64-bits coordinates are required to place objects at tens of AUs from the scene origin ), and render some effects such as the dust in camera space.

Besides impostors and minor bug fixes, I'm pretty much done with rings and asteroids fields.

Comments: 6 - Leave a Comment

Link



Sunday, July 15, 2007
Shadowing

I spent a week or two playing with a new shadowing algorithm, ie. the infamous trapezoidal shadow maps. I'll keep it short: it's an improvement over light-space shadow maps, but I'm still not happy with this variable resolution ( when the camera is looking in the light direction, or in the opposite direction ), resolution degenerates to standard shadow maps, and eveyrthing gets blurry ( plus it increases shadow acne ). So far, it is however the best shadowing solution I've explored.

I still have to experiment parallel-split shadow maps. They're quite similar to cascaded shadow maps in philosophy, so compared to trapezoidal shadow maps, I'm expecting:
- a worst best case (in other words, the nice sharp shadow that I have with trapezoidal shadow maps will look worse with parallel-split shadow maps)
- a best worst case (in other words, the horrible degenerated case of TSM will not happen with PSSM). Quality will be best balanced.
- in average, quality will be a bit lower with PSSM than TSM.
- performance wise, they'll be similar, but I might have to decrease the maximum shadowing range.

Frequently asked question

When will the engine be complete ? When will you start working on the game ?

The engine will never be complete. It'll be expanded, optimized and new modules added in the coming years. I can't say at a specific date: "the engine is complete!".

As for when I'll start working on the game, it's also an ambiguous question. The game is composed of thousands of tasks, some which are low-level, some which are higher level of abstraction. For example, the XML file describing how spaceships are assembled is definately not part of the engine. But although it's part of the game, it's still a very technical thing. So if we include this technical work, the answer to the question is: work on the game has started months, if not a good year ago. After all, some code of the ICP is getting reused in the game, so you could say that as soon as I started to work on the ICP, I started on the game.

But I have a feeling that people who ask when I'll start working on the game have in mind the following question: "When will you implement gameplay features ?" such as trading, A.I., going in stations / cities, etc.. In that case, it's not likely that I'll start on that part before end 2007, as there are tons of technical issues ( data structures, algorithms, databases ) related to the game that need to be set up first.

Procedural asteroid fields ( aka gas giant's rings )

In the past two weeks I've been working on procedural asteroid fields. I've recorded a new video ( see link below ). Don't expect anything fancy in the rendering area: it's just per-vertex lighting with a diffuse texture. The gas giant planet is missing too, at the center of the rings.

The asteroid field system is based on a combination of many elements, which are:

Ring geometry

The ring is composed of a disc of quads. Nothing special here, except that tesselation is dynamically adapted based on the distance to the camera ( similar to level-of-detail ). When the camera is on the rings, the geometry weights around 6500 triangles. When the camera is far away, it can decrease to no more than a thousand.





Ring noise

At a closer distance, some noise starts to appear on the rings. This is to simulate the thin dust composing the rings. In the same time, dust points get procedurally spawned, giving a parallax effect.



Asteroids meshes

Asteroids are not procedurally generated, only procedurally placed. There are 10 types of asteroid meshes. They are textured with a single diffuse map, but we found that setting the texture coordinates correctly to avoid seams was impossible ( and a real pain to get just "good enough" ). So instead, I came up with a technique used by NVidia in their "floating cave" demo, which avoid seams in texture coordinates. Basically, the asteroid is planar-mapped from 3 directions ( X Y and Z ); then, depending on the triangle normals, 3 weights are generated. The diffuse texture is then sampled 3 times and the weights are used to blend the 3 samples together.

Another problem with asteroids was that they became blurry up close. Increasing texture coordinates would virtually increase the resolution, but patterns would appear. Instead I've experimented a noise texture ( actually, 2 levels of noise textures ) that is modulating the diffuse color. Of course, it also requires to be sampled 3 times to avoid seams..

Procedural asteroids placement

The whole algorithm is based on an octree. A the moment, the ring has a diameter of 300,000 Km, and the octree a depth of 14 levels.

When the octree gets split into new children, depending on the depth level of the new node, asteroids of a certain size get spawned. For example, at level 10, asteroids that are Km-sized are generated, while at level 14, asteroids that are 50 to 100m only are generated. This ensures that when asteroids pop up on screen, their size on screen is not too large.

Each asteroid is assigned a unique ID that will be used in gameplay code later ( for example for mining ). Unique IDs are a real problem, as they are currently encoded on a 64-bits integer. You'd think 64 bits is more than enough, but there can be hundreds ( if not thousands ) of asteroids generated per octree node, with a depth of 14, the number of combinations grow exponentially.

Thanks to the unique IDs, all the code that generates asteroid attributes ( such as their type, position, orientation, speed, etc.. ) is replicable ( ie. it's not really random, as the same asteroid ID will end up with the exact same attributes each time it gets generated ). In other words, you can zoom out a million kilometers away and come back at the same place, the asteroid will be at the same place ( assuming it was motionless ) and look the same. It's important especially in a multiplayer context, as two different players need to see the same thing on screen, and transfering all those asteroid attributes from the server to the client would saturate bandwidth ( there are thousands of asteroids visible on screen ) quickly.





Asteroids also rotate and follow an elliptical orbit, which is randomized, giving an impression of chaos when you're inside the asteroid field.

Performance

Performance wasn't very good at first, especially when you were starting to move inside the field. The reason for that is that when asteroids are spawned, a new object must be added to the scene graph. When you're moving fast, thousands of objects must be added ( and in the opposite direction of the movement, removed ) to the scene graph. It really stresses the CPU.

I implemented a spawn queue to maintain a good performance. The algorithm is given a maximum amount of time ( around 5 milliseconds at the moment ) during which it tries to spawn as many asteroids objects as possible. The procedural algorithm fills this queue with new requests in a FIFO order.

Densities

Another aspect of the procedural asteroids generation are the spawn probabilities, related to the ring density. The ring has a small thickness ( currently of around 10 Km, although it's not a sharp thing ). The chance that any asteroid spawns above or under this 10-Km thickness is very low ( on my experiments, the most extreme case I've found is a huge asteroid that spawned 200 Km above from the ring plane ).

The ring density is taken from the ring texture ( at the moment, Saturn ring's texture ). The alpha of this texture contains a density value ranging from 0 to 1. It's used to change the probability that an asteroid should be spawned based on its position in the rings. In other words, if there are black spaces in the ring texture, asteroids will not get spawned there ( or at a lower probability ).

See this image, taken between two ring features:



Future work:

System belts are tricky because of the 64-bits UID limit. Exceeding this limit might be hard technically, and require all sorts of hacks. A better way to handle it would be to keep the 14 octree depth level, but since system belts are millions of times wider than a gas giant's ring, that means asteroids would be so sparse that they'be almost impossible to find. I'll continue to experiment.

Impostors: there is at the moment a distance at which asteroids are rendered as dots, and closer to that distance, get replaced by a real object. Instead of rendering dots, I plan to use an impostors system. I'm not sure if I'll do that in the coming weeks, or if I'll delay in many months. The popping of asteroids when they go from a dot to a real object isn't too horrible.

Collisions: there are currently no asteroids collisions, they just intersect each other. Ideally I'd detect collisions, play an explosion effect, and remove the two colliding asteroids ( or if a small one hits a big one, remove the small one only ). I'd have to keep a list of UIDs of destroyed asteroids, and check those IDs out each time asteroids are spawned. This might cause performance problem if the number of destroyed asteroids isn't kept under control.

Video:

Asteroid field, 16 MB Divx 5 ( low quality )


Comments: 11 - Leave a Comment

Link


All times are ET (US)

 
S
M
T
W
T
F
S
1
2
3
4
5
6
7
8
9
10
11
12
13
14
16
17
18
19
20
21
22
24
25
26
27
28
29
30
31

OPTIONS
Track this Journal

 RSS 

ARCHIVES
October, 2009
August, 2009
July, 2009
May, 2009
April, 2009
March, 2009
February, 2009
January, 2009
November, 2008
October, 2008
July, 2008
June, 2008
May, 2008
April, 2008
March, 2008
January, 2008
December, 2007
November, 2007
October, 2007
September, 2007
August, 2007
July, 2007
June, 2007
May, 2007
April, 2007
March, 2007
February, 2007
January, 2007
December, 2006
November, 2006
October, 2006
September, 2006
August, 2006
July, 2006
June, 2006
May, 2006
April, 2006
March, 2006
February, 2006
January, 2006
December, 2005
November, 2005
October, 2005
September, 2005
August, 2005
July, 2005
June, 2005
May, 2005
April, 2005
March, 2005
February, 2005
January, 2005
December, 2004
October, 2004
September, 2004
August, 2004