Houdini VOP raytracer part 5

Posted on October 2, 2013

Specular Hilight

A specular highlight is a bright spot of light that appears on shiny objects when illuminated. The term specular means that light is perfectly reflected in a mirror-like way from the light source to the viewer. We are going to cover two specular reflection models.

Phong reflection model.

K{\tiny spec} = \big\|R\big\| \big\|V\big\| cos^n \beta =(\hat{R} \cdot \hat{V})^n

Where \hat{R} is normalised mirror reflection of the light vector off the surface, and \hat{V} is normalised viewpoint vector. The number ^n is called the Phong exponent, and is a user-chosen value that controls the apparent smoothness of the surface. When calculating (\hat{R} \cdot \hat{V}), again we will get negative values like we had in diffuse calculation, so we have to clamp it, max(0,(\hat{R} \cdot \hat{V})).



You can refer to the example above, that we get specular also on the back of our sphere. There are few ways to fix that issue, for e.g. we can multiply sampled position by shadow that we already have calculated (shadowed area ==0, non shadowed ==1) or make another dot product test with normal vector.

Below is a phong model representation in Houdini nodes. First, calculate reflection vector \hat{R}. As law of reflection states – direction of incoming light (the incident ray), and the direction of outgoing light reflected (the reflected ray) make the same angle with respect to the surface normal. In this situation reflect vex node comes in handy. It takes input of vector to be reflected – in our case vector of Light towards the surface (It is very important to check your vector direction) and input of normalised surface normal vector. As an output we will get reflected R vector which should be normalised (\hat{R}). Vector \hat{V} is normalised Houdini (“I”) – vector towards Eye (Camera). After calculating dot product between those two vectors (\hat{R} \cdot \hat{V}) , we need make sure that we clamp negative values. I use clamp vex node instead of maxing it with zero as I know that values from dot product of normalised vectors won’t exceed value of 1. Last part is to use power function to control exponent and simple multiplication for overall intensity.

Screen Shot 2013-10-01 at 1.07.42 AM

Phong-Blinn reflection model

K{\tiny spec} = \big\|N\big\| \big\|H\big\| cos^n \beta =(\hat{N} \cdot \hat{H})^n

Where \hat{N} is normalised smooth surface normal vector off the surface, and \hat{H}  is the half-angle direction (the direction vector midway between L, the vector to the light, and V, the viewpoint vector).

First problem we will find here is that our halfway vector \hat{H} will jump as soon as angle in between L and V is larger than 180°. Here is an example with non clamped values of rotating light by 360°.


H – half-angle direction between L and V
N – smooth surface normal
R – Mirror reflection of the light vector
L – Light vector towards surface
V – viewpoint vector (eye/camera)

Here you can see both specular models with clamped values.


As you have noticed, Blinn reflection model give us wider specular as the angle between R-V is more aggressive than N-H. We can compensate the difference by adjusting exponent. Maxing (or clamping in this example) dot product is very important as we would get undesirable effect when calculating exponent from negative values.


First lets calculate \hat{H} vector between the viewer and light-source vector.

H = \frac{L + V} {|L + V|}

Halfway vector {H} equals sum of vectors {L} and {V} divided by sum of their lengths. In many internet examples you will see calculation of halfway vector presented like this:

H = \frac{L + V} {2}

This is not the mathematically correct way of calculating {H} vector but in our case vectors {L} and  {V} are normalised (their length is equal of 1.0) so sum of their lengths will equal 2.

 Next step is a dot product calculation with normalised surface normal. Rest of nodes are exactly the same as in phong model.


To get rid of jumping \hat{H} vector, we can add second dot product calculation for negated halfway vector.


Screen Shot 2013-10-01 at 12.52.06 AM

Mantra shader version of specular model

Mantra has build in specular vex node with few specular models. To create your own model, we need Illuminance Loop vex node that will iterate through all active lights in scene file. To get L vector, you can create global variables vex node (global variables vex node is different inside and outside illuminance loop). L vector vector provided by global variables is a “Direction From Surface to Light”  so we need to negate it (reverse its direction). Global I vector (eye) is “Direction From Eye to Surface” (equivalent of our V – Viewpoint vector), also needs to be negated for proper dot product calculation. This setup should produce exactly same effect as build in Phong model from specular vex node.




<< [ 4 ] [ 5 ] [ 6 ] >>


Be the first to leave a comment

Leave a Reply

%d bloggers like this: