lighting()

advertisement
Diffuse Illumination
• Diffuse illumination is associated with specific light sources
but is reflected uniformly in all directions. A white sheet of
paper has a high degree of diffuse reflectivity. It reflects
light but it also scatters it so that you cannot see the
reflection of other objects when looking at the paper. Here
is an example of an image with 3 light sources positioned
around a sphere:
Diffuse Illumination
• To model diffuse reflectivity requires the presence of one
or more light sources. The first type of light source that
we will consider is the point light source. This idealized
light source emits light uniformly in all directions. It may
be located on either side of the virtual screen but is itself
not visible.
Diffuse Illumination
• The lights will be managed in a way analogous to the visible objects,
but will reside on a separate list pointed to by the “lightList” pointer in
the scene_t class.
class scene_t
{
public:
scene_t(ifstream &infile);
int getindex(char *token, char *table[]);
void loadScene(ifstream &infile);
void dumpScene();
window_t *getWindow();
image_t *getPicture();
/** Lists of objects in the virtual world **/
list_t *sobjList;
/* scene objects list
list_t *lightList;
/* "Lights" list
private:
int magic;
window_t *window;
image_t *picture;
};
/* magic number
/* Window data
/* output image
*/
*/
*/
*/
*/
Properties of point light sources
• The pointlight_t class holds the location and color
intensity of a point light.
class pointlight_t : public entity_t
{
public:
pointlight_t(ifstream &infile, const string & objtype);
void load(ifstream &infile, const string & attr);
myvector getcenter();
mycolor getcolor();
double getbrightness();
void
dump();
myvector processLight (scene_t *scene, entity_t *ent, hitinfo_t *hit);
private:
myvector center;
mycolor color;
double brightness;
};
Properties of point light sources
• The color of the point light is specified by the color field.
The brightness value indicates how bright the light is.
• The r, g, b color intensities of the light can be computed
as an intensity_t by multiplying each component of the
light’s color by the light’s brightness.
• The effect of a light on the color of a pixel that is
illuminated by a light is the component-wise product of
the light’s intensity as computed above and the diffuse
reflectivity of the visible object.
Properties of point light sources
• In a ray traced scene consisting of a single plane and a
single light, it is not possible to determine from the image
whether a red material is being illuminated by a white
light or a white material is being illuminated by a red light!
• Furthermore, if a pure red light illuminates a pure green
sphere, the result is purely invisible! This effect is counter
to our experience because in the “real scene,”
monochromatic lights and objects with pure
monochromatic reflectivity are not commonly
encountered.
Specifying a light in a model description file
• In the model description language an example of
specifying a blue light is:
pointlight
name
bluelight ;
color
255 200 100 ;
brightness 6
center
0
4 -3 ; ;
• The attributes of a point light are the color and
brightness values of the light and the coordinates of the
center of the light.
Diffuse Illumination
• A constructor and appropriate load (), dump(), and
getter methods will need to be added to the ray tracer
to process the characteristics of a light as specified in
the SDL file.
• These methods should be placed in the module
pointlight.cpp
Determining diffuse illumination for a pixel
• Diffuse illumination should not be computed directly in
the rayTrace() function. The procedure is sufficiently
complicated that it should be implemented in a separate
module that we will call lighting.cpp. It will contain a
function called lighting() that will be called by the
rayTrace() function.
Determining diffuse illumination for a pixel
/**/
/* This function traces a single ray and returns the composite */
/* intensity of the light it encounters. It is recursive and */
/* so the start of the ray cannot be assumed to be the viewpt */
myvector rayTrace(scene_t *scene, point_t base, vector_t dir, double total_dist,
entity_t *self)
{
use closest() to determine closest object
if nothing hit return intensity values of 0 (black)
add distance from base to closest object to total_dist
set intensity to the color of closest object times the ambient light
of the scene
Add the diffuse light of the object at the hit point to the intensity
divide intensity by 255
divide intensity by total_distance
return intensity
}
Determining diffuse illumination for a pixel
Important notes:
• The ambient light is a property of the object as a whole.
• The diffuse light is a function of the specific hit point.
• The contribution of all lights that are visible from the hit
point must be summed.
Computing the diffuse reflectivity of an object
• A function having the following prototype provides a
useful front end for the diffuse computation. It should be
called from rayTrace() as shown in the pseudo code on
the previous slide.
intensity_t lighting(
scene_t *scene, /* pointer to scene structure */
entity_t *ent, /* pointer to scene object just hit */
hitinfo_t *hit) /* pointer to scene object’s hitinfo */
{
set total_illumination triple to zeros
for all lights on the light list
{
add return value from processLight(…) to total_illumination
}
return total_illumination
}
Computing the diffuse reflectivity of an object
•
•
Since there may be other types of lights than just point
lights that this procedure might process, this procedure
should be placed in the separate module lighting.cpp.
We use idealized point light sources which are
themselves invisible, but do emit illumination. Thus
lights themselves will not be visible in the scene but the
effect of the light will appear.
Determining if a point light illuminates the hit point
The processLight() function performs this portion of the algorithm.
intensity_t processLight(
scene _t *scene, /* pointer to scene’s entity_t */
entity_t *ent, /* the current scene object */
hitinfo_t *hit) /* pointer to scene object’s hitinfo data */
{
if the object hit occludes itself from the light source
return 0 triple
call closest(...) with a ray starting at the center of the light and
pointing in the direction of the hit point
if the object hit by this call is not the original object, //some other
// object occludes light
return 0 intensity
compute and return illumination intensity
}
Determining if a point light illuminates the hit point
• Determining if a light is occluded, and if not, the
contribution this light makes to the brightness and color
of a given pixel is described in the following sections.
This procedure should be placed in the pointlight.cpp
module.
Testing for occlusion
• The diagram below illustrates the ways in which objects
may occlude lights. The small yellow spheres represent
lights and the large blue ones visible objects.
Testing for occlusion
We will assume convex objects. An object is self-occluding if the
angle between the surface normal and a vector from the hit
point toward the light is larger than 90 degrees. In this case the
cos(θ) would be negative. Recall that the dot product of two unit
vectors computes the cosine of the angle between them. In the
illustration above cos(θ) would be positive since is less than 90
degrees, while cos(θ') would be negative and the light source to
the right of the object would be self-occluded.
Testing for occlusion
• A simple test for this condition is that an object is not
self-occluding if
the dot product of a unit vector from the hit point to
that light with the unitized surface normal is positive.
• To see if a light is occluded by another object, a ray can
be fired from the center of the light towards the hit point.
If the ray hits the original object then the light is not
occluded. Note this is the case with the red vector in the
illustration. If the ray hits a different object then the light
is occluded. This is the case with the orange ray.
Testing for occlusion
• We can use closest() to determine if the ray hits the original
object.
• The base of the ray is the coordinates of the center of the light
• The direction vector is a unit vector pointing in the direction
from the center of the light to the hit point (note this is a
vector pointing in the OPPOSITE direction than the vector used
to determine if the light was self-occluded, e.g. the purple
vector).
• For the red vector the “ent” pointer parameter and the entity
pointer returned by the call to closest(), starting from the
center of the light, would match.
• For the orange vector the “ent” parameter and the entity
pointer returned by closest() would not match since the ray hit
another object.
Computing the illumination
• If a light does illuminate the hit point, its effect must be
added to the pixel intensity of the current pixel. The
effect of the light is determined by the light’s color, the
light’s distance from the hit point, the angle of the light to
the hit point, and the diffuse reflectivity of the object
itself.
Computing the illumination
• The red, green and blue components of the effect of the
light can be computed as follows:
result.x = diffuse.x * intensity.x * cos(θ) / dist_from_pointlight_to_hitpoint
result.y = diffuse.y * intensity.y * cos(θ) / dist_from_pointlight_to_hitpoint
result.z = diffuse.z * intensity.z * cos(θ) / dist_from_pointlight_to_hitpoint
• The above computation assumes that diffuse contains the
object’s “diffuse”. The color intensities of the light are
computed as an intensity_t by multiplying each
component of the light’s color by the light’s brightness.
• Note: remember that “cos(θ)” is just the dot product of
the unit normal and the unit vector pointing from the hit
point to the center of the light (you don’t actually call
cos()).
Download