Home » Community » Forums » » Image Space Lighting
  Intel sponsors gamedev.net search:   
[Control Panel] [Register] [Bookmarks] [Who's Online] [Active Topics] [Stats] [FAQ] [Search]

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
Post Reply 
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'



 User Rating: 1107   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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.

 User Rating: 1293   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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

 User Rating: 1050   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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.

 User Rating: 1028   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by terra0nova
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.


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?

 User Rating: 1050   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

I found the code useful, since it provides a bare-bones OpenGL deferred renderer example. Seems a little less daunting now. ;)

 User Rating: 1029   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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.

 User Rating: 1028   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

excellent, i'll give that a try, converting my stuff from view space to world space.

thanks for the advice.


 User Rating: 1050   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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!

 User Rating: 1038   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by terra0nova
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,

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:

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.

You can still do FSAA by rendering to larger GBuffer. Clearly, though it won't be as effective as a native solution.

Quote:
Original post by terra0nova
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).

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:

Finally, I'm glad the article could be of help to you, AverageJoeSSU.

It was also useful for me. Nice and simple, and persuaded me to step up my half-assed implementation into something more proper .


 User Rating: 913   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by dietepiet
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.


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.

 User Rating: 1028   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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

 User Rating: 1050   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by terra0nova
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.


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 .

 User Rating: 913   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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!

Photobucket

Going to play around with it a bit more, and see about lowering the memory requirements. ;)

 User Rating: 1029   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by n00body
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!

Photobucket

Going to play around with it a bit more, and see about lowering the memory requirements. ;)


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?

 User Rating: 1050   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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.

 User Rating: 1000   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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
Photobucket

[Edited by - n00body on June 15, 2009 11:50:05 AM]

 User Rating: 1029   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by n00body
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. ;)


any chance you could link the view space stuff?

EDIT: I meant code =)

[Edited by - AverageJoeSSU on June 15, 2009 1:17:13 PM]

 User Rating: 1050   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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]

 User Rating: 1029   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by n00body
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


Awesome man, that should allow me to see what the heck i am doing wrong.

 User Rating: 1050   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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.

 User Rating: 1187   |  Rate This User  Send Private MessageView ProfileView JournalView GD Showcase Entries Report this Post to a Moderator | Link

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.

 User Rating: 1028   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

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.

 User Rating: 1029   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link

Quote:
Original post by terra0nova
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.


I am having trouble as well. revised code?



 User Rating: 1050   |  Rate This User  Send Private MessageView Profile Report this Post to a Moderator | Link
Page:   1 2 »»
All times are ET (US)

Post Reply
 Last Thread Next Thread 
Forum Rules:
You may not post new threads
You may post replies
You may not edit your posts
You may not use HTML in your posts
Jump To:
Administrative Options: