From 14d5ea07354c896eecfbea071d82c1f51ac72b3b Mon Sep 17 00:00:00 2001 From: jean-claude iehl <jean-claude.iehl@liris.cnrs.fr> Date: Wed, 20 Mar 2024 14:23:28 +0100 Subject: [PATCH] framebuffer: accumulation des samples sur des doubles, pour faire de belles courbes de convergence... --- code/projects/framebuffer.h | 77 +++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 code/projects/framebuffer.h diff --git a/code/projects/framebuffer.h b/code/projects/framebuffer.h new file mode 100644 index 0000000..464f926 --- /dev/null +++ b/code/projects/framebuffer.h @@ -0,0 +1,77 @@ + +#ifndef _FRAMEBUFFER_H +#define _FRAMEBUFFER_H + +#include <vector> + +#include "image.h" + + +// les floats 32 bits ne sont pas assez precis pour accumuler des milliers d'echantillons par pixel... +struct Framebuffer +{ + struct pixel + { + double r, g, b; + unsigned n; + }; + + std::vector<pixel> pixels; + std::vector<pixel> m2; + int m_width; + int m_height; + + Framebuffer( const int w, const int h ) : pixels(w*h), m2(w*h), m_width(w), m_height(h) {} + + int width() { return m_width; } + int height() { return m_height; } + + void splat( const float x, const float y, const Color& color ) + { + int px= int(x); + int py= int(y); + assert(px >= 0 && px < m_width); + assert(py >= 0 && py < m_height); + int offset= py * m_width + px; + + // evaluation numerique stable de la moyenne et de la variance + // cf https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm + pixels[offset].n++; + double r= color.r - pixels[offset].r; + double g= color.g - pixels[offset].g; + double b= color.b - pixels[offset].b; + + // moyenne + pixels[offset].r+= r / pixels[offset].n; + pixels[offset].g+= g / pixels[offset].n; + pixels[offset].b+= b / pixels[offset].n; + + // variance + m2[offset].r+= r * ( color.r - pixels[offset].r ); + m2[offset].g+= g * ( color.g - pixels[offset].g ); + m2[offset].b+= b * ( color.b - pixels[offset].b ); + } + + + // renvoie la moyenne / image classique. + Image flatten( ) + { + Image tmp(m_width, m_height); + for(unsigned i= 0; i < tmp.size(); i++) + tmp(i)= Color( float(pixels[i].r), float(pixels[i].g), float(pixels[i].b) ); + + return tmp; + } + + // renvoie la variance / image classique. + Image flatten_var( ) + { + Image tmp(m_width, m_height); + for(unsigned i= 0; i < tmp.size(); i++) + tmp(i)= Color( m2[i].r / pixels[i].n, m2[i].g / pixels[i].n, m2[i].b / pixels[i].n ); + + return tmp; + } +}; + +#endif -- GitLab