Lighting/Renderworld question
Blitz3D Forums/Blitz3D Programming/Lighting/Renderworld question
| ||
Hi there. So, I have a planet that is not really as big as it looks; to keep it within the default 1-1000 unit camera range, I've reduced it in size and use EntityOrder to put it in front of the skybox and behind the space ships. So far, so good. The problem is, it reflects the light coming from the exploding ships, which, while cool looking, is highly inaccurate. I have discovered that I can actually make the planet full size (I mean, actual size as in 1 meter/blitz unit!) if I want, and adjust the camera range accordingly. This would require three separate renders; one for the skybox, one for the planet, and one for everything else. Or, I can leave the planet where it is and not bother with the camera range, and just turn off the explosion lights during the planet render. Still multiple renders, just a different trick being employed. A. Which of these is better, or will actually work? B. Is there another option I haven't though of? Here is the newest demo. You'll see the planet is much improved with more colors and general richness. Press Enter to generate a new one. Thanks! |
| ||
Set the planet to use the FullBright and Vertex-Color FXs, then light your planet manually*. * You can try LightMesh, but I think setting each vertice's colors manually with some algorithm of your choice may look better, as you might be able to use some coloring effects in your code (according to the sun's position etc.). Note doing this should be very slow, so you'd light the planet as soon as you created it, then you'd leave it colored like that. |
| ||
Thanks for the response. I should mention that the planet rotates, so it needs to reflect the sunlight naturally. Fullbright would prevent that. I like where your head is at, though! (Actually it rotates unusually fast currently so I can see all of it. Forgot to mention that. Normally it's slower) |
| ||
Sure, off the top of my head: try layering meshes, all full-bright but educatedly colored.![]() Your original planet (#2), with a dark overlay mesh (#1) and highlight overlay mesh (#3). The dark and light overlay meshes should have the Multiply and Add EntityBlend values respectively (default entityblend mode is Alpha, and it wouldn't work for this effect). You can smoothly fade part of these overlay meshes with vertex-alpha, since they'll be full-bright and won't be receiving light. The idea is that the original planet spins normally, but these overlay meshes blend whatever detail passes through them. |
| ||
You can also use multiple rendering pass if you set the ClsMode of the camera and use clever pivots It's as fast as only one renderworld (or almost as fast) ------------------------------------------ - how to : ------------------------------------------ If we don't clear the Color buffer, the pixels remains (which is actually the desired effet) but the take care to clear the depth buffer ! else you 'll have some undesired entities from Far space drawn front of some objects on earth (it's due to the pixel compare function that compares a "depth" which actually is not the "real" depth, but the depth according to the camera range. for ex : a cube at 10 meters from camera -> Depth = 10/1.0 = 10 a planet at 5 000 000 from camera : 5 000 000 / 1000 000 = 5 the planet is front.) So, Clear the depth buffer on each rendering pass ! ------------------------------------------ Then, the process : + create a pivot for each "degree" of rendering (space-sky-earth-[micro?]) + use some const to deal with the scales (and remember that, even if we can use large float number, the precision will be lost at some range (probably a very big range, but anyway)) + when you create something, attach it to the good pivot (a tree is parented to earth, a planet is parented to the space, a cloud is parented to the sky ...etc ...) for rendering : 1 - Hide all layer's pivots and show the space's one -> Set the clsmode to clear everything (as it's the first rendering, it needs to clear the previous frame) -> render the world 2 - hide everything but the next step pivot (in this case, it's the sky pivot) -> set clsmode to clear the depth buffer but not the color buffer -> render the world 3 - hide everything [.....] etc ... (same as the second pass with the next pivot) 4- .... do the same for each rendering depth you need. [EDIT] A small SDK to create render pass (I added a funny Inverse fog on the really neay range, that fake ambient oclusion of the "player" when near from the cube or anything) And a more colorfull sky using the vertex color of the mesh |
| ||
I'd seriously reccomend using something like Bobysait suggested rather than trying to hack it up by other methods. Depending on how your world is setup you can either hide/show groups for the rendering or use a small section outside of the main world and render a camera from there first then do a second render without clearing the color buffer from where the actual player's eye is. |
| ||
Axel Wheeler: Search the forums for a program called "planet creator". I believe it is open source and is written in BlitzMax + miniB3D (Blitz3D). could have what you are looking for.. |
| ||
You guys are awesome! I work weekends and don't have time to digest this right now, but hopefully I'll get a chance in the morning... Thanks all! |
| ||
@Bobysait: how would you work out letting the player\ships come near those planets, or even enter their atmostphere, land etc? |
| ||
At the moment they are reaaaaally far from the planet, I don't think Axel was trying to make them landing. The method here is just to separate the different background at different scale. If you want a ship to land on a planet, then it means the planet is not that far, but its size would be so large when the ship will come close to the planet, that the float won't enable a good precision for this kind of thing unless you rescale the planet to something descent, but inappropriate for a "planet" So maybe, if we want this kind of thing, you need a Spore-like system. -> the zoom out effect when you live a planet and come to a universe scaling. Everything is just resized. I'm testing a system where the global pivots are suitable for this kind of purpose. I'll post it soon. |
| ||
Salut Boby ) JP972 |
| ||
how would you work out letting the player\ships come near those planets, or even enter their atmostphere, land etc? I like the Eve-Online method for this. Adjusting scale factors depending on the precision required. While in orbit and around a few thousand kilometres from the planet, the planet and maybe its moons can be "attached" to the Skybox as described in this thread - yet when approaching the planet, the scale is altered and LOD changes reflect this: The Planet and (Moons?) become Meshes, the Star may be attached to the Skybox. Small MESH Objects still in orbit can be freed, but if they still need referencing, stick a Sprite (or flat quad) if they still need to be visible, or just a Pivot to the relevant Skybox position. Clouds/atmosphere etc. can be realised. By committing these changes through careful use of Hiding then Freeing entities and 'Loading' then Showing (or Swapping) the entities this can be achieved smoothly and, even masked (as with Eve) via the use of a "Warp Drive" effect so it's not so obvious as things are popping into and out of existance. With the descent to a planet's surface, this 'masking effect' can be achieved with something like atmospheric burn-up or 'ploughing through cloud layers' provided of course that the planet has an atmosphere. Regardless of the approach, it's pretty unfeasible to have a consistent and comprehensive single-scaled planetary system. Just modelling the Earth, Moon and Sun to scales of size and distance can stretch the floating point arithmetic and rendering capabilities. Every space game or simulation in existence has always had a procedure for either altering scale or occluding via "rooms" (consider X games where each 'sector' in the universe had to be reached via a "gate" - effectively the same as a door between adjacent rooms which allowed specific point-to-point travel with no visibility through) |
| ||
Ok I can update you on this: Based on Bobysait's comment I basically went with a modified form of my first option; that is, the spinning planet is full size and distance and is rendered in the same Renderworld as the skybox, but it's entity order is later (closer) so one render takes care of skybox, planet, and stars (which are EntityCopies of the same quad set to different colors). The second render is standard 1-1000 range and takes care of everything that travels. This is working fine so far. This is most similar to Bobysait's solution except that he suggests using a system to hide the near entities during the far render and vice versa. This would be a burden since near objects also include things like fragments of broken ships and particles of various kinds (bullets, etc.). Add to this the fact that I am sometimes parenting and unparenting the various objects to other things during a given frame, so there is overhead in making sure everything ends up parented to a "hideme" pivot for rendering purposes. Doable, of course, but I wondered what the time saved would really be. I wrote a test. Long story short, it turns out that hiding the entities would save a little time, but most of the time saved is due to them being out of sight (i.e. in front of the camera range). I guess the difference is because if they are hidden the system dismisses them faster than having to calculate their distance and do a test. So the lesson is, if I scale up the number of nearby objects, I should consider hiding them during the far render to save a bit of extra time. (Of course there's no need to hide the far objects during the near render; there aren't enough of them to make a noticeable time difference.) |
| ||
The stuff behind the "global pivots" is a bit more complicated. When you call "renderworld", the entities are drawn according to the hierarchy. Just imagine that blitz use a kind of Linked-List for the "root" entities, and all the other entities are accessibles only with the hierarchy relative to those roots. so when the renderworld is called, it first loops the Root-entities and for each root, it performs a simple "If Show=true Then render children" if we made this in blitz it would/could(/should?) looks like this Type Entity field bbEntity ; the blitz entity field nextentity.Entity ; the next entity in the hierarchy (the next "child") field preventity.Entity ; the previous (for doubly-linked list) field parent.Entity ; the parent ^^ field firstchild.Entity ; the first child of this entity field lastchild.Entity ; and the last one. field Mat.Matrix ; the global 4*3 matrix (blitz3d use more than just a 4*3 matrix, it can be seen in the memory, where we find offsets for quaternions, position, scale, origin etc ... but let's simplify this with a single 4*3 matrix) field show ; a boolean value true/false (des/activated with Hide/ShowEntity) field .... all the entity stuff (class, flags, associated/derived objects etc ...) End type Type RootEntity Field entity.Entity End Type Type Camera Field entity.Entity Field frustum.Frustum Field ProjMat.Matrix Field ModelViewMat.Matrix End type Function RenderWorld() For camera= Each Camera if camera\Projmode>0 if camera\show=true For Root = Each RootEntity RenderEntity Root\Entity, Camera Next endif endif Next End Function Function RenderEntity(entity.Entity,camera.Camera) If Entity\Show=false then Return ; Else performs a frustum test with the bounding box if the entity is a "renderable" class Select EntityClass(entity\bbEntity) case "Mesh" If EntityInFrustum(entity,camera\Frustum) RenderMesh(entity) Endif case "Terrain" If EntityInFrustum(entity,camera\Frustum) RenderTerrain(entity) Endif case "Sprite", .... If EntityInFrustum(entity,camera\Frustum) RenderSprite(entity) Endif End Select ; finally, call the renderentity on each child (recursively) child = entity\firstChild while child<>null RenderEntity(child,camera) child=child\nextentity wend End function So, when you have a simple pivot containing all entities for a layer (like the background vs foreground layers), the renderworld will only perform one : "If Backgroundpivot\show = false then Return" (it's not exactly what is involved, but it's almost the same) When you don't hide the "root pivot", the renderworld will perform the "If Show = true/False" and as it is not hidden, it will check for each children (recursively) the frustum check ("EntityInView Test") and some other internal stuff Then, if you manage a lot of entities (like sprites for fake-stars or things like this) on a layer, then, just think you'll render the layer twice Of course, if there is only two planets (less than 10 entities) it saves ... 0.001 ms (?) which is not noticable ... One other point to check is that, some machines are lower on rendering lots of triangles as it really depends on both cpu AND gpu - with a good cpu and bad graphics card, rendering many entities won't be a big deal unless each entities is made of lots of polygons : and as you ask the graphics card to render them twice it will be twice lower. - with a bad cpu and a good graphics card, you can go for two or three or more renderworld without problems, but the framerate will decrease with more entities. So, in both cases, hiding the pivot you don't nead to render on the current rendering pass will prevent users with low cpu or low gpu (or both) from drastic slowdown. and of course, it's required only if you envisage to broadcast your app/game(s) Hope it's not too confused, but I think this post can maybe help people to understand what is involved in almost graphics engines based on hierarchy and then why some codes are slow or not depending on the computers that run them |
| ||
Yes, Bobysait, that is extremely useful information. Thanks! |