File: optics.isph

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 (169 lines) | stat: -rw-r--r-- 6,390 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
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include "../math/sampling.isph"

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

/*! Reflects a viewing vector V at a normal N. */
inline uniform Vec3f reflect(const uniform Vec3f& V, const uniform Vec3f& N) { return 2.0f*dot(V,N)*N-V; }
#ifdef ISPC
inline varying Vec3f reflect(const uniform Vec3f& V, const varying Vec3f& N) { return 2.0f*dot(V,N)*N-V; }
inline varying Vec3f reflect(const varying Vec3f& V, const uniform Vec3f& N) { return 2.0f*dot(V,N)*N-V; }
inline varying Vec3f reflect(const varying Vec3f& V, const varying Vec3f& 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 Vec3f reflect(const Vec3f &V, const Vec3f &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 Vec3f& V, const Vec3f& 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(make_Vec3f(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 Vec3f fresnelConductor(const float cosi, const Vec3f& eta, const Vec3f& k)
{
  const Vec3f tmp = eta*eta + k*k;
  const Vec3f Rpar = (tmp * (cosi*cosi) - 2.0f*eta*cosi + make_Vec3f(1.0f)) *
    rcp(tmp * (cosi*cosi) + 2.0f*eta*cosi + make_Vec3f(1.0f));
  const Vec3f Rper = (tmp - 2.0f*eta*cosi + make_Vec3f(cosi*cosi)) *
    rcp(tmp + 2.0f*eta*cosi + make_Vec3f(cosi*cosi));
  return 0.5f * (Rpar + Rper);
}

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

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

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

#if defined(ISPC)
inline varying FresnelConductor make_FresnelConductor(const varying Vec3f& eta, const varying Vec3f& k) {
  varying 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 Vec3f eval(const uniform FresnelDielectric& This, const float cosTheta) {
  return make_Vec3f(fresnelDielectric(cosTheta,This.etai/This.etat));
}

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

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

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

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

#if defined(ISPC)

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

/*! Samples the power cosine distribution. */
inline void sample(const uniform PowerCosineDistribution& This, const Vec3f& wo, const Vec3f& N, Sample3f &wi, const Vec2f s)
{
  Vec3f 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 varying PowerCosineDistribution& This, const Vec3f& wo, const Vec3f& N, Sample3f &wi, const Vec2f s)
{
  Vec3f 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 uniform PowerCosineDistribution make_PowerCosineDistribution(const uniform float _exp) {
  uniform PowerCosineDistribution m; m.exp = _exp; return m;
}

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