Light Probes Questions/Feedback

Discussion in 'Developer Preview Archive' started by AcidArrow, Dec 22, 2011.

  1. AcidArrow

    AcidArrow

    Member

    Joined:
    May 20, 2010
    Messages:
    1,332
    So I have a few Questions/Feedback. I realize this is a beta, so I'm here mostly to ask if things are working as intended or there is still work to be done on them.

    1) Is GUI for the placement of probes final? It seems a bit... un-intuitive.

    From what I see there is no list of the probes I added anywhere. And to manipulate them, I have to search for them in the scene view. Also clicking add probe adds a probe... somewhere? It is not selected after wards and I have to navigate the scene view to search for it. I was starting to get a bit overwhelmed and I only added probes to a small part of the scene.

    2) This is a bigger one for me. I like color correcting the lightmaps a lot (the images themselves). I usually add some more color and tint the whole lightmap a bit, some more contrast etc etc (I'm using single lightmaps mainly). Now the lightprobes seem to get their data from some cache which isn't affected from the lightmap image itself.

    So my problem is, I tint (let's say) my lightmaps red, but the lightprobes have the original colors and there is no way to edit them. I am sure that there is a very good technical reason why it works like it does, but I think there should be a way to edit the light probe data as well (maybe there is and I haven't found it? Or will there be one?).

    Can't the light probe data be exported as an image as well (an .exr) so I can edit them? That should work nicely and shouldn't be that hard to implement.
     
  2. antenna tree

    antenna tree

    Moderator

    Joined:
    Oct 30, 2005
    Messages:
    5,300
    1) The best way to layout probes, if by hand, is probably to create a light probe group, add a single probe, and then duplicate them using cmd/ctrl D. You can also rect select multiple probes and duplicate them to quickly start forming grids or other shapes.

    There are a few things that feel a little unpolished at the moment. For example no boolean rect selections and exiting light probe editing mode is a little too easy atm. But these are polish issues that I'm sure we'll nail before the final release.

    2) I'm not sure if this is possible, but it sounds like a useful, if not necessary, feature. Hopefully Robert or Kuba will see this thread and chime in.

    Also, there are new docs for light probes so make sure to check them out.
     
  3. Tim C

    Tim C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Messages:
    1,474
    To elaborate a little bit:

    1) When you click add probe it adds the probe at the current camera focal point, this is the same position that a gameobject would be added if you added one from the gameobject menu. After adding a probe it is desirable to edit them using cmd / ctrl + d and similar keyboard shortcuts. It's nice to use once you have used it for a few minutes.

    2) Look in the docs for LightProbes.coefficients. There is an example of how to modify the color of existing probes. :)
     
  4. AcidArrow

    AcidArrow

    Member

    Joined:
    May 20, 2010
    Messages:
    1,332
    @aNTeNNa trEE @stramit :

    1) Ok, thanks :D Duplicating with ctrl+D makes things a lot easier, it's much more usable now. I still think it needs polishing. I guess we'll see in the upcoming versions.

    2) So there is a lot of scripting potential with the LightProbes.coefficients command, that's very cool. Although it would be kinda hard to do something to the lightmaps through image editing and then replicating that with scripting.

    So I still think that encoding the lightprobe data to an exr and then being able to re-import them is a must.

    Maybe since LightProbes.coefficients seems pretty powerful, even if the devs don't provide such functionality a script could be written that export the data to an exr but that's an area of scripting I'm not really familiar with.
     
  5. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Messages:
    11,301
    Where's the shadowgun light probes shader that was promised at the unite conference? It was supposed to be on asset store.
     
  6. pixoloco

    pixoloco

    Member

    Joined:
    Dec 22, 2011
    Messages:
    47
    Is there a way to use directional lightmaps and probes to correctly lit a dynamic object with normal maps and standard shader ?
    I've made lots of tries but my dynamic object stay stubornly flat. As if my dynamic object was using the probe lighting per-vertex and not per-pixel.
     
  7. Zomby138

    Zomby138

    Member

    Joined:
    Nov 3, 2009
    Messages:
    412
    I can second that lightprobes seem to be sampled on a per vertex basis, ignoring bump maps.

    :(
     
  8. loken

    loken

    New Member

    Joined:
    Mar 25, 2009
    Messages:
    109
    Yeah, light probes with directional lightmaps don't really work. Is this a bug, or just a limitation?

    I can't even get dynamic objects to cast shadows or have body shadows if using directional lightmaps, so long as the "Use Light Probes" setting is on.
     
  9. AcidArrow

    AcidArrow

    Member

    Joined:
    May 20, 2010
    Messages:
    1,332
    I'm guessing we are missing a shader that uses the normal maps as well. It's probably coming in an upcoming beta/rc.
     
  10. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Messages:
    11,301
    To work with light probes.

    Note the soon on asset store part. Do you know when? I'd like to learn and develop from this. Source here (unity pdf file): http://blogs.unity3d.com/wp-content/uploads/2011/09/Shadowgun_Unite2011.pdf
     
  11. loken

    loken

    New Member

    Joined:
    Mar 25, 2009
    Messages:
    109
    Quite possible.

    It appears that shadow casting just doesn't occur when in Deferred mode while using Directional Lightmaps. Body shadows still seem wrong or off though.
     
  12. Tim C

    Tim C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Messages:
    1,474
    I believe that there is an issue with DLM's and light probes that we have fixed internally but didn't make it into the beta. Try this:

    -Bake DLM's
    -Turn mode to 'single lightmaps'
    -Bake probes only
    -Turn mode back to DLM's

    That should work :)
     
  13. Zomby138

    Zomby138

    Member

    Joined:
    Nov 3, 2009
    Messages:
    412
    When you say "DLM's" in this post, is that short for "Directional Lightmaps" or "Duel Lightmaps" ?
     
  14. Tim C

    Tim C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Messages:
    1,474
    Oh I didn't think about that ;) I meant Directional light maps, as that is the mode that has the issue in the release. Let me know if it works around the issue.
     
  15. Kuba

    Kuba

    Unity Technologies

    Joined:
    Jan 13, 2009
    Messages:
    222
    The interpretation of the data that is stored per light probe is not exactly intuitive (9 RGB coefficients per probe). Of course that data could be directly dumped to an exr file, but there is no point, since painting over that would give you... something unexpected. Also how would you identify which probe are you actually painting over now?

    Since the data is exposed, I'm sure that scripts making it more intuitive to modify that data will crop up. It is out of scope for 3.5 for such functionality to be built-in, though.
     
  16. Kuba

    Kuba

    Unity Technologies

    Joined:
    Jan 13, 2009
    Messages:
    222
    To see how it's currently done, you can grab e.g. the Bumped Specular shader, add #pragma debug to it and then hit "Open compiled shader" in the Editor. You'll see that the SH lighting is decoded per vertex by default:
    Code (csharp):
    1. float3 shlight = ShadeSH9 (float4(worldN,1.0));
    2. o.vlight = shlight;
    then interpolated per pixel and finally added to the resulting color:
    Code (csharp):
    1. c.rgb += o.Albedo * IN.vlight
    SH can of course be decoded per pixel. You will need to transform the normal from the normal map from tangent space into world space and pass into ShadeSH9.
     
  17. Kuba

    Kuba

    Unity Technologies

    Joined:
    Jan 13, 2009
    Messages:
    222
    Currently only indirect lighting is baked into light probes when baking in Directional Lightmaps mode. This is a bug that is already fixed for the next beta, please use the workaround suggested by stramit until then.

    This sounds like a real issue. Please submit a bug report and share the case number (and just the number). Thanks!
     
  18. loken

    loken

    New Member

    Joined:
    Mar 25, 2009
    Messages:
    109
    Will do. Stramit's suggestion has no effect on cast shadows from dynamic objects in DLM mode. As you said, there's still no direct light on the object. Will file report ASAP.
     
  19. AcidArrow

    AcidArrow

    Member

    Joined:
    May 20, 2010
    Messages:
    1,332
    It wouldn't work well for painting, but for global operations to all of the probes (like adjusting level or adding a slight tint to all of the probes) it would work fine. I don't really care if the resulting exr from the probes makes sense, I just want to be able to repeat whatever processing I do to the lightmap.exr (and this doesn't include painting).
     
  20. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Messages:
    11,301
    So which shader do I use in order to get:

    Character lighting
    • Initially was looking for a fast way to do perEpixel
    specular
    • Texture lookup to calculate diffuse + specular
    • RGB E diffuse
    • A E specular
    • Very flexible + constant cost:
    • “Trilight”: Key, Back, Fill in one go
    • Wrap light for skins
    • Custom lobes for metallics
    • Energy conserving specular highlight
    • Disadvantage: can be tricky on some GPUs
    • Soon on Asset Store!

    Will this be out soon on asset store?
     
  21. Oliver Eberlei

    Oliver Eberlei

    Member

    Joined:
    Jun 12, 2011
    Messages:
    76
    It says so doesn't it? I know it's hard to be patient with all the shiny new stuff going on here. Relax a little bit and go explore all the other new features you just got. Whenever they're ready for it, it will come out.
     
  22. Tim C

    Tim C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Messages:
    1,474
    I have no more information then you guys on this, but I would assume that it will not be on the asset store till 3.5 final is released. We wouldn't want 3.4 users to download something that would not work for them.
     
  23. TwiiK

    TwiiK

    Member

    Joined:
    Oct 23, 2007
    Messages:
    938
    Is there any good light probe examples around?

    I've been messing about with them, but I'm not really getting the results I want. And the workflow is a bit odd. :)

    Also, the "needs to form a volume" part confuses me. I'm testing with a room divided into 4 sections with a flat floor so I place all my probes at the same height where my character will walk. But it refuses to bake until I position one of them above the other. Why must I do that? I'm looking at the example images in the documentation and if there character wouldn't have been able to walk up onto those cubes every probe would be at the same height there as well.

    Also, why do you add probes as a component on objects? Currently I'm just selecting a random object in my scene and then adding every single probe to that one. Is that wrong? Should probes be put on the objects closest to it?

    I was expecting light probes to be separate game objects so I could easily manage them in my scene hiearchy.
     
  24. TwiiK

    TwiiK

    Member

    Joined:
    Oct 23, 2007
    Messages:
    938
    Attached is what I'm currently fiddling with.

    I keep getting a green tint in the red room and both a red and yellow tint behind the wall where there should be no light. Also the transition between the red and green room doesn't work at all, but between the green and blue room it works perfectly.

    Not really sure why and how to fix it. I'm guessing it has to do with the lines going between the probes?
     

    Attached Files:

  25. Zomby138

    Zomby138

    Member

    Joined:
    Nov 3, 2009
    Messages:
    412
    I'm adding all my probes to an empty object that I created to hold them.

    Dunno if that's what you're meant to do or what.
     
  26. Kuba

    Kuba

    Unity Technologies

    Joined:
    Jan 13, 2009
    Messages:
    222
    The reason is that the volume formed by the probes is tetrahedralized (divided into tetrahedra). This process cannot be done when all the probes are coplanar.

    Unfortunately a 2D mode (with triangulation instead of tethrahedralization) will not make it into 3.5 because of the time constraints.

    To handle cases like yours one can vary the height at which the probes are positioned. If it's important to capture lighting at a very specific height it might be better to duplicate the probes vertically. Don't worry about performance, place probes in a way that makes the interesting changes in lighting be captured and the tetrahedra to be shaped nicely (e.g. no looong tetrahedra).

    They would not be able to be at the same height because of the reason mentioned above.

    Light Probe Group can be added to an empty game object and all the probes can be created in that one group.

    One can also add Light Probe Groups to game objects that are parts of prefabs (like a building, room, etc.). The light probe positions are stored relatively to the game object having the Light Probe Group component, so that when you instantiate the prefab with such a game object the light probe positions are affected by the object's position and rotation.

    This helps a lot when placing the probes, but only then, Light Probe Groups do not exist at runtime.
    At bake time all the probes within the scene are used as one cloud of points anyways.
     
  27. TwiiK

    TwiiK

    Member

    Joined:
    Oct 23, 2007
    Messages:
    938
    Thanks for the reply, clears it up quite a bit. :)

    Having them as part of prefabs makes sense.

    As for the weird lighting I'm experiencing, I'm gradually improving it so I guess it's just about learning where to place the probes.
     
  28. Zomby138

    Zomby138

    Member

    Joined:
    Nov 3, 2009
    Messages:
    412
    I've got normal mapped light-probe light working on my characters, by adding the following line of code to the end of the .shader file

    Code (csharp):
    1. o.Emission = o.Albedo * ShadeSH9 (float4(o.Normal,0.0));
    Just after the "o.Normal = normalize(o.Normal);" line.

    This gives me albedo lighting but no specularity, which is good enough for me.
     
  29. rea

    rea

    Member

    Joined:
    Oct 10, 2009
    Messages:
    971
    So now we need to adding those line to every built in shader?(Depend on what do you need) o_O
     
  30. Zomby138

    Zomby138

    Member

    Joined:
    Nov 3, 2009
    Messages:
    412
    That's what I'll be doing till we get a more automated solution.
     
  31. pixoloco

    pixoloco

    Member

    Joined:
    Dec 22, 2011
    Messages:
    47
    thanks zomby, here's my custom shader :

    Code (csharp):
    1.  
    2. Shader "Custom Bumped Diffuse" {
    3. Properties {
    4.     _Color ("Main Color", Color) = (1,1,1,1)
    5.     _MainTex ("Base (RGB)", 2D) = "white" {}
    6.     _BumpMap ("Normalmap", 2D) = "bump" {}
    7. }
    8.  
    9. SubShader {
    10.     Tags { "RenderType"="Opaque" }
    11.     LOD 300
    12.  
    13. CGPROGRAM
    14. #pragma surface cussurf Wrap
    15.  
    16. sampler2D _MainTex;
    17. sampler2D _BumpMap;
    18. fixed4 _Color;
    19.  
    20.  
    21. struct Input {
    22.     float2 uv_MainTex;
    23.     float2 uv_BumpMap;
    24. };
    25.  
    26. half4 LightingWrap (SurfaceOutput s, half3 dir, half atten ) {
    27.       dir = normalize(dir);
    28.       half diff = dot (s.Normal, dir)*.8+.2;
    29.       half4 c;
    30.       half3 sh= ShadeSH9 (float4(s.Normal,1.0));
    31.       c.rgb = (s.Albedo * sh * diff) * atten *2 ;
    32.       c.a = s.Alpha;
    33.       return c;
    34. }
    35.  
    36. void cussurf (Input IN, inout SurfaceOutput o) {
    37.     fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    38.     o.Alpha = c.a;
    39.     o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    40.     o.Albedo = c.rgb;
    41. }
    42. ENDCG  
    43. }
    44.  
    45. FallBack "Diffuse"
    46. }
    47.  
    Not perfect, but good enough for testing until a better shader comes out.
     
  32. Kuba

    Kuba

    Unity Technologies

    Joined:
    Jan 13, 2009
    Messages:
    222
    Zomby138, rea, pixoloco: guys, srsly? :> I said world space normal...

     
  33. rea

    rea

    Member

    Joined:
    Oct 10, 2009
    Messages:
    971
    Uhhh???? sorry kinda confused here @_@
     
  34. pixoloco

    pixoloco

    Member

    Joined:
    Dec 22, 2011
    Messages:
    47
    With my understanding of shader programming, you could have said Atomic spaced normal maps , the result would have been the same :p
    If you have a better shader, feel free to share. We won't tell anybody, promise ;)
     
  35. robert

    robert

    Unity Technologies

    Joined:
    Dec 21, 2008
    Messages:
    253
    As Kuba said, it has to be the world space normal that is used to sample SH. But that's just common sense. After all the SH data is set in the uniforms, so it's the same values for all the pixels of the object. If you sample SH with normals say perpendicular to the surface, in tangent space they have the same coordinates across the mesh, so they will (incorrectly) return the same values. There's a comparison in the attached image.

    Here's the Bumped Diffuse shader, patched to use light probes per pixel, to get what you see on the sphere in the middle.

    Code (csharp):
    1. Shader "Bumped Diffuse, Per Pixel Probes" {
    2. Properties {
    3.     _Color ("Main Color", Color) = (1,1,1,1)
    4.     _MainTex ("Base (RGB)", 2D) = "white" {}
    5.     _BumpMap ("Normalmap", 2D) = "bump" {}
    6. }
    7.  
    8. SubShader {
    9.     Tags { "RenderType"="Opaque" }
    10.     LOD 300
    11.  
    12. CGPROGRAM
    13. #pragma surface surf Lambert novertexlights
    14. #pragma exclude_renderers flash
    15.  
    16. sampler2D _MainTex;
    17. sampler2D _BumpMap;
    18. fixed4 _Color;
    19.  
    20. struct Input {
    21.     float2 uv_MainTex;
    22.     float2 uv_BumpMap;
    23.     fixed3 worldNormal;
    24.     INTERNAL_DATA
    25. };
    26.  
    27. void surf (Input IN, inout SurfaceOutput o) {
    28.     fixed4 c = tex2D(_MainTex, IN.uv_MainTex) * _Color;
    29.     o.Albedo = c.rgb;
    30.     o.Alpha = c.a;
    31.     o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
    32.     fixed3 worldN = WorldNormalVector (IN, o.Normal);
    33.     o.Emission = ShadeSH9 (fixed4(worldN,1.0));
    34. }
    35. ENDCG  
    36. }
    37.  
    38. FallBack "Diffuse"
    39. }
    40.  
    It's just using the world space normal as described in the docs, so the added stuff is two last lines in the Input struct and two last lines in the surface function. There's also the novertexlights keyword to disable the built-in sampling of SH to avoid double lighting (noambient could be used as well).
     

    Attached Files:

  36. robert

    robert

    Unity Technologies

    Joined:
    Dec 21, 2008
    Messages:
    253
    Again, as Kuba said ;) your scene could really benefit from a 2D flat probe bake, but we had to postpone implementing handling of this special case for the next release. In the meantime it's possible to use light probes for flat scenes, but it requires some extra care: you have to make sure that the light probes really form a volume. Adding them flat and just lifting one a little bit won't cut it, as that will lead to long and thin tetrahedra, which connect one end of your scene with the other and you will get some weird interpolation.

    Instead you should add a couple of probes say 1-2 units higher. You will see that the connections no longer go from one end of the scene to the other and you should get the correct interpolation.

    To better see what's going on and which probes are being used, when the Scene View is in the Light Probes drawing mode (upper left corner drop down), select the renderer that is using the light probes (your character's skinned mesh renderer in this case). You will see a small probe drawn on top of it (that's the preview of the probe that will actually be used for rendering) and 4 or 3 blue lines connecting him to the probes that make up the averaged probe. Play around with the placement of the probes to see how it affects the tetrahedra structure showed by the yellow lines and which probes are then picked by the blue lines.

    You'll see that when the probes form a volume in your scene, things become nicely predictable.
     
  37. pixoloco

    pixoloco

    Member

    Joined:
    Dec 22, 2011
    Messages:
    47
    Thanks a lot for the shader and the explanation !
     
  38. robert

    robert

    Unity Technologies

    Joined:
    Dec 21, 2008
    Messages:
    253
  39. BrUnO XaVIeR

    BrUnO XaVIeR

    Member

    Joined:
    Dec 6, 2010
    Messages:
    1,541
    Robert got a fan here. :)
    Thank you very much for that.
     
  40. TehWut

    TehWut

    Member

    Joined:
    Jun 18, 2011
    Messages:
    1,579
    Is there some sort of Light probe tutorial (or documentation rather). I'm kind of just blindly trying to work the light probes. I would like to know the whole baking/placement/proper lighting process. I know there probably isn't, since it's such a new feature :/
     
    Last edited: Dec 27, 2011
  41. rea

    rea

    Member

    Joined:
    Oct 10, 2009
    Messages:
    971
    Umm I think i got some problem here, if i'm using lightprobe my character/or dynamic object didn't receive any lighting and shadow from any light (static dynamic). Here's the pic of it
    Forward rendering no lightprobe ( shadow increased just to showed it)
    $forward%20no%20lightprobe.png
    Forward rendering with lightprobe
    $forward%20with%20lightprobe.png
    And tried with deffered rendering too
    Deffered no lightprobe
    $deffered%20no%20lightprobe.png
    In deffered without lightprobe i got the lighting and shadow for dynamic object but the static object didn't receive any shadow at all.
    Deffered with lightprobe
    $deffered%20with%20lightprobe.png
    And in deffered with lightprobe the character didn't receive any shadow and lighting. I'm using directional lightmaps here. So any idea about this?
     
    Last edited: Dec 27, 2011
  42. AcidArrow

    AcidArrow

    Member

    Joined:
    May 20, 2010
    Messages:
    1,332
    Is it the same if you use single lightmaps?

    The only real problem I'm seeing is that Forward rendering and no probe should have a shadow cast on the character. At least I believe that's how it worked in 3.4 with single lightmaps.
     
  43. robert

    robert

    Unity Technologies

    Joined:
    Dec 21, 2008
    Messages:
    253
    Directional lightmaps work the same way as single lightmaps when it comes to deciding which lights will be baked, which will cast shadow, etc., and it's nothing like in dual lightmaps. So in short, both with single and with directional lightmaps:

    1. A light is always either fully baked or fully realtime. Auto lights are treated as fully baked.
    2. Static objects can cast shadows on static objects from baked lights and these are baked into the lightmap.
    3. Static objects can't cast shadows from static lights onto dynamic objects.
    4. Dynamic objects can cast shadows from static lights onto static objects, but these shadows need some special care and manual setting of the strength parameter so that the shadow blends with the baked shadow in the lightmap.

    To handle 3. in a completely baked environment you can use the light probes. You can place a couple of probes along the shadow edge on the dark side, a couple on the bright side. As your character crosses from light to shadow, it will fade from the bright probes to the dark ones, which usually looks pretty good, although you won't see the sharp shadow edge on him.

    When the lightmapper is in directional lightmaps mode, light probes behave the same way as if it was in single lightmaps mode, i.e. bake the full contribution (direct and indirect) from all baked only and auto lights. If you enable light probes on a dynamic object, it will stop using any auto lights (it's not using baked only lights already), to avoid double lighting, since their full contribution is already baked into the probes.

    In dual lightmaps mode, probes bake only indirect contribution from auto lights (and full contribution from all other lights), so direct light and shadow from auto lights onto dynamic objects using light probes is applied realtime (so you would get the sharp shadow edge on the dynamic object).
     
  44. robert

    robert

    Unity Technologies

    Joined:
    Dec 21, 2008
    Messages:
    253
    There's an entire man page about light probes installed on your disk.
     
  45. pixoloco

    pixoloco

    Member

    Joined:
    Dec 22, 2011
    Messages:
    47
    If you look at rea images, you can see that in "deffered with lightprobe" dynamic object shadows are not cast on static objects.
    The only way i found to cast shadows in deffered is to put the light in "realtime only" once it has been baked. But then i have double lighting.

    In forward, shadows are cast as intended.
     
  46. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Messages:
    11,301
    Hope its optimised for mobile :) I can't be patient its making me roll around of the floor clutching a teddy bear for my lost love.
     
  47. rea

    rea

    Member

    Joined:
    Oct 10, 2009
    Messages:
    971
    Yes it happen with single lightmaps too.
     
  48. robert

    robert

    Unity Technologies

    Joined:
    Dec 21, 2008
    Messages:
    253
    That's true, I responded in the other thread.
     
  49. Zomby138

    Zomby138

    Member

    Joined:
    Nov 3, 2009
    Messages:
    412
    Could someone explain to me why I get exactly the same results when I do

    Code (csharp):
    1. o.Emission = o.Albedo * ShadeSH9 (float4(o.Normal,1.0));
    as when I do

    Code (csharp):
    1. fixed3 worldN = WorldNormalVector (IN, o.Normal);
    2. o.Emission = o.Albedo * ShadeSH9 (float4(worldN,1.0));
    Seriousely, when I switch from one to the other the results are the same, to the pixel.
     
  50. Tim C

    Tim C

    Unity Technologies

    Joined:
    Feb 6, 2010
    Messages:
    1,474
    <ignore>
     
    Last edited: Dec 31, 2011