File: optics.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 (173 lines) | stat: -rw-r--r-- 6,137 bytes parent folder | download | duplicates (2)
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "../math/sampling.h"

namespace embree {

/*! \addtogroup rivl_render_embree_ivl */
/*! @{ */

/*! Reflects a viewing vector V at a normal N. */
inline Vec3fa reflect(const Vec3fa& V, const Vec3fa& N) { return 2.0f*dot(V,N)*N-V; }
#ifdef ISPC
inline Vec3fa reflect(const Vec3fa& V, const Vec3fa& N) { return 2.0f*dot(V,N)*N-V; }
inline Vec3fa reflect(const Vec3fa& V, const Vec3fa& N) { return 2.0f*dot(V,N)*N-V; }
inline Vec3fa reflect(const Vec3fa& V, const Vec3fa& N) { return 2.0f*dot(V,N)*N-V; }
#endif

/*! Reflects a viewing vector V at a normal N. Cosine between V
 *  and N is given as input. */
inline Vec3fa reflect(const Vec3fa &V, const Vec3fa &N, const float cosi) {
  return 2.0f*cosi*N-V;
}

// =======================================================
/*!Refracts a viewing vector V at a normal N using the relative
 *  refraction index eta. Eta is refraction index of outside medium
 *  (where N points into) divided by refraction index of the inside
 *  medium. The vectors V and N have to point towards the same side
 *  of the surface. The cosine between V and N is given as input and
 *  the cosine of -N and transmission ray is computed as output. */
inline Sample3f refract(const Vec3fa& V, const Vec3fa& N, const float eta,
                        const float cosi, float &cost)
{
  const float k = 1.0f-eta*eta*(1.0f-cosi*cosi);
  if (k < 0.0f) { cost = 0.0f; return make_Sample3f(Vec3fa(0.f),0.0f); }
  cost = sqrt(k);
  return make_Sample3f(eta*(cosi*N-V)-cost*N, sqr(eta));
}

/*! Computes fresnel coefficient for media interface with relative
 *  refraction index eta. Eta is the outside refraction index
 *  divided by the inside refraction index. Both cosines have to be
 *  positive. */
inline float fresnelDielectric(const float cosi, const float cost, const float eta)
{
  const float Rper = (eta*cosi -     cost) * rcp(eta*cosi +     cost);
  const float Rpar = (    cosi - eta*cost) * rcp(    cosi + eta*cost);
  return 0.5f*(Rpar*Rpar + Rper*Rper);
}

  /*! Computes fresnel coefficient for media interface with relative
   *  refraction index eta. Eta is the outside refraction index
   *  divided by the inside refraction index. The cosine has to be
   *  positive. */
inline float fresnelDielectric(const float cosi, const float eta)
{
  const float k = 1.0f-eta*eta*(1.0f-cosi*cosi);
  if (k < 0.0f) return 1.0f;
  const float cost = sqrt(k);
  return fresnelDielectric(cosi, cost, eta);
}

/*! Computes fresnel coefficient for conductor medium with complex
 *  refraction index (eta,k). The cosine has to be positive. */
inline Vec3fa fresnelConductor(const float cosi, const Vec3fa& eta, const Vec3fa& k)
{
  const Vec3fa tmp = eta*eta + k*k;
  const Vec3fa Rpar = (tmp * (cosi*cosi) - 2.0f*eta*cosi + Vec3fa(1.0f)) *
    rcp(tmp * (cosi*cosi) + 2.0f*eta*cosi + Vec3fa(1.0f));
  const Vec3fa Rper = (tmp - 2.0f*eta*cosi + Vec3fa(cosi*cosi)) *
    rcp(tmp + 2.0f*eta*cosi + Vec3fa(cosi*cosi));
  return 0.5f * (Rpar + Rper);
}

// =======================================================
struct FresnelConductor {
  Vec3fa eta;  //!< Real part of refraction index
  Vec3fa k;    //!< Imaginary part of refraction index
};

inline Vec3fa eval(const FresnelConductor& This, const float cosTheta) {
  return fresnelConductor(cosTheta,This.eta,This.k);
}

inline FresnelConductor make_FresnelConductor(const Vec3fa& eta, const Vec3fa& k) {
  FresnelConductor m; m.eta = eta; m.k = k; return m;
}

#if defined(ISPC)
inline FresnelConductor make_FresnelConductor(const Vec3fa& eta, const Vec3fa& k) {
  FresnelConductor m; m.eta = eta; m.k = k; return m;
}
#endif

// =======================================================
struct FresnelDielectric
{
  /*! refraction index of the medium the incident ray travels in */
  float etai;

  /*! refraction index of the medium the outgoing transmission rays
   *  travels in */
  float etat;
};

inline Vec3fa eval(const FresnelDielectric& This, const float cosTheta) {
  return Vec3fa(fresnelDielectric(cosTheta,This.etai/This.etat));
}

inline FresnelDielectric make_FresnelDielectric(const float etai, const float etat) {
  FresnelDielectric m; m.etai = etai; m.etat = etat; return m;
}

#if defined(ISPC)
inline FresnelDielectric make_FresnelDielectric(const float etai, const float etat) {
  FresnelDielectric m; m.etai = etai; m.etat = etat; return m;
}
#endif

// =======================================================
struct PowerCosineDistribution {
  float exp;
};

inline float eval(const PowerCosineDistribution &This, const float cosThetaH) {
  return (This.exp+2) * (1.0f/(2.0f*(float(M_PI)))) * pow(abs(cosThetaH), This.exp);
}

#if defined(ISPC)

inline float eval(const PowerCosineDistribution &This, const float cosThetaH) {
  return (This.exp+2) * (1.0f/(2.0f*(float(M_PI)))) * pow(abs(cosThetaH), This.exp);
}
#endif

/*! Samples the power cosine distribution. */
inline void sample(const PowerCosineDistribution& This, const Vec3fa& wo, const Vec3fa& N, Sample3f &wi, const Vec2f s)
{
  Vec3fa dir = powerCosineSampleHemisphere(This.exp,s);
  Sample3f wh;
  wh.v = frame(N) * dir;
  wh.pdf = powerCosineSampleHemispherePDF(dir,This.exp);
  Sample3f r = make_Sample3f(reflect(wo,wh.v),1.0f);
  wi = make_Sample3f(r.v,wh.pdf/(4.0f*abs(dot(wo,wh.v))));
}

/*! Samples the power cosine distribution. */
#if defined(ISPC)
inline void sample(const PowerCosineDistribution& This, const Vec3fa& wo, const Vec3fa& N, Sample3f &wi, const Vec2f s)
{
  Vec3fa dir = powerCosineSampleHemisphere(This.exp,s);
  Sample3f wh;
  wh.v = frame(N) * dir;
  wh.pdf = powerCosineSampleHemispherePDF(dir,This.exp);
  Sample3f r = make_Sample3f(reflect(wo,wh.v),1.0f);
  wi = make_Sample3f(r.v,wh.pdf/(4.0f*abs(dot(wo,wh.v))));
}
#endif

inline PowerCosineDistribution make_PowerCosineDistribution(const float _exp) {
  PowerCosineDistribution m; m.exp = _exp; return m;
}

#if defined(ISPC)
inline PowerCosineDistribution make_PowerCosineDistribution(const float _exp) {
  PowerCosineDistribution m; m.exp = _exp; return m;
}
#endif

} // namespace embree