CS 371
Computer Graphics
Spring 2005


6 More on Lighting & Ray Casting

6.1 The GraphicsWindow Library

Refer to the class notes from the previous class for details.
// This may look like C code, but it is really -*- C++ -*-

// GraphicsWindow.h

// (C) Bill Lenhart 1995

#ifndef GRAPHICSWINDOW_H
#define GRAPHICSWINDOW_H

#include <iostream>
#include <string>
#include <stdlib.h>
#include "GraphicsObject.h"

//////////////////////////
// class GraphicsWindow //
//////////////////////////

// A very basic window in which individual pixels can be manipulated.
// It extends a class called GraphicsObject which merely hides some
// low-level X-Windows set-up
class GraphicsWindow : public GraphicsObject {

public:

  // Pixel Writing Modes
  enum PenMode {CopyMode, IgnoreMode, XOrMode, AndMode, OrMode};

  // The constructors create--but do not display--the window
  // Default writing mode is CopyMode
  // Creates a window with default dimensions
  GraphicsWindow(void);

  // Creates a window with given dimensions
  GraphicsWindow(int xDim, int yDim);

  // Destructor
  ~GraphicsWindow(void);

// Window operations

// Make window visible
  void Show() const;

// Get Window dimensions
  int GetWidth(void) const;
  int GetHeight(void) const;

// Drawing Operations

// Draw a pixel at location (x,y): (0,0) is lower left pixel
  void DrawPixel(int x, int y) const;

// Draw a pixel at location (x,y) using color RRRRRRRRGGGGGGGGBBBBBBBB
  void DrawPixel(int x, int y, unsigned long colorIndex) const;

// Draw a pixel at location (x,y) using color (RRRRRRRR,GGGGGGGG,BBBBBBBB)
  void DrawPixel(int x, int y, int r, int g, int b) const;

// Draw a pixel at location (x,y) using color (r,g,b): 0 <= r,g,b <= 1;
  void DrawPixel(int x, int y, float r, float g, float b) const;

// Erase a pixel (only true erase in CopyMode)
  void ErasePixel(int x, int y) const;

// Erase the window (only true erase in CopyMode)
  void Erase(void) const;

// Erase the buffer
  void EraseBuffer(void) const;

// Draw an X in window 
  void BigX(void) const;

// Turn Double Buffering on/off
  void BufferOn(bool);

// Copy the buffer to the window
  void ShowBuffer(void) const;

// Where subsequent commands should draw
  void DrawToWindow(void);
  void DrawToBuffer(void);

  // Color Operations

  // Access foreground & background colors
  // color described by bits rrrrrrrrggggggggbbbbbbbb of unsigned long
  unsigned long GetForeground(void);

  unsigned long GetBackground(void);

  void SetForeground(unsigned long colorIndex);

  void SetBackground(unsigned long colorIndex);

  // color described by 0 <= r,g,b <= 255
  void SetForeground(int r, int g, int b);

  void SetBackground(int r, int g, int b);

  // color described by 0.0 <= r,g,b <= 1.0
  void SetForeground(float r, float g, float b);

  void SetBackground(float r, float g, float b);

// Pen Operations

// Get and Set Pen Mode
  PenMode GetPenMode(void);

  void SetPenMode(PenMode);

// Misc.

// Debugging Aids
// Draw a "unit pixel" segment between pixels  (x1,y1) and (x2,y2)
  void DebugSegment(int x1, int y1, int x2, int y2);

// Hey!  You know the rules....
// Warning:  XWindows below....
protected:

  static const int DEFAULT_X_DIM, DEFAULT_Y_DIM;

  // Window dimensions
  int width, height;

  // Window depth
  int depth;

  // where should drawing occur?
  Drawable currentCanvas;

  // buffer info
  Pixmap theBuffer;

  // Is double buffering in effect?
  bool bufferingOn;

// Pen Info

  PenMode thePenMode;

// Utility functions
  // Erase the buffer
  void EraseCanvas(Drawable) const;

// converting from X Drawing Mode to GraphicsWindow PenMode and back
  PenMode XToPenMode(int);
  int PenModeToX(PenMode);

// members for graphics context
  GC theGC;
  XSetWindowAttributes *theDWAttributes;
  
  Window theGraphicsWindow;

// location of window relative to root (parent) window
  int topLeftX,topLeftY;
  // width, in pixels, of border
  unsigned int borderWidth;
  // pixel to use for border
  unsigned long borderPixVal;
  // pixel to use for background
  unsigned long backgroundPixVal;

// Color info
  void defineWindow(int XDim, int YDim);

  void CreateXWindow();
};

#endif GRAPHICSWINDOW_H

6.2 More on Lighting

So far, our lighting model is, for each wavelength (e.g., red, green, and blue) considered:
I = Ia rhoa + Id rhod (l ·n)/(||l|| ||n||) + Is rhos ((r ·v)/((||r|| ||v||)))f.

This shading model is called Phong shading. If we surpress the specular component, we get what is often called Lambert shading. Some texts use a common value Id = Is, others include multiplicative factors, using Od Id and Os Is instead of Id and Is, where Od and Os are the same for all wavelengths. This provides easy adjustment of overall intensity. It is possible to speed up the computation of the specular component by the use of the half-way vector. See your text and class notes for details.

It is simple to include terms to adjust for the attenuating effects of distance and atmosphere, if the light source and eye are not at infinity. A positional point light source is given by a location in space. Such a source radiates light equally in all directions.

6.2.1 Distance & Atmospheric Attenuation

The distance of a positional light L from a surface point p can be used to compute an attenuation value fatt that can be multiplied by the diffuse and specular intensity components of the light. An obvious choice would be (1)/(d2), where d = ||L.position - p||, since this reflects the inverse square law describing how much light reaches the point. In practice, a formula of the form fatt = (1)/(a + b d + c d2) works better in most cases. fatt should be in the range [0,1].

For atmospheric attenuation, we use a technique known as depth cueing: For each wavelength, an intensity Idc is selected as the intensity we would see if the surface were completely obscured by the atmosphere. We then take the standard (say Phong) intensity I of the surface and combine it with Idc: I' = s I + (1 - s) Idc, where s is in the range [0,1] and depends on the distance from the surface to the eye. For example, we might use:
s = smin + ((D-Dmin)(smax - smin))/((Dmax - Dmin)), for points whose distance from the eye is between Dmin and Dmax. Then we would use s=1 for closer points and s=0 for farther points.


lenhart@cs.williams.edu