Move random number generation to the GPU
authorMartin Lambers <marlam@marlam.de>
Tue, 18 Dec 2018 11:03:36 +0000 (12:03 +0100)
committerMartin Lambers <marlam@marlam.de>
Tue, 18 Dec 2018 11:03:36 +0000 (12:03 +0100)
The random numbers are of lower quality than the CPU-produced ones, but should
be sufficient for noise simulation. The code is simplified and both CPU
processing time and bus transfers are reduced significantly.

However, overall simulation time does not necessarily decrease in all cases,
since CPU processing and bus transfers may have run asynchronously before,
depending on the application.

libcamsim/camsim.qrc
libcamsim/simulation-everything-fs.glsl
libcamsim/simulation-pmd-dignums-fs.glsl
libcamsim/simulation-whitenoise-fs.glsl [deleted file]
libcamsim/simulation-whitenoise-vs.glsl [deleted file]
libcamsim/simulation-zero-fs.glsl [deleted file]
libcamsim/simulation-zero-vs.glsl [deleted file]
libcamsim/simulator.cpp
libcamsim/simulator.hpp

index fe4f0fb..b1199d4 100644 (file)
@@ -7,10 +7,6 @@
     <file>simulation-oversampling-fs.glsl</file>
     <file>simulation-pmd-dignums-vs.glsl</file>
     <file>simulation-pmd-dignums-fs.glsl</file>
-    <file>simulation-whitenoise-vs.glsl</file>
-    <file>simulation-whitenoise-fs.glsl</file>
-    <file>simulation-zero-vs.glsl</file>
-    <file>simulation-zero-fs.glsl</file>
     <file>simulation-rgb-result-vs.glsl</file>
     <file>simulation-rgb-result-fs.glsl</file>
     <file>simulation-pmd-result-vs.glsl</file>
index 1974a46..273cf11 100644 (file)
@@ -137,6 +137,24 @@ smooth in float discardTriangle;
 
 #if $OUTPUT_RGB$
 layout(location = $OUTPUT_RGB_LOCATION$) out vec3 output_rgb;
+# if $GAUSSIAN_WHITE_NOISE$
+uniform vec4 random_noise_0; /* uniformly distributed in [0,1000]; to be set for each frame */
+uniform vec4 random_noise_1; /* uniformly distributed in [0,1000]; to be set for each frame */
+uniform float gwn_stddev;
+uniform float gwn_mean;
+float rnd_uniform(vec2 n)
+{
+    float r = fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); /* in [0,1) */
+    return 1.0 - r; /* in (0,1]; it is important for Box-Mueller transform that we do not return 0 */
+}
+vec2 rnd_gauss(vec2 texcoord, vec4 random_offset)
+{
+    const float two_pi = 6.28318530718;
+    // Box-Mueller transform
+    vec2 u = vec2(rnd_uniform(texcoord + random_offset.xy), rnd_uniform(texcoord + random_offset.zw));
+    return sqrt(-2.0 * log(u.x)) * vec2(cos(two_pi * u.y), sin(two_pi * u.y));
+}
+# endif
 #endif
 #if $OUTPUT_PMD$
 layout(location = $OUTPUT_PMD_LOCATION$) out vec2 output_pmd;
@@ -540,6 +558,11 @@ void main(void)
 #endif
 #if $OUTPUT_RGB$
     output_rgb = (lightness * (emissive_color + ambient_color) + total_color) / float(temporal_samples);
+# if $GAUSSIAN_WHITE_NOISE$
+    vec2 gwn0 = gwn_stddev * rnd_gauss(vtexcoord, random_noise_0) + gwn_mean;
+    vec2 gwn1 = gwn_stddev * rnd_gauss(vtexcoord, random_noise_1) + gwn_mean;
+    output_rgb = max(vec3(0.0), output_rgb + vec3(gwn0.xy, gwn1.x));
+# endif
 #endif
 #if $OUTPUT_PMD$
     output_pmd = vec2(total_energy_a, total_energy_b);
index dd4f8b2..589dfbe 100644 (file)
@@ -30,14 +30,32 @@ uniform sampler2D pmd_energies;
 uniform float wavelength;               // in nm = 1e-9m
 uniform float quantum_efficiency;
 uniform int max_electrons;              // maximum number of electrons per pixel
-#if $SHOT_NOISE$
-uniform sampler2D gaussian_noise_tex;
-#endif
 
 smooth in vec2 vtexcoord;
 
 layout(location = 0) out vec4 pmd_dignums;
 
+
+#if $SHOT_NOISE$
+
+uniform vec4 random_noise; /* uniformly distributed in [0,1000]; to be set for each frame */
+
+float rnd_uniform(vec2 n)
+{
+    float r = fract(sin(dot(n, vec2(12.9898, 4.1414))) * 43758.5453); /* in [0,1) */
+    return 1.0 - r; /* in (0,1]; it is important for Box-Mueller transform that we do not return 0 */
+}
+
+vec2 rnd_gauss(vec2 texcoord, vec4 random_offset)
+{
+    const float two_pi = 6.28318530718;
+    // Box-Mueller transform
+    vec2 u = vec2(rnd_uniform(texcoord + random_offset.xy), rnd_uniform(texcoord + random_offset.zw));
+    return sqrt(-2.0 * log(u.x)) * vec2(cos(two_pi * u.y), sin(two_pi * u.y));
+}
+
+#endif
+
 void main(void)
 {
     vec2 energies = texture(pmd_energies, vtexcoord).rg;
@@ -45,7 +63,7 @@ void main(void)
     vec2 electrons = ((quantum_efficiency * wavelength * energies) / hc) / 10000.0;
 #if $SHOT_NOISE$
     // Approximation of poisson noise
-    electrons += sqrt(electrons) * texture(gaussian_noise_tex, vtexcoord).rg;
+    electrons += sqrt(electrons) * rnd_gauss(vtexcoord, random_noise);
 #endif
     // transform electrons to range [0, 1]
     vec2 dignums = clamp(electrons, vec2(0.0), vec2(max_electrons)) / vec2(max_electrons);
diff --git a/libcamsim/simulation-whitenoise-fs.glsl b/libcamsim/simulation-whitenoise-fs.glsl
deleted file mode 100644 (file)
index e4d4e02..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2017, 2018
- * Computer Graphics Group, University of Siegen
- * Written by Martin Lambers <martin.lambers@uni-siegen.de>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#version 450
-
-uniform sampler2D noise_tex;
-
-smooth in vec2 vtexcoord;
-
-layout(location = 0) out vec3 output_noise;
-
-void main(void)
-{
-    output_noise = texture(noise_tex, vtexcoord).rgb;
-}
diff --git a/libcamsim/simulation-whitenoise-vs.glsl b/libcamsim/simulation-whitenoise-vs.glsl
deleted file mode 100644 (file)
index 7d1f2d9..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016, 2017, 2018
- * Computer Graphics Group, University of Siegen
- * Written by Martin Lambers <martin.lambers@uni-siegen.de>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#version 450
-
-layout(location = 0) in vec4 position;
-layout(location = 1) in vec2 texcoord;
-
-smooth out vec2 vtexcoord;
-
-void main(void)
-{
-    vtexcoord = texcoord;
-    gl_Position = position;
-}
diff --git a/libcamsim/simulation-zero-fs.glsl b/libcamsim/simulation-zero-fs.glsl
deleted file mode 100644 (file)
index 7ca80ee..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2017, 2018
- * Computer Graphics Group, University of Siegen
- * Written by Martin Lambers <martin.lambers@uni-siegen.de>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#version 450
-
-smooth in vec2 vtexcoord;
-
-layout(location = 0) out vec3 output0;
-#if $TWO_OUTPUTS$
-layout(location = 1) out vec3 output1;
-#endif
-
-void main(void)
-{
-    output0 = vec3(0.0);
-#if $TWO_OUTPUTS$
-    output1 = vec3(0.0);
-#endif
-}
diff --git a/libcamsim/simulation-zero-vs.glsl b/libcamsim/simulation-zero-vs.glsl
deleted file mode 100644 (file)
index 7d1f2d9..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2016, 2017, 2018
- * Computer Graphics Group, University of Siegen
- * Written by Martin Lambers <martin.lambers@uni-siegen.de>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#version 450
-
-layout(location = 0) in vec4 position;
-layout(location = 1) in vec2 texcoord;
-
-smooth out vec2 vtexcoord;
-
-void main(void)
-{
-    vtexcoord = texcoord;
-    gl_Position = position;
-}
index 23fca74..9b0077d 100644 (file)
@@ -262,7 +262,6 @@ Simulator::Simulator() :
     _pmdEnergyTexOversampled(0),
     _pmdEnergyTex(0),
     _pmdCoordinatesTex(0),
-    _gaussianNoiseTex(0),
     _postProcessingTex(0),
     _fbo(0),
     _fullScreenQuadVao(0)
@@ -452,8 +451,6 @@ void Simulator::recreateShadersIfNecessary()
     _lightPrg.removeAllShaders();
     _lightOversampledPrg.removeAllShaders();
     _pmdDigNumPrg.removeAllShaders();
-    _gaussianWhiteNoisePrg.removeAllShaders();
-    _zeroPrg.removeAllShaders();
     _rgbResultPrg.removeAllShaders();
     _pmdResultPrg.removeAllShaders();
     _pmdCoordinatesPrg.removeAllShaders();
@@ -579,6 +576,7 @@ void Simulator::recreateShadersIfNecessary()
         lightFs.replace("$LIGHT_SOURCES$", QString::number(_scene.lights.size()));
         lightFs.replace("$OUTPUT_SHADOW_MAP_DEPTH$", "0");
         lightFs.replace("$OUTPUT_RGB$", _output.rgb ? "1" : "0");
+        lightFs.replace("$GAUSSIAN_WHITE_NOISE$", _pipeline.gaussianWhiteNoise ? "1" : "0");
         lightFs.replace("$OUTPUT_PMD$", _output.pmd ? "1" : "0");
         lightFs.replace("$OUTPUT_EYE_SPACE_POSITIONS$", "0");
         lightFs.replace("$OUTPUT_CUSTOM_SPACE_POSITIONS$", "0");
@@ -634,7 +632,7 @@ void Simulator::recreateShadersIfNecessary()
                 tmpFloat[i] = lightIntensity(i);
             _lightPrg.setUniformValueArray("light_intensity", tmpFloat.constData(), _scene.lights.size(), 1);
         }
-        // additional simple programs for oversampling, white noise, and subframe combination
+        // additional simple programs for oversampling and subframe combination
         QString lightOversampledVs = readFile(":/libcamsim/simulation-oversampling-vs.glsl");
         QString lightOversampledFs = readFile(":/libcamsim/simulation-oversampling-fs.glsl");
         lightOversampledFs.replace("$TWO_INPUTS$", (_output.rgb && _output.pmd ? "1" : "0"));
@@ -662,21 +660,7 @@ void Simulator::recreateShadersIfNecessary()
             _pmdDigNumPrg.link();
             _pmdDigNumPrg.bind();
             _pmdDigNumPrg.setUniformValue("pmd_energies", 0);
-            _pmdDigNumPrg.setUniformValue("gaussian_noise_tex", 1);
         }
-        QString gaussianWhiteNoiseVs = readFile(":/libcamsim/simulation-whitenoise-vs.glsl");
-        QString gaussianWhiteNoiseFs = readFile(":/libcamsim/simulation-whitenoise-fs.glsl");
-        _gaussianWhiteNoisePrg.addShaderFromSourceCode(QOpenGLShader::Vertex, gaussianWhiteNoiseVs);
-        _gaussianWhiteNoisePrg.addShaderFromSourceCode(QOpenGLShader::Fragment, gaussianWhiteNoiseFs);
-        _gaussianWhiteNoisePrg.link();
-        _gaussianWhiteNoisePrg.bind();
-        _gaussianWhiteNoisePrg.setUniformValue("noise_tex", 0);
-        QString zeroVs = readFile(":/libcamsim/simulation-zero-vs.glsl");
-        QString zeroFs = readFile(":/libcamsim/simulation-zero-fs.glsl");
-        zeroFs.replace("$TWO_OUTPUTS$", (_output.rgb && _output.pmd ? "1" : "0"));
-        _zeroPrg.addShaderFromSourceCode(QOpenGLShader::Vertex, zeroVs);
-        _zeroPrg.addShaderFromSourceCode(QOpenGLShader::Fragment, zeroFs);
-        _zeroPrg.link();
         if (subFrames() > 1) {
             if (_output.rgb) {
                 QString rgbResultVs = readFile(":/libcamsim/simulation-rgb-result-vs.glsl");
@@ -933,11 +917,6 @@ void Simulator::recreateOutputIfNecessary()
     _pmdEnergyTex = 0;
     gl->glDeleteTextures(1, &_pmdCoordinatesTex);
     _pmdCoordinatesTex = 0;
-    gl->glDeleteTextures(1, &_gaussianNoiseTex);
-    _gaussianNoiseTex = 0;
-    _gaussianWhiteNoiseBuf.clear();
-    gl->glDeleteTextures(_gaussianWhiteNoiseTexs.size(), _gaussianWhiteNoiseTexs.constData());
-    _gaussianWhiteNoiseTexs.clear();
     gl->glDeleteTextures(_depthBuffers.size(), _depthBuffers.constData());
     _depthBuffers.clear();
     gl->glDeleteTextures(_rgbTexs.size(), _rgbTexs.constData());
@@ -1069,12 +1048,6 @@ void Simulator::recreateOutputIfNecessary()
         }
     }
     int extra = (subFrames() > 1 ? 1 : 0);
-    if (_output.rgb && _pipeline.gaussianWhiteNoise) {
-        _gaussianWhiteNoiseBuf.resize(3 * _projection.imageSize().width() * _projection.imageSize().height());
-        _gaussianWhiteNoiseTexs.resize(subFrames());
-        gl->glGenTextures(subFrames(), _gaussianWhiteNoiseTexs.data());
-        prepareOutputTexs(_projection.imageSize(), _gaussianWhiteNoiseTexs, GL_RGBA32F, false);
-    }
     _depthBuffers.resize(subFrames() + 1);
     gl->glGenTextures(subFrames() + 1, _depthBuffers.data());
     prepareDepthBuffers(_projection.imageSize(), _depthBuffers);
@@ -1093,10 +1066,6 @@ void Simulator::recreateOutputIfNecessary()
         _pmdDigNumTexs.resize(subFrames() + extra);
         gl->glGenTextures(subFrames() + extra, _pmdDigNumTexs.data());
         prepareOutputTexs(_projection.imageSize(), _pmdDigNumTexs, GL_RGBA32F, interpolation);
-        if (_pipeline.shotNoise) {
-            gl->glGenTextures(1, &_gaussianNoiseTex);
-            prepareOutputTexs(_projection.imageSize(), { _gaussianNoiseTex }, GL_RG32F, false);
-        }
     }
     if (_output.eyeSpacePositions) {
         _eyeSpacePosTexs.resize(subFrames());
@@ -1589,6 +1558,22 @@ void Simulator::simulate(
 
     // Set dynamic light properties. This is costly; do it only when we actually use light sources
     if (&prg == &_lightPrg) {
+        if (_output.rgb && _pipeline.gaussianWhiteNoise) {
+            QVector4D rn0, rn1;
+            std::uniform_real_distribution<float> distribution(0.0f, 1000.0f);
+            rn0.setX(distribution(_randomGenerator));
+            rn0.setY(distribution(_randomGenerator));
+            rn0.setZ(distribution(_randomGenerator));
+            rn0.setW(distribution(_randomGenerator));
+            rn1.setX(distribution(_randomGenerator));
+            rn1.setY(distribution(_randomGenerator));
+            rn1.setZ(distribution(_randomGenerator));
+            rn1.setW(distribution(_randomGenerator));
+            prg.setUniformValue("random_noise_0", rn0);
+            prg.setUniformValue("random_noise_1", rn1);
+            prg.setUniformValue("gwn_stddev", _pipeline.gaussianWhiteNoiseStddev);
+            prg.setUniformValue("gwn_mean", _pipeline.gaussianWhiteNoiseMean);
+        }
         int samplersForPowerFactorMaps = (_pipeline.lightPowerFactorMaps ? _scene.lights.size() : 0);
         int samplersForShadowMaps = (_pipeline.shadowMaps ? _scene.lights.size() : 0);
         QVector<float> tmpVec3_0(3 * _scene.lights.size());
@@ -1861,57 +1846,20 @@ void Simulator::simulatePMDDigNums()
     _pmdDigNumPrg.setUniformValue("wavelength", _pmd.wavelength);
     _pmdDigNumPrg.setUniformValue("quantum_efficiency", _pmd.quantumEfficiency);
     _pmdDigNumPrg.setUniformValue("max_electrons", _pmd.maxElectrons);
-    gl->glActiveTexture(GL_TEXTURE0);
-    gl->glBindTexture(GL_TEXTURE_2D, _pmdEnergyTex);
     if (_pipeline.shotNoise) {
-        // generate standard normal distributed noise
-        std::normal_distribution<float> distribution(0.0f, 1.0f);
-        auto gaussianRandomNumber = [&distribution, this]() { return distribution(_randomGenerator); };
-        auto bufferSize = 2 * _projection.imageSize().width() * _projection.imageSize().height();
-        QVector<float> buffer(bufferSize);
-        for (int i = 0; i < bufferSize; i++)
-            buffer[i] = gaussianRandomNumber();
-        gl->glActiveTexture(GL_TEXTURE1);
-        glUploadTex(_pbo, _gaussianNoiseTex,
-                _projection.imageSize().width(), _projection.imageSize().height(),
-                GL_RG32F, GL_RG, GL_FLOAT,
-                buffer.constData(), buffer.size() * sizeof(float));
-        gl->glBindTexture(GL_TEXTURE_2D, _gaussianNoiseTex);
+        QVector4D rn;
+        std::uniform_real_distribution<float> distribution(0.0f, 1000.0f);
+        rn.setX(distribution(_randomGenerator));
+        rn.setY(distribution(_randomGenerator));
+        rn.setZ(distribution(_randomGenerator));
+        rn.setW(distribution(_randomGenerator));
+        _pmdDigNumPrg.setUniformValue("random_noise", rn);
     }
-    gl->glBindVertexArray(_fullScreenQuadVao);
-    gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
-    ASSERT_GLCHECK();
-}
-
-void Simulator::simulateGaussianWhiteNoise(int subFrame)
-{
-    // create new gaussian white noise texture for each (sub)frame
-    std::normal_distribution<float> distribution(
-            _pipeline.gaussianWhiteNoiseMean,
-            _pipeline.gaussianWhiteNoiseStddev);
-    for (int i = 0; i < _gaussianWhiteNoiseBuf.size(); i++)
-        _gaussianWhiteNoiseBuf[i] = distribution(_randomGenerator);
-
-    auto gl = getGlFunctionsFromCurrentContext(Q_FUNC_INFO);
-    ASSERT_GLCHECK();
-    _gaussianWhiteNoisePrg.bind();
-    glUploadTex(_pbo, _gaussianWhiteNoiseTexs[subFrame],
-            _projection.imageSize().width(), _projection.imageSize().height(),
-            GL_RGB32F, GL_RGB, GL_FLOAT,
-            _gaussianWhiteNoiseBuf.constData(), _gaussianWhiteNoiseBuf.size() * sizeof(float));
     gl->glActiveTexture(GL_TEXTURE0);
-    gl->glBindTexture(GL_TEXTURE_2D, _gaussianWhiteNoiseTexs[subFrame]);
+    gl->glBindTexture(GL_TEXTURE_2D, _pmdEnergyTex);
     gl->glBindVertexArray(_fullScreenQuadVao);
     gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
     ASSERT_GLCHECK();
-    // now we have added the noise to the FBO via additive blending,
-    // but we might have created negative energy values which does not make sense.
-    // remove these via max-blending with 0
-    _zeroPrg.bind();
-    gl->glBlendEquation(GL_MAX);
-    gl->glEnable(GL_BLEND);
-    gl->glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
-    ASSERT_GLCHECK();
 }
 
 void Simulator::simulateRGBResult()
@@ -2071,10 +2019,6 @@ void Simulator::simulate(long long frameTimestamp)
             if (_pipeline.postprocLensDistortion) {
                 simulatePostprocLensDistortion(_lightSimOutputTexs[subFrame]);
             }
-            if (_output.rgb && _pipeline.gaussianWhiteNoise) {
-                prepareFBO(_projection.imageSize(), 0, false, { _rgbTexs[subFrame] }, -1, 0, true, false);
-                simulateGaussianWhiteNoise(subFrame);
-            }
             if (_output.srgb) {
                 prepareFBO(_projection.imageSize(), 0, false, { _srgbTexs[subFrame] });
                 convertToSRGB(subFrame);
@@ -2207,11 +2151,6 @@ unsigned int Simulator::getReflectiveShadowMapCubeArrayTex(int lightIndex, int i
             ? (i == -1 ? _reflectiveShadowMapTexs[0][lightIndex] : _reflectiveShadowMapTexs[i][lightIndex]) : 0);
 }
 
-unsigned int Simulator::getGaussianWhiteNoiseTex(int i) const
-{
-    return ((_output.rgb && _pipeline.gaussianWhiteNoise && haveValidOutput(i)) ? (i == -1 ? _gaussianWhiteNoiseTexs[0] : _gaussianWhiteNoiseTexs[i]) : 0);
-}
-
 unsigned int Simulator::getDepthTex(int i) const
 {
     return ((((!spatialOversampling() && !temporalOversampling())
index 1f7beb6..8612eb3 100644 (file)
@@ -383,8 +383,6 @@ private:
     QOpenGLShaderProgram _lightPrg;              // simulate rgb and pmd phase for current time stamp
     QOpenGLShaderProgram _lightOversampledPrg;   // reduce spatially oversampled rgb and pmd phase
     QOpenGLShaderProgram _pmdDigNumPrg;          // convert energies to PMD digital numbers, possibly with shot noise
-    QOpenGLShaderProgram _gaussianWhiteNoisePrg; // add gaussian white noise
-    QOpenGLShaderProgram _zeroPrg;               // produce all-zero output
     QOpenGLShaderProgram _rgbResultPrg;          // combine rgb subframes to final result
     QOpenGLShaderProgram _pmdResultPrg;          // combine pmd phase subframes to final result
     QOpenGLShaderProgram _pmdCoordinatesPrg;     // compute cartesian coordinates from pmd range
@@ -408,9 +406,6 @@ private:
     unsigned int _pmdEnergyTexOversampled;
     unsigned int _pmdEnergyTex;
     unsigned int _pmdCoordinatesTex;
-    unsigned int _gaussianNoiseTex;               // for shot noise generation, dynamically generated
-    QVector<float> _gaussianWhiteNoiseBuf;        // reused vector to generate gaussian white noise
-    QVector<unsigned int> _gaussianWhiteNoiseTexs;// subFrames
     QVector<unsigned int> _depthBuffers;          // subFrames+1
     QVector<unsigned int> _rgbTexs;               // subFrames+1
     QVector<unsigned int> _srgbTexs;              // subFrames+1
@@ -490,7 +485,6 @@ private:
             const QVector<Transformation>& objectTransformations);
     void simulateOversampledLight();
     void simulatePMDDigNums();
-    void simulateGaussianWhiteNoise(int subFrame);
     void simulateRGBResult();
     void simulatePMDResult();
     void simulatePMDCoordinates();
@@ -682,15 +676,6 @@ public:
     TexData getReflectiveShadowMapBRDFSpecularParameters(int lightIndex, int cubeSide, int i = -1) const
     { return TexData(getReflectiveShadowMapCubeArrayTex(lightIndex, i), cubeSide, 4, GL_RGBA32F, { "ksr", "ksg", "ksb", "shininess" }, _pbo); }
 
-    /*! \brief Get the texture containing gaussian white noise applied to RGB simulation
-     * results. This is floating point texture where three components contain independent noise values.
-     * The texture returned is for the given subframe \a i or the final result (if \a i is -1). */
-    unsigned int getGaussianWhiteNoiseTex(int i = -1) const;
-
-    /*! \brief Convenience wrapper for \a getGaussianWhiteNoiseTex() */
-    TexData getGaussianWhiteNoise(int i = -1) const
-    { return TexData(getGaussianWhiteNoiseTex(i), -1, -1, GL_RGB32F, { "noise_a", "noise_b", "noise_c" }, _pbo); }
-
     /*! \brief Get the output texture containing OpenGL depth buffer data
      * for the given subframe \a i or the final result (if \a i is -1)
      * Depths of the final result are always the same as those for the first subframe.