Subversion Repositories gelsvn

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
346 awk 1
#ifndef __PATHTRACER_CORE__HPP__
2
#define __PATHTRACER_CORE__HPP__
3
 
4
#include "CGLA/Vec2f.h"
5
#include "CGLA/Vec3f.h"
6
 
7
#include <limits>
8
 
9
struct ray
10
{
11
	ray(void) : origin(0.f), direction(0.f), distance(0.f), depth(0) {}
12
 
13
	CGLA::Vec3f origin;
14
	CGLA::Vec3f direction;
15
 
16
	float distance;
17
	int depth;
18
};
19
 
20
struct hit_info
21
{
22
	hit_info(void) : 
23
		distance(0.f),
24
		position(0.f), geometric_normal(0.f), shading_normal(0.f),
25
		inside(false),
26
		emitted(0.f),
27
		diffuse(0.f), glossy(0.f), shininess(0.f),
28
		reflection(0.f), refraction(0.f),
29
		ior(0.f), extinction(0.f) {}
30
 
31
	float distance;
32
	CGLA::Vec3f position;
33
	CGLA::Vec3f geometric_normal;
34
	CGLA::Vec3f shading_normal;
35
 
36
	//The tangent, bitangent, and shading_normal form an orthonormal basis
37
	CGLA::Vec3f tangent;
38
	CGLA::Vec3f bitangent;
39
 
40
	//texture coordinates
41
	CGLA::Vec2f texcoords;
42
 
43
	//flag to indicate if the inside of the object (wrt the normal) was hit
44
	bool inside;
45
 
46
	//emitted radiance
47
	CGLA::Vec3f emitted;
48
 
49
	//diffuse reflectivity (rho)
50
	CGLA::Vec3f diffuse;
51
 
52
	//parameters for the modified Phong reflectance model
53
	CGLA::Vec3f glossy;
54
	float shininess;
55
 
56
	//parameters for perfect specular reflection/refraction
57
	CGLA::Vec3f reflection;
58
	CGLA::Vec3f refraction;
59
 
60
	//index of refraction + complex part
61
	float ior;
62
	float extinction;
63
};
64
 
65
//RGB to intensity
66
inline float intensity(const CGLA::Vec3f& v)
67
{
68
	return v[0] * 0.27f + v[1] * 0.67f + v[2] * 0.06f;
69
}
70
 
71
//standard fresnel formula (see eg. Jensen p. 23)
72
inline float fresnel_dielectric(float cosi, float cost, float eta)
73
{
74
	assert(cosi>0.f && cost>0.f);
75
 
76
	float etai = 1.f;
77
	float etat = eta;
78
 
79
	float Fs = (etai*cosi - etat*cost) / (etai*cosi + etat*cost);
80
	float Fp = (etat*cosi - etai*cost) / (etat*cosi + etai*cost);
81
 
82
	float F = 0.5f * (Fs*Fs + Fp*Fp);
83
	assert(F>=0.f && F<=1.f);
84
	return F; 
85
}
86
 
87
//standard fresnel formula (see eg. Pharr et all p. 422)
88
inline float fresnel_conductor(float cosi, float eta, float extinction)
89
{
90
	assert(cosi >= 0.f);
91
 
92
	float z = eta*eta + extinction*extinction;
93
 
94
	float Fp = (z * cosi*cosi - 2.f * eta * cosi + 1.f)	/
95
		(z + 2.f * eta * cosi + 1.f);
96
 
97
	float Fs = (z - 2.f * eta * cosi + cosi * cosi) /
98
		(z + 2.f * eta * cosi + cosi * cosi);
99
 
100
	float F = (Fp + Fs) * 0.5f;
101
	assert(F>=0.f && F<=1.f);
102
	return F;
103
}
104
 
105
//reflect vector around normal. n should be normalized.
106
inline CGLA::Vec3f reflect(const CGLA::Vec3f& n, const CGLA::Vec3f& r)
107
{
108
	return 2.f * n * dot(n, r) - r;
109
}
110
 
111
//eta = eta_from / eta_to
112
inline bool refract(const CGLA::Vec3f & n, const CGLA::Vec3f & i, 
113
					float eta, CGLA::Vec3f & t)
114
{
115
	float c1 = dot(i,n);
116
	float c2 = 1.f - eta*eta * (1.f - c1*c1);
117
 
118
	if (c2 < 0.f)
119
		return false;
120
 
121
	float c3 = std::sqrt(c2);
122
	t = -eta*i + (eta*c1 - c3) * n;
123
 
124
	return true;
125
}
126
 
127
//helper function, clamps v to range [i; a]
128
template <class T>
129
T clamp(const T& v, const T& i, const T& a)
130
{
131
	return std::min(std::max(v, i), a);
132
}
133
 
134
//mersenne twister
135
extern "C" double genrand_real2(void);
136
inline float random(void)
137
{
138
	return float(genrand_real2());
139
}
140
 
141
//evaluation of the diffuse brdf
142
inline CGLA::Vec3f lambertian_brdf(const hit_info& hi,
143
								   const CGLA::Vec3f& wi,
144
								   const CGLA::Vec3f& wo)
145
{
146
	return hi.diffuse / float(M_PI);
147
}
148
 
149
//sampling of diffuse brdf, wi = sampled direction, should return probability
150
inline float sample_lambertian(const hit_info& hi,
151
							const CGLA::Vec3f& wo, CGLA::Vec3f& wi)
152
{
153
	CGLA::Vec3f x, y, z = hi.shading_normal;
154
	orthogonal(z, x, y);
155
	float e0 = random();
156
	float e1 = random();
157
	float cost = std::sqrt(e0);
158
	float sint = std::sqrt(1.f - e0);
159
	float cosp = std::cos(e1 * 2.f * float(M_PI));
160
	float sinp = std::sin(e1 * 2.f * float(M_PI));
161
	CGLA::Vec3f dir(sint*cosp, sint*sinp, cost);
162
 
163
	wi = dir(0) * x + dir(1) * y + dir(2) * z;
164
	return 1.f / float(M_PI) * cost;
165
}
166
 
167
//evaluation of the phong brdf 
168
inline CGLA::Vec3f phong_brdf(const hit_info& hi,
169
							   const CGLA::Vec3f& wi,const CGLA::Vec3f& wo)
170
{
171
	float dwi = dot(wi, hi.geometric_normal);
172
	float dwo = dot(wo, hi.geometric_normal);
173
	float same_hemisphere = dwi * dwo > 0.f;
174
 
175
	if (same_hemisphere)
176
	{
177
		//glossy contribution
178
		if (intensity(hi.glossy) > 0.f)
179
		{
180
			float cost = std::max(dot(reflect(hi.shading_normal, wi), wo),
181
				0.f);
182
			float cosn = std::pow(cost, hi.shininess);
183
			return hi.glossy * (hi.shininess+2.f)/(2.f * float(M_PI))*cosn;
184
		}
185
	}
186
	return CGLA::Vec3f(0.f);
187
}
188
 
189
//sampling of phong brdf, wi = sampled direction, should return probability
190
inline float sample_phong(const hit_info& hi,
191
						  const CGLA::Vec3f& wo, CGLA::Vec3f& wi)
192
{
193
	float e0 = random();
194
	float e1 = random();
195
 
196
	float cost = std::pow(e0, 1.f/(hi.shininess + 1.f));
197
	float sint = std::sqrt(1.f - std::pow(e0, 2.f/(hi.shininess + 1.f)));
198
	float cosp = std::cos(e1 * 2.f * float(M_PI));
199
	float sinp = std::sin(e1 * 2.f * float(M_PI));
200
 
201
	CGLA::Vec3f dir(sint*cosp, sint*sinp, cost);
202
 
203
	CGLA::Vec3f x, y, z = reflect(hi.shading_normal, wo);
204
	orthogonal(z, x, y);
205
 
206
	float cosn = std::pow(dir(2), hi.shininess);
207
	wi = dir(0) * x + dir(1) * y + dir(2) * z;
208
 
209
	return (hi.shininess+1.f) / (2.f * float(M_PI)) * cosn;
210
}
211
 
212
//convenience function to evaluate the non-specular parts of the bsdf
213
inline CGLA::Vec3f bsdf_evaluate(const hit_info& hi, 
214
								 const CGLA::Vec3f& wi, const CGLA::Vec3f& wo)
215
{
216
	CGLA::Vec3f fs(0.f);
217
 
218
	fs += lambertian_brdf(hi, wi, wo);
219
	fs += phong_brdf(hi, wi, wo);
220
 
221
	return fs;
222
}
223
 
224
//epsilon for shadow testing
225
static const float epsilon = 1e-5f;
226
 
227
static const float step = 1e-1f;
228
 
229
#endif
230
 
231
//02566 framework, Anders Wang Kristensen, awk@imm.dtu.dk, 2007