package renderer.canvas; import basics.math.algebra.Vector; import optics.light.Color; public class ContributionBuffer { // linear rgb colors private volatile Color[][] buffer; // amount of samples for every pixel private volatile double[][] samples; private int width; private int height; private int maxSample; public ContributionBuffer(int width, int height) { this.width = width; this.height = height; this.buffer = new Color[width][height]; this.samples = new double[width][height]; for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { this.buffer[x][y] = Color.BLACK; } } } public void contribute(int x, int y, Color color) { buffer[x][y] = buffer[x][y].add(color); samples[x][y]++; maxSample = Math.max(maxSample, (int) samples[x][y]); } /** * Set all color values and sample count to zero * All other calls to contribute() should be blocked during execution */ public void clear() { for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { // clear color Color color = buffer[x][y]; color.r = color.g = color.b = 0; // reset sample count samples[x][y] = 0; } } } private int getRGB(int x, int y) { Color linearRGB = buffer[x][y].scale(1.0 / samples[x][y]); linearRGB.colorCorrect(); int red = (int) (linearRGB.r* 255.0); int green = (int) (linearRGB.g * 255.0); int blue = (int) (linearRGB.b * 255.0); red = Math.max(Math.min(red, 255), 0); green = Math.max(Math.min(green, 255), 0); blue = Math.max(Math.min(blue, 255), 0); return 0xff000000 | red << 16 | green << 8 | blue; } public Color getPixel(int x, int y) { return buffer[x][y].scale(1.0 / samples[x][y]); } public void visualizeSamples(int[] buffer) { for (int y = 0; y < height; y++) { int col = y * width; for (int x = 0; x < width; x++) { buffer[col + x] = Color.diagonal(samples[x][y] / maxSample).getIntRGB(); } } } public void blit(int[] buffer) { for (int y = 0; y < height; y++) { int col = y * width; for (int x = 0; x < width; x++) { buffer[col + x] = getRGB(x, y); } } } public int getWidth() { return width; } public int getHeight() { return height; } }