SH implementation in a large environment

Started by
11 comments, last by Wicked Ewok 19 years, 10 months ago
I'm trying to implement Spherical Harmonics into an existing game engine. The trouble I am having is finding a good way to divide the world up to calculate SH weights. In demos, you see SH being encoded for entire scenes which consist of 3-4 objects at most. But with an actual game, your environment will consist of up to several thousand objects. Low frequency SH approximations will not be able to adequately handle the lighting solutions of such scenes. Therefore it seems proper to break the scene up into smaller segments. The problem is how you can make sure that the segments you break them up into can still be efficiently rendered. One solution might be to determine a solution for each object in its own little quadrant of the world. For each object, several other objects will affect it, and you include these potential effectors in the SH calculation for that object. One problem with this is that you have to load different SH solutions for each object in the world. My concern is that it might slow things down tremendously. Also, a certain object, say the size of a building, may have thousands of effectors because it spans over a large set of lights and smaller objects. One would probably have to break larger blocks into smaller segments. Another attempt at a solution might be to divide the world into sectors. But this time, you would have to deal with the borders around sectors, and those very large objects that extend several sectors. Any ideas on how to attack this problem? I'm all ears. Thanks! -Marv [edited by - Wicked Ewok on May 19, 2004 7:47:24 PM]
-=~''^''~=-.,_Wicked_,.-=~''^''~=-
Advertisement
I''m no expert in, nor huge fan of sh, but I ran some experiments on a small test level model, using the new dx9sdk beta 3 recently.

It''s a 32x32 meter world, with dense world geometry ( 4 rooms or so with pillars & pits, etc. ). I ran it through the vertex sh calculator sample in the sdk, and it did a pretty good job for a directional light casting fuzzy shadows.

Since lights in my world don''t move, it really didn''t buy me much, but I certainly didn''t have to break the world into smaller pieces for the sake of sh.

I break it into smaller pieces for things like culling, etc.

SimmerD, that''s nice to know. I''m still concerned though, because the world in which I have to implement this can be up to 5 miles x 5miles large, with a several thousand objects for one map already placed in about a 300x300 meter zone. I can try to go ahead and implement it, as I will also be using new D3D Precomputed Radience Transfer(PRT) functions, but using it to replace the existing engine''s lightmap system will be no easy task. I think it might be an issue later on, if not already with the size of the map, that it might either take too long to compile the PRT data or slow down rendering time. Wonders what to do. I read up that ATI had tried solving such a problem. They used what they called ''blockers'' and ''receivers'' flags assigned to various objects. However, it was not clear to me whether these flags were algorithmically set or if you had to place them manually on objects basing it on your own intuition whether an object will effect another or not. They do calculate PRT solutions on a per object basis. I guess it might not be such an issue to have a few thousand objects per object''s solution, because, as you pointed out, your scene ran fine with a dense world geometry. But then, you would reset solution data per object you render, which might take some time?

I''ll try to link the ATI site tomorrow when I''m back at the office.
-=~''^''~=-.,_Wicked_,.-=~''^''~=-
It is difficult to use the current PRT functions of the D3dx with a whole scene, because it is difficult(but not impossible) to extract the coefficients of each object from the buffer into the object''s textures or blend weights.
I asked about that on directx dev mailing list and Ben luna from microsoft said that these functions are completely improved in the new directx, but I don''t have the beta to tell you what changes they made.
Ati made a sample for the x800 that uses these new functions.you can see it on their site.
you cannot calculate the spherical harmonics for one object only, the whole world should be taken, to handle color bleeding between objects, light interreflections, shadowing and so on.
I think they will improve the speed and memory usage also of the PRT functions,as they are very slow and their memory usage is very very high.
not back at the office. I have finals to study for, sigh.

mohamed, yes, I''m using the new summer 2004 version of D3D, and they have scrapped all the old PRT functions in the original SDK and reimplemented a whole new interface for it. I have some faith in that they aren''t ''that'' slow, especially since you pointed out, they were improved since the original SDK version.

one more thing is that the whole world does not necessarily have to be taken to calculate an PRT weight for a mesh, only the objects that are near it or effect it in some way or another. For example, a rock that is occluded by a tree will not be seen to particular objects, and thus can be filtered out of the equation. Because a scene can get so complex, it might be necessary(I still have a strong feeling it really is necessary), to calculate seperate PRT data for each object based on it''s own ''sub-environment'', that is, the environment with objects that actually affect its lighting and color.
-=~''^''~=-.,_Wicked_,.-=~''^''~=-
but this may by difficult specially with specualr or reflecting object which will be affected by the whole world.
also this is dependant on the type of materials you are using.if you are not using emmisive materials this can be ture but using non emmisive materials that have a high emmisive light power (as lava for example) can affect far objects.
also note that objects can be affected by the shadow of far objects.in dome screen shots, the shadow of some comums affect far objects when the light source is near the ground.

Mohammad Adel
Optimize

"If A is a success in life, then A equals X plus Y plus Z. Work is X; Y is play; and Z is keeping your mouth shut". Einstien

[edited by - mohamed adel on May 20, 2004 7:44:58 PM]
I guess it depends on what you mean by ''far''. I agree that several thousand objects might need to be included, but as with most LOD algorithms, objects a mile away usually don''t affect scenes(terrain is the exception), and if bigger buildings would or should show up on an normal environment reflection cubemap, you would not necessarily have to include them for SH because of its inherit low frequency qualities. When a map is in the order of miles x miles, with tens of thousands of objects in an environment, I think you would consider doing PRT on an selective object by object basis.
-=~''^''~=-.,_Wicked_,.-=~''^''~=-
Why not just break whole scene into Octree?
For each vertex in a node of the octree, calculate its coefficients by firing a number of rays from the vertex( Monte Carlo Integration). Octree here is kind of speedup structure which is used to speed up the ray tracing. If a node hit by the rays is far away from the vertex, just ignore it. If not, use intersection test to check if the ray hit any triangles assigned in the node. In this way, u don't need to care about objects.
I don't know any thing about D3D Precomputed Radience Transfer(PRT) functions, I just implement SH lighting on my own.

[edited by - wanzi on May 20, 2004 8:55:06 PM]
The D3D PRT functions take a meshes and computes the weights for those meshes. Using D3D's PRT functions, the problem seems to me, less of an integration problem for calculating the weights(because D3D does that for you automatically) and more of a bandwidth problem after you have calculated the weights. For example, supposed you had 100,000 objects in a scene in which you only view 300 objects at a time(and pretend the complexity of geometry per object is 5k polygons, so that's 150k's worth of polygons). There might not be space to load the entire PRT data(100k objects = 500,000,000 polygons? sheesh )and make it easily GPU accessible. Correct me if I'm wrong here, because I'm still relatively new to this. So what ATI's paper outlined(again, link to follow) was to compute a -complete- lighting solution for each object, taking into account relative objects in the scene(those labeled as receivers are effected by certain effectors). If you did it on a vertex level, you're asking that the entire scene, once again, be one whole mesh, with a single resulting PRT solution. The question is, how now, do I divide the world into objects' local spaces(consisting of only other objects that affect one object) so that I can calculate a complete PRT solution for each object, or is that even the only approach one can take when doing large scale environments using PRT?

The concern for calculating unique PRT solutions for each object in that object's local space is that for each object rendered, you would have to load its PRT data to be GPU accesible, and that might be at the costly expense of performance. And just how would I determine what other objects effect an object? Casting rays out of an object and testing if anything occludes it and if it does, test it's size-distance ratio and see if you have to include it as a potential effector?

[edited by - Wicked Ewok on May 21, 2004 3:44:57 AM]
-=~''^''~=-.,_Wicked_,.-=~''^''~=-
PRT only gives meaningful occlusion & interreflection information if the occluder vs occludee relationship doesn''t change. That means either

a) large-scale shadows where object a occludes object b, and neither animates its shape from the light''s perspective, or moves

or

b) a small-scale self-shadowing term that''s purely local to a vertex neighborhood, and one that wouldn''t be invalidated by an animating mesh. For instance, the mouth interior should be dark pretty much no matter what.

This topic is closed to new replies.

Advertisement