Shaders and texture maps

Texture mapping enhances the visual richness of 3D graphics by creating the appearance of complexity without modeling and rendering every 3D detail on a surface. The data contained in a texture map can do many things such as represent base colors of a surface, be used for normal vector perturbation (bump map), or represent a simple reflection that simulates the surrounding environment of 3D graphics. Figure 197 shows the shaders and their texture maps. Note that TSurfaceShader uses all three texture maps.


Image mapping

TImageMapShader is used with TImageTextureMap make a solid surface color modification. The TImageMap class is used with shaders that interpret the contents of a map as a solid surface color modification. The texture created by a TImageMap instance is applied to a surface in much the same way that wallpaper is applied to a wall. The value extracted from TImageMap can be used for a direct color substitution, as an index to another color map, or as a multiplier. Figure 198 shows the image map class architecture.


The TImageMapShader::ComputeShade function (called by the drawing port) gets the color value from the TImageMap instance. The value extracted from the image map can be one of the following constants:

kDirectSubstitution: The color extracted from the map is the base color and is substituted for whatever color is set in the TGrafBundle3D or TReflectanceShader.

kMultiplier: The color extracted from the map is converted to a gray scale value and used as a multiplier for the color defined in the TGrafBundle3D instance or TReflectanceShader.

TImageMapShader has a default TReflectanceShader instance. Once the color is extracted from TImageMap, the color is modified by light sources defined in TReflectanceShader. Use the TImageMapShader::SetChildShader function to change the default TReflectanceShader.

Bump mapping

TBumpMapShader is used with TBumpTextureMap to simulate or bumpy or dimpled surface. It is a useful alternative to creating the same effect by altering the surface geometry or modulating the color of a flat surface. The bump map changes the reflection model by using a perturbed surface normal; however, the surface perturbations do not appear on the silhouette edge as they would if the surface geometry were altered instead. Figure 199 shows the bump map class architecture.


The TBumpMapShader::ComputeShade function (called by the drawing port) gets the luminance value from the TBumpMap instance that is indexed by the texture coordinates. This value is used in the new surface normal to compute the displayed color.

TBumpMapShader has a default TReflectanceShader instance. Once the original normal is modified by TBumpMap, the color of the graphic is modified by light sources defined in TReflectanceShader. TBumpMapShader::SetChildShader changes the default TReflectanceShader.

The following code puts a bump map shader onto the cylinder sweep in Figure 200.


    1  TGLoop contour( TGEllipse( TGRect( 0, 0, 200, 200 ) ) );
    2  contour.ReverseDirection();
    3  
    4  TGCurve3D trajectory( TGPoint3D( 100, 0 , 100 ), 
    5                      TGPoint3D( 100, 50, 100 ), 
    6                      TGPoint3D( 100, 75, 100), 
    7                      TGPoint3D( 100, 100, 100 ) );
    8  
    9  TSweep3D simpleSweep( contour, trajectory, TGPoint3D( 1, 0, 0 ) );
    10  
    11  TGrafBundle3D*  surfaceBundle = new TGrafBundle3D( new TRGBColor( .75, .75, .75 ), 
    12                                                  TAttributeState::kFill  );
    13  simpleSweep.AdoptBundle( surfaceBundle );
    14  
    15  TGPolygon polygonGeometry;
    16  polygonGeometry.Append( TGPoint( 0, 0 ) );
    17  polygonGeometry.Append( TGPoint( 50, 0 ) );
    18  polygonGeometry.Append( TGPoint( 50, 50 ) );
    19  polygonGeometry.Append( TGPoint( 0, 50 ) );
    20  
    21  TPolygon* bump = new TPolygon( polygonGeometry );
    22  
    23  TA8R8G8B8Image image( TGPoint( 0, 0 ), 50, 50, TGImage::k72DPI );
    24  TGrafPort* imagePort = image.GetGrafPort();
    25  bump->Draw( *imagePort );
    26  
    27  TBumpTextureMap bumpTexture( image );
    28  TBumpMapShader* bumpMapShader = new TBumpMapShader( bumpTexture );
    29  surfaceBundle->AdoptOutsideShader( bumpMapShader );
    30  
    31  simpleSweep.Draw( port );
Lines 1 through 9: Create the cyllinder sweep.

Lines 11 through 13: Create and adopt a fill bundle that gives a light gray outside surface color.

Lines 15 through 25: Create an image graphic and draw a square polygon into it to be the bump.

Lines 26 through 29: Create a bump texture map, use the bump texture map to create a bump map shader, adopt the bump map shader to be the outside shader.

Line 31: Draw the sweep.

Procedure Mapping

TProcedureMapShader is used with TProcedureMap derived classes (TMarbleProcedureMap or TWrinkleProcedureMap) to define a solid surface color over a 3D region of space. It uses the position, normal, and geometry of the graphic to apply texture to the surface. A complex 3D graphic might have many textures to represent different materials. Figure 201 shows the procedure maps available. Two default solid texture classes are provided. They are TMarbleProcedureMap for material simulation, and TWrinkleProcedureMap for normal perturbation.

NOTE It is often harder to synthesize a precise texture with a procedure map than with an image map. When an image of a texture can be obtained, and there is an obvious mapping from this image to the object to be textured exists, it is probably easier to store the image digitally and use an image map shader.


The TProcedureMapShader::ComputeShade function (called by the drawing port) gets the position, normal, and geometry values from the TProcedureMap instance.

TProcedureMapShader has a default TReflectanceShader instance that computes color based on light sources and the modified TShadingSample instance. Use the TProcedureMapShader::SetChildShader function to change the default TReflectanceShader.

White noise

The basic element in procedure textures is white noise. As shown in Figure 202, the abstract base class TNoiseProcedureMap::SetGrafNoise function takes a TGrafNoise instance as a parameter. The TGrafNoise abstract base class and its derived class TLatticeNoise represent white noise.

TLatticeNoise fills the entire 3D space with a small set of random numbers. The TLatticeNoise::Turbulent function is generated from the TLatticeNoise::Noise function and creates the visual impression of fluid flow. The default procedure texture is TLatticeNoise. You can derive from TGrafNoise and create your own algorithm if you prefer.


Example TMarbleProcedureMap

The TMarbleProcedureMap class provides a good example for studying the relationship between TNoise and procedure maps. You can use this example to write your own procedure maps.

One of the constructors and the SetColorSpline function take a parameter of type TShaderColorSpline. TShaderColorSpline is an abstract base class whose derived classes let you map a value between zero and one, inclusively, to the surface color. TRGBShaderColorSpline is derived from TShaderColorSpline.

      class TMarbleProcedureMap : public TNoiseProcedureMap
      {
          public:
                  TMarbleProcedureMap();
                  //Scale a point in world space
                  TMarbleProcedureMap( const TMarbleProcedureMap&, double scale = 1 );
                  TMarbleProcedureMap( const TShaderColorSpline& );
      
                  virtual ~TMarbleProcedureMap();
      
                  virtual void SetColorSpline( const TShaderColorSpline& map );
                  virtual void GetValue( TShadingSample& shadeSample, 
                                          const TSceneBundle& sceneBundle );
                  virtual void SetNoise( const TNoise& );
                  virtual void SetScale( double scale );
                  virtual Boolean NeedShadingNormal();
                  virtual Boolean NeedTangent();
      
                  // Other member functions
                  ...
      };
When a parameter of type TRGBShaderColorSpline is passed to the constructor or to SetColorSpline, the marble map computes the noise intensity and uses the value to evaluate the color spline. The color is extracted from the spline stored in TShadingInfo.fBaseColor for future processing. The following code shows the TRGBShaderColorSpline class.

      class TRGBShaderColorSpline : public TShaderColorSpline
      {
          public:
              virtual void GetColor( double val, TColor& retVal ) const;
              virtual void SetColors( long numberVal, const TRGBColor[] );
      
              TRGBShaderColorSpline();
              TRGBShaderCOlorSpline( long totalVal, const TRGBColor[] );
      
              //Other member functions
              ...
      };
The following code shows the TMarbleProcedureMap::GetValue function.

      void TMarbleProcedureMap::GetValue(     TShadingSample& shadingSample, 
                                              const TSceneBundle );
      {
          TGPoint3D scaledPoint( fScale * (shadingSample.fPosition ) );
      
          //Find the surface element area in texture space
          pixelSize = sqrt(ComputeArea( scaledPoint ) );
      
          //Find turbulence with pixel size
          double turb = fMarbleNoise>Turbulence( scaledPoint, pixelSize );
          fColorSpline>GetColor( turb, *shadingInfo.fBaseColor );
      }

Example TWrinkleProcedureMap

The TWrinkleProcedureMap class provides a good example for altering the incoming normal. You can use this example to write your own procedure maps.

      class TWrinkleProcedureMap : public TNoiseProcedureMap
      {
          public:
              TWrinkleProcedureMap();
              TWrinkleProcedureMap( const TWrinkleProcedureMap& );
              
              virtual ~TWrinkleProcedureMap();
      
              virtual SetNoise( const TNoise& noise );
              virtual void GetValue( TShadingSample& sample, const TSceneBundle& ) const;
              virtual void SetScale( double scale );
      };
The following code shows the TWrinkleProcedureMap::GetValue functions.

      void TWrinkleProcedureMap::GetValue( TShadingSample& shadingSample, 
                                              const TSceneBundle& /* stage bundle */);
      {
          TGPoint3D scaledPoint( fScale * shadingSample.fPosition );
          TGPOint3D result;
      
          //Returns a small amount of perturbation as a vector
          fWrinkleNoise>Turbulence( scaledPoint, result );
          shadingSample.fShadingNormal += result ;
          shadingSample.fShadingNormal.NormalizeAsVector();
      }

Surface shading

TSurfaceShader is a convenient class that can be used in most programs. It creates a texture map by combining an image texture map, bump texture map, and procedure texture map. The order in which these texture maps are accessed affects the final computational result; therefore, TSurfaceShader has a rule for map access. The rule is that TSurfaceShader accesses the map that modifies the surface color first, followed by the map that modifies the shading normal as follows:

1. TImageMap, which modifies surface color.

2. TProcedureMap that modifies surface color.

3. TBumpMap, which modifies shading normal.

4. TProcedureMap that modifies surface color.


[Contents] [Previous] [Next]
Click the icon to mail questions or corrections about this material to Taligent personnel.
Copyright©1995 Taligent,Inc. All rights reserved.

Generated with WebMaker