How to get the reflected light vector in Cycle Renderer?

Hello there!

I’m searching for a solution to calculate a reflected light vector. I want to use this to get the angle between the reflected light vector and the incoming camera vector. The resulting angle should be used with a color gradient or as a blending factor.

I know it isn’t possible to obtain a light position in Cycle. That’s why I’m using a Combine XYZ with Driver to connect one light position (sun).

The formula to calculate the reflected light vector should be:

R = L - 2 N ( L . N )

L - light vector
N - normal (of shading point)
. - dot product

To get the final angle between the reflected light vector and the camera, I’d just take the dot product between the two vectors.

I’ve translated both terms into these networks:

and

(can’t post another image, I’ll try to post it in a comment)

Unfortunately, it doesn’t work. The resulting value is somewhat dependent on both inputs (camera, light position), but it’s nowhere near the expected result. The yellow material should only be visible when the light is reflected. At least to my understanding.

Could anyone help me with this? Thank you!

1 Like

And the dot product between the reflected light vector and the incoming camera ray with a simple two color material blending to show the result:

1 Like

First, welcome to the comunity.

This is a tricky matter, as we don’t have access to the output vector… Well the output vector is easy to find in a glossy with no roughness, which is Out = 2*N*(N.In) - In (, or in 2.82+ series, with Out = -Reflect(I, N))… but with roughness, you don’t have N anymore; It is computed for each sample by microfaceting the original N.

To escape this dilema, you cannot use the builtin roughness; you need to create your own microfaceting, in order to have the real N (the half-vector to be more precise) for each sample. This however is not optimized for a clean rendering, and Cycles might miss a light if it’s too small, creating a huge amount of noise.
I use this method (explained here) to make diffraction gratings, thought it can be tweaked to produce other structural colors to some extend, but it requires lots of samples to get it look good.

As secrop mentioned, you can use the built-in reflect function in later versions of Blender. This seems to work fine:

Here, I’m using an empty to represent a point light for per-sample light vectors. I’m sure there’s some way I could do the same thing for a sun lamp, but it’s early and my brain isn’t working very well yet. Point lamp makes it easier to see that it’s working right. (Like in that picture, incoming dot reflect is near 1 on the cube face and on the silhouette of the suzanne.)

The formula you’re using is the negative of formulas I’ve seen online. But the formula you want is going to depend on how you define your vectors. Is your light vector the vector from your surface to your light, or the vector from your light to your surface? (Have to be careful about the same thing with your incoming.)

Also, of course, remember you’re getting the reflect from a sun lamp here, not a point lamp. For a point lamp, light vector is a per-sample quantity.

Finally, I’m not sure if the reflection of light over n is really what you want. In 3D rendering, a much more commonly used value is the half vector (light+incoming/2, or consider it the bisection of the angle formed by light and incoming), which is frequently compared to the normal.

Like I said, I don’t think my head’s all there yet, I need a few more cups of coffee, so I might have said something dumb, be on your toes.

1 Like

Hi @Bandages thank you for this example.
I’ve set this up, and I’m trying to figure how to “Squeeze” the specularity like this:

I’ve tried using the vector math node subtract after the result of the dot product, but all that does is to intensify or diminish the reflection.