File: NextEventEstimation.ispc

package info (click to toggle)
ospray 3.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 10,040 kB
  • sloc: cpp: 80,569; ansic: 951; sh: 805; makefile: 171; python: 69
file content (152 lines) | stat: -rw-r--r-- 4,881 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
// Copyright 2009 Intel Corporation
// SPDX-License-Identifier: Apache-2.0

#include "render/pathtracer/NextEventEstimation.ih"
#include "render/pathtracer/PathStructs.ih"
#include "render/pathtracer/PathTracerDefines.ih"
#include "render/pathtracer/PathTracerUtil.ih"
#include "render/pathtracer/TransparentShadow.ih"

#ifdef OSPRAY_ENABLE_VOLUMES
#include "render/pathtracer/volumes/VolumeSampler.ih"
#endif

#include "common/RayCone.ih"
#include "common/World.ih"
#include "math/Distribution1D.ih"
#include "math/random.ih"
#include "math/sampling.ih"
// c++ shared
#include "lights/LightDispatch.ih"
#include "lights/LightShared.h"

OSPRAY_BEGIN_ISPC_NAMESPACE

SYCL_EXTERNAL vec3f nextEventEstimation(const PathContext &pathContext,
    PathState &pathState,
    PathVertex &pathVertex,
    float rayConeWidth,
    const uniform FeatureFlagsHandler &ffh)
{
  const uniform FeatureFlags ff = getFeatureFlags(ffh);

  // direct lighting including shadows and MIS
  vec3f L = make_vec3f(0.f);

  const uint32 numLightSamples = pathState.firstBounceLight
      ? pathContext.numFirstBounceLightSamples
      : pathContext.numIndirectBounceLightSamples;

  // remember for MIS
  pathVertex.numLightSamples = numLightSamples;

  for (uniform uint32 i = 0; i < numLightSamples; i++) {
    // select a random light source from the list
    float ss;
    const vec2f s = LDSampler_get3LightSamples(
        pathState.ldSampler, i, numLightSamples > 1, ss);
    const Sample1D lSelectSample = Distribution1D_sample(
        pathContext.numLights, pathContext.lightsCDF, 0, ss);

    const float lightSelectionProb = lSelectSample.prob * numLightSamples;
    const Light *light = pathContext.lights[lSelectSample.idx];
    // sample the contribution from the random light source
    Light_SampleRes ls;
    foreach_unique (l in light)
      ls = Light_dispatch_sample(l, pathVertex.dg, s, pathState.time, ffh);

    // adjust the contribution with the probabiltiy of selecting the light
    // source
    ls.weight = ls.weight / lightSelectionProb;
    ls.pdf *= lightSelectionProb;

    // skip when zero contribution from light
    if (reduce_max(ls.weight) <= 0.0f | ls.pdf <= PDF_CULLING)
      continue;

    // evaluate BSDF
    Scattering_EvalRes fe;
    if (ff.geometry && pathVertex.type == SURFACE) {
      foreach_unique (f in pathVertex.bsdf)
        if (f != NULL)
          fe = BSDF_dispatch_eval(f, pathVertex.wo, ls.dir, ffh);
    } else {
#ifdef OSPRAY_ENABLE_VOLUMES
      if (ff.other & FFO_VOLUME_IN_SCENE) {
        foreach_unique (v in pathVertex.volume)
          if (v != NULL)
            fe = HenyeyGreenstein_eval(v->anisotropy, pathVertex.wo, ls.dir);
      }
#endif
    }

    // skip when zero contribution from material
    if (reduce_max(fe.value) <= 0.0f)
      continue;

    // test for shadows with rayCones
    Ray shadowRay;
    vec3f org = pathVertex.dg.P;
    if (pathVertex.type != VOLUME) {
      if (dot(pathVertex.dg.Ng, ls.dir) < 0.f)
        org = org - (2.0f * pathVertex.dg.epsilon) * pathVertex.dg.Ng;
    }
    setRay(shadowRay, org, ls.dir, 0.f, ls.dist, pathState.time);
    // connect ray cone to point on light
    RayCone shadowCone;
    shadowCone.width = rayConeWidth;
    shadowCone.dwdt = -rayConeWidth * rcp(ls.dist);

    // Trace ray in clipping geometries scene, fill array with ray intervals
    RayIntervals rayIntervals;
    traceClippingRay(pathContext.world, shadowRay, rayIntervals, ffh);

    const vec3f throughput = pathState.throughput * fe.value;

    const vec3f unshadedLightContrib = throughput * ls.weight;
    const vec3f lightContrib = transparentShadow(pathContext.context,
        pathContext.world,
        unshadedLightContrib,
        shadowRay,
        shadowCone,
        rayIntervals,
        pathState.currentMedium,
        ffh);
    if (reduce_max(lightContrib) > 0) {
#ifdef OSPRAY_ENABLE_VOLUMES
      if (ff.other & FFO_VOLUME_IN_SCENE) {
        const float T = volumeTransmittance(pathContext.world,
            shadowRay,
            rayIntervals,
            &pathState.randomSampler,
            ffh);
        if (reduce_max(T) > 0) {
          // we have to use an independent transmittance estimate for MIS to get
          // a correct result
          const float T_mis =
#ifdef OSPRAY_PATHTRACER_DEBUG
              pathContext.disableFWD || pathContext.disableNEE
              ? 1.f
              :
#endif
              volumeTransmittance(pathContext.world,
                  shadowRay,
                  rayIntervals,
                  &pathState.randomSampler,
                  ffh);
          L = L
              + T * lightContrib
                  * misHeuristic(pathContext, ls.pdf, fe.pdf * T_mis);
        }
      } else
#endif
      {
        L = L + lightContrib * misHeuristic(pathContext, ls.pdf, fe.pdf);
      }
    }
  }

  return L;
}

OSPRAY_END_ISPC_NAMESPACE