|
||||||||||||||||||
Add Forum to Favorites | Send Topic To a Friend | View Forum FAQ | Track this topic Page: 1 2 »» |
Last Thread Next Thread ![]() |
| Image Space Lighting |
|
![]() Nairb Member since: 10/10/2000 From: Morgantown, WV, United States |
||||
|
|
||||
| Decent article. Very grounded explanation of the technique. Some suggestions: (1) It would be good to touch on the shortcomings of the technique. Huge memory requirements; trickiness of alpha blending and antialiasing. (2) Might be good to throw out some of the common terms associated with this so people know what to Google when doing their own research, eg: 'G-Buffer' |
||||
|
||||
![]() Schrompf Member since: 7/26/2006 From: Dresden, Germany |
||||
|
|
||||
| I had a strange flashback reading this article. It nicely describes the basics of Deferred Rendering, but where exactly is the difference? Deferred Rendering is well-established and known for quite some time. Plus the references to games using the "built-in" lighting functionality of graphics cards doesn't exactly increase my trust in the article's quality. The omission of the actual shortcomings of Deferred Rendering that Nairb described doesn't help the case either. The article is nicely written, but to me it appears as if it is ten years late. |
||||
|
||||
![]() AverageJoeSSU Member since: 6/30/2007 From: Santa Clara, CA, United States |
||||
|
|
||||
| I kindly disagree, I believe this article is FANTASTIC... I have seen too many posts of people implementing their own deferred renderers and running into all kinds of weird problems. This article as said above provides a clear, compilable, code base that people can reference. I am one of those people that have a complex renderer with normal mapping and custom meshes, and i am having problems with all of my lighting moving with the camera. This code will allow me to see what calculations are in the wrong space. Speaking of which, i dont see you multiplying your camera position with the light position anywhere, which leads me to suspect you dont calculate the lighting in view space? im still looking at the code though maybe i'll find it |
||||
|
||||
![]() terra0nova Member since: 3/31/2007 |
||||
|
|
||||
| In answer to some of your comments, yes - this is not a novel technique, it has been used in several games, and the paper cited is a 2006 paper. There are some large disadvantages to this technique, as mentioned as well. If you use deferred rendering, you must store the scene information into floating point textures the size of the screen, which takes up a lot of memory, and makes hardware-accelerated anti-aliasing impossible (and other forms of antialiasing are typically more expensive or not as good). I agree that discussing more of these drawbacks would have made the article more complete, however, these drawbacks are more related to deferred rendering in general, and this technique only suffers from these drawbacks because it requires deferred rendering. This paper goes through my own implementation of deferred lighting, and walks through all of the steps and explains the math and theory clearly, from deferred rendering, to computing the lighting's area of effect, to rendering the proxy shape and computing the per pixel lighting. There is no great novel difference between this approach and deferred lighting (there are a few differences, but nothing notable). For those who already know a lot about deferred lighting, I can understand why this article might sound "ten years late." Finally, I'm glad the article could be of help to you, AverageJoeSSU. Also, the lighting calculation, as you suspected, is not in view space, it is in world space. The light source's proxy shape is projected to screen space (hence the name) - and this is done by just rasterizing the proxy shape with the scene's modelview matrix. To do the computation in world space, the position of the light source in world space is sent to the shader using a uniform variable. Doing the lighting computation itself in screen space would cause floating point errors, and perspective projection problems, so for simplicity sake, I do the actual lighting computation in world space. It is good to keep track of what variables are in what spaces - in the demo code, the deferred textures store the world position and normal (not the screen space one), so that the lighting computation can be done in world space in the next step. |
||||
|
||||
![]() AverageJoeSSU Member since: 6/30/2007 From: Santa Clara, CA, United States |
||||
|
|
||||
Quote: Yeah. I am trying to do my stuff in view space, and I believe some of my lighting calculations are off because of it. This may sound kind of newb, but could someone explain how these spaces relate to these calculations? I understand what they are, but when you say you do them in world space (i assume this means the HV and all that are in world space), do they eventually end up in view space? Or is that only done to the light's volume? |
||||
|
||||
![]() n00body Member since: 10/21/2006 From: Bloomington, IN, United States |
||||
|
|
||||
| I found the code useful, since it provides a bare-bones OpenGL deferred renderer example. Seems a little less daunting now. ;) |
||||
|
||||
![]() terra0nova Member since: 3/31/2007 |
||||
|
|
||||
| The lighting computation is done entirely in world space. The resulting color is written to the screen space pixel, so if that's what you mean by "eventually end up in view space," yes. However, the lighting computation is never transformed into view space, the lighting computation (only diffuse in the demo code, but you can compute any brdf) is done entirely in world space, and then the hardware's rasterizer takes care of adding the illumination to the correct pixel in view space. I would strongly recommend against doing the computation in view space - especially if you are using perspective projection. View space with perspective projection is not euclidean - the distance between two points close to the camera is different than the distance between two points far from the camera. Two points in view space could seem very close together by euclidean distance, but actually be very far apart - this will cause serious problems for standard lighting computation unless you correct for this. Save yourself a big headache - do everything in world space (which is euclidean). Oh, and if anyone is confused about the "FBO_SAME_FORMAT" variable in the demo code, this is actually a bug fix for ATI cards. On some ATI cards, all color attachments of the framebuffer must be the same format (ex. GL_RGBA). If you try to compile the framebuffer with color attachments of different formats on an ATI card, you'll get an GL_FRAMEBUFFER_INCOMPLETE_FORMATS exception. NVIDIA cards don't seem to have this problem. The code first tries to use color attachments with different formats (to save space), and if the framebuffer status is GL_FRAMEBUFFER_INCOMPLETE_FORMATS, then it recompiles the framebuffer object using color attachments of all the same format. |
||||
|
||||
![]() AverageJoeSSU Member since: 6/30/2007 From: Santa Clara, CA, United States |
||||
|
|
||||
| excellent, i'll give that a try, converting my stuff from view space to world space. thanks for the advice. |
||||
|
||||
![]() dietepiet Member since: 9/12/2007 |
||||
|
|
||||
| I read the article, and although it is a very useful introduction into deferred shading, it seems that the comparison with normal lighting is not really fare. In any reasonable old-style engine, you would not iterate trough all lights in the scene for each rendered pixel. You would use you spatial data structure (some octree or whatever) to select only lights for each object that contribute significantly to its color. So, when you have large view-space lights which only light relatively few pixels on one or two objects (for example large lights in outer space), you only apply the lights to those objects. In deferred shading, you would have to render the complete bounding volume of the light, even though hardly any pixels are actually light. I do not want to advocate against the value of deferred shading, but I think that the performance comparison in this article is highly biased because of a bad implementation of old-style lighting. That said, in many situations, deferred shading does outperform old style lighting and therefore is very useful! |
||||
|
||||
![]() nullsquared Member since: 9/1/2005 From: New York |
|||||
|
|||||
Quote: Not necessarily true. For example, I use a GBuffer with 4 byte (not floating point) RGBA textures. At 1440x900, this is around 20 MB, which is pretty much nothing. And, yes, there still is enough space for normal mapping, 32-bit depth, precomputed AO, diffuse, specular, and emissive. Quote: You can still do FSAA by rendering to larger GBuffer. Clearly, though it won't be as effective as a native solution. Quote: Are you talking about post-projection space? Yes, that is a bad idea. However, view space is the space when the eye is found at the origin. This is no less euclidean than world space, where the camera is simply not at the origin. Doing lighting computations in view space is actually very beneficial. For example, the eye direction is just -normalize(fragPos.xyz). Or, depending on how you've set things up, it might just be -rayDir (as is the case for me ).Quote: It was also useful for me. Nice and simple, and persuaded me to step up my half-assed implementation into something more proper . |
|||||
|
|||||
![]() terra0nova Member since: 3/31/2007 |
||||
|
|
||||
Quote: You do no have to compute the light for pixels do not receive light. You can reject pixels early (using a comparison and discard in shader, or the z-buffer), so while you have to traverse over pixels in the light's bounding volume, don't you have to traverse over all pixels using old style lighting and an acceleration structure? Both techniques have this cost, but deferred lighting usually covers less pixels, and doesn't have any per pixel acceleration structure traversal cost. Using acceleration structures is useful for when all lights affect the majority of the pixels, in which case you can adaptively cluster lights by stopping at nodes high up in the tree (based on solid angle) instead of traversing all the way down to leaf nodes. However, when the scene is filled with lots of small lights, which is the situation the article covers, deferred lighting will be more efficient than accelerated per-pixel lighting. @nullsquared: I always think of "view space" and "screen space" as "post-projection space," and the space you described I think of as "camera space." However, that is just lingo - so it's possible I just misunderstood what you were saying, AverageJoe. Are you doing the lighting computation in a projected or non-projected space? As for non-floating point textures, yes, you can use other formats, packing the data into ubyte textures, or using 16-bit floating point textures (as opposed to 32). However, I don't know if it's just me, but I always seem to find small artifacts due to the round off error - especially with the packed normals. However, the artifacts created are small, and you save a lot of space this way, so doing experiments with different texture formats is very useful. And, FSAA was the "more expensive" form of anti-aliasing I mentioned, you can actually get better results with FSAA than hardware supported anti-aliasing (as it averages over all pixels, and not just the edge pixels, removing aliasing artifacts from shaders and textures). It requires more work and a larger render buffer (as you mentioned), so it's more expensive, but works well. You can also perform normal blending at the edges of a normal sized gbuffer, which removes the aliasing and is cheaper, but doesn't take into account the sub-pixel details, and so looks over-blurred and not as good. |
||||
|
||||
![]() AverageJoeSSU Member since: 6/30/2007 From: Santa Clara, CA, United States |
||||
|
|
||||
| My stuff is in view space, non projected. Problem is I'm not sure everything is in view space. I can post my shader when I get home |
||||
|
||||
![]() nullsquared Member since: 9/1/2005 From: New York |
||||
|
||||
Quote: Your advice is true - experiment with various formats and methods, and pick the one that suits you best in terms of performance, quality, and memory usage. To elaborate on my case: indeed, flat surfaces tend to have some small banding artifacts with the specular term. Normally, this is minimal due to 16-bit floating point normals; however, I compress the 32-bit normals not only to 16-bit, but to 16-bit spherical coordinates . Yet, the artifacts seem to almost disappear with normal mapping. Therefore, my engine documentation actually recommends normal mapped objects - normal mapping comes in practically for free, and it hides most of the artifacts . |
||||
|
||||
![]() n00body Member since: 10/21/2006 From: Bloomington, IN, United States |
||||
|
|
||||
Decided to play around with your code a little bit. So far, I've added random colors for the cubes, linear accumulation of the lights to a RGBA16F buffer, and gamma correction of the final result. The end result looks pretty nice, and still runs smoothly. Enjoy! ![]() Going to play around with it a bit more, and see about lowering the memory requirements. ;) |
||||
|
||||
![]() AverageJoeSSU Member since: 6/30/2007 From: Santa Clara, CA, United States |
||||
|
|
||||
Quote: nice =) So after comparing shaders, I noticed I have two Light Positions in my shader, one in view space and one that isnt, yikes. I cleaned that up, but now I have this funky feeling that my directional light isnt behaving correctly. here is a video, ignore the first 15 secs, after that I am barrel-rolling the camera. the light should not change when the camera rolls like that. Any ideas what could cause this? |
||||
|
||||
![]() stormblaast Member since: 6/15/2009 From: Oslo, Norway |
||||
|
|
||||
| Nice work, excellent article! Note that you need to add #include <cstdlib> to main.cpp get it to compile with gcc 4.3+ on Linux. |
||||
|
||||
![]() n00body Member since: 10/21/2006 From: Bloomington, IN, United States |
||||
|
|
||||
| After a few modifications, I now have all the calculations being performed in view space. With that modification, I was able to switch all the targets to RGBA16F targets, for a noticeable speed boost, with no noticeable loss of quality. Still going to see if I can trim it even further. ;) EDIT: More tinkering. :D ![]() [Edited by - n00body on June 15, 2009 11:50:05 AM] |
||||
|
||||
![]() AverageJoeSSU Member since: 6/30/2007 From: Santa Clara, CA, United States |
||||
|
|
||||
Quote: any chance you could link the view space stuff? EDIT: I meant code =) [Edited by - AverageJoeSSU on June 15, 2009 1:17:13 PM] |
||||
|
||||
![]() n00body Member since: 10/21/2006 From: Bloomington, IN, United States |
||||
|
|
||||
| Oh, I hadn't seen your post, AverageJoeSSU. I'll need to do some touching up of the code, since I was just making modifications here and there. However, I should be able to post it tonight. EDIT: Okay here is the code. I've modified the following files: main.cpp, light.vert, light.frag, finalPass.vert, finalPass.frag. Any places you see the word "ADDED", I have made changes and tried to leave some notes. I make no guarantees that it will run the same way on your system, and don't plan to offer any support. With that understood, here it is: http://www.megaupload.com/?d=2FFOHNHQ [Edited by - n00body on June 15, 2009 2:34:06 PM] |
||||
|
||||
![]() AverageJoeSSU Member since: 6/30/2007 From: Santa Clara, CA, United States |
||||
|
|
||||
Quote: Awesome man, that should allow me to see what the heck i am doing wrong. |
||||
|
||||
![]() sprite_hound GDNet+ Member since: 2/20/2007 From: Southampton, United Kingdom |
||||
|
|
||||
| Very nice. It even works on my old Geforce 7600GT (albeit with rather low fps). I've been meaning to switch to using deferred rendering at some point soon. This looks like it would be a nice way to start off. |
||||
|
||||
![]() terra0nova Member since: 3/31/2007 |
||||
|
|
||||
| Hey, looked at your code n00body, and the result was quite smooth for only 16 bit floating point buffers. There were some artifacts noticeable, but nothing like the banding caused by performing the calculation in world space, and a few fps faster than using 32-bit floating point buffers. I had a little trouble compiling it in visual studio, an exit redefinition because you included the glew and glut headers before the stdlib header, and there were some glew link errors because you didn't use the EXT forms of the function (although that might be because of my version of opengl that came with visual studio 2005). If anyone else is having problems like this, I'll send the revised code. |
||||
|
||||
![]() n00body Member since: 10/21/2006 From: Bloomington, IN, United States |
||||
|
|
||||
| I see. I was unaware of those issues, as I was using visual studio 2008 Express for my compilation, as well as standard GLUT, rather than freeglut. Also, yes I was switching over to the ARB version of FBOs, just to make the code a little more readable. They work on my 6800 GT, so long as the drivers are up to date. I don't know what the situation is for SM 3.0 ATI cards. My next modification will be trying to get it down to just 4 fp16 render targets. Hopefully that will provide another boost. |
||||
|
||||
![]() AverageJoeSSU Member since: 6/30/2007 From: Santa Clara, CA, United States |
||||
|
|
||||
Quote: I am having trouble as well. revised code? |
||||
|
||||
|
Page: 1 2 »» All times are ET (US) ![]() |
Last Thread Next Thread ![]() |
|