Jump to content

  • Log In with Google      Sign In   
  • Create Account

Awesome job so far everyone! Please give us your feedback on how our article efforts are going. We still need more finished articles for our May contest theme: Remake the Classics

jcabeleira

Member Since 24 Sep 2003
Offline Last Active Yesterday, 07:56 AM
*****

#5061884 Results on Voxel Cone Tracing - Part 2

Posted by jcabeleira on 14 May 2013 - 03:39 PM

Hello, guys. Please forgive me for the shameless self promotion, I'd just like to share and discuss the results I got with my Voxel Cone Tracing implementation. So, in my last post I presented an early version of my own implementation of global illumination using voxel cone tracing, since then I've done a lot of improvements and ended up creating a demo that you can find here to show it. Very soon I'll be writing a set of articles explaining the implementation in more detail but for now I'll outline the most important aspects:

 

My implementation uses two 128x128x128 3D textures to store the voxelized scene, a small texture and a larger one, where the small one covers a 30x30x30m volume of the scene while the larger one covers a 120x120x120m volume. Together they provide a voxelized representation of the scene with enough quality and range for the GI processing. The volumes are fixed at the world origin, they do not follow the camera because that makes the lighting unstable, I know this  is impractical for a video game but it's enough to cover the smalll scene of my demo.

No Sparse Voxel Octree is used, this is because I concluded from my early experiments that traversing the tree takes a huge toll on performance probably because the divergent code paths and incoherent memory accesses are not very GPU friendly. So, In general volume textures seem to provide much better performance that octrees at the expense of huge memory waste (because of empty voxels). I haven't profiled one method against the other, my choice was based simply on experiments so please feel free to argue against these arguments and provide your own insight on the subject.

 

The scene is voxelized in real-time using a similar version of the technique described by Cyrril Crassin in the free OpenGL Insights chapter that is available here. The voxelization is quite fast and can be performed in real-time without a great impact on performance which allows to make the lighting dynamic, if any object or light source moves you'll see the lighting change accordingly.

Once the voxel volume is ready it is possible to simulate a second bounce of GI by revoxelizing the scene to a second volume while using the first volume to perform cone tracing for each fragment that is inserted into the volume. Note however that this is very expensive and doesn't compensate the reduced improvement in visual quality so it's disabled by default in the demo.

 

The diffuse lighting is calculated in groups of 3x3 pixels to improve the performance and a edge refinement is done later to fix the difficult cases. For each group of 3x3 pixels 16 cones are traced in all directions with 32 samples per cone. The tracing of each cone is done pretty much like Crassin describes in his paper, for each sample inside the cone we read the corresponding mipmap level of the volume texture and accumulate both the color and the opacity of the voxel information that was read.

 

The specular lighting is calculated by tracing a cone along the reflection vector. Voxel cone tracing gives the flexibility to generate sharp and glossy reflections which is really neat. In general both look good but the lack of resolution of the voxel volume prevents the accurate rendering of glass and mirror materials. Sharp reflections are problematic also because they require an insane amount of samples per cone (200 in the demo) to avoid missing scene features like thin walls. The tracing is optimized to skip large portions of empty space by sampling a lower resolution mipmap level of the voxel volume and checking its opacity (similar to sphere tracing), if the opacity is zero then there are no objects nearby and we can skip that space altogether. This is essentially an GPU friendly approximation of what is done with a Sparse Voxel Octree.

 

So this concludes the overview of the implementation. Please feel free to leave your comments.

 

Don't forget to try the demo (I recommend running it on a Nvidia GTX 680 or similar, it's untested for AMD hardware so I have now idea how it runs on it).

 

Here is some eye candy :

 

 

SerenityRevisited1.jpgSerenityRevisited3.jpgSerenityRevisited2.jpg




#5049875 Deferred Ambient Light via CubeMap, Edge Artefacts

Posted by jcabeleira on 04 April 2013 - 03:40 AM

That happens because of the mipmapping and the lack of correct derivatives. In forward rendering pixels are processed in 2x2 groups, even if some of the pixels don't fall inside the primitve they are still processed as if they were just to provide you with the screen space derivatives that you need to perform mipmapping.

In deferred rendering you haven't such derivatives, you're processing pixels in 2x2 groups but you're reading your data from a buffer so at the edges of objects some pixels may fall inside of a different primitive than the one you'd expect.

 

The simplest solution for that is to disable the mipmapping for that texture or supply your g-buffer with the screen space derivatives and use them when sampling from the texture.




#5034616 IslandWorld

Posted by jcabeleira on 20 February 2013 - 11:04 AM

Your images look quite noisy, do you have mipmapping enabled?

 

Other than that, nice work! Keep it up.




#5014277 Voxel Cone Tracing, more drama

Posted by jcabeleira on 25 December 2012 - 05:43 PM

Probably I should do it manually, because when simply calling "glGenerateMipmap( GL_TEXTURE_3D )", the framerate dies directly. Instead I could loop through all mipmap levels, and re-inject all voxels for each level. Injecting is more costly, but there are way less voxels than pixels in a 128^3 texture (times 6, and 2 or 3 grids).

 

Yeah, I can confirm that glGenerateMipmap(GL_TEXTURE_3D) kills the framerate, not sure why but it seems the driver performs the mipmapping on the CPU.

I think the best alternative is to simply create a shader that computes each mipmap level based on the previous one because it runs fast and is fairly easy to do. Re-injecting the voxels into each mipmap level as you suggest seems overkill and may not give you the desired results because you need the information about the empty voxels of the previous mipmap level to obtain partially transparent voxels on the new level. Are you doing this?

 

I should be averaging, eventually by summing up the amount of voxels being inserted in a particular cell (thus additive blend first, then divide through its value). But there is a catch, the values are spread over 6 directional textures, so it could happen you only insert half the occlusion of a voxel into a cell for a particular side. How to average that?

 

Yeah, averaging is the right thing to do. Regarding the directional textures, you should propably average them as usual too. Just ensure you don't increment the counter when the voxel does not contribute for the radiance (when the weight of the voxel for that particular directional texture is <= 0.0).

 

PS: Merry Christmas to you too and to everyone else reading this ;D




#5013805 Voxel Cone Tracing, more drama

Posted by jcabeleira on 23 December 2012 - 06:49 PM

If I may ask, how do your textures cover the world (texture count, resolution, cubic cm coverage per pixel)? I suppose you use a cascaded approach like they do in LPV, thus having multiple sized textures following the camera. Do you really mipmap anything, or just interpolate between the multiple textures?

The biggest limitation of my implementation is precisely the world coverage which is currently very limited. I'm using a 128x128x128 volume represented by six 3D textures (6 textures for the anisotropic voxel representation that Crassin uses) that covers an area of 30x30x30 meters.
I'm planning on implementing the cascaded approach very soon which should only require small changes to the cone tracing algorithm. Essentially, when the cone exits the smaller volume it should start sampling immediately from the bigger volume, I think it's not necessary to interpolate between the two volumes when moving from one volume to the other, in particular for the diffuse GI effect which tends to smooth everything out, but if somekind of seam or artifacts appears then an interpolation scheme like the one used for LPVs can be used for this too.

Anyhow, you said your solution didn't show banding errors. How did you manage that? Even with more steps and only using the finest mipmap level (which is smooth as you can see in the shots above), banding keeps occuring beceause of the sampling coordinate offsets.

I didn't have to do anything, the only banding I get is in the specular reflection which is smooth as seen in the UE4 screenshot I showed you. For the diffuse GI you shouldn't get any banding whatsoever because the tracing with wide cone angles smooths everything out.
What do you mean with the banding being caused by the sampling coordinate offsets?

>> The red carpet receives some reflected light from the object in the center
True, but would that really result in that much light? Maybe my math is wrong, but each pixel in my case launches 9 rays, and the result is the average of them. In this particular scenario, the carpet further away may only hit the object with 1 or 2 rays, while the carpet beneath is hits it much more times. In my case the distant carpet would probably either be too dark, or the carpet below the object too bright. In the shot the light spreads more equally (realistically) though.

Now that you mention it, probably it shouldn't receive that much light. From what I've seen from my implementation, the light bleeding with VCT tends to be a bit excessive probably because no distance attenuation is applied to the cone tracing (another thing for my TODO list). I'm not sure if UE4 uses distance attenuation or not, their GDC presention doesn't mention anything about it and I believe Crassin's paper doesn't either. That's definitely something that we should investigate.

Probably Unreal4 GI lighting solution isn't purely VCT indeed, but all in all, it seems to be good enough for true realtime graphics. One of the ideas I have is to make a 2 bounce system. Sure, my computer is too slow to even do 1 bounce properly, but I could make a quality setting that toggles between 0, 1 or 2 realtime bounces. In case I only pick 1, the first bounce is baked (using the static lights only) into the geometry. Not 100% realtime then, but hence none of the solutions in nowadays games are. A supercomputer could eventually toggle to 2 realtime bounces.

A few days ago I implemented a 2 bounce VCT by voxelizing the scene once with direct lighting and then voxelizing the scene again with direct lighting and diffuse GI (generated by tracing the first voxel volume). The results are similar to the single bounce GI with the difference that surfaces that were previously too dark because they couldn't receive bounced light are now properly lit thus resulting in a more uniform lighting.


#5013119 Voxel Cone Tracing, more drama

Posted by jcabeleira on 21 December 2012 - 08:11 AM

Let's walk through the issues. But first, there might be bugs in my implementation that contribute to these errors. Then again, ALL raymarch / 3D-texture related techniques I tried so far are showing the same problems, not VCT in particular. So maybe I'm always making the same mistakes.

 

 

Then you must be doing something wrong, I have an implementation working with 3D textures that gives flawless results for the diffuse GI (smooth and reallistic lighting, no artifacts nor banding).

 

 

1- Light doesn't spread that far
In Tower22, the environments are often narrow corridors. If you shine a light there, the opposite wall, floor or ceiling would catch light, making an "area" around a spotlight. But that's pretty much it. Not that I expect too much from a single bounce, but in Unreal4, the area is noticably affected by incoming light. Even if it's just a narrow beam falling through a ceiling gap. The light gradually fades in or not, nost just pops in a messy way on surfaces that suddenly catch a piece of light.

 

 

Try to remove the opacity calculation from the cone tracing and see if the light spreads further. I'm saying this because I've seen the voxel opacity causing too much blocking of the light and cause some of the simptoms you describe. In your case the light has to go through corridors which is problematic because in the mipmapped representation of the scene the opacity of the walls is propagated to the empty spaces of the corridor thus causing unwanted occlusion.

 

 

 

Assuming the light only comes from the topleft corner, then how does the shadowed parts of the red-carpet compute light if they only use 1 bounce?? The first bounce would fire the light back into the air, explaining the ceiling, spheres and walls receiving some "red" from the carpet. But the floor itself should remain black mostly.

 

 

The red carpet receives some reflected light from the object in the center of the room which is directly lit from the sun.

 

 

This has to do with mipmapping problems, see picture. The higher mipmapped levels aren't always smoothed, making them look MineCrafted. This is because when I sample from the brick corners in their child nodes, those locations may not be filled by geometry at that exact location (thus black pixels). Ifso, the
mipmapper samples from the brick center instead to prevent the result turning black. Well, difficult story.

 

 

You'll need to have your mipmapping working perfectly for the technique to work, taking shortcuts like this will hurt the quality badly. Make sure the octree mipmmapping gives the same results as a mipmapped 3D texture. 

 

 

My previous post explained it with pictures pretty well, and the conclusion was that you will always have banding errors more or less. Unless doing truly crazy tricks. In fact, user Jcabeleira showed me a picture of Unreal4 banding artifacts. However, those bands looked way less horrible than mines. Is it because they apply very strong blurring afterwards? I think their initial input already looks smoother. Also in the Crassin video, the glossy reflections look pretty smooth. Probably he uses a finer octree, more rays, more steps, and so on. Or is there something else I should know about?

 

 

The banding artifacts from the Unreal 4 demo are smooth because their mipmapping is good, I'm convinced that most of your problems are caused by the fact that your mipmapping isn't right yet. And yes, Crassing doesn't show the banding probably because he used a high resolution (which is only possible because his test scene is really small).




#5010156 Voxel Cone Tracing, raymarch collision testing problems

Posted by jcabeleira on 13 December 2012 - 05:20 AM

>> I've seen these problems appear in the video of Unreal Engine 4 Elemental demo
In a strange way, that sounds like a relief. If the smart guys over there didn't solve it yet, then I don't have to shame myself hehe. And more important, it indicates with some blurring or other post-enhancements, the artifact is probably not that noticable. At least, I didn't see it when watching that movie.


The artifact is actually very noticeable, but in the video they barely show VCT being used for sharp/glossy reflections which is why you haven't noticed it. In the screenshot bellow taken from their video you can see the smooth banding effect I told you. In general, VCT reflections look like if the reflected objects are made of aligned neon lights, which is why they don't look very good even for glossy reflections.

Posted Image



Doing different averaging when mipmapping isn't easy, at least not in the way how I construct the whole thing. I had to make some crazy workarounds, as OpenCL on my computer doesn't allow to write pixels in a 3D texture.Then again, "vacuum" nodes are sort of ignored, as they don't have an "occlusion" factor either. If in the image above the ray samples on the empty side of a brick, it won't directly stop. However, in order to prevent skipping the wall I should at least take 2 (or 4?) steps inside a node. And maybe increase the occlusion value for "geometry pixels" on higher levels to assure the ray stops in time. Anyone knows if the guys that made the VCT techniques are doing such tricks as well?


If you do a bottom-up approach for the mipmap generation, going from leaf nodes no the root node, you should be able to choose whatever mipmapping scheme you want right?

One other thing I could try -but I'm afraid it leads to other errors- is doing a "inflate" filter: all non-filled brick pixels will copy the color (and maybe occlusion) from their neighbors that actually are filled.


That could avoid missing the walls but it would also make the reflected scene look..well..inflated, which be particularly bad for small objects which would get deformed.

Global Illumination.... argh!

Yeah, man, I feel ya.


#5009832 Voxel Cone Tracing, raymarch collision testing problems

Posted by jcabeleira on 12 December 2012 - 08:21 AM

Hi

Your analysis of the problem is pretty accurate. You'll always get rays leaking through geometry with cone tracing due to the fact that a voxel averages the opacity of the underlying geometry. Moreover, when doing reflections you must ensure that the distance between samples is small enough so that you don't miss the walls and if possible ensure that you hit the center of the voxels to obtain maximum opacity and immediately kill the rest of the ray.

Regarding the banding, you'll always get a banding effect when using cone tracing to render reflections due to the fact that the voxels are not sampled at their center. The problem is that the reflection rays for neighbour pixels will intersect the same voxel at slightly different positions which will yield different opacities depending on the linear interpolation of the texel and give a banding effect. The strange thing is that this banding should be smooth while yours shows harsh transitions.

Unfortunately, none of the above problems is easy to solve. I've seen these problems appear in the video of Unreal Engine 4 Elemental demo so I assume they also suffer from them to some extend. I can also tell you from my experience that in general, glossy and sharp reflections rendered through voxel cone tracing yield poor quality due to these and other limitations.

Regarding the color darkening, you should be careful when creating the mipmaps. Instead of just averaging the voxels you should probably add a weighting factor so that empty voxels are ignored. You may even need to apply a different approach regarding color and opacity, intuitively I'd say that empty voxels should be ignored when calculating the color average to avoid darkening (because empty = black) while for opacity you should take the average of the voxels. Of course, to do this you'd need a custom mipmap creation shader.


#4989256 Unreal 4 voxels

Posted by jcabeleira on 11 October 2012 - 02:49 PM

The indirect light does indeed get shadowed due to the cone tracing, although not perfectly due to the approximations introduced by the voxelizations and the tracing itself. At the SIGGRAPH presentation they mentioned that they were still using SSAO to add some small-scale AO from features that weren't adequately captured by the voxelization, but I think that's a judgement call that you'd have to make for yourself.


The shadowing is better that you may think, it can even be used for direct lighting. A friend of mine has been exploring the use of area lights with voxel cone tracing and has obtained very promising results. He was able to inject area lights into the voxel volume and get very reallistic lighting and soft shadows running perfectly in real-time. The whole thing looked like it was rendered offline even with a modest configuration of cone and sample count.


UE4 still needs AO and deferred ? that´s a pretty curious statement. cone tracing´s second step (the actual cone tracing) should be done from a deferred target otherwise you are risking suiciding your framerate. Secondly, AO is the base effect that cone tracing can achieve, thirdly they have SSAO to complement like MJP says.


They only need SSAO because they're using a small number of cones for the sake of performance. If they decided to use a higher number of cones, from my experiments 16 cones would be enough, they would get the excelent quality AO for free (at the cost of frame rate, of course) for both large and small scale details.


#4982360 Results on Voxel Cone Tracing

Posted by jcabeleira on 21 September 2012 - 07:09 AM

I mean that, there is a white wall, a green wall, and a blue wall occluding green wall. The green wall will be still illuminationg the white wall, but it shouldn't. Because the blue wall is occluding the green wall. Shouldn't you stop tracing at the first intersection you find? Also, you do cone tracing for each pixel, yeah?


Cone tracing voxel mipmaps means you progressively lookat higher and higher level mipmaps. A higher level mipmap stores an occlusion distribution built from child voxels (and not concrete occluders). In his case, I think he's just storing average occlusion for the voxel, and not something that varies by direction/position/etc


jameszhao00, you're right. The voxels of the highest resolution mipmap are either completely opaque or completely transparent. But for the lower resolution voxels they usually are partially transparent due to the averaging of the voxels. Therefore, calculating occlusion is not as simple as looking for the first intersection (i.e. the first fully opaque voxel), when sampling the voxels we need to keep track of the accumulated opacity of all the voxels we have sampled so far. When the accumulated opacity reaches 1.0 we can stop tracing because the next samples would be completely occluded.


#4982080 Results on Voxel Cone Tracing

Posted by jcabeleira on 20 September 2012 - 10:40 AM

Thanks for your replies, guys.

I downloaded the demo on your site, im pretty sure its the same one but I only get a black screen O.o


Sorry to disappoint you but the demo on my site is a bit old and doesn't include these new features. The black screen must be caused by some incompatibility with your graphics card, unfortunately the demo was only tested on an Nvidia GTX 260 so it should work well on any NVidia card above that. Also, make sure you have updated drivers.

How are you choosing your grid bounds?
- Is the voxelization done at runtime? I assume no? ("voxelization is performed on the CPU with raytracing")
- The intersection generated by the +X ray is injected into the -X 3D texture?
- During cone trace, how are you dealing with occlusion?
- "which makes them look displaced from the scene even for glossy reflections." What does this mean? Shouldn't Eye <-> Glossy <-> Diffuse <-> Light work?

Also, is there SSAO in those screenshots?


The grid is fixed at the world origin with dimensions of 30x30x30 meters.
The voxelization can be redone in runtime but it is not real-time. The raytracing takes about 1 second and inserting the points into the volumes is slow as hell taking about 8 seconds. This step is far from optimized because I'm not even using vertex buffers for rendering the points, I'm rendering them with glBegin/glEnd (shame on me, I know). EDIT: i've replaced the point injection with vertex arrays and now it is done instantaneously.
The intersection generated by the +X ray is not necessarly injected into the -X volume. The rays are cast in all 6 directions only to ensure the voxel representation of the scene has no holes. The injection into the 6 destination volumes depends only on the normal of the point which is what represents the direction of the radiance.
Occlusion is dealt by keeping track of the accumulated opacity of all the samples processed for that cone. Think of it as regular transparency blending, where each sample is a semi transparent window that partially occludes the next sample.
The reflections don't look good because the voxel representation of the scene contains only direct lighting. So, what you'll see in the reflection is the scene lit by your light sources but being completely black on the shadows.
Regarding the SSAO, yes I have it. But the cool thing about this technique is that if you use enough cones you don't even need SSAO since the technique provides that effect for free and with much more realism.


#4981735 Results on Voxel Cone Tracing

Posted by jcabeleira on 19 September 2012 - 10:25 AM

Ei, guys!
I'd like to show you guys the results of my attempt on implementing the real-time global illumination used by the Unreal Engine 4 and discuss the results I got.

Here is an overview of the implementation:
  • I do not own a DX11 grade graphics card so my implementation uses simple 3D textures instead of Sparse Voxel Octrees and the voxelization is performed on the CPU with raytracing . For each voxel, the raytracer sends a ray in each axis direction (-X, +X, -Y, +Y, -Z, +Z) with distance clamping to avoid intersecting geometry outside the voxel and stores the color and normal of the intersection point.
  • Six 128x128x128 3D textures are used to represent the anisotropic radiance of the voxel volume, i.e. the radiance that goes in each axis direction (-X, +X, -Y, +Y, -Z, +Z).The points that were calculated before are rendered into these volume textures, their illumination is calculated and they are injected into the 3D textures by weighting their normals against the direction that each of the 3D texture represents thus giving us how much of the lighting goes into each direction.
  • After the 3D textures are created we need to generate their mipmaps so we can perform cone tracing. This step requires a custom mipmapping step that adds the radiance of neighbouring texels instead of averaging becase without it empty voxels wich are black would darken the radiance in the deeper mipmap levels.
  • Once the volumes are ready the GI  is rendered with a full screen pass where 16 uniformly distributed cones are cast. For each cone, 20 samples are taken along it with a fixed distance between samples. For each sample, the sample radius is calculated from the cone angle and the distance to the source point and used to calculate the correspondent mipmap level. The anisotropic radiance is sampled from the 6 volumes and weighted by the cone direction.

Regarding performance, these are my thoughts:
  • Using a fullscreen pass for the GI, with 16 cones per pixel, 20 samples per cone gives an average of 2 FPS on my GTX260 Mobile.
  • Using a configuration similar to the UE4, rendering at 1/3 of the screen resolution (which should be fairly equivalent to their 3x3 interlacing method) with 9 cones per pixel, 20 samples per cone (it is unknown how much samples UE4 uses for each cone) I obtain 10 FPS.
  • It would be interesting to see how this runs on a more powerfull GPU like the GTX680 that it was used on the UE4 presentation
  • I'm also curious to see if a Sparse Voxel Octree would increase or reduce the performance (please share your thoughts on this)

Regarding quality:
  • The overall quality fairly independent on the number of cones. Usually, 9 cones provide acceptable quality while 16 cones provide good quality and 32 is similar to 16 cones while providing subtle fine details.
  • Specular reflections are not that good for two reasons: the low resolution of the volume and the fact that the reflection has no GI, only direct illumination, which makes them look displaced from the scene even for glossy reflections.
  • In certain situation some bleeding shows up on the corners, probably due to the discretization of the scene and low resolution of the volume


The following screenshots were taken with the following configuration: fullscreen resolution, 16 cones per pixel, 40 samples per cone.

Posted Image Posted ImagePosted ImagePosted ImagePosted ImagePosted Image


#4908327 Screen Space Motion Blur artifacts

Posted by jcabeleira on 01 February 2012 - 04:24 AM

What wrapping mode is set for the sampled texture?


Clamp to edge.

What is stored in gl_TexCoord[0].st? The screen coordinates?


Yes, the screen coordinates in the [0, 1] range. These are used to sample the color buffer texture which is a simple 2D texture.

Both the current position and the previous position would need to be divided by their (different) w coordinates in the fragment shader. I don't see that.


I already know the current screen space position of the pixel, it's simply gl_TexCoord[0].st (scaled and bias to the [-1, 1] range), so I don't need to project its world space position to screen space. By doing so, I would be unprojecting from screen space to world space when reconstructing the position from depth and then projecting back again to screen space when multiplying by the current view/projection matrix, which is redundant.
That was actually my first approach and the code was very similar to the one you suggested however it yielded the same artifacts.

Your subtraction is operating on things that are in different coordinate spaces, which will never produce correct results. I don't see the current projection matrix being applied. You also don't want to remap to [0,1] before subtracting.


The coordinate space is the same, the current screen space position of the pixel is given in the [0, 1] range and the previous screen space position is given in the [-1, 1] range but converted to the [0, 1] range using the instruction: "previousProjection.xy = previousProjection.xy * 0.5 + 0.5;". Nevertheless, I modified the code to keep things in the [-1, 1] range but the artifact remains:

void main()
{
  //Obtain the world space position of the pixel.
  vec3 position = reconstructPositionFromDepth(gl_TexCoord[0].st);

  //Current screen space position in the [-1, 1] range.
  vec2 currentProjection = gl_TexCoord[0].st * 2.0 - 1.0;
  //Previous screen space position in the [-1, 1] range.
  vec4 previousProjection = previousMatrix * vec4(position, 1.0);
  previousProjection.xy /= previousProjection.w;
.
  vec2 motion = (currentProjection.xy - previousProjection.xy) / 2.0;

  gl_FragColor= vec4(motion, 0, 0);



#4805551 Propagation in LPV

Posted by jcabeleira on 02 May 2011 - 11:23 AM

By "coeff" I mean the SH coefficients stored in the cells. SHBasis(dir) *  coeff is the way I calculate light intensity. "SHBasis()" is the  function I used to calculate the basis function for a 2 band SH given a  normal/direction. The dot product of SHBasis and coeff will restore the  original function I think.


Ok, I'm not sure if the math terms are correct (I tend to ignore all the math mambo jumbo) but the idea is. I'm sorry for misunderstanding.

I think in Crytek's paper they propagate light from the source cell to  each face of the destination cell. In "Intensity propagation" section  they said "Next we compute the flux on to each of the faces of the  adjacent destination cell". So I guess they calculate the flux into each  face separately.  When calculating the flux value they use the  intensity of center direction of the visibility cone as the average  intensity over the solid angle. So they multiply this value by  solidAngle/4*PI to get the total flux from source cell to this face.  However the above calculation will give us a "flux" value, to store it  in the destination cell we need to represent the flux value in Spherical  Harmonics Coefficients, that is what "reprojection" part try to do. To  calculate the SH Coeffs for this incident flux they put a new point  light source at the center of the destination cell and let that point  light source to "cause exactly as much flux as the face received". Then  they add the new SH Coeffs for the incident flux to the destination  cell's SH Coeffs.


I think what you're saying is partially true. The first LPV paper suggests that "flux per face" approach that you're mentioning. The problem with that approach is that it requires you to represent visibility cones using 2-band SHs which are too inaccurate for that purpose. Notice that the first band represents radiance going in all directions while the second band represents a 90º cone with a cosine weight, so there's no way you can represent a visibility cone accurately, in particular a narrow one.

I think it was due to this fact that in their second paper they suggested the approach I told you about. Even though they over complicated the explanation with mathematical jargon, at some point of the paper they did explain it in simple terms. When transferring radiance from one cell to another, they just get the color of the radiance that goes in the direction of the destination cell, scale it by the solid angle and build a SH that represents the 90º cone of radiance that goes in that direction.

Notice that unlike what you said, you don't create a point light on the destination cell, you creating a spot light (the cone) which represents the radiance that goes in that particular direction (e.g. left or right or anything else). If you create a point light, in the next propagation step you would be propagating the radiance you received back to its source cell because the radiance would have lost its directionality.

PS: your English is fine, no need to apologize.


#4076873 Shadow volumes in Doom3

Posted by jcabeleira on 09 October 2007 - 04:14 AM

Quote:
Original post by Matt Aufderheide
I don't know how Doom3 handles the extrusion, but there is a way to generate a capped mesh as a pre-process; this can then be extruded by a vertex shader. This is going to be higher poly, but saves a lot of CPU processing of vertices. This seems to be the most efficient way to use modern GPUs to accelerate shadow volumes.


Capping the areas as a preprocess would be a posible solution but I haven't seen any information related to capping geometry in the Doom3 map files.

The reason I'm asking how are shadows generated in Doom3 is because I've made a Doom3 map viewer, and the only closed geometry I found, in the file, to generate the map shadows was... the entire map's geometry!!! I do this by unifing all the areas geometries, wich are not closed meshes, into a single one wich results in a closed mesh.


Quote:
Original post by MENTAL
Taking a wild stab in the dark:

1) any light not 100% outside the frustum (remember to check the light based on it's radius, not just the center) gets added to a potential shadow-casting list.

2) check to see if the light is in a visible area. if not, discard the light. for static lights, the area can be calculated once at level startup. for dynamic lights, you need to recalculate this everytime the light moves.

3) You're now left with a small set of lights that are actually visible. start the actual shadow volume calcs here.

FYI, if you have mainly static lights then doing stage 2 before stage 1 might be more beneficial, as all you are doing is a simple bitset lookup. For lots of dynamic lights, stage 1 should be faster.


Yes I do that already, but you didn't understood my problem, I don't need to select wich lights affect visible geometry, I need to select a closed piece of geometry from wich I can generate shadows for the visible sections of the map.


PARTNERS