Archived

This topic is now archived and is closed to further replies.

Wicked Ewok

SH implementation in a large environment

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Hi Wicked Ewok!

The problem is not the SH encoding.

The lighting quality problems for complex objects are due to the fundamental assumption of PRT that lighting at point p is a good approximation for lighting at neighboring points. This assumption makes it possible to precompute indirect transfer functions for the object. Another important assumption is that lighting is sampled sparsely near the surface of the object, perhaps only at a single point.

These two assumptions together may produce significant errors in the lighting simulation for complex objects. The solution is to increase the number of points at which lighting is sampled. Best results would be achieved by sampling the lighting for each vertex, but this might be too costly.. :o)

With this in mind, subdividing the world into smaller chunks might seem to improve the quality of the lighting. However, computing separate global illumination solutions ("local GI solutions") for each chunk does not produce correct results, because the transfer due to neighboring chunks remains unaccounted for. In other words, you might see some visual artifacts.

Hope I understood your posts correctly.

-- Jani

Share this post


Link to post
Share on other sites
SimmerD - yes, that's why we're using this to replace our static lightmap system(where lights and objects couldn't move), except now, the lights will be able to move.

Scytheman, yeah, I can imagine having some very bad errors if you calculated by chunks. But how about for each object, find all the major influencing objects using some heuristic and create PRT data for that object's heuristically calculated local space. The errors would be minimal as all objects that majorly affect the object whose PRT data is being calculated is included.

Again the problem is figuring out a good solution to calculate PRT data in a huge world, with both memory and performance constraints.

here's the ATI link that describes using receivers and blockers:
http://www.gdconf.com/archives/2004/oat_chris.pdf



[edited by - Wicked Ewok on May 25, 2004 5:55:25 PM]

Share this post


Link to post
Share on other sites
Hello again Wicked!

Yes, the ATI demo makes the compromise of treating some surfaces as receivers and others blockers. This is probably the best available solution to enable PRT lighting in arbitrary environments at the cost of reduced lighting simulation quality.

It does look good, though! And that''s what matters most.

Yeah, you could try devising a heuristic for this receiver-blocker classification or let the level designer assign these roles to objects. I must say I haven''t put much thought on how to use PRT in a game engine yet, but this is interesting stuff.

I suspect the most versatile and efficient engine combines PRT with other existing techniques like shadow maps/volumes. For example, rendering shadows of dynamic objects using PRT''s neighborhood transfer isn''t problem-free as far as I know.

-- Jani

Share this post


Link to post
Share on other sites