748d272c9dc1a604bcdc675c758ee9841ad4380d
[camsim.git] / libcamsim / simulator.cpp
1 /*
2  * Copyright (C) 2012, 2013, 2014, 2016, 2017, 2018
3  * Computer Graphics Group, University of Siegen
4  * Written by Martin Lambers <martin.lambers@uni-siegen.de>,
5  * Hendrik Sommerhoff <hendrik.sommerhoff@student.uni-siegen.de>
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include <cmath>
27 #include <random>
28 #include <utility>
29
30 #include <QtMath>
31 #include <QString>
32 #include <QFile>
33
34 #include "simulator.hpp"
35 #include "gl.hpp"
36
37
38 namespace CamSim {
39
40 ChipTiming::ChipTiming() :
41     exposureTime(1.0 / 60.0),
42     readoutTime(1.0 / 60.0),
43     pauseTime(0.0)
44 {
45 }
46
47 ChipTiming ChipTiming::fromSubFramesPerSecond(float sfps)
48 {
49     ChipTiming t;
50     t.exposureTime = 0.0;
51     t.readoutTime = 1.0 / sfps;
52     t.pauseTime = 0.0;
53     return t;
54 }
55
56 PMD::PMD() :
57     pixelSize(12.0 * 12.0),
58     pixelContrast(0.75),
59     modulationFrequency(10e6),
60     wavelength(880.0),
61     quantumEfficiency(0.8),
62     maxElectrons(100000)
63 {
64 }
65
66 Projection::Projection()
67 {
68     _w = 640;
69     _h = 480;
70     _t = std::tan(qDegreesToRadians(70.0f) / 2.0f);
71     _b = -_t;
72     _r = _t * _w / _h;
73     _l = -_r;
74     _k1 = 0.0f;
75     _k2 = 0.0f;
76     _p1 = 0.0f;
77     _p2 = 0.0f;
78 }
79
80 QMatrix4x4 Projection::projectionMatrix(float n, float f) const
81 {
82     QMatrix4x4 m;
83     m.frustum(_l * n, _r * n, _b * n, _t * n, n, f);
84     return m;
85 }
86
87 QSize Projection::imageSize() const
88 {
89     return { _w, _h };
90 }
91
92 QVector2D Projection::centerPixel() const
93 {
94     return QVector2D(
95         _r / (_r - _l) * _w - 0.5f,
96         _t / (_t - _b) * _h - 0.5f);
97 }
98
99 QVector2D Projection::focalLengths() const
100 {
101     return QVector2D(
102         1.0f / ((_r - _l) / _w),
103         1.0f / ((_t - _b) / _h));
104 }
105
106 Projection Projection::fromFrustum(int imageWidth, int imageHeight, float l, float r, float b, float t)
107 {
108     Projection p;
109     p._w = imageWidth;
110     p._h = imageHeight;
111     p._l = l;
112     p._r = r;
113     p._b = b;
114     p._t = t;
115     return p;
116 }
117
118 Projection Projection::fromOpeningAngle(int imageWidth, int imageHeight, float fovyDegrees)
119 {
120     float t = std::tan(qDegreesToRadians(fovyDegrees / 2.0f));
121     float b = -t;
122     float r = t * imageWidth / imageHeight;
123     float l = -r;
124     return fromFrustum(imageWidth, imageHeight, l, r, b, t);
125 }
126
127 Projection Projection::fromIntrinsics(int imageWidth, int imageHeight, float centerX, float centerY, float focalLengthX, float focalLengthY)
128 {
129     float r_minus_l = imageWidth / focalLengthX;
130     float l = -(centerX + 0.5f) * r_minus_l / imageWidth;
131     float r = r_minus_l + l;
132     float t_minus_b = imageHeight / focalLengthY;
133     float b = -(centerY + 0.5f) * t_minus_b / imageHeight;
134     float t = t_minus_b + b;
135     return fromFrustum(imageWidth, imageHeight, l, r, b, t);
136 }
137
138 void Projection::setDistortion(float k1, float k2, float p1, float p2)
139 {
140     _k1 = k1;
141     _k2 = k2;
142     _p1 = p1;
143     _p2 = p2;
144 }
145
146 void Projection::distortion(float* k1, float* k2, float* p1, float* p2)
147 {
148     *k1 = _k1;
149     *k2 = _k2;
150     *p1 = _p1;
151     *p2 = _p2;
152 }
153
154 Pipeline::Pipeline() :
155     nearClippingPlane(0.1f),
156     farClippingPlane(100.0f),
157     mipmapping(true),
158     anisotropicFiltering(true),
159     transparency(false),
160     normalMapping(true),
161     ambientLight(false),
162     thinLensVignetting(false),
163     thinLensApertureDiameter(8.89f), // 0.889 cm aperture (so that F-number is 1.8)
164     thinLensFocalLength(16.0f),
165     shotNoise(false),
166     gaussianWhiteNoise(false),
167     gaussianWhiteNoiseMean(0.0f),
168     gaussianWhiteNoiseStddev(0.05f),
169     preprocLensDistortion(false),
170     preprocLensDistortionMargin(0.0f),
171     postprocLensDistortion(false),
172     shadowMaps(false),
173     shadowMapFiltering(true),
174     reflectiveShadowMaps(false),
175     lightPowerFactorMaps(false),
176     subFrameTemporalSampling(true),
177     spatialSamples(1, 1),
178     temporalSamples(1)
179 {
180 }
181
182 Output::Output() :
183     rgb(true),
184     srgb(false),
185     pmd(false),
186     eyeSpacePositions(false),
187     customSpacePositions(false),
188     eyeSpaceNormals(false),
189     customSpaceNormals(false),
190     depthAndRange(false),
191     indices(false),
192     forwardFlow3D(false),
193     forwardFlow2D(false),
194     backwardFlow3D(false),
195     backwardFlow2D(false)
196 {
197 }
198
199 Simulator::Simulator() :
200     _recreateTimestamps(true),
201     _recreateShaders(true),
202     _recreateOutput(true),
203     _pbo(0),
204     _depthBufferOversampled(0),
205     _rgbTexOversampled(0),
206     _pmdEnergyTexOversampled(0),
207     _pmdEnergyTex(0),
208     _gaussianNoiseTex(0),
209     _postProcessingTex(0),
210     _fbo(0),
211     _fullScreenQuadVao(0)
212 {
213 }
214
215 void Simulator::setCameraAnimation(const Animation& animation)
216 {
217     _cameraAnimation = animation;
218     _recreateTimestamps = true;
219 }
220
221 void Simulator::setCameraTransformation(const Transformation& transformation)
222 {
223     _cameraTransformation = transformation;
224 }
225
226 void Simulator::setScene(const Scene& scene)
227 {
228     _scene = scene;
229     _recreateShaders = true;    // number of light sources might have changed
230     _recreateTimestamps = true; // animations changed
231     _recreateOutput = true;     // number of light sources and objects changed
232 }
233
234 void Simulator::setChipTiming(const ChipTiming& chipTiming)
235 {
236     _chipTiming = chipTiming;
237     _recreateTimestamps = true;
238 }
239
240 void Simulator::setPMD(const PMD& pmd)
241 {
242     _pmd = pmd;
243 }
244
245 void Simulator::setProjection(const Projection& projection)
246 {
247     _projection = projection;
248     _recreateOutput = true;
249 }
250
251 void Simulator::setPipeline(const Pipeline& pipeline)
252 {
253     _pipeline = pipeline;
254     _recreateShaders = true;
255     _recreateOutput = true;
256 }
257
258 void Simulator::setOutput(const Output& output)
259 {
260     _output = output;
261     _recreateShaders = true;
262     _recreateOutput = true;
263 }
264
265 void Simulator::setCustomTransformation(const Transformation& transformation)
266 {
267     _customTransformation = transformation;
268 }
269
270 int Simulator::subFrames() const
271 {
272     return (_output.pmd ? 4 : 1);
273 }
274
275 void Simulator::recreateTimestampsIfNecessary()
276 {
277     if (!_recreateTimestamps)
278         return;
279
280     _startTimestamp = _cameraAnimation.startTime();
281     _endTimestamp = _cameraAnimation.endTime();
282     for (int i = 0; i < _scene.lightAnimations.size(); i++) {
283         long long s = _scene.lightAnimations[i].startTime();
284         if (s < _startTimestamp)
285             _startTimestamp = s;
286         long long e = _scene.lightAnimations[i].endTime();
287         if (e > _endTimestamp)
288             _endTimestamp = e;
289     }
290     for (int i = 0; i < _scene.objectAnimations.size(); i++) {
291         long long s = _scene.objectAnimations[i].startTime();
292         if (s < _startTimestamp)
293             _startTimestamp = s;
294         long long e = _scene.objectAnimations[i].endTime();
295         if (e > _endTimestamp)
296             _endTimestamp = e;
297     }
298     _haveLastFrameTimestamp = false;
299     _recreateTimestamps = false;
300 }
301
302 long long Simulator::startTimestamp()
303 {
304     recreateTimestampsIfNecessary();
305     return _startTimestamp;
306 }
307
308 long long Simulator::endTimestamp()
309 {
310     recreateTimestampsIfNecessary();
311     return _endTimestamp;
312 }
313
314 long long Simulator::subFrameDuration()
315 {
316     return _chipTiming.subFrameDuration() * 1e6;
317 }
318
319 long long Simulator::frameDuration()
320 {
321     return subFrameDuration() * subFrames() + _chipTiming.pauseTime * 1e6;
322 }
323
324 float Simulator::framesPerSecond()
325 {
326     return 1e6f / frameDuration();
327 }
328
329 long long Simulator::nextFrameTimestamp()
330 {
331     recreateTimestampsIfNecessary();
332     if (_haveLastFrameTimestamp) {
333         return _lastFrameTimestamp + frameDuration();
334     } else {
335         return startTimestamp();
336     }
337 }
338
339 static QString readFile(const QString& filename)
340 {
341     QFile f(filename);
342     f.open(QIODevice::ReadOnly);
343     QTextStream in(&f);
344     return in.readAll();
345 }
346
347 void Simulator::recreateShadersIfNecessary()
348 {
349     if (!_recreateShaders)
350         return;
351
352     // Sanity checks
353     if (_scene.lights.size() < 1) {
354         qCritical("No lights in scene");
355         std::exit(1);
356     }
357     if (_scene.lights.size() != _scene.lightAnimations.size()) {
358         qCritical("Invalid number of light animations in scene");
359         std::exit(1);
360     }
361     if (_scene.objects.size() != _scene.objectAnimations.size()) {
362         qCritical("Invalid number of object animations in scene");
363         std::exit(1);
364     }
365     if (_pipeline.spatialSamples.width() < 1 || _pipeline.spatialSamples.width() % 2 != 1
366             || _pipeline.spatialSamples.height() < 1 || _pipeline.spatialSamples.height() % 2 != 1) {
367         qCritical("Invalid number of spatial samples in pipeline configuration");
368         std::exit(1);
369     }
370     if (_pipeline.spatialSampleWeights.size() > 0
371             && _pipeline.spatialSampleWeights.size()
372             != _pipeline.spatialSamples.width() * _pipeline.spatialSamples.height()) {
373         qCritical("Invalid number of spatial sample weights in pipeline configuration");
374         std::exit(1);
375     }
376     if (_pipeline.temporalSamples < 1) {
377         qCritical("Invalid number of temporal samples in pipeline configuration");
378         std::exit(1);
379     }
380     if (_pipeline.preprocLensDistortion && _pipeline.postprocLensDistortion) {
381         qCritical("Cannot enable both preproc and postproc lens distortion");
382         std::exit(1);
383     }
384     if (_pipeline.postprocLensDistortion
385             && (_output.indices || _output.forwardFlow3D || _output.forwardFlow2D
386                 || _output.backwardFlow3D || _output.backwardFlow2D)) {
387         qCritical("Postproc lens distortion cannot be applied to indices, flow3d, flow2D outputs");
388         std::exit(1);
389     }
390
391     // Clear the existing programs
392     _shadowMapPrg.removeAllShaders();
393     _reflectiveShadowMapPrg.removeAllShaders();
394     _depthPrg.removeAllShaders();
395     _lightPrg.removeAllShaders();
396     _lightOversampledPrg.removeAllShaders();
397     _pmdDigNumPrg.removeAllShaders();
398     _gaussianWhiteNoisePrg.removeAllShaders();
399     _zeroPrg.removeAllShaders();
400     _rgbResultPrg.removeAllShaders();
401     _pmdResultPrg.removeAllShaders();
402     _geomPrg.removeAllShaders();
403     _flowPrg.removeAllShaders();
404     _convertToSRGBPrg.removeAllShaders();
405     _postprocLensDistortionPrg.removeAllShaders();
406
407     // Create programs as necessary. The relevant ones are all derived from
408     // the following ├╝bershaders. Unnecessary input and output statements are
409     // deactivated via preprocessor directives. The GLSL compiler is expected
410     // to eleminate the resulting unused code (e.g. all light computations
411     // when only geometry information is written).
412     QString simVs = readFile(":/libcamsim/simulation-everything-vs.glsl");
413     QString simFs = readFile(":/libcamsim/simulation-everything-fs.glsl");
414
415     // Shadow map programs
416     if (_pipeline.shadowMaps || _pipeline.reflectiveShadowMaps) {
417         QString baseShadowMapVs = simVs;
418         QString baseShadowMapFs = simFs;
419         baseShadowMapVs.replace("$PREPROC_LENS_DISTORTION$", "0");
420         baseShadowMapFs.replace("$PREPROC_LENS_DISTORTION$", "0");
421         baseShadowMapFs.replace("$LIGHT_SOURCES$", "1");
422         baseShadowMapFs.replace("$OUTPUT_RGB$", "0");
423         baseShadowMapFs.replace("$OUTPUT_PMD$", "0");
424         baseShadowMapFs.replace("$OUTPUT_DEPTH_AND_RANGE$", "0");
425         baseShadowMapFs.replace("$OUTPUT_INDICES$", "0");
426         baseShadowMapFs.replace("$OUTPUT_FORWARDFLOW3D$", "0");
427         baseShadowMapFs.replace("$OUTPUT_FORWARDFLOW2D$", "0");
428         baseShadowMapFs.replace("$OUTPUT_BACKWARDFLOW3D$", "0");
429         baseShadowMapFs.replace("$OUTPUT_BACKWARDFLOW2D$", "0");
430         baseShadowMapFs.replace("$OUTPUT_BACKWARDVISIBILITY$", "0");
431         baseShadowMapFs.replace("$TRANSPARENCY$", _pipeline.transparency ? "1" : "0");
432         baseShadowMapFs.replace("$NORMALMAPPING$", "0");
433         baseShadowMapFs.replace("$SHADOW_MAPS$", "0");
434         baseShadowMapFs.replace("$REFLECTIVE_SHADOW_MAPS$", "0");
435         baseShadowMapFs.replace("$POWER_FACTOR_MAPS$", powerTexs() ? "1" : "0");
436         if (_pipeline.shadowMaps) {
437             QString shadowMapFs = baseShadowMapFs;
438             shadowMapFs.replace("$OUTPUT_SHADOW_MAP_DEPTH$", "1");
439             shadowMapFs.replace("$OUTPUT_EYE_SPACE_POSITIONS$", "0");
440             shadowMapFs.replace("$OUTPUT_CUSTOM_SPACE_POSITIONS$", "0");
441             shadowMapFs.replace("$OUTPUT_EYE_SPACE_NORMALS$", "0");
442             shadowMapFs.replace("$OUTPUT_CUSTOM_SPACE_NORMALS$", "0");
443             shadowMapFs.replace("$OUTPUT_RADIANCES$", "0");
444             shadowMapFs.replace("$OUTPUT_BRDF_DIFF_PARAMS$", "0");
445             shadowMapFs.replace("$OUTPUT_BRDF_SPEC_PARAMS$", "0");
446             _shadowMapPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, baseShadowMapVs);
447             _shadowMapPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, shadowMapFs);
448             if (!_shadowMapPrg.link()) {
449                 qCritical("Cannot link shadow map program");
450                 std::exit(1);
451             }
452         }
453         if (_pipeline.reflectiveShadowMaps) {
454             QString reflectiveShadowMapFs = baseShadowMapFs;
455             reflectiveShadowMapFs.replace("$OUTPUT_SHADOW_MAP_DEPTH$", "0");
456             reflectiveShadowMapFs.replace("$OUTPUT_EYE_SPACE_POSITIONS$", "0");
457             reflectiveShadowMapFs.replace("$OUTPUT_CUSTOM_SPACE_POSITIONS$", "1");
458             reflectiveShadowMapFs.replace("$OUTPUT_EYE_SPACE_NORMALS$", "0");
459             reflectiveShadowMapFs.replace("$OUTPUT_CUSTOM_SPACE_NORMALS$", "1");
460             reflectiveShadowMapFs.replace("$OUTPUT_RADIANCES$", "1");
461             reflectiveShadowMapFs.replace("$OUTPUT_BRDF_DIFF_PARAMS$", "1");
462             reflectiveShadowMapFs.replace("$OUTPUT_BRDF_SPEC_PARAMS$", "1");
463             reflectiveShadowMapFs.replace("$OUTPUT_CUSTOM_SPACE_POSITIONS_LOCATION$", "0");
464             reflectiveShadowMapFs.replace("$OUTPUT_CUSTOM_SPACE_NORMALS_LOCATION$", "1");
465             reflectiveShadowMapFs.replace("$OUTPUT_RADIANCES_LOCATION$", "2");
466             reflectiveShadowMapFs.replace("$OUTPUT_BRDF_DIFF_PARAMS_LOCATION$", "3");
467             reflectiveShadowMapFs.replace("$OUTPUT_BRDF_SPEC_PARAMS_LOCATION$", "4");
468             _reflectiveShadowMapPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, baseShadowMapVs);
469             _reflectiveShadowMapPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, reflectiveShadowMapFs);
470             if (!_reflectiveShadowMapPrg.link()) {
471                 qCritical("Cannot link reflective shadow map program");
472                 std::exit(1);
473             }
474         }
475     }
476
477     // Prerender depth only
478     QString depthVs = simVs;
479     QString depthFs = simFs;
480     depthVs.replace("$PREPROC_LENS_DISTORTION$", _pipeline.preprocLensDistortion ? "1" : "0");
481     depthFs.replace("$PREPROC_LENS_DISTORTION$", _pipeline.preprocLensDistortion ? "1" : "0");
482     depthFs.replace("$LIGHT_SOURCES$", "1");
483     depthFs.replace("$OUTPUT_SHADOW_MAP_DEPTH$", "0");
484     depthFs.replace("$OUTPUT_RGB$", "0");
485     depthFs.replace("$OUTPUT_PMD$", "0");
486     depthFs.replace("$OUTPUT_EYE_SPACE_POSITIONS$", "0");
487     depthFs.replace("$OUTPUT_CUSTOM_SPACE_POSITIONS$", "0");
488     depthFs.replace("$OUTPUT_EYE_SPACE_NORMALS$", "0");
489     depthFs.replace("$OUTPUT_CUSTOM_SPACE_NORMALS$", "0");
490     depthFs.replace("$OUTPUT_DEPTH_AND_RANGE$", "0");
491     depthFs.replace("$OUTPUT_INDICES$", "0");
492     depthFs.replace("$OUTPUT_FORWARDFLOW3D$", "0");
493     depthFs.replace("$OUTPUT_FORWARDFLOW2D$", "0");
494     depthFs.replace("$OUTPUT_BACKWARDFLOW3D$", "0");
495     depthFs.replace("$OUTPUT_BACKWARDFLOW2D$", "0");
496     depthFs.replace("$OUTPUT_BACKWARDVISIBILITY$", "0");
497     depthFs.replace("$OUTPUT_RADIANCES$", "0");
498     depthFs.replace("$OUTPUT_BRDF_DIFF_PARAMS$", "0");
499     depthFs.replace("$OUTPUT_BRDF_SPEC_PARAMS$", "0");
500     depthFs.replace("$TRANSPARENCY$", _pipeline.transparency ? "1" : "0");
501     depthFs.replace("$NORMALMAPPING$", "0");
502     depthFs.replace("$SHADOW_MAPS$", "0");
503     depthFs.replace("$REFLECTIVE_SHADOW_MAPS$", "0");
504     depthFs.replace("$POWER_FACTOR_MAPS$", "0");
505     _depthPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, depthVs);
506     _depthPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, depthFs);
507     if (!_depthPrg.link()) {
508         qCritical("Cannot link depth simulation program");
509         std::exit(1);
510     }
511
512     // Light-based simulation programs
513     if (_output.rgb || _output.pmd) {
514         QVector<int> tmpInt(_scene.lights.size());
515         QVector<float> tmpVec3(3 * _scene.lights.size());
516         QVector<float> tmpFloat(_scene.lights.size());
517         QString lightVs = simVs;
518         QString lightFs = simFs;
519         lightVs.replace("$PREPROC_LENS_DISTORTION$", _pipeline.preprocLensDistortion ? "1" : "0");
520         lightFs.replace("$PREPROC_LENS_DISTORTION$", _pipeline.preprocLensDistortion ? "1" : "0");
521         lightFs.replace("$LIGHT_SOURCES$", QString::number(_scene.lights.size()));
522         lightFs.replace("$OUTPUT_SHADOW_MAP_DEPTH$", "0");
523         lightFs.replace("$OUTPUT_RGB$", _output.rgb ? "1" : "0");
524         lightFs.replace("$OUTPUT_PMD$", _output.pmd ? "1" : "0");
525         lightFs.replace("$OUTPUT_EYE_SPACE_POSITIONS$", "0");
526         lightFs.replace("$OUTPUT_CUSTOM_SPACE_POSITIONS$", "0");
527         lightFs.replace("$OUTPUT_EYE_SPACE_NORMALS$", "0");
528         lightFs.replace("$OUTPUT_CUSTOM_SPACE_NORMALS$", "0");
529         lightFs.replace("$OUTPUT_DEPTH_AND_RANGE$", "0");
530         lightFs.replace("$OUTPUT_INDICES$", "0");
531         lightFs.replace("$OUTPUT_FORWARDFLOW3D$", "0");
532         lightFs.replace("$OUTPUT_FORWARDFLOW2D$", "0");
533         lightFs.replace("$OUTPUT_BACKWARDFLOW3D$", "0");
534         lightFs.replace("$OUTPUT_BACKWARDFLOW2D$", "0");
535         lightFs.replace("$OUTPUT_BACKWARDVISIBILITY$", "0");
536         lightFs.replace("$OUTPUT_RADIANCES$", "0");
537         lightFs.replace("$OUTPUT_BRDF_DIFF_PARAMS$", "0");
538         lightFs.replace("$OUTPUT_BRDF_SPEC_PARAMS$", "0");
539         lightFs.replace("$OUTPUT_RGB_LOCATION$", "0");
540         lightFs.replace("$OUTPUT_PMD_LOCATION$", _output.rgb ? "1" : "0");
541         lightFs.replace("$TRANSPARENCY$", _pipeline.transparency ? "1" : "0");
542         lightFs.replace("$NORMALMAPPING$", _pipeline.normalMapping ? "1" : "0");
543         lightFs.replace("$SHADOW_MAPS$", _pipeline.shadowMaps ? "1" : "0");
544         lightFs.replace("$SHADOW_MAP_FILTERING$", _pipeline.shadowMapFiltering ? "1" : "0");
545         lightFs.replace("$REFLECTIVE_SHADOW_MAPS$", _pipeline.reflectiveShadowMaps ? "1" : "0");
546         lightFs.replace("$POWER_FACTOR_MAPS$", powerTexs() ? "1" : "0");
547         _lightPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, lightVs);
548         _lightPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, lightFs);
549         if (!_lightPrg.link()) {
550             qCritical("Cannot link light simulation program");
551             std::exit(1);
552         }
553         _lightPrg.bind();
554         // set static light source properties
555         for (int i = 0; i < _scene.lights.size(); i++)
556             tmpInt[i] = _scene.lights[i].type;
557         _lightPrg.setUniformValueArray("light_type", tmpInt.constData(), _scene.lights.size());
558         for (int i = 0; i < _scene.lights.size(); i++)
559             tmpFloat[i] = qDegreesToRadians(_scene.lights[i].innerConeAngle);
560         _lightPrg.setUniformValueArray("light_inner_cone_angle", tmpFloat.constData(), _scene.lights.size(), 1);
561         for (int i = 0; i < _scene.lights.size(); i++)
562             tmpFloat[i] = qDegreesToRadians(_scene.lights[i].outerConeAngle);
563         _lightPrg.setUniformValueArray("light_outer_cone_angle", tmpFloat.constData(), _scene.lights.size(), 1);
564         for (int i = 0; i < _scene.lights.size(); i++) {
565             tmpVec3[3 * i + 0] = _scene.lights[i].attenuationConstant;
566             tmpVec3[3 * i + 1] = _scene.lights[i].attenuationLinear;
567             tmpVec3[3 * i + 2] = _scene.lights[i].attenuationQuadratic;
568         }
569         _lightPrg.setUniformValueArray("light_attenuation", tmpVec3.constData(), _scene.lights.size(), 3);
570         for (int i = 0; i < _scene.lights.size(); i++)
571             for (int j = 0; j < 3; j++)
572                 tmpVec3[3 * i + j] = _scene.lights[i].color[j];
573         _lightPrg.setUniformValueArray("light_color", tmpVec3.constData(), _scene.lights.size(), 3);
574         if (_output.pmd) {
575             for (int i = 0; i < _scene.lights.size(); i++)
576                 tmpFloat[i] = lightIntensity(i);
577             _lightPrg.setUniformValueArray("light_intensity", tmpFloat.constData(), _scene.lights.size(), 1);
578         }
579         // additional simple programs for oversampling, white noise, and subframe combination
580         QString lightOversampledVs = readFile(":/libcamsim/simulation-oversampling-vs.glsl");
581         QString lightOversampledFs = readFile(":/libcamsim/simulation-oversampling-fs.glsl");
582         lightOversampledFs.replace("$TWO_INPUTS$", (_output.rgb && _output.pmd ? "1" : "0"));
583         lightOversampledFs.replace("$WEIGHTS_WIDTH$", QString::number(_pipeline.spatialSamples.width()));
584         lightOversampledFs.replace("$WEIGHTS_HEIGHT$", QString::number(_pipeline.spatialSamples.height()));
585         _lightOversampledPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, lightOversampledVs);
586         _lightOversampledPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, lightOversampledFs);
587         _lightOversampledPrg.link();
588         _lightOversampledPrg.bind();
589         _lightOversampledPrg.setUniformValue("oversampled0", 0);
590         _lightOversampledPrg.setUniformValue("oversampled1", 1);
591         int weightCount = _pipeline.spatialSamples.width() * _pipeline.spatialSamples.height();
592         QVector<float> defaultWeights(weightCount, 1.0f);
593         _lightOversampledPrg.setUniformValueArray("weights",
594                 _pipeline.spatialSampleWeights.size() > 0
595                 ? _pipeline.spatialSampleWeights.constData()
596                 : defaultWeights.constData(),
597                 weightCount, 1);
598         if (_output.pmd) {
599             QString pmdDigNumVs = readFile(":/libcamsim/simulation-pmd-dignums-vs.glsl");
600             QString pmdDigNumFs = readFile(":/libcamsim/simulation-pmd-dignums-fs.glsl");
601             pmdDigNumFs.replace("$SHOT_NOISE$", _pipeline.shotNoise ? "1" : "0");
602             _pmdDigNumPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, pmdDigNumVs);
603             _pmdDigNumPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, pmdDigNumFs);
604             _pmdDigNumPrg.link();
605             _pmdDigNumPrg.bind();
606             _pmdDigNumPrg.setUniformValue("pmd_energies", 0);
607             _pmdDigNumPrg.setUniformValue("gaussian_noise_tex", 1);
608         }
609         QString gaussianWhiteNoiseVs = readFile(":/libcamsim/simulation-whitenoise-vs.glsl");
610         QString gaussianWhiteNoiseFs = readFile(":/libcamsim/simulation-whitenoise-fs.glsl");
611         _gaussianWhiteNoisePrg.addShaderFromSourceCode(QOpenGLShader::Vertex, gaussianWhiteNoiseVs);
612         _gaussianWhiteNoisePrg.addShaderFromSourceCode(QOpenGLShader::Fragment, gaussianWhiteNoiseFs);
613         _gaussianWhiteNoisePrg.link();
614         _gaussianWhiteNoisePrg.bind();
615         _gaussianWhiteNoisePrg.setUniformValue("noise_tex", 0);
616         QString zeroVs = readFile(":/libcamsim/simulation-zero-vs.glsl");
617         QString zeroFs = readFile(":/libcamsim/simulation-zero-fs.glsl");
618         zeroFs.replace("$TWO_OUTPUTS$", (_output.rgb && _output.pmd ? "1" : "0"));
619         _zeroPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, zeroVs);
620         _zeroPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, zeroFs);
621         _zeroPrg.link();
622         if (subFrames() > 1) {
623             if (_output.rgb) {
624                 QString rgbResultVs = readFile(":/libcamsim/simulation-rgb-result-vs.glsl");
625                 QString rgbResultFs = readFile(":/libcamsim/simulation-rgb-result-fs.glsl");
626                 rgbResultFs.replace("$SUBFRAMES$", QString::number(subFrames()));
627                 _rgbResultPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, rgbResultVs);
628                 _rgbResultPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, rgbResultFs);
629                 _rgbResultPrg.link();
630                 _rgbResultPrg.bind();
631                 QVector<int> samplers(subFrames());
632                 for (int i = 0; i < samplers.size(); i++)
633                     samplers[i] = i;
634                 _rgbResultPrg.setUniformValueArray("texs", samplers.constData(), samplers.size());
635             }
636             if (_output.pmd) {
637                 QString pmdResultVs = readFile(":/libcamsim/simulation-pmd-result-vs.glsl");
638                 QString pmdResultFs = readFile(":/libcamsim/simulation-pmd-result-fs.glsl");
639                 _pmdResultPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, pmdResultVs);
640                 _pmdResultPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, pmdResultFs);
641                 _pmdResultPrg.link();
642                 _pmdResultPrg.bind();
643                 QVector<int> samplers(subFrames());
644                 for (int i = 0; i < samplers.size(); i++)
645                     samplers[i] = i;
646                 _pmdResultPrg.setUniformValueArray("phase_texs", samplers.constData(), samplers.size());
647             }
648         }
649         // conversion from linear RGB to sRGB
650         if (_output.srgb) {
651             QString convVs = readFile(":/libcamsim/convert-to-srgb-vs.glsl");
652             QString convFs = readFile(":/libcamsim/convert-to-srgb-fs.glsl");
653             _convertToSRGBPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, convVs);
654             _convertToSRGBPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, convFs);
655             _convertToSRGBPrg.link();
656         }
657     }
658
659     // Geometry simulation program
660     if (_output.eyeSpacePositions || _output.customSpacePositions
661             || _output.eyeSpaceNormals || _output.customSpaceNormals
662             || _output.depthAndRange || _output.indices) {
663         QString geomVs = simVs;
664         QString geomFs = simFs;
665         geomVs.replace("$PREPROC_LENS_DISTORTION$", _pipeline.preprocLensDistortion ? "1" : "0");
666         geomFs.replace("$PREPROC_LENS_DISTORTION$", _pipeline.preprocLensDistortion ? "1" : "0");
667         geomFs.replace("$LIGHT_SOURCES$", "1");
668         geomFs.replace("$OUTPUT_SHADOW_MAP_DEPTH$", "0");
669         geomFs.replace("$OUTPUT_RGB$", "0");
670         geomFs.replace("$OUTPUT_PMD$", "0");
671         geomFs.replace("$OUTPUT_EYE_SPACE_POSITIONS$", QString::number(_output.eyeSpacePositions ? 1 : 0));
672         geomFs.replace("$OUTPUT_CUSTOM_SPACE_POSITIONS$", QString::number(_output.customSpacePositions ? 1 : 0));
673         geomFs.replace("$OUTPUT_EYE_SPACE_NORMALS$", QString::number(_output.eyeSpaceNormals ? 1 : 0));
674         geomFs.replace("$OUTPUT_CUSTOM_SPACE_NORMALS$", QString::number(_output.customSpaceNormals ? 1 : 0));
675         geomFs.replace("$OUTPUT_DEPTH_AND_RANGE$", QString::number(_output.depthAndRange ? 1 : 0));
676         geomFs.replace("$OUTPUT_INDICES$", QString::number(_output.indices ? 1 : 0));
677         geomFs.replace("$OUTPUT_FORWARDFLOW3D$", "0");
678         geomFs.replace("$OUTPUT_FORWARDFLOW2D$", "0");
679         geomFs.replace("$OUTPUT_BACKWARDFLOW3D$", "0");
680         geomFs.replace("$OUTPUT_BACKWARDFLOW2D$", "0");
681         geomFs.replace("$OUTPUT_BACKWARDVISIBILITY$", "0");
682         geomFs.replace("$OUTPUT_RADIANCES$", "0");
683         geomFs.replace("$OUTPUT_BRDF_DIFF_PARAMS$", "0");
684         geomFs.replace("$OUTPUT_BRDF_SPEC_PARAMS$", "0");
685         geomFs.replace("$TRANSPARENCY$", _pipeline.transparency ? "1" : "0");
686         geomFs.replace("$NORMALMAPPING$", _pipeline.normalMapping ? "1" : "0");
687         geomFs.replace("$SHADOW_MAPS$", "0");
688         geomFs.replace("$REFLECTIVE_SHADOW_MAPS$", "0");
689         geomFs.replace("$POWER_FACTOR_MAPS$", "0");
690         int outputIndex = 0;
691         if (_output.eyeSpacePositions)
692             geomFs.replace("$OUTPUT_EYE_SPACE_POSITIONS_LOCATION$", QString::number(outputIndex++));
693         if (_output.customSpacePositions)
694             geomFs.replace("$OUTPUT_CUSTOM_SPACE_POSITIONS_LOCATION$", QString::number(outputIndex++));
695         if (_output.eyeSpaceNormals)
696             geomFs.replace("$OUTPUT_EYE_SPACE_NORMALS_LOCATION$", QString::number(outputIndex++));
697         if (_output.customSpaceNormals)
698             geomFs.replace("$OUTPUT_CUSTOM_SPACE_NORMALS_LOCATION$", QString::number(outputIndex++));
699         if (_output.depthAndRange)
700             geomFs.replace("$OUTPUT_DEPTH_AND_RANGE_LOCATION$", QString::number(outputIndex++));
701         if (_output.indices)
702             geomFs.replace("$OUTPUT_INDICES_LOCATION$", QString::number(outputIndex++));
703         _geomPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, geomVs);
704         _geomPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, geomFs);
705         if (!_geomPrg.link()) {
706             qCritical("Cannot link geometry simulation program");
707             std::exit(1);
708         }
709     }
710
711     // Flow simulation program
712     if (_output.forwardFlow3D || _output.forwardFlow2D || _output.backwardFlow3D || _output.backwardFlow2D) {
713         QString flowVs = simVs;
714         QString flowFs = simFs;
715         flowVs.replace("$PREPROC_LENS_DISTORTION$", _pipeline.preprocLensDistortion ? "1" : "0");
716         flowFs.replace("$PREPROC_LENS_DISTORTION$", _pipeline.preprocLensDistortion ? "1" : "0");
717         flowFs.replace("$LIGHT_SOURCES$", "1");
718         flowFs.replace("$OUTPUT_SHADOW_MAP_DEPTH$", "0");
719         flowFs.replace("$OUTPUT_RGB$", "0");
720         flowFs.replace("$OUTPUT_PMD$", "0");
721         flowFs.replace("$OUTPUT_EYE_SPACE_POSITIONS$", "0");
722         flowFs.replace("$OUTPUT_CUSTOM_SPACE_POSITIONS$", "0");
723         flowFs.replace("$OUTPUT_EYE_SPACE_NORMALS$", "0");
724         flowFs.replace("$OUTPUT_CUSTOM_SPACE_NORMALS$", "0");
725         flowFs.replace("$OUTPUT_DEPTH_AND_RANGE$", "0");
726         flowFs.replace("$OUTPUT_INDICES$", "0");
727         flowFs.replace("$OUTPUT_FORWARDFLOW3D$", QString::number(_output.forwardFlow3D ? 1 : 0));
728         flowFs.replace("$OUTPUT_FORWARDFLOW2D$", QString::number(_output.forwardFlow2D ? 1 : 0));
729         flowFs.replace("$OUTPUT_BACKWARDFLOW3D$", QString::number(_output.backwardFlow3D ? 1 : 0));
730         flowFs.replace("$OUTPUT_BACKWARDFLOW2D$", QString::number(_output.backwardFlow2D ? 1 : 0));
731         flowFs.replace("$OUTPUT_RADIANCES$", "0");
732         flowFs.replace("$OUTPUT_BRDF_DIFF_PARAMS$", "0");
733         flowFs.replace("$OUTPUT_BRDF_SPEC_PARAMS$", "0");
734         flowFs.replace("$TRANSPARENCY$", _pipeline.transparency ? "1" : "0");
735         flowFs.replace("$NORMALMAPPING$", _pipeline.normalMapping ? "1" : "0");
736         flowFs.replace("$SHADOW_MAPS$", "0");
737         flowFs.replace("$REFLECTIVE_SHADOW_MAPS$", "0");
738         flowFs.replace("$POWER_FACTOR_MAPS$", "0");
739         int outputIndex = 0;
740         if (_output.forwardFlow3D)
741             flowFs.replace("$OUTPUT_FORWARDFLOW3D_LOCATION$", QString::number(outputIndex++));
742         if (_output.forwardFlow2D)
743             flowFs.replace("$OUTPUT_FORWARDFLOW2D_LOCATION$", QString::number(outputIndex++));
744         if (_output.backwardFlow3D)
745             flowFs.replace("$OUTPUT_BACKWARDFLOW3D_LOCATION$", QString::number(outputIndex++));
746         if (_output.backwardFlow2D)
747             flowFs.replace("$OUTPUT_BACKWARDFLOW2D_LOCATION$", QString::number(outputIndex++));
748         _flowPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, flowVs);
749         _flowPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, flowFs);
750         if (!_flowPrg.link()) {
751             qCritical("Cannot link flow simulation program");
752             std::exit(1);
753         }
754     }
755
756     // Postproc lens distortion program
757     if (_pipeline.postprocLensDistortion) {
758         QString distortionVS = readFile(":/libcamsim/simulation-postproc-lensdistortion-vs.glsl");
759         QString distortionFS = readFile(":/libcamsim/simulation-postproc-lensdistortion-fs.glsl");
760         _postprocLensDistortionPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, distortionVS);
761         _postprocLensDistortionPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, distortionFS);
762         if (!_postprocLensDistortionPrg.link()) {
763             qCritical("Cannot link postproc lens distortion program");
764             std::exit(1);
765         }
766     }
767
768     _haveLastFrameTimestamp = false;
769     _recreateShaders = false;
770 }
771
772 void Simulator::prepareDepthBuffers(QSize size, const QVector<unsigned int>& depthBufs)
773 {
774     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
775     ASSERT_GLCHECK();
776     for (int i = 0; i < depthBufs.size(); i++) {
777         gl->glBindTexture(GL_TEXTURE_2D, depthBufs[i]);
778         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
779         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
780         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
781         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
782         gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, size.width(), size.height(),
783                 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
784     }
785     ASSERT_GLCHECK();
786 }
787
788 void Simulator::prepareOutputTexs(QSize size, const QVector<unsigned int>& outputTexs, int internalFormat, bool interpolation)
789 {
790     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
791     ASSERT_GLCHECK();
792     bool isIntegerFormat = (internalFormat == GL_R32UI || internalFormat == GL_RG32UI
793             || internalFormat == GL_RGB32UI || internalFormat == GL_RGBA32UI);
794     GLenum format = isIntegerFormat ? GL_RGBA_INTEGER : GL_RGBA;
795     GLenum type = isIntegerFormat ? GL_UNSIGNED_INT : GL_FLOAT;
796     for (int i = 0; i < outputTexs.size(); i++) {
797         gl->glBindTexture(GL_TEXTURE_2D, outputTexs[i]);
798         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, interpolation ? GL_LINEAR : GL_NEAREST);
799         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, interpolation ? GL_LINEAR : GL_NEAREST);
800         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
801         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
802         gl->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, size.width(), size.height(),
803                 0, format, type, NULL);
804     }
805     ASSERT_GLCHECK();
806 }
807
808 bool Simulator::spatialOversampling() const
809 {
810     return (_pipeline.spatialSamples.width() > 1 || _pipeline.spatialSamples.height() > 1);
811 }
812
813 QSize Simulator::spatialOversamplingSize() const
814 {
815     return QSize(
816             _projection.imageSize().width() * _pipeline.spatialSamples.width(),
817             _projection.imageSize().height() * _pipeline.spatialSamples.height());
818 }
819
820 bool Simulator::temporalOversampling() const
821 {
822     return (_pipeline.temporalSamples > 1);
823 }
824
825 bool Simulator::powerTexs() const
826 {
827     for (int i = 0; i < _scene.lights.size(); i++)
828         if (_scene.lights[i].powerFactorTex != 0
829                 || _scene.lights[i].powerFactors.size() > 0
830                 || _scene.lights[i].powerFactorMapCallback)
831             return true;
832     return false;
833 }
834
835 void Simulator::recreateOutputIfNecessary()
836 {
837     if (!_recreateOutput)
838         return;
839
840     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
841     ASSERT_GLCHECK();
842
843     // Delete all existing output
844     _timestamps.clear();
845     _cameraTransformations.clear();
846     _lightTransformations.clear();
847     _objectTransformations.clear();
848     for (int i = 0; i < _shadowMapDepthBufs.size(); i++)
849         gl->glDeleteTextures(_shadowMapDepthBufs[i].size(), _shadowMapDepthBufs[i].constData());
850     _shadowMapDepthBufs.clear();
851     for (int i = 0; i < _reflectiveShadowMapDepthBufs.size(); i++)
852         gl->glDeleteTextures(_reflectiveShadowMapDepthBufs[i].size(), _reflectiveShadowMapDepthBufs[i].constData());
853     _reflectiveShadowMapDepthBufs.clear();
854     for (int i = 0; i < _reflectiveShadowMapTexs.size(); i++)
855         gl->glDeleteTextures(_reflectiveShadowMapTexs[i].size(), _reflectiveShadowMapTexs[i].constData());
856     _reflectiveShadowMapTexs.clear();
857     gl->glDeleteBuffers(1, &_pbo);
858     _pbo = 0;
859     gl->glDeleteTextures(1, &_depthBufferOversampled);
860     _depthBufferOversampled = 0;
861     gl->glDeleteTextures(1, &_rgbTexOversampled);
862     _rgbTexOversampled = 0;
863     gl->glDeleteTextures(1, &_pmdEnergyTexOversampled);
864     _pmdEnergyTexOversampled = 0;
865     gl->glDeleteTextures(1, &_pmdEnergyTex);
866     _pmdEnergyTex = 0;
867     gl->glDeleteTextures(1, &_gaussianNoiseTex);
868     _gaussianNoiseTex = 0;
869     _gaussianWhiteNoiseBuf.clear();
870     gl->glDeleteTextures(_gaussianWhiteNoiseTexs.size(), _gaussianWhiteNoiseTexs.constData());
871     _gaussianWhiteNoiseTexs.clear();
872     gl->glDeleteTextures(_depthBuffers.size(), _depthBuffers.constData());
873     _depthBuffers.clear();
874     gl->glDeleteTextures(_rgbTexs.size(), _rgbTexs.constData());
875     _rgbTexs.clear();
876     gl->glDeleteTextures(_srgbTexs.size(), _srgbTexs.constData());
877     _srgbTexs.clear();
878     gl->glDeleteTextures(_pmdDigNumTexs.size(), _pmdDigNumTexs.constData());
879     _pmdDigNumTexs.clear();
880     gl->glDeleteTextures(_eyeSpacePosTexs.size(), _eyeSpacePosTexs.constData());
881     _eyeSpacePosTexs.clear();
882     gl->glDeleteTextures(_customSpacePosTexs.size(), _customSpacePosTexs.constData());
883     _customSpacePosTexs.clear();
884     gl->glDeleteTextures(_eyeSpaceNormalTexs.size(), _eyeSpaceNormalTexs.constData());
885     _eyeSpaceNormalTexs.clear();
886     gl->glDeleteTextures(_customSpaceNormalTexs.size(), _customSpaceNormalTexs.constData());
887     _customSpaceNormalTexs.clear();
888     gl->glDeleteTextures(_depthAndRangeTexs.size(), _depthAndRangeTexs.constData());
889     _depthAndRangeTexs.clear();
890     gl->glDeleteTextures(_indicesTexs.size(), _indicesTexs.constData());
891     _indicesTexs.clear();
892     gl->glDeleteTextures(_forwardFlow3DTexs.size(), _forwardFlow3DTexs.constData());
893     _forwardFlow3DTexs.clear();
894     gl->glDeleteTextures(_forwardFlow2DTexs.size(), _forwardFlow2DTexs.constData());
895     _forwardFlow2DTexs.clear();
896     gl->glDeleteTextures(_backwardFlow3DTexs.size(), _backwardFlow3DTexs.constData());
897     _backwardFlow3DTexs.clear();
898     gl->glDeleteTextures(_backwardFlow2DTexs.size(), _backwardFlow2DTexs.constData());
899     _backwardFlow2DTexs.clear();
900     _lightSimOutputTexs.clear();
901     _geomSimOutputTexs.clear();
902     _flowSimOutputTexs.clear();
903     _oversampledLightSimOutputTexs.clear();
904     gl->glDeleteTextures(1, &_postProcessingTex);
905     _postProcessingTex = 0;
906
907     // Create new output as needed
908     _timestamps.resize(subFrames());
909     _cameraTransformations.resize(subFrames());
910     _lightTransformations.resize(subFrames());
911     for (int i = 0; i < _lightTransformations.size(); i++)
912         _lightTransformations[i].resize(_scene.lights.size());
913     _objectTransformations.resize(subFrames());
914     for (int i = 0; i < _objectTransformations.size(); i++)
915         _objectTransformations[i].resize(_scene.objects.size());
916     if (_pipeline.shadowMaps) {
917         gl->glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
918         _shadowMapDepthBufs.resize(subFrames());
919         for (int subFrame = 0; subFrame < subFrames(); subFrame++) {
920             _shadowMapDepthBufs[subFrame].resize(_scene.lights.size());
921             for (int light = 0; light < _scene.lights.size(); light++) {
922                 _shadowMapDepthBufs[subFrame][light] = 0;
923                 if (_scene.lights[light].shadowMap) {
924                     gl->glGenTextures(1, &(_shadowMapDepthBufs[subFrame][light]));
925                     gl->glBindTexture(GL_TEXTURE_CUBE_MAP, _shadowMapDepthBufs[subFrame][light]);
926                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, _pipeline.shadowMapFiltering ? GL_NEAREST : GL_LINEAR);
927                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, _pipeline.shadowMapFiltering ? GL_NEAREST : GL_LINEAR);
928                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
929                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
930                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
931                     for (int cubeSide = 0; cubeSide < 6; cubeSide++) {
932                         gl->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeSide, 0,
933                                 GL_DEPTH_COMPONENT32F,
934                                 _scene.lights[light].shadowMapSize,
935                                 _scene.lights[light].shadowMapSize,
936                                 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
937                     }
938                 }
939             }
940         }
941     }
942     if (_pipeline.reflectiveShadowMaps) {
943         gl->glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
944         _reflectiveShadowMapDepthBufs.resize(subFrames());
945         _reflectiveShadowMapTexs.resize(subFrames());
946         for (int subFrame = 0; subFrame < subFrames(); subFrame++) {
947             _reflectiveShadowMapDepthBufs[subFrame].resize(_scene.lights.size());
948             _reflectiveShadowMapTexs[subFrame].resize(_scene.lights.size());
949             for (int light = 0; light < _scene.lights.size(); light++) {
950                 _reflectiveShadowMapDepthBufs[subFrame][light] = 0;
951                 _reflectiveShadowMapTexs[subFrame][light] = 0;
952                 if (_scene.lights[light].reflectiveShadowMap) {
953                     gl->glGenTextures(1, &(_reflectiveShadowMapDepthBufs[subFrame][light]));
954                     gl->glBindTexture(GL_TEXTURE_CUBE_MAP, _reflectiveShadowMapDepthBufs[subFrame][light]);
955                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
956                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
957                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
958                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
959                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
960                     for (int cubeSide = 0; cubeSide < 6; cubeSide++) {
961                         gl->glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeSide, 0,
962                                 GL_DEPTH_COMPONENT24,
963                                 _scene.lights[light].reflectiveShadowMapSize,
964                                 _scene.lights[light].reflectiveShadowMapSize,
965                                 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
966                     }
967                     gl->glGenTextures(1, &(_reflectiveShadowMapTexs[subFrame][light]));
968                     gl->glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, _reflectiveShadowMapTexs[subFrame][light]);
969                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
970                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
971                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
972                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
973                     gl->glTexParameteri(GL_TEXTURE_CUBE_MAP_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
974                     gl->glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, GL_RGBA32F,
975                             _scene.lights[light].reflectiveShadowMapSize,
976                             _scene.lights[light].reflectiveShadowMapSize, 6 * 5,
977                             0, GL_RGBA, GL_FLOAT, NULL);
978                 }
979             }
980         }
981     }
982     ASSERT_GLCHECK();
983     gl->glGenBuffers(1, &_pbo);
984     if (_output.rgb || _output.pmd) {
985         gl->glGenTextures(1, &_depthBufferOversampled);
986         prepareDepthBuffers(spatialOversamplingSize(), { _depthBufferOversampled });
987     }
988     if (_output.rgb) {
989         gl->glGenTextures(1, &_rgbTexOversampled);
990         prepareOutputTexs(spatialOversamplingSize(), { _rgbTexOversampled }, GL_RGBA32F, false);
991     }
992     if (_output.pmd) {
993         gl->glGenTextures(1, &_pmdEnergyTexOversampled);
994         prepareOutputTexs(spatialOversamplingSize(), { _pmdEnergyTexOversampled }, GL_RG32F, false);
995         gl->glGenTextures(1, &_pmdEnergyTex);
996         prepareOutputTexs(_projection.imageSize(), { _pmdEnergyTex }, GL_RG32F, false);
997     }
998     int extra = (subFrames() > 1 ? 1 : 0);
999     if (_output.rgb && _pipeline.gaussianWhiteNoise) {
1000         _gaussianWhiteNoiseBuf.resize(3 * _projection.imageSize().width() * _projection.imageSize().height());
1001         _gaussianWhiteNoiseTexs.resize(subFrames());
1002         gl->glGenTextures(subFrames(), _gaussianWhiteNoiseTexs.data());
1003         prepareOutputTexs(_projection.imageSize(), _gaussianWhiteNoiseTexs, GL_RGBA32F, false);
1004     }
1005     _depthBuffers.resize(subFrames() + 1);
1006     gl->glGenTextures(subFrames() + 1, _depthBuffers.data());
1007     prepareDepthBuffers(_projection.imageSize(), _depthBuffers);
1008     bool interpolation = (_pipeline.postprocLensDistortion);
1009     if (_output.rgb) {
1010         _rgbTexs.resize(subFrames() + extra);
1011         gl->glGenTextures(subFrames() + extra, _rgbTexs.data());
1012         prepareOutputTexs(_projection.imageSize(), _rgbTexs, GL_RGBA32F, interpolation);
1013         if (_output.srgb) {
1014             _srgbTexs.resize(subFrames() + extra);
1015             gl->glGenTextures(subFrames() + extra, _srgbTexs.data());
1016             prepareOutputTexs(_projection.imageSize(), _srgbTexs, GL_RGBA8, false);
1017         }
1018     }
1019     if (_output.pmd) {
1020         _pmdDigNumTexs.resize(subFrames() + extra);
1021         gl->glGenTextures(subFrames() + extra, _pmdDigNumTexs.data());
1022         prepareOutputTexs(_projection.imageSize(), _pmdDigNumTexs, GL_RGBA32F, interpolation);
1023         if (_pipeline.shotNoise) {
1024             gl->glGenTextures(1, &_gaussianNoiseTex);
1025             prepareOutputTexs(_projection.imageSize(), { _gaussianNoiseTex }, GL_RG32F, false);
1026         }
1027     }
1028     if (_output.eyeSpacePositions) {
1029         _eyeSpacePosTexs.resize(subFrames());
1030         gl->glGenTextures(subFrames(), _eyeSpacePosTexs.data());
1031         prepareOutputTexs(_projection.imageSize(), _eyeSpacePosTexs, GL_RGBA32F, interpolation);
1032     }
1033     if (_output.customSpacePositions) {
1034         _customSpacePosTexs.resize(subFrames());
1035         gl->glGenTextures(subFrames(), _customSpacePosTexs.data());
1036         prepareOutputTexs(_projection.imageSize(), _customSpacePosTexs, GL_RGBA32F, interpolation);
1037     }
1038     if (_output.eyeSpaceNormals) {
1039         _eyeSpaceNormalTexs.resize(subFrames());
1040         gl->glGenTextures(subFrames(), _eyeSpaceNormalTexs.data());
1041         prepareOutputTexs(_projection.imageSize(), _eyeSpaceNormalTexs, GL_RGBA32F, interpolation);
1042     }
1043     if (_output.customSpaceNormals) {
1044         _customSpaceNormalTexs.resize(subFrames());
1045         gl->glGenTextures(subFrames(), _customSpaceNormalTexs.data());
1046         prepareOutputTexs(_projection.imageSize(), _customSpaceNormalTexs, GL_RGBA32F, interpolation);
1047     }
1048     if (_output.depthAndRange) {
1049         _depthAndRangeTexs.resize(subFrames());
1050         gl->glGenTextures(subFrames(), _depthAndRangeTexs.data());
1051         prepareOutputTexs(_projection.imageSize(), _depthAndRangeTexs,
1052                 _pipeline.postprocLensDistortion ? GL_RGBA32F : GL_RG32F, interpolation);
1053         // the reason for using 4 instead of 2 components if lens distortion is active
1054         // is that only then the internal formats of this texture and _postProcessingTex
1055         // are compatible for glCopySubImageData().
1056     }
1057     if (_output.indices) {
1058         _indicesTexs.resize(subFrames());
1059         gl->glGenTextures(subFrames(), _indicesTexs.data());
1060         prepareOutputTexs(_projection.imageSize(), _indicesTexs, GL_RGBA32UI, false);
1061     }
1062     if (_output.forwardFlow3D) {
1063         _forwardFlow3DTexs.resize(subFrames() + extra);
1064         gl->glGenTextures(subFrames() + extra, _forwardFlow3DTexs.data());
1065         prepareOutputTexs(_projection.imageSize(), _forwardFlow3DTexs, GL_RGBA32F, false);
1066     }
1067     if (_output.forwardFlow2D) {
1068         _forwardFlow2DTexs.resize(subFrames() + extra);
1069         gl->glGenTextures(subFrames() + extra, _forwardFlow2DTexs.data());
1070         prepareOutputTexs(_projection.imageSize(), _forwardFlow2DTexs, GL_RG32F, false);
1071     }
1072     if (_output.backwardFlow3D) {
1073         _backwardFlow3DTexs.resize(subFrames() + extra);
1074         gl->glGenTextures(subFrames() + extra, _backwardFlow3DTexs.data());
1075         prepareOutputTexs(_projection.imageSize(), _backwardFlow3DTexs, GL_RGBA32F, false);
1076     }
1077     if (_output.backwardFlow2D) {
1078         _backwardFlow2DTexs.resize(subFrames() + extra);
1079         gl->glGenTextures(subFrames() + extra, _backwardFlow2DTexs.data());
1080         prepareOutputTexs(_projection.imageSize(), _backwardFlow2DTexs, GL_RG32F, false);
1081     }
1082     if (_pipeline.postprocLensDistortion) {
1083         gl->glGenTextures(1, &_postProcessingTex);
1084         prepareOutputTexs(_projection.imageSize(), { _postProcessingTex }, GL_RGBA32F, false);
1085         gl->glBindTexture(GL_TEXTURE_2D, _postProcessingTex);
1086     }
1087
1088     // Prepare output texture lists for light simulation, flow simulation, and geometry simulation
1089     _lightSimOutputTexs.resize(subFrames());
1090     _geomSimOutputTexs.resize(subFrames());
1091     _flowSimOutputTexs.resize(subFrames() + extra);
1092     if (_output.rgb)
1093         for (int i = 0; i < _lightSimOutputTexs.size(); i++)
1094             _lightSimOutputTexs[i].append(_rgbTexs[i]);
1095     if (_output.pmd)
1096         for (int i = 0; i < _lightSimOutputTexs.size(); i++)
1097             _lightSimOutputTexs[i].append(_pmdEnergyTex);
1098     if (_output.eyeSpacePositions)
1099         for (int i = 0; i < _geomSimOutputTexs.size(); i++)
1100             _geomSimOutputTexs[i].append(_eyeSpacePosTexs[i]);
1101     if (_output.customSpacePositions)
1102         for (int i = 0; i < _geomSimOutputTexs.size(); i++)
1103             _geomSimOutputTexs[i].append(_customSpacePosTexs[i]);
1104     if (_output.eyeSpaceNormals)
1105         for (int i = 0; i < _geomSimOutputTexs.size(); i++)
1106             _geomSimOutputTexs[i].append(_eyeSpaceNormalTexs[i]);
1107     if (_output.customSpaceNormals)
1108         for (int i = 0; i < _geomSimOutputTexs.size(); i++)
1109             _geomSimOutputTexs[i].append(_customSpaceNormalTexs[i]);
1110     if (_output.depthAndRange)
1111         for (int i = 0; i < _geomSimOutputTexs.size(); i++)
1112             _geomSimOutputTexs[i].append(_depthAndRangeTexs[i]);
1113     if (_output.indices)
1114         for (int i = 0; i < _geomSimOutputTexs.size(); i++)
1115             _geomSimOutputTexs[i].append(_indicesTexs[i]);
1116     if (_output.forwardFlow3D)
1117         for (int i = 0; i < _flowSimOutputTexs.size(); i++)
1118             _flowSimOutputTexs[i].append(_forwardFlow3DTexs[i]);
1119     if (_output.forwardFlow2D)
1120         for (int i = 0; i < _flowSimOutputTexs.size(); i++)
1121             _flowSimOutputTexs[i].append(_forwardFlow2DTexs[i]);
1122     if (_output.backwardFlow3D)
1123         for (int i = 0; i < _flowSimOutputTexs.size(); i++)
1124             _flowSimOutputTexs[i].append(_backwardFlow3DTexs[i]);
1125     if (_output.backwardFlow2D)
1126         for (int i = 0; i < _flowSimOutputTexs.size(); i++)
1127             _flowSimOutputTexs[i].append(_backwardFlow2DTexs[i]);
1128     if (_output.rgb)
1129         _oversampledLightSimOutputTexs.append(_rgbTexOversampled);
1130     if (_output.pmd)
1131         _oversampledLightSimOutputTexs.append(_pmdEnergyTexOversampled);
1132
1133     _haveLastFrameTimestamp = false;
1134     _recreateOutput = false;
1135     ASSERT_GLCHECK();
1136 }
1137
1138 float Simulator::lightIntensity(int lightSourceIndex) const
1139 {
1140     const Light& light = _scene.lights[lightSourceIndex];
1141     float intensity = light.power * 1e3f;
1142     if (light.type == SpotLight) {
1143         float apertureAngle = qDegreesToRadians(light.outerConeAngle);
1144         float solidAngle = 2.0f * static_cast<float>(M_PI) * (1.0f - std::cos(apertureAngle / 2.0f));
1145         intensity /= solidAngle;
1146     } else {
1147         intensity /= 4.0f * static_cast<float>(M_PI);
1148     }
1149     return intensity;
1150 }
1151
1152 void Simulator::simulateTimestamps(long long t)
1153 {
1154     for (int subFrame = 0; subFrame < subFrames(); subFrame++) {
1155         if (_pipeline.subFrameTemporalSampling) {
1156             _timestamps[subFrame] = t + subFrame * subFrameDuration();
1157         } else {
1158             _timestamps[subFrame] = t;
1159         }
1160         simulateSampleTimestamp(_timestamps[subFrame],
1161                 _cameraTransformations[subFrame],
1162                 _lightTransformations[subFrame],
1163                 _objectTransformations[subFrame]);
1164     }
1165 }
1166
1167 void Simulator::simulateSampleTimestamp(long long t,
1168         Transformation& cameraTransformation,
1169         QVector<Transformation>& lightTransformations,
1170         QVector<Transformation>& objectTransformations)
1171 {
1172     cameraTransformation = _cameraAnimation.interpolate(t);
1173     for (int i = 0; i < _scene.lights.size(); i++) {
1174         lightTransformations[i] = _scene.lightAnimations[i].interpolate(t);
1175     }
1176     for (int i = 0; i < _scene.objects.size(); i++) {
1177         objectTransformations[i] = _scene.objectAnimations[i].interpolate(t);
1178     }
1179 }
1180
1181 void Simulator::prepareFBO(QSize size,
1182         unsigned int depthBuf, bool reuseDepthBufData,
1183         const QList<unsigned int>& colorAttachments,
1184         int cubeMapSide, int arrayTextureLayers,
1185         bool enableBlending, bool clearBlendingColorBuffer)
1186 {
1187     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1188     ASSERT_GLCHECK();
1189
1190     if (_fbo == 0) {
1191         gl->glGenFramebuffers(1, &_fbo);
1192     }
1193     gl->glBindFramebuffer(GL_FRAMEBUFFER, _fbo);
1194     ASSERT_GLCHECK();
1195
1196     // Set new color attachments and select them with drawBuffers
1197     int texTarget;
1198     if (cubeMapSide >= 0)
1199         texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + cubeMapSide;
1200     else
1201         texTarget = GL_TEXTURE_2D;
1202     gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, texTarget, depthBuf, 0);
1203     QVector<GLenum> drawBuffers;
1204     if (arrayTextureLayers >= 1) {
1205         Q_ASSERT(colorAttachments.size() == 1); // currently we handle only one array texture as output
1206         drawBuffers.resize(arrayTextureLayers);
1207         for (int i = 0; i < 8; i++) {
1208             if (i < arrayTextureLayers) {
1209                 int layer = i;
1210                 if (cubeMapSide >= 0)
1211                     layer = 6 * i + cubeMapSide;
1212                 gl->glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, colorAttachments[0], 0, layer);
1213                 drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
1214             } else {
1215                 gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, 0, 0);
1216             }
1217         }
1218     } else if (arrayTextureLayers == 0) {
1219         drawBuffers.resize(colorAttachments.size());
1220         for (int i = 0; i < 8; i++) {
1221             if (i < colorAttachments.size()) {
1222                 gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, texTarget, colorAttachments[i], 0);
1223                 drawBuffers[i] = GL_COLOR_ATTACHMENT0 + i;
1224             } else {
1225                 gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, 0, 0);
1226             }
1227         }
1228     } else { // arrayTextureLayers < 0 means we want layered rendering into the array texture
1229         Q_ASSERT(colorAttachments.size() == 1); // currently we handle only one array texture for layered output
1230         drawBuffers.resize(1);
1231         drawBuffers[0] = GL_COLOR_ATTACHMENT0;
1232         gl->glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, colorAttachments[0], 0);
1233     }
1234     gl->glDrawBuffers(drawBuffers.size(), drawBuffers.constData());
1235     ASSERT_GLCHECK();
1236
1237     // Set remaining parameters
1238     gl->glViewport(0, 0, size.width(), size.height());
1239     gl->glEnable(GL_DEPTH_TEST);
1240     if (reuseDepthBufData) {
1241         gl->glDepthMask(GL_FALSE);
1242         gl->glDepthFunc(GL_LEQUAL);
1243     } else {
1244         gl->glClear(GL_DEPTH_BUFFER_BIT);
1245         gl->glDepthMask(GL_TRUE);
1246         gl->glDepthFunc(GL_LESS);
1247     }
1248     ASSERT_GLCHECK();
1249
1250     // Set up additive blending if requested
1251     if (enableBlending) {
1252         gl->glBlendEquation(GL_FUNC_ADD);
1253         gl->glBlendFunc(GL_ONE, GL_ONE);
1254         gl->glEnable(GL_BLEND);
1255         if (clearBlendingColorBuffer)
1256             gl->glClear(GL_COLOR_BUFFER_BIT);
1257     } else {
1258         gl->glDisable(GL_BLEND);
1259         gl->glClear(GL_COLOR_BUFFER_BIT);
1260     }
1261     ASSERT_GLCHECK();
1262
1263     // Create the fullscreen quad vao if it does not exist yet
1264     if (_fullScreenQuadVao == 0) {
1265         QVector3D quadPositions[] = {
1266             QVector3D(-1.0f, -1.0f, 0.0f), QVector3D(+1.0f, -1.0f, 0.0f),
1267             QVector3D(+1.0f, +1.0f, 0.0f), QVector3D(-1.0f, +1.0f, 0.0f)
1268         };
1269         QVector2D quadTexcoords[] = {
1270             QVector2D(0.0f, 0.0f), QVector2D(1.0f, 0.0f),
1271             QVector2D(1.0f, 1.0f), QVector2D(0.0f, 1.0f)
1272         };
1273         unsigned int quadIndices[] = {
1274             0, 1, 3, 1, 2, 3
1275         };
1276         gl->glGenVertexArrays(1, &_fullScreenQuadVao);
1277         gl->glBindVertexArray(_fullScreenQuadVao);
1278         GLuint positionBuffer;
1279         gl->glGenBuffers(1, &positionBuffer);
1280         gl->glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
1281         gl->glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(QVector3D), quadPositions, GL_STATIC_DRAW);
1282         gl->glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
1283         gl->glEnableVertexAttribArray(0);
1284         GLuint texcoordBuffer;
1285         gl->glGenBuffers(1, &texcoordBuffer);
1286         gl->glBindBuffer(GL_ARRAY_BUFFER, texcoordBuffer);
1287         gl->glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(QVector2D), quadTexcoords, GL_STATIC_DRAW);
1288         gl->glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
1289         gl->glEnableVertexAttribArray(1);
1290         GLuint indexBuffer;
1291         gl->glGenBuffers(1, &indexBuffer);
1292         gl->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer);
1293         gl->glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(unsigned int), quadIndices, GL_STATIC_DRAW);
1294         gl->glBindVertexArray(0);
1295     }
1296     ASSERT_GLCHECK();
1297 }
1298
1299 void Simulator::drawScene(QOpenGLShaderProgram& prg,
1300         const QMatrix4x4& projectionMatrix,
1301         const QMatrix4x4& viewMatrix,
1302         const QMatrix4x4& lastViewMatrix,
1303         const QMatrix4x4& nextViewMatrix,
1304         const QVector<Transformation>& objectTransformations,
1305         const QVector<Transformation>& lastObjectTransformations,
1306         const QVector<Transformation>& nextObjectTransformations)
1307 {
1308     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1309     ASSERT_GLCHECK();
1310
1311     for (int i = 0; i < _scene.objects.size(); i++) {
1312         prg.setUniformValue("object_index", i);
1313         // Set dynamic object uniforms (i.e. matrices)
1314         QMatrix4x4 invertedViewMatrix = viewMatrix.inverted();
1315         QMatrix4x4 modelMatrix = objectTransformations[i].toMatrix4x4();
1316         QMatrix4x4 modelViewMatrix = viewMatrix * modelMatrix;
1317         QMatrix3x3 normalMatrix = modelViewMatrix.normalMatrix();
1318         QMatrix4x4 modelViewProjectionMatrix = projectionMatrix * modelViewMatrix;
1319         prg.setUniformValue("projection_matrix", projectionMatrix);
1320         prg.setUniformValue("modelview_matrix", modelViewMatrix);
1321         prg.setUniformValue("modelview_projection_matrix", modelViewProjectionMatrix);
1322         prg.setUniformValue("normal_matrix", normalMatrix);
1323         QMatrix4x4 lastModelMatrix = lastObjectTransformations[i].toMatrix4x4();
1324         QMatrix4x4 lastModelViewMatrix = lastViewMatrix * lastModelMatrix;
1325         QMatrix4x4 lastModelViewProjectionMatrix = projectionMatrix * lastModelViewMatrix;
1326         prg.setUniformValue("last_modelview_matrix", lastModelViewMatrix);
1327         prg.setUniformValue("last_modelview_projection_matrix", lastModelViewProjectionMatrix);
1328         QMatrix4x4 nextModelMatrix = nextObjectTransformations[i].toMatrix4x4();
1329         QMatrix4x4 nextModelViewMatrix = nextViewMatrix * nextModelMatrix;
1330         QMatrix4x4 nextModelViewProjectionMatrix = projectionMatrix * nextModelViewMatrix;
1331         prg.setUniformValue("next_modelview_matrix", nextModelViewMatrix);
1332         prg.setUniformValue("next_modelview_projection_matrix", nextModelViewProjectionMatrix);
1333         QMatrix4x4 customMatrix = _customTransformation.toMatrix4x4() * invertedViewMatrix;
1334         QMatrix3x3 customNormalMatrix = customMatrix.normalMatrix();
1335         prg.setUniformValue("custom_matrix", customMatrix);
1336         prg.setUniformValue("custom_normal_matrix", customNormalMatrix);
1337         if (_pipeline.shadowMaps) {
1338             prg.setUniformValue("inverted_view_matrix", invertedViewMatrix.toGenericMatrix<3, 3>());
1339         }
1340         for (int j = 0; j < _scene.objects[i].shapes.size(); j++) {
1341             prg.setUniformValue("shape_index", j);
1342             // Set dynamic shape uniforms (i.e. material)
1343             const Shape& shape = _scene.objects[i].shapes[j];
1344             const Material& material = _scene.materials[shape.materialIndex];
1345             if (material.isTwoSided)
1346                 gl->glDisable(GL_CULL_FACE);
1347             else
1348                 gl->glEnable(GL_CULL_FACE);
1349             prg.setUniformValue("material_index", shape.materialIndex);
1350             prg.setUniformValue("material_type", static_cast<int>(material.type));
1351             prg.setUniformValue("material_ambient", _pipeline.ambientLight ? material.ambient : QVector3D(0.0f, 0.0f, 0.0f));
1352             prg.setUniformValue("material_diffuse", material.diffuse);
1353             prg.setUniformValue("material_specular", material.specular);
1354             prg.setUniformValue("material_emissive", material.emissive);
1355             prg.setUniformValue("material_shininess", material.shininess);
1356             prg.setUniformValue("material_opacity", material.opacity);
1357             prg.setUniformValue("material_bumpscaling", material.bumpScaling);
1358             prg.setUniformValue("material_have_ambient_tex", _pipeline.ambientLight && material.ambientTex > 0 ? 1 : 0);
1359             prg.setUniformValue("material_ambient_tex", 0);
1360             prg.setUniformValue("material_have_diffuse_tex", material.diffuseTex > 0 ? 1 : 0);
1361             prg.setUniformValue("material_diffuse_tex", 1);
1362             prg.setUniformValue("material_have_specular_tex", material.specularTex > 0 ? 1 : 0);
1363             prg.setUniformValue("material_specular_tex", 2);
1364             prg.setUniformValue("material_have_emissive_tex", material.emissiveTex > 0 ? 1 : 0);
1365             prg.setUniformValue("material_emissive_tex", 3);
1366             prg.setUniformValue("material_have_shininess_tex", material.shininessTex > 0 ? 1 : 0);
1367             prg.setUniformValue("material_shininess_tex", 4);
1368             prg.setUniformValue("material_have_lightness_tex", material.lightnessTex > 0 ? 1 : 0);
1369             prg.setUniformValue("material_lightness_tex", 5);
1370             prg.setUniformValue("material_have_opacity_tex", material.opacityTex > 0 ? 1 : 0);
1371             prg.setUniformValue("material_opacity_tex", 6);
1372             prg.setUniformValue("material_have_bump_tex", material.bumpTex > 0 ? 1 : 0);
1373             prg.setUniformValue("material_bump_tex", 7);
1374             prg.setUniformValue("material_have_normal_tex", material.normalTex > 0 ? 1 : 0);
1375             prg.setUniformValue("material_normal_tex", 8);
1376             // Bind textures
1377             unsigned int textures[9] = { material.ambientTex, material.diffuseTex, material.specularTex,
1378                 material.emissiveTex, material.shininessTex, material.lightnessTex, material.opacityTex,
1379                 material.bumpTex, material.normalTex };
1380             for (int i = 0; i < 9; i++) {
1381                 gl->glActiveTexture(GL_TEXTURE0 + i);
1382                 gl->glBindTexture(GL_TEXTURE_2D, textures[i]);
1383                 gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
1384                         _pipeline.mipmapping ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
1385                 gl->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT,
1386                         _pipeline.anisotropicFiltering ? 4.0f : 1.0f);
1387             }
1388             // Draw shape
1389             gl->glBindVertexArray(shape.vao);
1390             gl->glDrawElements(GL_TRIANGLES, shape.indices, GL_UNSIGNED_INT, 0);
1391         }
1392     }
1393     ASSERT_GLCHECK();
1394 }
1395
1396 static QVector2D undistortPoint(QVector2D point,
1397         float k1, float k2, float p1, float p2,
1398         QVector2D focalLengths, QVector2D centerPixel, QSize imageSize)
1399 {
1400     QVector2D viewPortCoord = QVector2D(
1401             point.x() * 0.5f + 0.5f,
1402             0.5f - point.y() * 0.5f);
1403     QVector2D pixelCoord = QVector2D(
1404             viewPortCoord.x() * imageSize.width(),
1405             viewPortCoord.y() * imageSize.height());
1406     float x = (pixelCoord.x() - centerPixel.x()) / focalLengths.x();
1407     float y = (pixelCoord.y() - centerPixel.y()) / focalLengths.y();
1408     float r2 = x * x + y * y;
1409     float r4 = r2 * r2;
1410     float invFactor = 1.0 / (4.0 * k1 * r2 + 6.0 * k2 * r4 + 8.0 * p1 * y + 8.0 * p2 * x + 1.0);
1411     float dx = x * (k1 * r2 + k2 * r4) + (2.0 * p1 * x * y + p2 * (r2 + 2.0 * x * x));
1412     float dy = y * (k1 * r2 + k2 * r4) + (p1 * (r2 + 2.0 * y * y) + 2.0 * p2 * x * y);
1413     x -= invFactor * dx;
1414     y -= invFactor * dy;
1415     x = x * focalLengths.x() + centerPixel.x();
1416     y = y * focalLengths.y() + centerPixel.y();
1417     viewPortCoord = QVector2D(x / (float)imageSize.width(), y / (float)imageSize.height());
1418     float ndcX = viewPortCoord.x() * 2.0f - 1.0f;
1419     float ndcY = 1.0f - viewPortCoord.y() * 2.0f;
1420     return QVector2D(ndcX, ndcY);
1421 }
1422
1423 void Simulator::simulate(
1424         QOpenGLShaderProgram& prg, int subFrame,
1425         long long t, long long lastT, long long nextT, unsigned int lastDepthBuf,
1426         const Transformation& cameraTransformation,
1427         const QVector<Transformation>& lightTransformations,
1428         const QVector<Transformation>& objectTransformations)
1429 {
1430     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1431     ASSERT_GLCHECK();
1432
1433     prg.bind();
1434
1435     // Basic matrices
1436     QMatrix4x4 cameraMatrix = _cameraTransformation.toMatrix4x4() * cameraTransformation.toMatrix4x4();
1437     QMatrix4x4 viewMatrix = cameraMatrix.inverted();
1438     QMatrix4x4 projectionMatrix = _projection.projectionMatrix(_pipeline.nearClippingPlane, _pipeline.farClippingPlane);
1439     QMatrix4x4 lastViewMatrix = viewMatrix;
1440     QVector<Transformation> lastObjectTransformations = objectTransformations;
1441     QMatrix4x4 nextViewMatrix = viewMatrix;
1442     QVector<Transformation> nextObjectTransformations = objectTransformations;
1443     if (lastT != t) {
1444         Transformation lastCameraTransformation;
1445         QVector<Transformation> lastLightTransformations = lightTransformations;;
1446         simulateSampleTimestamp(lastT, lastCameraTransformation, lastLightTransformations, lastObjectTransformations);
1447         QMatrix4x4 lastCameraMatrix = _cameraTransformation.toMatrix4x4() * lastCameraTransformation.toMatrix4x4();
1448         lastViewMatrix = lastCameraMatrix.inverted();
1449     }
1450     if (nextT != t) {
1451         Transformation nextCameraTransformation;
1452         QVector<Transformation> nextLightTransformations = lightTransformations;;
1453         simulateSampleTimestamp(nextT, nextCameraTransformation, nextLightTransformations, nextObjectTransformations);
1454         QMatrix4x4 nextCameraMatrix = _cameraTransformation.toMatrix4x4() * nextCameraTransformation.toMatrix4x4();
1455         nextViewMatrix = nextCameraMatrix.inverted();
1456     }
1457
1458     // Set static parameters that do not trigger recreateShaders
1459     prg.setUniformValue("viewport_width", _projection.imageSize().width());
1460     prg.setUniformValue("viewport_height", _projection.imageSize().height());
1461     prg.setUniformValue("far_plane", _pipeline.farClippingPlane);
1462     gl->glActiveTexture(GL_TEXTURE9);
1463     gl->glBindTexture(GL_TEXTURE_2D, lastDepthBuf);
1464     prg.setUniformValue("last_depth_buf", 9);
1465     if (_pipeline.thinLensVignetting) {
1466         prg.setUniformValue("thin_lens_vignetting", 1);
1467         prg.setUniformValue("frac_apdiam_foclen", _pipeline.thinLensApertureDiameter / _pipeline.thinLensFocalLength);
1468     } else {
1469         prg.setUniformValue("thin_lens_vignetting", 0);
1470     }
1471     prg.setUniformValue("temporal_samples", _pipeline.temporalSamples);
1472     prg.setUniformValue("exposure_time", static_cast<float>(_chipTiming.exposureTime * 1e6));
1473     prg.setUniformValue("pixel_area_factor", 1.0f / (_pipeline.spatialSamples.width() * _pipeline.spatialSamples.height()));
1474     if (_output.pmd) {
1475         prg.setUniformValue("pixel_area", static_cast<float>(_pmd.pixelSize));
1476         prg.setUniformValue("frac_modfreq_c", static_cast<float>(_pmd.modulationFrequency / speedOfLight));
1477         prg.setUniformValue("contrast", static_cast<float>(_pmd.pixelContrast));
1478         prg.setUniformValue("tau", subFrame * static_cast<float>(M_PI_2));
1479     }
1480     if (_pipeline.preprocLensDistortion) {
1481         float k1, k2, p1, p2;
1482         _projection.distortion(&k1, &k2, &p1, &p2);
1483         QVector2D focalLengths = _projection.focalLengths();
1484         QVector2D centerPixel = _projection.centerPixel();
1485         QSize imageSize = _projection.imageSize();
1486         // Undistort all cube edges and find max x and y components
1487         QVector2D undistortedCubeCorner[4];
1488         undistortedCubeCorner[0] = undistortPoint(QVector2D(1.0, 1.0),
1489                 k1, k2, p1, p2, focalLengths, centerPixel, imageSize);
1490         undistortedCubeCorner[1] = undistortPoint(QVector2D(1.0, -1.0),
1491                 k1, k2, p1, p2, focalLengths, centerPixel, imageSize);
1492         undistortedCubeCorner[2] = undistortPoint(QVector2D(-1.0, 1.0),
1493                 k1, k2, p1, p2, focalLengths, centerPixel, imageSize);
1494         undistortedCubeCorner[3] = undistortPoint(QVector2D(-1.0, -1.0),
1495                 k1, k2, p1, p2, focalLengths, centerPixel, imageSize);
1496         float maxX = std::abs(undistortedCubeCorner[0].x());
1497         float maxY = std::abs(undistortedCubeCorner[0].y());
1498         for (int i = 0; i < 3; i++) {
1499             if (std::abs(undistortedCubeCorner[i].x()) > maxX)
1500                 maxX = std::abs(undistortedCubeCorner[i].x());
1501             if (std::abs(undistortedCubeCorner[i].y()) > maxY)
1502                 maxY = std::abs(undistortedCubeCorner[i].y());
1503         }
1504         prg.setUniformValue("k1", k1);
1505         prg.setUniformValue("k2", k2);
1506         prg.setUniformValue("p1", p1);
1507         prg.setUniformValue("fx", focalLengths.x());
1508         prg.setUniformValue("fy", focalLengths.y());
1509         prg.setUniformValue("cx", centerPixel.x());
1510         prg.setUniformValue("cy", centerPixel.y());
1511         prg.setUniformValue("width", imageSize.width());
1512         prg.setUniformValue("height", imageSize.height());
1513         prg.setUniformValue("undistortedCubeCorner", QVector2D(maxX, maxY));
1514         prg.setUniformValue("lensDistMargin", _pipeline.preprocLensDistortionMargin);
1515     }
1516
1517     // Set dynamic light properties. This is costly; do it only when we actually use light sources
1518     if (&prg == &_lightPrg) {
1519         int samplersForPowerFactorMaps = (_pipeline.lightPowerFactorMaps ? _scene.lights.size() : 0);
1520         int samplersForShadowMaps = (_pipeline.shadowMaps ? _scene.lights.size() : 0);
1521         QVector<float> tmpVec3_0(3 * _scene.lights.size());
1522         QVector<float> tmpVec3_1(3 * _scene.lights.size());
1523         QVector<float> tmpVec3_2(3 * _scene.lights.size());
1524         QVector<int> tmpInt_0(_scene.lights.size());
1525         QVector<int> tmpInt_1(_scene.lights.size());
1526         QVector<int> tmpInt_2(_scene.lights.size());
1527         QVector<int> tmpInt_3(_scene.lights.size());
1528         QVector<int> tmpInt_4(_scene.lights.size());
1529         QVector<int> tmpInt_5(_scene.lights.size());
1530         QVector<int> tmpInt_6(_scene.lights.size());
1531         QVector<float> tmpFloat_0(_scene.lights.size());
1532         QVector<float> tmpFloat_1(_scene.lights.size());
1533         QVector<float> tmpFloat_2(_scene.lights.size());
1534         QVector<float> tmpFloat_3(_scene.lights.size());
1535         QVector<float> tmpFloat_4(_scene.lights.size());
1536         for (int i = 0; i < _scene.lights.size(); i++) {
1537             QVector3D lightPosition = lightTransformations[i].translation + _scene.lights[i].position;
1538             QVector3D lightDirection = lightTransformations[i].rotation * _scene.lights[i].direction;
1539             QVector3D lightUp = lightTransformations[i].rotation * _scene.lights[i].up;
1540             if (!_scene.lights[i].isRelativeToCamera) {
1541                 lightPosition = viewMatrix.map(lightPosition);
1542                 lightDirection = viewMatrix.mapVector(lightDirection);
1543                 lightUp = viewMatrix.mapVector(lightUp);
1544             }
1545             for (int j = 0; j < 3; j++)
1546                 tmpVec3_0[3 * i + j] = lightPosition[j];
1547             for (int j = 0; j < 3; j++)
1548                 tmpVec3_1[3 * i + j] = lightDirection[j];
1549             for (int j = 0; j < 3; j++)
1550                 tmpVec3_2[3 * i + j] = lightUp[j];
1551             if (_pipeline.shadowMaps) {
1552                 tmpInt_0[i] = (_scene.lights[i].shadowMap ? 1 : 0);
1553                 tmpInt_1[i] = 10 + samplersForPowerFactorMaps + i;
1554                 gl->glActiveTexture(GL_TEXTURE0 + tmpInt_1[i]);
1555                 gl->glBindTexture(GL_TEXTURE_CUBE_MAP, _shadowMapDepthBufs[subFrame][i]);
1556                 tmpFloat_0[i] = _scene.lights[i].shadowMapDepthBias;
1557             }
1558             if (_pipeline.reflectiveShadowMaps) {
1559                 tmpInt_2[i] = (_scene.lights[i].reflectiveShadowMap ? 1 : 0);
1560                 tmpInt_3[i] = 10 + samplersForPowerFactorMaps + samplersForShadowMaps + i;
1561                 tmpInt_4[i] = std::sqrt(3.0f) * _scene.lights[i].reflectiveShadowMapSize;
1562                 gl->glActiveTexture(GL_TEXTURE0 + tmpInt_3[i]);
1563                 gl->glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY, _reflectiveShadowMapTexs[subFrame][i]);
1564             }
1565             if (_pipeline.lightPowerFactorMaps) {
1566                 tmpInt_5[i] = (_scene.lights[i].powerFactorTex == 0 ? 0 : 1);
1567                 tmpInt_6[i] = 10 + i;
1568                 gl->glActiveTexture(GL_TEXTURE10 + i);
1569                 gl->glBindTexture(GL_TEXTURE_2D, _scene.lights[i].powerFactorTex);
1570                 tmpFloat_1[i] = qDegreesToRadians(_scene.lights[i].powerFactorMapAngleLeft);
1571                 tmpFloat_2[i] = qDegreesToRadians(_scene.lights[i].powerFactorMapAngleRight);
1572                 tmpFloat_3[i] = qDegreesToRadians(_scene.lights[i].powerFactorMapAngleBottom);
1573                 tmpFloat_4[i] = qDegreesToRadians(_scene.lights[i].powerFactorMapAngleTop);
1574             }
1575         }
1576         prg.setUniformValueArray("light_position", tmpVec3_0.constData(), _scene.lights.size(), 3);
1577         prg.setUniformValueArray("light_direction", tmpVec3_1.constData(), _scene.lights.size(), 3);
1578         prg.setUniformValueArray("light_up", tmpVec3_2.constData(), _scene.lights.size(), 3);
1579         if (_pipeline.shadowMaps) {
1580             prg.setUniformValueArray("light_have_shadowmap", tmpInt_0.constData(), _scene.lights.size());
1581             prg.setUniformValueArray("light_shadowmap", tmpInt_1.constData(), _scene.lights.size());
1582             prg.setUniformValueArray("light_depth_bias", tmpFloat_0.constData(), _scene.lights.size(), 1);
1583         }
1584         if (_pipeline.reflectiveShadowMaps) {
1585             prg.setUniformValueArray("light_have_reflective_shadowmap", tmpInt_2.constData(), _scene.lights.size());
1586             prg.setUniformValueArray("light_reflective_shadowmap", tmpInt_3.constData(), _scene.lights.size());
1587             prg.setUniformValueArray("light_reflective_shadowmap_hemisphere_samples_root", tmpInt_4.constData(), _scene.lights.size());
1588         }
1589         if (_pipeline.lightPowerFactorMaps) {
1590             prg.setUniformValueArray("light_have_power_factor_tex", tmpInt_5.constData(), _scene.lights.size());
1591             prg.setUniformValueArray("light_power_factor_tex", tmpInt_6.constData(), _scene.lights.size());
1592             prg.setUniformValueArray("light_power_factor_left", tmpFloat_1.constData(), _scene.lights.size(), 1);
1593             prg.setUniformValueArray("light_power_factor_right", tmpFloat_2.constData(), _scene.lights.size(), 1);
1594             prg.setUniformValueArray("light_power_factor_bottom", tmpFloat_3.constData(), _scene.lights.size(), 1);
1595             prg.setUniformValueArray("light_power_factor_top", tmpFloat_4.constData(), _scene.lights.size(), 1);
1596         }
1597     }
1598     ASSERT_GLCHECK();
1599
1600     drawScene(prg, projectionMatrix, viewMatrix, lastViewMatrix, nextViewMatrix,
1601             objectTransformations, lastObjectTransformations, nextObjectTransformations);
1602 }
1603
1604 void Simulator::simulateShadowMap(bool reflective,
1605         int subFrame, int lightIndex,
1606         const Transformation& cameraTransformation,
1607         const QVector<Transformation>& lightTransformations,
1608         const QVector<Transformation>& objectTransformations)
1609 {
1610     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1611     ASSERT_GLCHECK();
1612
1613     QOpenGLShaderProgram& prg = (reflective ? _reflectiveShadowMapPrg : _shadowMapPrg);
1614     prg.bind();
1615     const Light& light = _scene.lights[lightIndex];
1616     const Transformation& lightTransformation = lightTransformations[lightIndex];
1617
1618     // Light pose
1619     QVector3D lightPosition = lightTransformation.translation + light.position;
1620     QVector3D lightDirection = lightTransformation.rotation * light.direction;
1621     QVector3D lightUp = lightTransformation.rotation * light.up;
1622     if (light.isRelativeToCamera) {
1623         QMatrix4x4 cameraMatrix = _cameraTransformation.toMatrix4x4() * cameraTransformation.toMatrix4x4();
1624         lightPosition = cameraMatrix.map(lightPosition);
1625         lightDirection = cameraMatrix.mapVector(lightDirection);
1626         lightUp = cameraMatrix.mapVector(lightUp);
1627     }
1628
1629     // Set static parameters that do not trigger recreateShaders
1630     prg.setUniformValue("far_plane", _pipeline.farClippingPlane);
1631     prg.setUniformValue("last_depth_buf", 0);
1632     prg.setUniformValue("thin_lens_vignetting", 0);
1633
1634     // Set light properties
1635     int itmp;
1636     float ftmp;
1637     float vtmp[3];
1638     itmp = light.type;
1639     prg.setUniformValueArray("light_type", &itmp, 1);
1640     vtmp[0] = 0.0f;
1641     vtmp[1] = 0.0f;
1642     vtmp[2] = 0.0f;
1643     prg.setUniformValueArray("light_position", vtmp, 1, 3);
1644     vtmp[2] = -1.0f;
1645     prg.setUniformValueArray("light_direction", vtmp, 1, 3);
1646     vtmp[2] = 0.0f;
1647     vtmp[1] = 1.0f;
1648     prg.setUniformValueArray("light_up", vtmp, 1, 3);
1649     ftmp = qDegreesToRadians(light.innerConeAngle);
1650     prg.setUniformValueArray("light_inner_cone_angle", &ftmp, 1, 1);
1651     ftmp = qDegreesToRadians(light.outerConeAngle);
1652     prg.setUniformValueArray("light_outer_cone_angle", &ftmp, 1, 1);
1653     vtmp[0] = light.attenuationConstant;
1654     vtmp[1] = light.attenuationLinear;
1655     vtmp[2] = light.attenuationQuadratic;
1656     prg.setUniformValueArray("light_attenuation", vtmp, 1, 3);
1657     vtmp[0] = light.color[0];
1658     vtmp[1] = light.color[1];
1659     vtmp[2] = light.color[2];
1660     prg.setUniformValueArray("light_color", vtmp, 1, 3);
1661     ftmp = lightIntensity(lightIndex);
1662     prg.setUniformValueArray("light_intensity", &ftmp, 1, 1);
1663     itmp = (light.powerFactorTex == 0 ? 0 : 1);
1664     if (_pipeline.lightPowerFactorMaps) {
1665         prg.setUniformValueArray("light_have_power_factor_tex", &itmp, 1);
1666         itmp = 10;
1667         prg.setUniformValueArray("light_power_factor_tex", &itmp, 1);
1668         gl->glActiveTexture(GL_TEXTURE10);
1669         gl->glBindTexture(GL_TEXTURE_2D, light.powerFactorTex);
1670         ftmp = qDegreesToRadians(light.powerFactorMapAngleLeft);
1671         prg.setUniformValueArray("light_power_factor_left", &ftmp, 1, 1);
1672         ftmp = qDegreesToRadians(light.powerFactorMapAngleRight);
1673         prg.setUniformValueArray("light_power_factor_right", &ftmp, 1, 1);
1674         ftmp = qDegreesToRadians(light.powerFactorMapAngleBottom);
1675         prg.setUniformValueArray("light_power_factor_bottom", &ftmp, 1, 1);
1676         ftmp = qDegreesToRadians(light.powerFactorMapAngleTop);
1677         prg.setUniformValueArray("light_power_factor_top", &ftmp, 1, 1);
1678     }
1679     ASSERT_GLCHECK();
1680
1681     // Configure the custom space for positions and normals,
1682     // which in our case is the eye space of the camera.
1683     Transformation customTransformationBak;
1684     if (reflective) {
1685         QMatrix4x4 cameraMatrix = _cameraTransformation.toMatrix4x4() * cameraTransformation.toMatrix4x4();
1686         customTransformationBak = _customTransformation;
1687         _customTransformation = Transformation::fromMatrix4x4(cameraMatrix.inverted());
1688     }
1689
1690     QMatrix4x4 projectionMatrix;
1691     projectionMatrix.perspective(90.0f, 1.0f, _pipeline.nearClippingPlane, _pipeline.farClippingPlane);
1692
1693     const QVector3D cubeLightDir[6] = {
1694         QVector3D(+1.0f, 0.0f, 0.0f),
1695         QVector3D(-1.0f, 0.0f, 0.0f),
1696         QVector3D(0.0f, +1.0f, 0.0f),
1697         QVector3D(0.0f, -1.0f, 0.0f),
1698         QVector3D(0.0f, 0.0f, +1.0f),
1699         QVector3D(0.0f, 0.0f, -1.0f),
1700     };
1701     const QVector3D cubeLightUp[6] = {
1702         // Note that these up vectors are the opposite of what one would expect...
1703         QVector3D(0.0f, -1.0f, 0.0f),
1704         QVector3D(0.0f, -1.0f, 0.0f),
1705         QVector3D(0.0f, 0.0f, +1.0f),
1706         QVector3D(0.0f, 0.0f, -1.0f),
1707         QVector3D(0.0f, -1.0f, 0.0f),
1708         QVector3D(0.0f, -1.0f, 0.0f),
1709     };
1710     for (int cubeSide = 0; cubeSide < 6; cubeSide++) {
1711         QMatrix4x4 viewMatrix;
1712         viewMatrix.lookAt(lightPosition, lightPosition + cubeLightDir[cubeSide], cubeLightUp[cubeSide]);
1713         if (reflective) {
1714             prepareFBO(QSize(light.reflectiveShadowMapSize, light.reflectiveShadowMapSize),
1715                     _reflectiveShadowMapDepthBufs[subFrame][lightIndex], false,
1716                     { _reflectiveShadowMapTexs[subFrame][lightIndex] }, cubeSide, 5);
1717         } else {
1718             prepareFBO(QSize(light.shadowMapSize, light.shadowMapSize),
1719                     _shadowMapDepthBufs[subFrame][lightIndex], false,
1720                     {}, cubeSide);
1721         }
1722         drawScene(prg, projectionMatrix, viewMatrix, viewMatrix, viewMatrix,
1723                 objectTransformations, objectTransformations, objectTransformations);
1724     }
1725
1726     if (reflective) {
1727         _customTransformation = customTransformationBak;
1728     }
1729 }
1730
1731 void Simulator::simulateShadowMaps(int subFrame,
1732         const Transformation& cameraTransformation,
1733         const QVector<Transformation>& lightTransformations,
1734         const QVector<Transformation>& objectTransformations)
1735 {
1736     for (int l = 0; l < _scene.lights.size(); l++) {
1737         const Light& light = _scene.lights[l];
1738         if (_pipeline.shadowMaps && light.shadowMap) {
1739             simulateShadowMap(false, subFrame, l,
1740                     cameraTransformation, lightTransformations, objectTransformations);
1741         }
1742         if (_pipeline.reflectiveShadowMaps && light.reflectiveShadowMap) {
1743             simulateShadowMap(true, subFrame, l,
1744                     cameraTransformation, lightTransformations, objectTransformations);
1745         }
1746     }
1747 }
1748
1749 void Simulator::simulateDepth(int subFrame, long long t,
1750         const Transformation& cameraTransformation,
1751         const QVector<Transformation>& lightTransformations,
1752         const QVector<Transformation>& objectTransformations)
1753 {
1754     simulate(_depthPrg, subFrame, t, t, t, 0,
1755             cameraTransformation, lightTransformations, objectTransformations);
1756 }
1757
1758 void Simulator::simulateLight(int subFrame, long long t,
1759         const Transformation& cameraTransformation,
1760         const QVector<Transformation>& lightTransformations,
1761         const QVector<Transformation>& objectTransformations)
1762 {
1763     simulate(_lightPrg, subFrame, t, t, t, 0,
1764             cameraTransformation, lightTransformations, objectTransformations);
1765 }
1766
1767 void Simulator::simulateOversampledLight()
1768 {
1769     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1770     ASSERT_GLCHECK();
1771     _lightOversampledPrg.bind();
1772     gl->glActiveTexture(GL_TEXTURE0);
1773     gl->glBindTexture(GL_TEXTURE_2D, _oversampledLightSimOutputTexs[0]);
1774     if (_oversampledLightSimOutputTexs.size() > 1) {
1775         gl->glActiveTexture(GL_TEXTURE1);
1776         gl->glBindTexture(GL_TEXTURE_2D, _oversampledLightSimOutputTexs[1]);
1777     }
1778     gl->glBindVertexArray(_fullScreenQuadVao);
1779     gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
1780     ASSERT_GLCHECK();
1781 }
1782
1783 void Simulator::simulatePMDDigNums()
1784 {
1785     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1786     ASSERT_GLCHECK();
1787     _pmdDigNumPrg.bind();
1788     _pmdDigNumPrg.setUniformValue("wavelength", _pmd.wavelength);
1789     _pmdDigNumPrg.setUniformValue("quantum_efficiency", _pmd.quantumEfficiency);
1790     _pmdDigNumPrg.setUniformValue("max_electrons", _pmd.maxElectrons);
1791     gl->glActiveTexture(GL_TEXTURE0);
1792     gl->glBindTexture(GL_TEXTURE_2D, _pmdEnergyTex);
1793     if (_pipeline.shotNoise) {
1794         // generate standard normal distributed noise
1795         std::normal_distribution<float> distribution(0.0f, 1.0f);
1796         auto gaussianRandomNumber = [&distribution, this]() { return distribution(_randomGenerator); };
1797         auto bufferSize = 2 * _projection.imageSize().width() * _projection.imageSize().height();
1798         QVector<float> buffer(bufferSize);
1799         for (int i = 0; i < bufferSize; i++)
1800             buffer[i] = gaussianRandomNumber();
1801         gl->glActiveTexture(GL_TEXTURE1);
1802         glUploadTex(_pbo, _gaussianNoiseTex,
1803                 _projection.imageSize().width(), _projection.imageSize().height(),
1804                 GL_RG32F, GL_RG, GL_FLOAT,
1805                 buffer.constData(), buffer.size() * sizeof(float));
1806         gl->glBindTexture(GL_TEXTURE_2D, _gaussianNoiseTex);
1807     }
1808     gl->glBindVertexArray(_fullScreenQuadVao);
1809     gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
1810     ASSERT_GLCHECK();
1811 }
1812
1813 void Simulator::simulateGaussianWhiteNoise(int subFrame)
1814 {
1815     // create new gaussian white noise texture for each (sub)frame
1816     std::normal_distribution<float> distribution(
1817             _pipeline.gaussianWhiteNoiseMean,
1818             _pipeline.gaussianWhiteNoiseStddev);
1819     for (int i = 0; i < _gaussianWhiteNoiseBuf.size(); i++)
1820         _gaussianWhiteNoiseBuf[i] = distribution(_randomGenerator);
1821
1822     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1823     ASSERT_GLCHECK();
1824     _gaussianWhiteNoisePrg.bind();
1825     glUploadTex(_pbo, _gaussianWhiteNoiseTexs[subFrame],
1826             _projection.imageSize().width(), _projection.imageSize().height(),
1827             GL_RGB32F, GL_RGB, GL_FLOAT,
1828             _gaussianWhiteNoiseBuf.constData(), _gaussianWhiteNoiseBuf.size() * sizeof(float));
1829     gl->glActiveTexture(GL_TEXTURE0);
1830     gl->glBindTexture(GL_TEXTURE_2D, _gaussianWhiteNoiseTexs[subFrame]);
1831     gl->glBindVertexArray(_fullScreenQuadVao);
1832     gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
1833     ASSERT_GLCHECK();
1834     // now we have added the noise to the FBO via additive blending,
1835     // but we might have created negative energy values which does not make sense.
1836     // remove these via max-blending with 0
1837     _zeroPrg.bind();
1838     gl->glBlendEquation(GL_MAX);
1839     gl->glEnable(GL_BLEND);
1840     gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
1841     ASSERT_GLCHECK();
1842 }
1843
1844 void Simulator::simulateRGBResult()
1845 {
1846     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1847     ASSERT_GLCHECK();
1848     _rgbResultPrg.bind();
1849     for (int i = 0; i < subFrames(); i++) {
1850         gl->glActiveTexture(GL_TEXTURE0 + i);
1851         gl->glBindTexture(GL_TEXTURE_2D, _rgbTexs[i]);
1852     }
1853     gl->glBindVertexArray(_fullScreenQuadVao);
1854     gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
1855     ASSERT_GLCHECK();
1856 }
1857
1858 void Simulator::simulatePMDResult()
1859 {
1860     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1861     ASSERT_GLCHECK();
1862     _pmdResultPrg.bind();
1863     _pmdResultPrg.setUniformValue("frac_c_modfreq",
1864             static_cast<float>(speedOfLight / _pmd.modulationFrequency));
1865     for (int i = 0; i < subFrames(); i++) {
1866         gl->glActiveTexture(GL_TEXTURE0 + i);
1867         gl->glBindTexture(GL_TEXTURE_2D, _pmdDigNumTexs[i]);
1868     }
1869     gl->glBindVertexArray(_fullScreenQuadVao);
1870     gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
1871     ASSERT_GLCHECK();
1872 }
1873
1874 void Simulator::simulateGeometry(int subFrame)
1875 {
1876     simulate(_geomPrg, subFrame,
1877             _timestamps[subFrame], _timestamps[subFrame], _timestamps[subFrame], 0,
1878             _cameraTransformations[subFrame], _lightTransformations[subFrame],
1879             _objectTransformations[subFrame]);
1880 }
1881
1882 void Simulator::simulateFlow(int subFrame, long long lastT, long long nextT, unsigned int lastDepthBuf)
1883 {
1884     simulate(_flowPrg, subFrame,
1885             _timestamps[subFrame], lastT, nextT, lastDepthBuf,
1886             _cameraTransformations[subFrame], _lightTransformations[subFrame],
1887             _objectTransformations[subFrame]);
1888 }
1889
1890 void Simulator::simulatePostprocLensDistortion(const QList<unsigned int>& textures)
1891 {
1892     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1893     ASSERT_GLCHECK();
1894     _postprocLensDistortionPrg.bind();
1895     float k1, k2, p1, p2;
1896     _projection.distortion(&k1, &k2, &p1, &p2);
1897     QVector2D centerPixel = _projection.centerPixel();
1898     QVector2D focalLengths = _projection.focalLengths();
1899     _postprocLensDistortionPrg.setUniformValue("k1", k1);
1900     _postprocLensDistortionPrg.setUniformValue("k2", k2);
1901     _postprocLensDistortionPrg.setUniformValue("p1", p1);
1902     _postprocLensDistortionPrg.setUniformValue("p2", p2);
1903     _postprocLensDistortionPrg.setUniformValue("fx", focalLengths.x());
1904     _postprocLensDistortionPrg.setUniformValue("fy", focalLengths.y());
1905     _postprocLensDistortionPrg.setUniformValue("cx", centerPixel.x());
1906     _postprocLensDistortionPrg.setUniformValue("cy", centerPixel.y());
1907     gl->glBindVertexArray(_fullScreenQuadVao);
1908     gl->glActiveTexture(GL_TEXTURE0);
1909     for (int i = 0; i < textures.size(); i++) {
1910         prepareFBO(_projection.imageSize(), 0, false, { _postProcessingTex });
1911         gl->glBindTexture(GL_TEXTURE_2D, textures[i]);
1912         float borderColor[] = { 0.0f, 0.0f, 0.0f, 0.0f };
1913         gl->glTexParameterfv(GL_TEXTURE_2D,  GL_TEXTURE_BORDER_COLOR, borderColor);
1914         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
1915         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
1916         gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
1917         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1918         gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1919         gl->glCopyImageSubData(_postProcessingTex, GL_TEXTURE_2D, 0, 0, 0, 0,
1920                 textures[i], GL_TEXTURE_2D, 0, 0, 0, 0,
1921                 _projection.imageSize().width(), _projection.imageSize().height(), 1);
1922     }
1923     ASSERT_GLCHECK();
1924 }
1925
1926 void Simulator::convertToSRGB(int texIndex)
1927 {
1928     auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
1929     ASSERT_GLCHECK();
1930     _convertToSRGBPrg.bind();
1931     gl->glActiveTexture(GL_TEXTURE0);
1932     gl->glBindTexture(GL_TEXTURE_2D, _rgbTexs[texIndex]);
1933     gl->glBindVertexArray(_fullScreenQuadVao);
1934     gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
1935     ASSERT_GLCHECK();
1936 }
1937
1938 void Simulator::simulate(long long frameTimestamp)
1939 {
1940     recreateShadersIfNecessary();
1941     recreateOutputIfNecessary();
1942
1943     // Determine sub frame timestamps as well as camera, light, and object
1944     // transformations at these timestamps. This handles _pipeline.subFrameTemporalSampling.
1945     simulateTimestamps(frameTimestamp);
1946
1947     // Simulate sub frames
1948     for (int subFrame = 0; subFrame < subFrames(); subFrame++) {
1949         long long tempSampleDuration = subFrameDuration() / _pipeline.temporalSamples;
1950         if (_output.rgb || _output.pmd) {
1951             long long tempSampleTimestamp = _timestamps[subFrame];
1952             Transformation cameraTransformation = _cameraTransformations[subFrame];
1953             QVector<Transformation> lightTransformations = _lightTransformations[subFrame];
1954             QVector<Transformation> objectTransformations = _objectTransformations[subFrame];
1955             for (int tempSample = 0; tempSample < _pipeline.temporalSamples; tempSample++) {
1956                 if (tempSample > 0) {
1957                     tempSampleTimestamp = _timestamps[subFrame] + tempSample * tempSampleDuration;
1958                     simulateSampleTimestamp(tempSampleTimestamp, cameraTransformation, lightTransformations, objectTransformations);
1959                 }
1960                 for (int l = 0; l < _scene.lights.size(); l++)
1961                     _scene.lights[l].updatePowerFactorTex(_pbo, tempSampleTimestamp);
1962                 if (_pipeline.shadowMaps || _pipeline.reflectiveShadowMaps)
1963                     simulateShadowMaps(subFrame, cameraTransformation, lightTransformations, objectTransformations);
1964                 // The following is the core rendering step for light simulation
1965                 if (spatialOversampling() || temporalOversampling()) {
1966                     prepareFBO(spatialOversamplingSize(), _depthBufferOversampled, false, _oversampledLightSimOutputTexs);
1967                     simulateLight(subFrame, tempSampleTimestamp, cameraTransformation, lightTransformations, objectTransformations);
1968                     prepareFBO(_projection.imageSize(), 0, false, _lightSimOutputTexs[subFrame], -1, 0, temporalOversampling(), tempSample == 0);
1969                     simulateOversampledLight();
1970                 } else {
1971                     // short cut for common case; the above would also be correct but requires an additional render pass
1972                     prepareFBO(_projection.imageSize(), _depthBuffers[subFrame], false, _lightSimOutputTexs[subFrame]);
1973                     simulateLight(subFrame, tempSampleTimestamp, cameraTransformation, lightTransformations, objectTransformations);
1974                 }
1975             }
1976             if (_output.pmd) {
1977                 prepareFBO(_projection.imageSize(), 0, false, { _pmdDigNumTexs[subFrame] });
1978                 simulatePMDDigNums();
1979             }
1980             if (_pipeline.postprocLensDistortion) {
1981                 simulatePostprocLensDistortion(_lightSimOutputTexs[subFrame]);
1982             }
1983             if (_output.rgb && _pipeline.gaussianWhiteNoise) {
1984                 prepareFBO(_projection.imageSize(), 0, false, { _rgbTexs[subFrame] }, -1, 0, true, false);
1985                 simulateGaussianWhiteNoise(subFrame);
1986             }
1987             if (_output.srgb) {
1988                 prepareFBO(_projection.imageSize(), 0, false, { _srgbTexs[subFrame] });
1989                 convertToSRGB(subFrame);
1990             }
1991         }
1992         if (_output.eyeSpacePositions || _output.customSpacePositions
1993                 || _output.eyeSpaceNormals || _output.customSpaceNormals
1994                 || _output.depthAndRange || _output.indices) {
1995             prepareFBO(_projection.imageSize(), _depthBuffers[subFrame], false, _geomSimOutputTexs[subFrame]);
1996             simulateGeometry(subFrame);
1997             if (_pipeline.postprocLensDistortion) {
1998                 simulatePostprocLensDistortion(_geomSimOutputTexs[subFrame]);
1999             }
2000         }
2001         if (_output.forwardFlow2D || _output.forwardFlow3D || _output.backwardFlow3D || _output.backwardFlow2D) {
2002             long long lastSubFrameTimestamp;
2003             if (subFrame == 0 && !_haveLastFrameTimestamp) {
2004                 lastSubFrameTimestamp = frameTimestamp;
2005             } else if (subFrame == 0) {
2006                 lastSubFrameTimestamp = _lastFrameTimestamp;
2007                 if (_pipeline.subFrameTemporalSampling)
2008                     lastSubFrameTimestamp += (subFrames() - 1) * subFrameDuration();
2009             } else {
2010                 lastSubFrameTimestamp = _timestamps[subFrame - 1];
2011             }
2012             long long nextSubFrameTimestamp;
2013             if (subFrame == subFrames() - 1) {
2014                 nextSubFrameTimestamp = frameTimestamp + frameDuration();
2015             } else {
2016                 nextSubFrameTimestamp = _timestamps[subFrame + 1];
2017             }
2018             static bool depthBufferPingPong = true; // static: initialized only once and value kept between calls!
2019             unsigned long lastSubFrameDepthBuffer;
2020             unsigned long depthBuffer = _depthBuffers[subFrame];
2021             if (subFrame == 0 && !_haveLastFrameTimestamp) {
2022                 lastSubFrameDepthBuffer = 0;
2023             } else {
2024                 if (subFrame == 0) {
2025                     if (subFrames() == 1) {
2026                         if (depthBufferPingPong) {
2027                             depthBuffer = _depthBuffers[1];
2028                             lastSubFrameDepthBuffer = _depthBuffers[0];
2029                         } else {
2030                             depthBuffer = _depthBuffers[0];
2031                             lastSubFrameDepthBuffer = _depthBuffers[1];
2032                         }
2033                         depthBufferPingPong = !depthBufferPingPong;
2034                     } else {
2035                         lastSubFrameDepthBuffer = _depthBuffers[subFrames() - 1];
2036                     }
2037                 } else {
2038                     lastSubFrameDepthBuffer = _depthBuffers[subFrame - 1];
2039                 }
2040             }
2041             prepareFBO(_projection.imageSize(), depthBuffer, false, _flowSimOutputTexs[subFrame]);
2042             simulateFlow(subFrame, lastSubFrameTimestamp, nextSubFrameTimestamp, lastSubFrameDepthBuffer);
2043         }
2044     }
2045
2046     // Simulate final frames.
2047     // Note that this is not necessary for geometry simulation since we have that info
2048     // already in the first subframe.
2049     // It is however necessary for flow simulation because full-frame timestamps differ
2050     // from sub-frame timestamps.
2051     if (subFrames() > 1) {
2052         if (_output.rgb) {
2053             prepareFBO(_projection.imageSize(), 0, false, { _rgbTexs[subFrames()] });
2054             simulateRGBResult();
2055             if (_output.srgb) {
2056                 prepareFBO(_projection.imageSize(), 0, false, { _srgbTexs[subFrames()] });
2057                 convertToSRGB(subFrames());
2058             }
2059         }
2060         if (_output.pmd) {
2061             prepareFBO(_projection.imageSize(), 0, false, { _pmdDigNumTexs[subFrames()] });
2062             simulatePMDResult();
2063         }
2064         if (_output.forwardFlow3D || _output.forwardFlow2D || _output.backwardFlow3D || _output.backwardFlow2D) {
2065             long long lastFrameTimestamp = frameTimestamp - frameDuration();
2066             long long nextFrameTimestamp = frameTimestamp + frameDuration();
2067             unsigned long lastFrameDepthBuffer = 0;
2068             if (_haveLastFrameTimestamp) {
2069                 lastFrameDepthBuffer = _depthBuffers[0]; // first subframe timestamp == frame timestamp
2070             }
2071             prepareFBO(_projection.imageSize(), _depthBuffers[subFrames()], false, _flowSimOutputTexs[subFrames()]);
2072             simulateFlow(0, lastFrameTimestamp, nextFrameTimestamp, lastFrameDepthBuffer);
2073         }
2074     }
2075
2076     _lastFrameTimestamp = frameTimestamp;
2077     _haveLastFrameTimestamp = true;
2078 }
2079
2080 long long Simulator::getTimestamp(int i) const
2081 {
2082     if (!_haveLastFrameTimestamp || i < -1 || i >= subFrames())
2083         return 0;
2084     else
2085         return _timestamps[i < 0 ? 0 : i];
2086 }
2087
2088 bool Simulator::haveValidOutput(int i) const
2089 {
2090     return (!_recreateOutput && _haveLastFrameTimestamp && i >= -1 && i < subFrames());
2091 }
2092
2093 bool Simulator::haveShadowMap(int lightIndex) const
2094 {
2095     return (_pipeline.shadowMaps && lightIndex >= 0 && lightIndex < _scene.lights.size() && _scene.lights[lightIndex].shadowMap);
2096 }
2097
2098 bool Simulator::haveReflectiveShadowMap(int lightIndex) const
2099 {
2100     return (_pipeline.reflectiveShadowMaps && lightIndex >= 0 && lightIndex < _scene.lights.size() && _scene.lights[lightIndex].reflectiveShadowMap);
2101 }
2102
2103 unsigned int Simulator::getShadowMapCubeTex(int lightIndex, int i) const
2104 {
2105     return ((haveValidOutput(i) && haveShadowMap(lightIndex))
2106             ? (i == -1 ? _shadowMapDepthBufs[0][lightIndex] : _shadowMapDepthBufs[i][lightIndex]) : 0);
2107 }
2108
2109 unsigned int Simulator::getReflectiveShadowMapCubeArrayTex(int lightIndex, int i) const
2110 {
2111     return ((haveValidOutput(i) && haveReflectiveShadowMap(lightIndex))
2112             ? (i == -1 ? _reflectiveShadowMapTexs[0][lightIndex] : _reflectiveShadowMapTexs[i][lightIndex]) : 0);
2113 }
2114
2115 unsigned int Simulator::getGaussianWhiteNoiseTex(int i) const
2116 {
2117     return ((_output.rgb && _pipeline.gaussianWhiteNoise && haveValidOutput(i)) ? (i == -1 ? _gaussianWhiteNoiseTexs[0] : _gaussianWhiteNoiseTexs[i]) : 0);
2118 }
2119
2120 unsigned int Simulator::getDepthTex(int i) const
2121 {
2122     return ((((!spatialOversampling() && !temporalOversampling())
2123                     || _output.eyeSpacePositions || _output.customSpacePositions
2124                     || _output.eyeSpaceNormals || _output.customSpaceNormals
2125                     || _output.depthAndRange || _output.indices
2126                     || _output.forwardFlow3D || _output.forwardFlow2D
2127                     || _output.backwardFlow3D || _output.backwardFlow2D)
2128                 && haveValidOutput(i)) ? (i == -1 ? _depthBuffers[0] : _depthBuffers[i]) : 0);
2129 }
2130
2131 unsigned int Simulator::getRGBTex(int i) const
2132 {
2133     return ((_output.rgb && haveValidOutput(i)) ? (i == -1 ? _rgbTexs.last() : _rgbTexs[i]) : 0);
2134 }
2135
2136 unsigned int Simulator::getSRGBTex(int i) const
2137 {
2138     return ((_output.rgb && _output.srgb && haveValidOutput(i)) ? (i == -1 ? _srgbTexs.last() : _srgbTexs[i]) : 0);
2139 }
2140
2141 unsigned int Simulator::getPMDTex(int i) const
2142 {
2143     return ((_output.pmd && haveValidOutput(i)) ? (i == -1 ? _pmdDigNumTexs.last() : _pmdDigNumTexs[i]) : 0);
2144 }
2145
2146 unsigned int Simulator::getEyeSpacePositionsTex(int i) const
2147 {
2148     return ((_output.eyeSpacePositions && haveValidOutput(i)) ? (i == -1 ? _eyeSpacePosTexs[0] : _eyeSpacePosTexs[i]) : 0);
2149 }
2150
2151 unsigned int Simulator::getCustomSpacePositionsTex(int i) const
2152 {
2153     return ((_output.customSpacePositions && haveValidOutput(i)) ? (i == -1 ? _customSpacePosTexs[0] : _customSpacePosTexs[i]) : 0);
2154 }
2155
2156 unsigned int Simulator::getEyeSpaceNormalsTex(int i) const
2157 {
2158     return ((_output.eyeSpaceNormals && haveValidOutput(i)) ? (i == -1 ? _eyeSpaceNormalTexs[0] : _eyeSpaceNormalTexs[i]) : 0);
2159 }
2160
2161 unsigned int Simulator::getCustomSpaceNormalsTex(int i) const
2162 {
2163     return ((_output.customSpaceNormals && haveValidOutput(i)) ? (i == -1 ? _customSpaceNormalTexs[0] : _customSpaceNormalTexs[i]) : 0);
2164 }
2165
2166 unsigned int Simulator::getDepthAndRangeTex(int i) const
2167 {
2168     return ((_output.depthAndRange && haveValidOutput(i)) ? (i == -1 ? _depthAndRangeTexs[0] : _depthAndRangeTexs[i]) : 0);
2169 }
2170
2171 unsigned int Simulator::getIndicesTex(int i) const
2172 {
2173     return ((_output.indices && haveValidOutput(i)) ? (i == -1 ? _indicesTexs[0] : _indicesTexs[i]) : 0);
2174 }
2175
2176 unsigned int Simulator::getForwardFlow3DTex(int i) const
2177 {
2178     return ((_output.forwardFlow3D && haveValidOutput(i)) ? (i == -1 ? _forwardFlow3DTexs.last() : _forwardFlow3DTexs[i]) : 0);
2179 }
2180
2181 unsigned int Simulator::getForwardFlow2DTex(int i) const
2182 {
2183     return ((_output.forwardFlow2D && haveValidOutput(i)) ? (i == -1 ? _forwardFlow2DTexs.last() : _forwardFlow2DTexs[i]) : 0);
2184 }
2185
2186 unsigned int Simulator::getBackwardFlow3DTex(int i) const
2187 {
2188     return ((_output.backwardFlow3D && haveValidOutput(i)) ? (i == -1 ? _backwardFlow3DTexs.last() : _backwardFlow3DTexs[i]) : 0);
2189 }
2190
2191 unsigned int Simulator::getBackwardFlow2DTex(int i) const
2192 {
2193     return ((_output.backwardFlow2D && haveValidOutput(i)) ? (i == -1 ? _backwardFlow2DTexs.last() : _backwardFlow2DTexs[i]) : 0);
2194 }
2195
2196 static const Transformation NullTransformation;
2197
2198 const Transformation& Simulator::getCameraTransformation(int i) const
2199 {
2200     return (haveValidOutput(i) ? (i == -1 ? _cameraTransformations[0] : _cameraTransformations[i]) : NullTransformation);
2201 }
2202
2203 const Transformation& Simulator::getLightTransformation(int lightIndex, int i) const
2204 {
2205     if (lightIndex >= 0 && lightIndex < _scene.lights.size() && haveValidOutput(i))
2206         return (i == -1 ? _lightTransformations[lightIndex][0] : _lightTransformations[lightIndex][i]);
2207     else
2208         return NullTransformation;
2209 }
2210
2211 const Transformation& Simulator::getObjectTransformation(int objectIndex, int i) const
2212 {
2213     if (objectIndex >= 0 && objectIndex < _scene.objects.size() && haveValidOutput(i))
2214         return (i == -1 ? _objectTransformations[objectIndex][0] : _objectTransformations[objectIndex][i]);
2215     else
2216         return NullTransformation;
2217 }
2218
2219 }