/* JWildfire - an image and animation processor written in Java Copyright (C) 1995-2017 Andreas Maschke This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this software; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jwildfire.create.tina.render; import org.jwildfire.create.tina.base.Layer; import org.jwildfire.create.tina.base.XYZPoint; import org.jwildfire.create.tina.palette.RenderColor; import org.jwildfire.create.tina.random.AbstractRandomGenerator; import org.jwildfire.create.tina.variation.FlameTransformationContext; public class PostBlurRenderIterationState extends DefaultRenderIterationState { private static final long serialVersionUID = 1L; private int blurRadius; private double blurFade; private double blurKernel[][]; private int rasterWidth, rasterHeight; public PostBlurRenderIterationState(AbstractRenderThread pRenderThread, FlameRenderer pRenderer, RenderPacket pPacket, Layer pLayer, FlameTransformationContext pCtx, AbstractRandomGenerator pRandGen, boolean pUsePlotBuffer) { super(pRenderThread, pRenderer, pPacket, pLayer, pCtx, pRandGen, pUsePlotBuffer); } @Override public void init() { blurRadius = flame.getPostBlurRadius(); blurKernel = createBlurKernel(blurRadius, flame.getPostBlurFallOff()); blurFade = flame.getPostBlurFade(); if (blurFade < 0.0) { blurFade = 0.0; } else if (blurFade > 1.0) { blurFade = 1.0; } rasterWidth = renderer.rasterWidth; rasterHeight = renderer.rasterHeight; } private double[][] createBlurKernel(int radius, double fallOff) { double kernel[][]; if (radius <= 0) { kernel = new double[1][1]; kernel[0][0] = 1.0; } else { kernel = new double[2 * radius + 1][2 * radius + 1]; kernel[0][0] = 1.0; for (int y = -radius, i = 0; y <= radius; y++, i++) { for (int x = -radius, j = 0; x <= radius; x++, j++) { double r = Math.sqrt(x * x + y * y) / (double) (radius); kernel[i][j] = Math.pow(2, -r * fallOff); // System.out.println(i + " " + j + " " + " r=" + r + ", k=" + kernel[i][j]); } } } return kernel; } @Override protected void plotPoint(int screenX, int screenY, double rawX, double rawY, double intensity, XYZPoint origin) { if (p.rgbColor) { plotRed = p.redColor; plotGreen = p.greenColor; plotBlue = p.blueColor; } else { RenderColor color = colorProvider.getColor(p, q); plotRed = color.red; plotGreen = color.green; plotBlue = color.blue; } transformPlotColor(p); if (ctx.random() > blurFade) { for (int k = screenY - blurRadius, yk = 0; k <= screenY + blurRadius; k++, yk++) { if (k >= 0 && k < rasterHeight) { for (int l = screenX - blurRadius, xk = 0; l <= screenX + blurRadius; l++, xk++) { if (l >= 0 && l < rasterWidth) { // y, x double scl = blurKernel[yk][xk]; double finalRed = plotRed * scl * prj.intensity; double finalGreen = plotGreen * scl * prj.intensity; double finalBlue = plotBlue * scl * prj.intensity; plotBuffer[plotBufferIdx++].set(l, k, finalRed, finalGreen, finalBlue, rawX, rawY, prj.z * view.bws, p.material, prj.dofDist, origin.x, origin.y, origin.z, p.receiveOnlyShadows); if (plotBufferIdx >= plotBuffer.length) { applySamplesToRaster(); } if (observers != null && observers.size() > 0) { for (IterationObserver observer : observers) { observer.notifyIterationFinished(renderThread, l, k, prj, q.x, q.y, q.z, finalRed, finalGreen, finalBlue); } } } } } } } else { double finalRed = plotRed * prj.intensity; double finalGreen = plotGreen * prj.intensity; double finalBlue = plotBlue * prj.intensity; plotBuffer[plotBufferIdx++].set(screenX, screenY, finalRed, finalGreen, finalBlue, rawX, rawY, prj.z * view.bws, p.material, prj.dofDist, origin.x, origin.y, origin.z, p.receiveOnlyShadows); if (plotBufferIdx >= plotBuffer.length) { applySamplesToRaster(); } if (observers != null && observers.size() > 0) { for (IterationObserver observer : observers) { observer.notifyIterationFinished(renderThread, screenX, screenY, prj, q.x, q.y, q.z, finalRed, finalGreen, finalBlue); } } } } }