Jump to content

Reflection Occlusion


Recommended Posts

hmm... reflection occlusion it's just a occlusion pratly driven by occlusion information, right? I don't know how complicated is your scene but what I would do its just multiplication of reflection pass by your occlusion pass little modified in post for greater contrast (I always do it like that). Maybe it's not best idea for complicated scenes but works fine for most of them.

You can of course multiplay reflections (either raytraced or mapped) by occlusion just in shader body, but you will miss your chance to tweak it later in composition and I'm telling you, that's a pitty!

My approach, for sure not the best one, and among others:

1 - enviroment mapped reflection pass (very often twice or more)

2 - raytracing for selected object if needed

3 - occlusion pass (wonderfully speeded with mantra GI cache)

4 - normal maps

5 - fresnel with smoothing eta (like 0.6 for metal)

6 - and rest of familly (diff, spec almost alway x 2 in two different shading models to mix/tweak/cheat in post)

then reflection are muliplayed by fresnel (fresnel pass has shifted blacks and whites for scaling reflection)

then if needed I can scale reflections with normal maps (darker ground reflect or brighter sky)

then reflections (many reflections added together) are mult by occlusion pass with remapped contrast.

and vuala! you have your occlusion reflection. You can also use occlusion pass as a matte to mix raytraced with mapped reflection.

And rest of the job... as usually: spec, diff etc.

cheers,

SY

Link to comment
Share on other sites

hmm... reflection occlusion it's just a occlusion pratly driven by occlusion information, right?

27022[/snapback]

Generally speaking, the two big differences between ambient occlusion and reflection occlusion are the cone angle and "centre vector" (I'm sure it has a fancier name). With ambient occlusion, you often call (I'm going to use PRMan syntax, sorry) "occlusion(P,N,PI/2)" whereas, for reflection occlusion, you'd want to call "occlusion(P,R,SOMETHING_SMALL)" where SOMETHING_SMALL is determined by the glossiness of your surface. In the standard Occlusion VOP, plugging in the reflection vector for the N input will take care of the "centre vector", but I'm not sure how you can reduce the cone angle.

Cheers!

Link to comment
Share on other sites

o! great, thanks for more info against my ignorant's way. I'm not really sure but is ambient VOP just a simplfied version of vex func with all this stuff like cone angle?

as taken from RenderMan pictures, "real" reflection occlusion with properites as you specified, are just B/W map of highly contrasted occlusion. So good point with using standard ambient occlusion is that you save one pass more of rendering. I used to make some comparisions, and I almost alway could reproduce reflection occlusion map from ambient occlusion map with some tweakings. But, of course, you're right, there are differences, and for situation they can by noticable, its better to use "real" occlusion reflection...

but what is "real" anyway..? ;)

thanks again for info.

SY.

Link to comment
Share on other sites

  • 4 weeks later...
is there a way to get something like this with mantra. I know mentalray can, but I would be interessted in a mantraway. does it mean to code this by hand or are there some shaders or vex

(what about bent normals)

As rjpieke already mentioned, reflection occlusion is simply "ambient occlusion" except centered in the direction of mirror reflection, and with a smaller angular spread (possibly zero for perfect mirrors). The average unoccluded direction, or "bent normal" is typically computed as part of the occlusion calculation (ambient or otherwise). Of course, the term "bent normal" is meaningless in the case of reflection occlusion, since there's no relationship to the surface normal at all in that case.

Both of these things are available in VEX (as in RSL) through one of the forms of the occlusion() function, specifically:

void occlusion(vector P, vector N, float &coverage, vector &missed_direction, [options])

Instead of computing color information from ambient occlusion, this form of the occlusion() function will compute the coverage (the percentage of occlusion), and the average direction of empty space. The average direction can be used to lookup the color in a pre-blurred environment map.

Unfortunately, this form of the occlusion function is not available in VOPs -- or rather, it is only available through the Inline VOP.

One last thing: unless 90% your reflections are coming from some infinitely distant environment map, and unless tracing that small percentage incurred an unacceptable overhead to the renders (usually not the case in either Mantra or Renderman nowadays), I would definitely not bother with reflection occlusion. I believe that technique (from the SIGG2002 renderman notes), though useful sometimes, is generally not as necessary these days as it was then.

HTH.

P.S: The link you posted is busted.

Link to comment
Share on other sites

  • 3 years later...

Bringing back this thread with a question... (thanks for the great info, everyone)

And to recap, forum user rob has now wrapped the occlusion() form that supports coverage/cone angle into a VOP otl:

Thanks rob.

So, the question: what is the "correct" way of using a reflection occlusion pass in comp (or use that grayscale value in a shader)?

Existing papers (Sigg "02, etc) say that the pass is used to "attenuate" the reflections from the environment texture map.

Does this mean I should multiply the reflection occlusion value into the color looked up from environment() ?

Or should it be subtracted from the environment() color?

Link to comment
Share on other sites

  • 2 weeks later...

Bringing back this thread with a question... (thanks for the great info, everyone)

And to recap, forum user rob has now wrapped the occlusion() form that supports coverage/cone angle into a VOP otl:

Thanks rob.

So, the question: what is the "correct" way of using a reflection occlusion pass in comp (or use that grayscale value in a shader)?

Existing papers (Sigg "02, etc) say that the pass is used to "attenuate" the reflections from the environment texture map.

Does this mean I should multiply the reflection occlusion value into the color looked up from environment() ?

Or should it be subtracted from the environment() color?

What I did was to modify the trace vop to output the ray length normalized to the max distance (much better than just On/Off occ), as well as color.

I can select whether to use occluded only or regular * occluded at the ray bounce limit (it's manually set at the mo).

This came about due to the need to use very few refl bounces, say 1 or 2, and how the bright environment map reflections become very obvious (way too bright at the ray bounce limit), this is because they dont have a chance to diminish in intensity sufficiently within so few bounces. So the idea is to let the reflection occlusion (which is actually a black = near, white = far ramp) multiply the reflection at the bounce limit. In other words, in a four bounce reflection, it will bounce once, twice, three times then at the fourth the occlusion takes place based on distance, thus faking the infinite decrease in energy with subsequent imaginary bounces...

Hope this helps

S

btw, this was one of my very first attempts at coding!

Outer Code

#include <voptype.h>
#include <voplib.h>

vector4
axis_vop_trace_refl(vector Nf, nN, PP, dir, bg; string envmap, scope; float bias, maxdist, angle, thresh, jitter, occpower, occmaxdist; int occluded, occstartlevel; int samples; float nhit; string envobj; float envgain;)
{
    nhit = 0;
    vector sum = 0;
    vector raydir = 0;
    vector Cf = 0;
    vector4 sumdist = 0;
    float  dist = 0;
    int raylevel = getraylevel();
    vector hitOf, hitP;
    float  hitAf;   

    gather (PP, dir,
            "Cf", Cf,
            "Of", hitOf,
            "Af", hitAf,
            "P",  hitP,
            "ray:direction", raydir,
            "distribution", "uniform",
            "samples", samples,
            "scope", scope,
            "bias", bias,
            "maxdist", maxdist,
            "angle", angle,
            "raystyle", "reflect",
            "rayweight", thresh,
            "samplebase", jitter,
            "variancevar", "hitRefl")
    {
        dist = length(hitP-PP);

        if (occluded == 1)
        {
            dist = fit(dist,occmaxdist,0,1,0);
            sum += vop_trace_environment(envmap, envobj, raydir, bg)*pow(dist,occpower) * envgain;
        }

        else
        {
            if ((raylevel+1) >= occstartlevel)
            {
                dist = pow(fit(dist,occmaxdist,0,1,0),occpower);
                sum += Cf * dist;
            }
            else
            {
                sum += Cf;
            }
        }
        if (vop_maxcomp(hitOf) < 1)
        {
            sum += (set(1,1,1) - hitOf) *
                   (vop_trace_environment(envmap, envobj, raydir, bg) * envgain);
        }

        nhit += 1;
    }
    else
    {
        dist += 1;
        sum += vop_trace_environment(envmap, envobj, raydir, bg) * envgain;
        nhit += 1;
    }
    sumdist += sum;
    setcomp(sumdist,dist, 3);
    return sumdist;
}



Inner Code:

VOPpoint  $pp = ($isconnected_pos != 0) ? $pos : P;
VOPnormal $nn = ($isconnected_nN  != 0) ? $nN  : normalize(N);
VOPvector $ii = normalize(I);
VOPnormal $nf = vop_frontface($nn, $ii);
VOPvector $rr = ($isconnected_dir != 0) ? $dir : reflect($ii,$nn);
VOPfloat  $Kf = ($isconnected_Kt != 0) ? $Kt  : 1;
VOPfloat  $angle_rad = radians($angle);

VOPint $scount = clamp($samples*vop_getrayweight(), 1.0, VOP_CAST_FLOAT($samples));
VOPfloat $thresh = $Kf * vop_maxcomp($tint) / VOP_CAST_FLOAT($scount);

VOPfloat $nhit = 0;

$clr = axis_vop_trace_refl($nf, $nn, $pp, $rr, $bg, $envmap, $scope, $bias, $maxdist, $angle_rad, $thresh, $jitter, $occpower, $occmaxdist, $occluded, $occstartlevel, $scount, $nhit, $envobj, $envgain);

#if defined(__vex)
  if ($angle_rad == 0)
        $F = specular($rr);
  else {
        bsdf $rlobe = cone($rr, $angle_rad);
        $F = (1.0 / luminance(albedo($rlobe))) * $rlobe;
  }
  $F *= ($Kf * $tint);
#else
  $F = 1;
#endif

$clr *= ($Kf * $tint)/max(1,$nhit);

Edited by Serg
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...