File: sampling.h

package info (click to toggle)
embree 4.3.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 100,656 kB
  • sloc: cpp: 228,918; xml: 40,944; ansic: 2,685; python: 812; sh: 635; makefile: 228; csh: 42
file content (159 lines) | stat: -rw-r--r-- 4,506 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

/*! \brief utility library containing sampling functions */

// convention is to return the sample (Vec3fa) generated from given Vec2f 's'ample as last parameter
// sampling functions often come in pairs: sample and pdf (needed later for MIS)
// good reference is "Total Compendium" by Philip Dutre http://people.cs.kuleuven.be/~philip.dutre/GI/

#include "../math/vec.h"
#include "../math/linearspace.h"

namespace embree {

struct Sample3f
{
  Vec3fa v;
  float pdf;
};

inline Sample3f make_Sample3f(const Vec3fa& v, const float pdf) {
  Sample3f s; s.v = v; s.pdf = pdf; return s;
}

#if defined(ISPC)
inline Sample3f make_Sample3f(const Vec3fa& v, const float pdf) {
  Sample3f s; s.v = v; s.pdf = pdf; return s;
}
#endif

inline Vec3fa cartesian(const float phi, const float sinTheta, const float cosTheta)
{
  const float sinPhi = sinf(phi);
  const float cosPhi = cosf(phi);
  //sincosf(phi, &sinPhi, &cosPhi);
  return Vec3fa(cosPhi * sinTheta,
                    sinPhi * sinTheta,
                    cosTheta);
}

inline Vec3fa cartesian(const float phi, const float cosTheta)
{
  return cartesian(phi, cos2sin(cosTheta), cosTheta);
}


/// cosine-weighted sampling of hemisphere oriented along the +z-axis
////////////////////////////////////////////////////////////////////////////////

inline Vec3fa cosineSampleHemisphere(const Vec2f s)
{
  const float phi = 2.0f * float(M_PI) * s.x;
  const float cosTheta = sqrt(s.y);
  const float sinTheta = sqrt(1.0f - s.y);
  return cartesian(phi, sinTheta, cosTheta);
}

inline float cosineSampleHemispherePDF(const Vec3fa &dir)
{
  return dir.z / float(M_PI);
}

inline float cosineSampleHemispherePDF(float cosTheta)
{
  return cosTheta / float(M_PI);
}

/*! Cosine weighted hemisphere sampling. Up direction is provided as argument. */
inline Sample3f cosineSampleHemisphere(const float  u, const float  v, const Vec3fa& N)
{
  Vec3fa localDir = cosineSampleHemisphere(Vec2f(u,v));
  Sample3f s;
  s.v = frame(N) * localDir;
  s.pdf = cosineSampleHemispherePDF(localDir);
  return s;
}

/// power cosine-weighted sampling of hemisphere oriented along the +z-axis
////////////////////////////////////////////////////////////////////////////////

inline Vec3fa powerCosineSampleHemisphere(const float n, const Vec2f &s)
{
  const float phi =float(two_pi) * s.x;
  const float cosTheta = pow(s.y, 1.0f / (n + 1.0f));
  return cartesian(phi, cosTheta);
}

inline float powerCosineSampleHemispherePDF(const float cosTheta, const float n) // TODO: order of arguments
{
  return (n + 1.0f) * (0.5f / float(M_PI)) * pow(cosTheta, n);
}

inline float powerCosineSampleHemispherePDF(const Vec3fa& dir, const float n) // TODO: order of arguments
{
  return (n + 1.0f) * (0.5f / float(M_PI)) * pow(dir.z, n);
}

/// sampling of cone of directions oriented along the +z-axis
////////////////////////////////////////////////////////////////////////////////

inline Vec3fa uniformSampleCone(const float cosAngle, const Vec2f &s)
{
  const float phi =float(two_pi) * s.x;
  const float cosTheta = 1.0f - s.y * (1.0f - cosAngle);
  return cartesian(phi, cosTheta);
}

inline float uniformSampleConePDF(const float cosAngle)
{
    return rcp(float(two_pi)*(1.0f - cosAngle));
}

inline float _uniformSampleConePDF(const float cosAngle)
{
    return rcp(float(two_pi)*(1.0f - cosAngle));
}


/// sampling of disk
////////////////////////////////////////////////////////////////////////////////

inline Vec3fa uniformSampleDisk(const float radius, const Vec2f &s)
{
  const float r = sqrtf(s.x) * radius;
  const float phi =float(two_pi) * s.y;
  const float sinPhi = sinf(phi);
  const float cosPhi = cosf(phi);
  //sincosf(phi, &sinPhi, &cosPhi);
  return Vec3fa(r * cosPhi, r * sinPhi, 0.f);
}

inline float uniformSampleDiskPDF(const float radius)
{
  return rcp(float(M_PI) * sqr(radius));
}

inline float _uniformSampleDiskPDF(const float radius)
{
  return rcp(float(M_PI) * sqr(radius));
}


/// sampling of triangle abc
////////////////////////////////////////////////////////////////////////////////

inline Vec3fa uniformSampleTriangle(const Vec3fa &a, const Vec3fa &b, const Vec3fa &c, const Vec2f &s)
{
  const float su = sqrtf(s.x);
  return c + (1.0f - su) * (a-c) + (s.y*su) * (b-c);
}

inline float uniformSampleTrianglePDF(const Vec3fa &a, const Vec3fa &b, const Vec3fa &c)
{
  return 2.0f * rcp(abs(length(cross(a-c, b-c))));
}

} // namespace embree