1 #ifndef PROCEDURAL_HXX
  2 #define PROCEDURAL_HXX
  3 
  4 #include "Shader.hxx"
  5 #include "PerlinNoise.hxx"
  6 
  7 /**
  8  * wood and marble effect supported
  9  */
 10 enum shadetype
 11 {
 12     wood,
 13     marble,
 14     granit
 15 };
 16  
 17 class ProceduralShader : public Shader
 18 {
 19     public:
 20         /**
 21          * Vec3f origin:    Ursprung (von dort aus breiten sich die Jahresring aus)
 22          * Vec3f direction: Richtung (in diese Richtung breiten sich die Jahresringe aus)
 23          */  
 24         Vec3f origin;
 25         Vec3f dir;
 26         
 27         /** 
 28          * parameters for Perlin Noise
 29          */
 30         float persistence;
 31         float frequency;
 32         float octaves;
 33         
 34         enum shadetype type;
 35             
 36         /**
 37          * constructor
 38          */  
 39         ProceduralShader(Scene* scene, float persistence, float frequency, float octaves, enum shadetype type)
 40         : Shader(scene), persistence(persistence), frequency(frequency), octaves(octaves), type(type)
 41         {
 42                dir = Vec3f(1,1,0);
 43             origin = Vec3f(0,0,0);
 44         }
 45         
 46         ~ProceduralShader()
 47         {};     
 48         
 49         void setDir( Vec3f pdir )
 50         {
 51             dir = pdir; 
 52             Normalize(dir);
 53         }
 54         
 55         void setOrigin( Vec3f porigin ) 
 56         {
 57             origin = porigin;
 58         }
 59         
 60         Vec3f Shade(Ray &ray)
 61         {
 62             Vec3f hitpoint = ray.org + ray.t * ray.dir;
 63                     
 64             PerlinNoise* noise = new PerlinNoise();
 65             float random = noise->PerlinNoise3D( hitpoint, persistence, (int) octaves );
 66             
 67             switch (type)
 68             {
 69                 case wood:
 70                 {
 71                     /**
 72                      * predefined wood color
 73                      */
 74                     Vec3f lightwood = Vec3f(.69, .44, .25);
 75                     Vec3f darkwood  = Vec3f(.35, .22, .08);
 76                     
 77                     /** 
 78                      * compute point PP from where rings should start
 79                      * and then move point in direction dir
 80                      */
 81                     Vec3f PP = hitpoint - origin;
 82                     Vec3f move_dist  = Dot(-PP,dir);
 83                     Vec3f move_point = PP + dir * move_dist;
 84 
 85                     /**
 86                      * compute the distance
 87                      * and take the frequency and some randomness into account
 88                      */
 89                     float dist = powf(Length(move_point),2.0);
 90                     float value = dist / frequency;
 91                     value += random;
 92                     
 93                     /**
 94                      * get value between 0 and 1
 95                      * and then use linear interpolation, to compute composition of light wood and dark wood
 96                      */
 97                     value -= floor(value);
 98                     
 99                     return ( (1.0 - value) * lightwood + value * darkwood );
100                 }
101                             
102                 case marble:
103                 {
104                     /**
105                      * predefined marble colors
106                      */
107                     Vec3f light_marble = Vec3f(0.7);
108                     Vec3f dark_marble = Vec3f(0.15);
109                     
110                     Vec3f PP = hitpoint;
111                     float angle = Dot( PP, dir );
112                     
113                     /**
114                      * function as introduced by Perlin
115                      */
116                     float value = sinf ( frequency * ( angle + random ) );
117                     
118                     /**
119                      * get value between 0 and 1
120                      * and then use linear interpolation, to compute composition of light wood and dark wood
121                      */                 
122                     value -= floor(value);
123                     
124                     return ( (1.0 - value) * light_marble + value * dark_marble );
125                 }
126                 
127                 case granit:
128                 {
129                     /**
130                      * define 'number' colors
131                      */
132                     unsigned int number = 6;
133                     
134                     std::vector<Vec3f> color;
135 
136                     /**
137                      * predefine colors
138                      */
139                     color.push_back( Vec3f( 0.9 ) );
140                     color.push_back( Vec3f( 0.4 ) );
141                     color.push_back( Vec3f( 0.3 ) );
142                     color.push_back( Vec3f( 0.7 ) );
143                     color.push_back( Vec3f( 0.2 ) );
144                     color.push_back( Vec3f( 0.4 ) );
145                     
146                     /**
147                      * value in between [0 and number]
148                      */
149                     float value = number * (random - floorf(random));
150                     
151                     int index = (int) floor(value);
152                     
153                     return color[index];
154                 }
155                 
156                 default:
157                     return Vec3f();
158             }
159         }
160 };
161 
162 #endif


syntax highlighted by Code2HTML, v. 0.9.1