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