Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Integrating SSR: Help?

Discussion in 'Unity 5 Pre-order Beta' started by PhobicGunner, Feb 14, 2015.

  1. PhobicGunner

    PhobicGunner

    Joined:
    Jun 28, 2011
    Posts:
    1,813
    Okay, so this might be a bit of an odd question, but here goes.

    I've been taking this screen space reflections package and modifying it to work in Unity 5. Thus far, everything has gone well. I've got it working with Command Buffers and currently it hooks into BeforeImageEffects, does its thing, and combines the SSR with the screen.
    However.
    This package did not have any kind of PBR support.

    That being said, let's say I have a full-screen texture which contains just the screen space reflections, and I have access to the specular and normal G-Buffers from my shader. How might I go about utilizing the specular, roughness, and normals to actually integrate this thing properly with PBR? Specifically, I'm not sure how to:
    1. Properly calculate fresnel
    2. Blur the reflection based on surface roughness (if my SSR texture encoded ray distance in alpha, potentially also distance-dependant blur?)
    3. Colorize the reflection based on specular color.
    Any sort of help in this regard would be immensely useful. It's just this one last step between my game and beautiful, shiny SSR heaven.
     
  2. Roni92

    Roni92

    Joined:
    Nov 29, 2013
    Posts:
    225
    Livenda is working to make their candela reflections work in 5.
     
  3. Zeblote

    Zeblote

    Joined:
    Feb 8, 2013
    Posts:
    1,102
    It'll only take 3 years.
     
    PhobicGunner likes this.
  4. PhobicGunner

    PhobicGunner

    Joined:
    Jun 28, 2011
    Posts:
    1,813
    And by then U5 might have their SSR implementation finished and built-in anyway.
     
  5. larsbertram1

    larsbertram1

    Joined:
    Oct 7, 2008
    Posts:
    6,900
    hi there,
    i never really looked into screen spaced reflections but i see no reason why those should be treated differently compared to ambient specular reflections from cubemaps.

    so if you want to go with the standard shader you should probably have a look into the standard brdf:
    this is how brdf1 integrates specular reflections:
    gi.specular * FresnelLerp (specColor, grazingTerm, nv);

    where "gi.specular" is just the sampled result from the cubemap – already "blurred" = convolved according to smoothness. it might be a bit to expensive to convolve the whole screen so may just blurred samples in the different mip levels of the reflection texture might be enough.

    lars
     
  6. PhobicGunner

    PhobicGunner

    Joined:
    Jun 28, 2011
    Posts:
    1,813
    First results of my efforts.



    I already had a gaussian-style blur pass in there, so I just modified that to change blur radius depending on roughness per pixel. Did try the mip-levels thing but it didn't work at all so I guess the render texture doesn't have mip-mapping enabled? And there's no option in CommandBuffer.GetTemporaryRenderTexture to enable mip-mapping... so looks like I'll have to stick with the blur pass.

    EDIT
    One issue currently is that the blur does not take distance into account, which means distant reflections will look blurrier than nearby reflections.
     
    Botanika likes this.
  7. Roni92

    Roni92

    Joined:
    Nov 29, 2013
    Posts:
    225
    I like your progress, looks very promising. What you can say performance-wise in presented scene? I mean, more or less, do we talk here about 1ms or 5ms(would be nice with your cpu and gpu info)? What about flexibility, can you exclude objects from ssrr, and can it cooperate with reflection probes( probes for rough, non reflective objs, ssrr for reflective would be good idea to save performance). Keep up good work :D
     
  8. PhobicGunner

    PhobicGunner

    Joined:
    Jun 28, 2011
    Posts:
    1,813
    I'm running on a 3.5 GHZ 6-core CPU, and a GTX 780 Ti for the graphics card.

    I see the renderer hovering between 1.8 and 2 ms with SSR disabled, with SSR enabled it ranges between 2 and 2.3 ms with occasional spikes up to 3 ms. CPU time appears mostly unaffected (which is to be expected, since this is primarily a graphics-heavy technique).

    Here's how it works so far.
    Basically, it hooks into the command buffer pipeline and runs before image effects. So, by that point Unity has completely rendered the frame (but has not applied any image effects to it yet).
    It then applies the SSR effect on top of that rendered frame, same way the Plawius package which I was using as a base does, as well as Candela's SSR.
    That means that it just renders on top of whatever Unity outputs, including cubemap reflections. In fact I do have a reflection probe in that video.

    The other thing here is that excluding objects from SSR would actually be a lot more work and less efficient. I already have the rendered frame at my disposal and I just reuse it for the raymarching (along with the camera's depth texture). Excluding things would mean re-rendering the frame entirely with a different layer mask, rather than simply re-using what Unity has already rendered.

    EDIT
    I should note that, while I don't see any sort of visible slowdown from SSR whatsoever, I have a GPU meter in my task bar and I *can* see a fairly drastic increase in GPU usage when I enable SSR. However, I'm not at all surprised by the increased usage given how heavy SSR is in general.
     
    SAOTA likes this.
  9. SAOTA

    SAOTA

    Joined:
    Feb 9, 2015
    Posts:
    220
    Nice!! This is moving along nicely.
     
  10. Aieth

    Aieth

    Joined:
    Apr 13, 2013
    Posts:
    805
    It all depends on how physically based you want to take it :)

    1&3:
    These questions are actually the same. What you want to do, ideally, is trace a bunch of importance sampled rays in various directions and weight them together, while running a full BRDF on every sample. However, more than just one ray really isnt feasible (except for reference, but you don't want to do 16 rays per pixel in real time!).

    What is instead typically done is preintegrating a BRDF into a lookup texture, usually making a simplification such as N=V=R. This quickly gets pretty complicated though, so if you just want an analytical solution I know Lazarov posted one in his presentations on Call of Duty, it should be findable on google (or perhaps its already in Unity 5 source code, I have not checked, I know its in Unreals). As for the specular color, it is just another word for the index of refraction between two mediums (in rendering that is usually a material and air (but could be water!)). So it goes into the fresnel approximation, which is usually Schlicks (due to how well it correlates with ground truth).

    2:
    I've recently been working on this myself. I don't know how mathy you want to go, but its hard to keep it physically based unless you do :) You can just arbitrarily blur it as well as you have been doing.
    The approach I decided with was deriving a way to calculate cone width based on roughness. I did this by running importance samples of my BRDF and storing how much each sample deviated from the reflection vector. I then summed up to a specified % of energy conservation (I chose 75% to avoid huge cones). I then did that for each 0.1 of roughness increment and ran a least square fit on it to produce a polynomial approximation. I then used that approximation to calculate the radius of the cone at the intersection point (as in, the point where the ray intersected something).

    So: roughness -> cone angle -> cone radius at intersection point
    The cone radius forms a cirlce. I then calculate what percentage of the view frustum this circle contains (based on the circle and the angle from the camera to the circles center). I then average this percentage in x and y (to avoid different blur radius in x&y, and to avoid the artifact of a very wide or tall blur).

    I then perform 4 separable gaussian blurs, each half the size of the previous one, using a gaussian distribution that is fit to my BRDF. These blur passes are also luma weighted to keep bright pixels from causing large flickers.

    Finally I do a combination pass that uses the blur percentage to choose which of the blurs go into what pixel. It works pretty well and gives contact hardening reflections on rough surfaces and smooth surfaces get blurry reflections far away.

    If the numerical analysis is too tricky, its easier to calculate the angle of a blinn-phong cone than any other BRDF, and I know theres code on the internet for it.

    Hope this made at least a little bit of sense :)
     
  11. PhobicGunner

    PhobicGunner

    Joined:
    Jun 28, 2011
    Posts:
    1,813
    A little?
    TBH I think I'm a bit too stupid to be doing this properly ;)

    So what I've got at the moment is one massive hack that seems to look okay and I might leave it that way because it's already taken a little bit of brain breaking to get to this point as it is.