Sign in to follow this  

Rim/Fresnel Light vs. self-shadowing

This topic is 2840 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have a question regarding rim/fresnel lighting (do those terms usually refer to the same thing): If I use it, edges will of course be highlighted more or less. A problem I am seeing is when the object is also shadowing itself. I often have relatively ugly artifacts near the edge of the self-casted shadow (I hope that makes sense) that are usually hidden by the very low diffuse light. The fresnel term lights it up though making those artifacts very visible. On possible solution I could think of was applying the fresnel after the shadow mapping so to speak. But that would be somewhat unrealistic and worse, could look awkward if one object was (completely) shadowed by something else. Is this a common problem, how could it be avoided?

Share this post


Link to post
Share on other sites
to get correct results, you need to get per-pixel directional occlusion for your model.
you could fake this with standard ambient occlusion, and weight your rim-lighting with the scalar occlusion value, or use more complex representations (for example, a scalar occlusion factor + an average aperture direction vector, or spherical harmonics)

I doubt that using shadow maps for this would produce good results. the shadow maps encode occlusion for the vector going from the point you're shading to your light, whereas you want the occlusion for the vector going from the camera to the pixel/fragment, reflected along the pixel's normal.

Share this post


Link to post
Share on other sites
Hm, not sure we mean the same thing. I'll try to explain my problem again.

Consider a sphere and a directional light. One half of the sphere will be completely dark, the other one is light and gets continually darker. The dark side is self-shadowed as well, which doesn't make a difference because it is dark anyway.
With rim lighting however, portions of the unlit side will be lit and thus make the self-shadowing artifacts visible.
I believe in that case pixel-perfect occlusion wouldn't help either.

Do you know what I mean? Tomorrow I could post a screen shot.

Share this post


Link to post
Share on other sites

Please do post some screenshots. I'm trying to visualize what's wrong, but I think we're a bit in the dark what the problem is exactly [smile]

If I understand correctly, your problem basically is that you have artifacts on the edge where selfshadowing starts, right? The rim lighting is only making them visible, but a high ambient term for example would also make the problem pop up? If so, you might just want to focus on fixing the shadowing artifacts (higher resolution/better filtering/more offset etc).

Regardless of that, is rim lighting realistic anyway? Isn't it just a fancy effect, maybe a crude approximation to subsurface scattering? I'm not arguing either way, but if it's unrealistic in the first place, attentuating the rim lighting by the 'shadow factor' would probably be your best bet.

Share this post


Link to post
Share on other sites
Quote:
Original post by remigius
If I understand correctly, your problem basically is that you have artifacts on the edge where selfshadowing starts, right? The rim lighting is only making them visible, but a high ambient term for example would also make the problem pop up? If so, you might just want to focus on fixing the shadowing artifacts (higher resolution/better filtering/more offset etc).

That is exactly the problem. (Except that I don't believe a high ambient would have the same effect, as the shadowed area basically only is lit by ambient.)
Even if I get rid of the shadow artifacts, I would still have the problem, that the self-shadowing starts rather abruptly when it's not hidden by gradually darkening diffuse lighting. Don't you agree?

Share this post


Link to post
Share on other sites
AFAIK, rim lighting / fresnel reflection / whatever you call it, represents the reflection of the environment on the object.
therefore it should not be bound to the shadowmap. you can see this as an additive emission term.
if it emphasizes some shadowmap artifacts, It might be because you're applying the rim lighting contribution to the wrong part of your lighting equation?
seeing some screenshots of these self-shadowing artifacts would definitely help.

basically, you should have something like:

FinalColor = DiffuseColor * (DiffuseLighting * ShadowCoeff + AmbientLighting) + EmissionColor + Specular + EnvironmentReflection;

(conceptually, Specular and EnvironmentReflection could be merged into the same term)

your rim lighting contribution is located in the 'EnvironmentReflection' part.
it should not be affected at all by any shadowing artefacts. it doesn't increase their contrast, it doesn't light-up backfaces.

Share this post


Link to post
Share on other sites
Hm. Apart from the problem I'm having it seems that I might have misunderstood something here.

In as much is the rim lighting affected by an actual light source? Lets say I have 3 contributing light sources, do I compute the fresnel term once or 3 times? What if I have zero lights?

Share this post


Link to post
Share on other sites
hm. perhaps you're talking about the normal reflectance factor used for the specular highlights then?

rim-lighting does not depend on the number of lights, it's a global term, like ambient. you can compute rim lighting from an environmental cubemap, or a constant color, etc...

however, you can add a fresnel term to your specular highlights too, making them brighter at a grazing angle (like human skin). is this what you want to achieve ?
in this case you will have a distinct fresnel computation per-light.

Share this post


Link to post
Share on other sites
Quote:
Original post by momotte
however, you can add a fresnel term to your specular highlights too, making them brighter at a grazing angle (like human skin). is this what you want to achieve ?
in this case you will have a distinct fresnel computation per-light.

Aha, thanks for the explanation. I suppose I was trying to achieve something like that. But I'm not getting it right now. The grazing angle is computed between the surface normal and the view direction, right? So where does the lighting computation come into play here?
I appreciate the help, as I am a bit confused by the rim lighting term.


Share this post


Link to post
Share on other sites
that's right for the 'global' rim-lighting, where you sample the environment (and where you would need perpixel occlusion information)
with V = normalize(ViewPos - PixelPos)
you'd do:

reflectedRay = reflect(V, N);
rim_lighting = sample_environment(reflectedRay) * fresnel2(dot(N, V), Kr) * occlusion(reflectedRay, ...);

with:

float fresnel2(float v, float kr) { return kr + fresnel(v) * (1.0 - kr); }

here, kr represents the amount of reflected light at normal incidence, between 0 and 1


for specular highlights, you could try:

for each light:
L = normalize(LightPos - PixelPos);
H = normalize(L + V); // half-vector
spec = shadowCoeff * fresnel2(dot(H, V), Kr) * shininess * pow(dot(N, H), specularExponent); // or whatever specular function you're using...

Share this post


Link to post
Share on other sites
What if we use a half-lambert lighting model? The shadow will flicker on the edges too, as the light goes beyond N dot L..how would you handle this?

Share this post


Link to post
Share on other sites
That's an interesting question...

I guess you could try fading away the shadow contribution depending on various parameters, like the distance between the shadow caster and receiver, and the real N.L value.
fade away the contribution when both the N.L value is close to zero and the shadow-caster to receiver distance is small enough?

something like:

ndotlScaler = 1.0f / 0.2; // 0.2 == distance below witch the fading will start
distanceScaler = 1.0f / 0.2; // 0.2 == distance below witch the fading will start
ndotlFader = nDotL * ndotlScaler;
distanceFader = (pixelDepth - shadowDepth) * distanceScaler; // (assuming positive linear depth values)
shadowCoeff = 1.0f - (1.0f - shadowCoeff) * clamp(ndotlFader * distanceFader, 0.0f, 1.0f); // assuming shadow coeff to 0 means fully shadowed, 1 fully lit

?

I'm not sure it would look good enough though...
perhaps just the distance fade would be better. you'd still get shadows from objects in front of the receiver, but it would kind of disable shadows for the receiver itself...

or using a min(ndotlFader, distanceFader) might be better than the mul.
it looks like it would require a lot of tweaking to get right...

by the way, do games that use half-lambert lighting (like team forteress2), actually have self-shadowing objects ?

Share this post


Link to post
Share on other sites

This topic is 2840 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this