Subversion Repositories gelsvn

Rev

Rev 353 | Details | Compare with Previous | Last modification | View Log | RSS feed

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