From b2600f0ffff1302b1d57d55cc56352e1d8cd54ed Mon Sep 17 00:00:00 2001 From: mfeemster Date: Sun, 2 Nov 2014 23:16:34 -0800 Subject: [PATCH] Remove passes. Fix some table dimensions. Proper locale for normalized weight. --- .../Installer/FractoriumInstaller.wixproj | 2 +- Builds/MSVC/Installer/Product.wxs | 2 +- Source/Ember/Ember.h | 12 +- Source/Ember/EmberDefines.h | 2 +- Source/Ember/EmberToXml.h | 1 - Source/Ember/Renderer.cpp | 437 ++++++++---------- Source/Ember/Renderer.h | 3 +- Source/Ember/RendererBase.cpp | 11 +- Source/Ember/RendererBase.h | 1 - Source/Ember/SheepTools.h | 7 - Source/Ember/TemporalFilter.h | 35 +- Source/Ember/Xform.h | 4 +- Source/EmberAnimate/EmberAnimate.rc | 8 +- Source/EmberCL/RendererCL.cpp | 28 +- Source/EmberCL/RendererCL.h | 4 +- Source/EmberGenome/EmberGenome.cpp | 1 - Source/EmberGenome/EmberGenome.rc | 8 +- Source/EmberRender/EmberRender.rc | 8 +- Source/Fractorium/AboutDialog.ui | 2 +- Source/Fractorium/FinalRenderDialog.ui | 8 +- Source/Fractorium/Fractorium.cpp | 1 - Source/Fractorium/Fractorium.h | 6 +- Source/Fractorium/Fractorium.rc | Bin 4574 -> 4574 bytes Source/Fractorium/Fractorium.ui | 33 +- Source/Fractorium/FractoriumEmberController.h | 2 - Source/Fractorium/FractoriumParams.cpp | 15 +- Source/Fractorium/FractoriumXforms.cpp | 2 +- Source/Fractorium/OptionsDialog.ui | 8 +- 28 files changed, 257 insertions(+), 394 deletions(-) diff --git a/Builds/MSVC/Installer/FractoriumInstaller.wixproj b/Builds/MSVC/Installer/FractoriumInstaller.wixproj index 87b6ffd..4951f58 100644 --- a/Builds/MSVC/Installer/FractoriumInstaller.wixproj +++ b/Builds/MSVC/Installer/FractoriumInstaller.wixproj @@ -6,7 +6,7 @@ 3.7 {c8096c47-e358-438c-a520-146d46b0637d} 2.0 - Fractorium_Beta_0.4.1.3 + Fractorium_Beta_0.4.1.4 Package $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets diff --git a/Builds/MSVC/Installer/Product.wxs b/Builds/MSVC/Installer/Product.wxs index 728785d..83f5a8d 100644 --- a/Builds/MSVC/Installer/Product.wxs +++ b/Builds/MSVC/Installer/Product.wxs @@ -1,6 +1,6 @@ - + diff --git a/Source/Ember/Ember.h b/Source/Ember/Ember.h index 7742c1d..b479350 100644 --- a/Source/Ember/Ember.h +++ b/Source/Ember/Ember.h @@ -93,7 +93,6 @@ public: m_OrigFinalRasH = ember.m_OrigFinalRasH; m_OrigPixPerUnit = ember.m_OrigPixPerUnit; m_Supersample = ember.m_Supersample; - m_Passes = ember.m_Passes; m_TemporalSamples = ember.m_TemporalSamples; m_Symmetry = ember.m_Symmetry; @@ -186,7 +185,6 @@ public: m_OrigFinalRasH = 1080; m_OrigPixPerUnit = 240; m_Supersample = 1; - m_Passes = 1; m_TemporalSamples = 1000; m_Symmetry = 0; m_Quality = 100; @@ -778,7 +776,6 @@ public: InterpT<&Ember::m_CamDepthBlur>(embers, coefs, size); InterpX::m_CamMat>(embers, coefs, size); InterpT<&Ember::m_Rotate>(embers, coefs, size); - InterpI<&Ember::m_Passes>(embers, coefs, size); InterpI<&Ember::m_TemporalSamples>(embers, coefs, size); InterpT<&Ember::m_MaxRadDE>(embers, coefs, size); InterpT<&Ember::m_MinRadDE>(embers, coefs, size); @@ -1309,7 +1306,6 @@ public: m_MinRadDE = 0; m_CurveDE = T(0.4); m_GammaThresh = T(0.01); - m_Passes = 1; m_TemporalSamples = 1000; m_SpatialFilterType = GAUSSIAN_SPATIAL_FILTER; m_AffineInterp = INTERP_LOG; @@ -1341,7 +1337,6 @@ public: m_MinRadDE = -1; m_CurveDE = -1; m_GammaThresh = -1; - m_Passes = 0; m_TemporalSamples = 0; m_SpatialFilterType = GAUSSIAN_SPATIAL_FILTER; m_AffineInterp = INTERP_LOG; @@ -1381,7 +1376,6 @@ public: << "Original Raster Width: " << m_OrigFinalRasW << endl << "Original Raster Height: " << m_OrigFinalRasH << endl << "Supersample: " << m_Supersample << endl - << "Passes: " << m_Passes << endl << "Temporal Samples: " << m_TemporalSamples << endl << "Symmetry: " << m_Symmetry << endl @@ -1468,11 +1462,7 @@ public: //The multiplier in size of the histogram and DE filtering buffers. Must be at least one, preferrably never larger than 4, only useful at 2. //Xml field: "supersample" or "overample (deprecated)". size_t m_Supersample; - - //Times to run the algorithm while clearing the histogram, but not the filter. Almost always set to 1 and may even be deprecated. - //Xml field: "passes". - size_t m_Passes; - + //When animating, split each pass into this many pieces, each doing a fraction of the total iterations. Each temporal sample //will render an interpolated instance of the ember that is a fraction of the current ember and the next one. //When rendering a single image, this field is always set to 1. diff --git a/Source/Ember/EmberDefines.h b/Source/Ember/EmberDefines.h index 452944e..6adb8eb 100644 --- a/Source/Ember/EmberDefines.h +++ b/Source/Ember/EmberDefines.h @@ -36,7 +36,7 @@ namespace EmberNs extern void sincos(float x, float *s, float *c); #endif -#define EMBER_VERSION "0.4.1.3" +#define EMBER_VERSION "0.4.1.4" #define EPS6 T(1e-6) #define EPS std::numeric_limits::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way. #define ISAAC_SIZE 4 diff --git a/Source/Ember/EmberToXml.h b/Source/Ember/EmberToXml.h index e949f12..f345279 100644 --- a/Source/Ember/EmberToXml.h +++ b/Source/Ember/EmberToXml.h @@ -155,7 +155,6 @@ public: os << " temporal_filter_width=\"" << ember.m_TemporalFilterWidth << "\""; os << " quality=\"" << ember.m_Quality << "\""; - os << " passes=\"" << ember.m_Passes << "\""; os << " temporal_samples=\"" << ember.m_TemporalSamples << "\""; os << " background=\"" << ember.m_Background.r << " " << ember.m_Background.g << " " << ember.m_Background.b << "\""; os << " brightness=\"" << ember.m_Brightness << "\""; diff --git a/Source/Ember/Renderer.cpp b/Source/Ember/Renderer.cpp index f0d7ae4..afe8619 100644 --- a/Source/Ember/Renderer.cpp +++ b/Source/Ember/Renderer.cpp @@ -265,14 +265,13 @@ bool Renderer::CreateTemporalFilter(bool& newAlloc) //Use intelligent testing so it isn't created every time a new ember is passed in. if ((!m_TemporalFilter.get()) || - (m_Ember.m_Passes != m_TemporalFilter->Passes()) || (m_Ember.m_TemporalSamples != m_TemporalFilter->TemporalSamples()) || (m_Ember.m_TemporalFilterType != m_TemporalFilter->FilterType()) || (m_Ember.m_TemporalFilterWidth != m_TemporalFilter->FilterWidth()) || (m_Ember.m_TemporalFilterExp != m_TemporalFilter->FilterExp())) { m_TemporalFilter = unique_ptr>( - TemporalFilterCreator::Create(m_Ember.m_TemporalFilterType, m_Ember.m_Passes, m_Ember.m_TemporalSamples, m_Ember.m_TemporalFilterWidth, m_Ember.m_TemporalFilterExp)); + TemporalFilterCreator::Create(m_Ember.m_TemporalFilterType, m_Ember.m_TemporalSamples, m_Ember.m_TemporalFilterWidth, m_Ember.m_TemporalFilterExp)); newAlloc = true; } @@ -287,15 +286,13 @@ bool Renderer::CreateTemporalFilter(bool& newAlloc) /// future-proofs the algorithm for GPU-based renderers. /// If the caller calls Abort() at any time, or the progress function returns 0, /// the entire rendering process will exit as soon as it can. +/// The concept of passes from flam3 has been removed as it was never used. /// The loop structure is: /// { -/// Passes (Default 1) +/// Temporal Samples (Default 1 for single image) /// { -/// Temporal Samples (Default 1 for single image) +/// Iterate (Either to completion or to a specified number of iterations) /// { -/// Iterate (Either to completion or to a specified number of iterations) -/// { -/// } /// } /// } /// @@ -326,11 +323,11 @@ eRenderStatus Renderer::Run(vector& finalImage, doubl m_InRender = true; EnterRender(); m_Abort = false; - bool filterAndAccumOnly = (m_ProcessAction == FILTER_AND_ACCUM && Passes() == 1); + bool filterAndAccumOnly = m_ProcessAction == FILTER_AND_ACCUM; bool accumOnly = m_ProcessAction == ACCUM_ONLY; bool resume = m_ProcessState != NONE; bool newFilterAlloc; - size_t temporalSample = 0, pass; + size_t temporalSample = 0; T deTime; eRenderStatus success = RENDER_OK; //double iterationTime = 0; @@ -349,7 +346,6 @@ eRenderStatus Renderer::Run(vector& finalImage, doubl if (!resume)//Beginning, reset everything. { - m_LastPass = 0; m_LastTemporalSample = 0; m_LastIter = 0; m_LastIterPercent = 0; @@ -360,9 +356,8 @@ eRenderStatus Renderer::Run(vector& finalImage, doubl m_Background.Clear(); } //User requested an increase in quality after finishing. - else if (m_ProcessState == ITER_STARTED && m_ProcessAction == KEEP_ITERATING && TemporalSamples() == 1 && Passes() == 1) + else if (m_ProcessState == ITER_STARTED && m_ProcessAction == KEEP_ITERATING && TemporalSamples() == 1) { - m_LastPass = 0; m_LastTemporalSample = 0; m_LastIter = m_Stats.m_Iters; m_LastIterPercent = 0;//Might skip a progress update, but shouldn't matter. @@ -372,10 +367,7 @@ eRenderStatus Renderer::Run(vector& finalImage, doubl m_Background.Clear(); } - pass = (resume ? m_LastPass : 0); - //Make sure values are within valid range. - ClampGteRef(m_Ember.m_Passes, size_t(1)); ClampGteRef(m_Ember.m_Supersample, size_t(1)); //Make sure to get most recent update since loop won't be entered to call Interp(). @@ -426,199 +418,176 @@ eRenderStatus Renderer::Run(vector& finalImage, doubl if (!resume) ResetBuckets(true, false);//Only reset hist here and do accum when needed later on. - //Passes, outermost loop 1. - for (; (pass < Passes()) && !m_Abort;) - { - deTime = T(time) + m_TemporalFilter->Deltas()[pass * m_Ember.m_TemporalSamples]; + deTime = T(time) + m_TemporalFilter->Deltas()[0]; - //Interpolate and get an ember for DE purposes. - //Additional interpolation will be done in the temporal samples loop. + //Interpolate and get an ember for DE purposes. + //Additional interpolation will be done in the temporal samples loop. + //it.Tic(); + if (m_Embers.size() > 1) + Interpolater::Interpolate(m_Embers, deTime, 0, m_Ember); + //it.Toc("Interp 2"); + + ClampGte(m_Ember.m_MinRadDE, 0); + ClampGte(m_Ember.m_MaxRadDE, 0); + + if (!CreateDEFilter(newFilterAlloc)) + { + m_ErrorReport.push_back("Density filter creation failed, aborting.\n"); + success = RENDER_ERROR; + goto Finish; + } + + //Temporal samples, loop 1. + temporalSample = resume ? m_LastTemporalSample : 0; + for (; (temporalSample < TemporalSamples()) && !m_Abort;) + { + T colorScalar = m_TemporalFilter->Filter()[temporalSample]; + T temporalTime = T(time) + m_TemporalFilter->Deltas()[temporalSample]; + + //Interpolate again. //it.Tic(); if (m_Embers.size() > 1) - Interpolater::Interpolate(m_Embers, deTime, 0, m_Ember); - //it.Toc("Interp 2"); + Interpolater::Interpolate(m_Embers, temporalTime, 0, m_Ember);//This will perform all necessary precalcs via the ember/xform/variation assignment operators. - ClampGte(m_Ember.m_MinRadDE, 0); - ClampGte(m_Ember.m_MaxRadDE, 0); + //it.Toc("Interp 3"); - if (!CreateDEFilter(newFilterAlloc)) + if (!resume && !AssignIterator()) { - m_ErrorReport.push_back("Density filter creation failed, aborting.\n"); + m_ErrorReport.push_back("Iterator assignment failed, aborting.\n"); success = RENDER_ERROR; goto Finish; } - //Temporal samples, loop 2. - temporalSample = resume ? m_LastTemporalSample : 0; - for (; (temporalSample < TemporalSamples()) && !m_Abort;) + ComputeCamera(); + + //For each temporal sample, the palette m_Dmap needs to be re-created with color scalar. 1 if no temporal samples. + MakeDmap(colorScalar); + + //The actual number of times to iterate. Each thread will get (totalIters / ThreadCount) iters to do. + //This is based on zoom and scale calculated in ComputeCamera(). + //Note that the iter count is based on the final image dimensions, and not the super sampled dimensions. + size_t itersPerTemporalSample = ItersPerTemporalSample();//The total number of iterations for this temporal sample without overrides. + size_t sampleItersToDo;//The number of iterations to actually do in this sample, considering overrides. + + if (subBatchCountOverride > 0) + sampleItersToDo = subBatchCountOverride * SubBatchSize() * ThreadCount();//Run a specific number of sub batches. + else + sampleItersToDo = itersPerTemporalSample;//Run as many iters as specified to complete this temporal sample. + + sampleItersToDo = min(sampleItersToDo, itersPerTemporalSample - m_LastIter); + EmberStats stats = Iterate(sampleItersToDo, temporalSample);//The heavy work is done here. + + //If no iters were executed, something went catastrophically wrong. + if (stats.m_Iters == 0) { - T colorScalar = m_TemporalFilter->Filter()[pass * TemporalSamples() + temporalSample]; - T temporalTime = T(time) + m_TemporalFilter->Deltas()[pass * TemporalSamples() + temporalSample]; - - //Interpolate again. - //it.Tic(); - if (m_Embers.size() > 1) - Interpolater::Interpolate(m_Embers, temporalTime, 0, m_Ember);//This will perform all necessary precalcs via the ember/xform/variation assignment operators. - - //it.Toc("Interp 3"); - - if (!resume && !AssignIterator()) - { - m_ErrorReport.push_back("Iterator assignment failed, aborting.\n"); - success = RENDER_ERROR; - goto Finish; - } - - ComputeCamera(); - - //For each temporal sample, the palette m_Dmap needs to be re-created with color scalar. 1 if no temporal samples. - MakeDmap(colorScalar); - - //The actual number of times to iterate. Each thread will get (totalIters / ThreadCount) iters to do. - //This is based on zoom and scale calculated in ComputeCamera(). - //Note that the iter count is based on the final image dimensions, and not the super sampled dimensions. - size_t itersPerTemporalSample = ItersPerTemporalSample();//The total number of iterations for this temporal sample in this pass without overrides. - size_t sampleItersToDo;//The number of iterations to actually do in this sample in this pass, considering overrides. - - if (subBatchCountOverride > 0) - sampleItersToDo = subBatchCountOverride * SubBatchSize() * ThreadCount();//Run a specific number of sub batches. - else - sampleItersToDo = itersPerTemporalSample;//Run as many iters as specified to complete this temporal sample. - - sampleItersToDo = min(sampleItersToDo, itersPerTemporalSample - m_LastIter); - EmberStats stats = Iterate(sampleItersToDo, pass, temporalSample);//The heavy work is done here. - - //If no iters were executed, something went catastrophically wrong. - if (stats.m_Iters == 0) - { - m_ErrorReport.push_back("Zero iterations ran, rendering failed, aborting.\n"); - success = RENDER_ERROR; - Abort(); - goto Finish; - } - - if (m_Abort) - { - success = RENDER_ABORT; - goto Finish; - } - - //Accumulate stats whether this batch ran to completion or exited prematurely. - m_LastIter += stats.m_Iters;//Sum of iter count of all threads, reset each temporal sample. - m_Stats.m_Iters += stats.m_Iters;//Sum of iter count of all threads, cumulative from beginning to end. - m_Stats.m_Badvals += stats.m_Badvals; - m_Stats.m_IterMs += stats.m_IterMs; - - //After each temporal sample, accumulate these. - //Allow for incremental rendering by only taking action if the iter loop for this temporal sample is completely done. - if (m_LastIter >= itersPerTemporalSample) - { - m_Vibrancy += m_Ember.m_Vibrancy; - m_Gamma += m_Ember.m_Gamma; - m_Background.r += m_Ember.m_Background.r; - m_Background.g += m_Ember.m_Background.g; - m_Background.b += m_Ember.m_Background.b; - m_VibGamCount++; - m_LastIter = 0; - temporalSample++; - } - - m_LastTemporalSample = temporalSample; - - if (subBatchCountOverride > 0)//Don't keep going through this loop if only doing an incremental render. - break; - }//Temporal samples. - - //If we've completed all temporal samples and all passes, then it was a complete render, so report progress. - if ((Passes() == 1 || pass == Passes() - 1) && (temporalSample >= TemporalSamples())) - { - m_ProcessState = ITER_DONE; - - if (m_Callback && !m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 100.0, 0, 0)) - { - Abort(); - success = RENDER_ABORT; - goto Finish; - } + m_ErrorReport.push_back("Zero iterations ran, rendering failed, aborting.\n"); + success = RENDER_ERROR; + Abort(); + goto Finish; } -FilterAndAccum: - if (filterAndAccumOnly || temporalSample >= TemporalSamples() || forceOutput) + if (m_Abort) { - //t.Toc("Iterating and accumulating"); - //Compute k1 and k2. - eRenderStatus fullRun = RENDER_OK;//Whether density filtering was run to completion without aborting prematurely or triggering an error. - T passFilter = T(1) / T(Passes());//Original used an array, but every element in the array had the same value, so just use a single value here. - - T area = FinalRasW() * FinalRasH() / (m_PixelsPerUnitX * m_PixelsPerUnitY);//Need to use temps from field if ever implemented. - m_K1 = (Brightness() * T(268.0) * passFilter) / 256; - - //When doing an interactive render, force output early on in the render process, before all iterations are done. - //This presents a problem with the normal calculation of K2 since it relies on the quality value; it will scale the colors - //to be very dark. Correct it by pretending the number of iters done is the exact quality desired and then scale according to that. - if (forceOutput) - { - T quality = ((T)m_Stats.m_Iters / (T)FinalDimensions()) * (m_Scale * m_Scale); - m_K2 = (Supersample() * Supersample() * Passes()) / (area * quality * m_TemporalFilter->SumFilt()); - } - else - m_K2 = (Supersample() * Supersample() * Passes()) / (area * m_ScaledQuality * m_TemporalFilter->SumFilt()); - - if (filterAndAccumOnly || pass == 0) - ResetBuckets(false, true);//Only the histogram was reset above, now reset the density filtering buffer. - //t.Tic(); - - //Apply appropriate filter if iterating is complete. - if (filterAndAccumOnly || temporalSample >= TemporalSamples()) - { - fullRun = m_DensityFilter.get() ? GaussianDensityFilter() : LogScaleDensityFilter(); - } - else - { - //Apply requested filter for a forced output during interactive rendering. - if (m_DensityFilter.get() && m_InteractiveFilter == FILTER_DE) - fullRun = GaussianDensityFilter(); - else if (!m_DensityFilter.get() || m_InteractiveFilter == FILTER_LOG) - fullRun = LogScaleDensityFilter(); - } - - //Only update state if iterating and filtering finished completely (didn't arrive here via forceOutput). - if (fullRun == RENDER_OK && m_ProcessState == ITER_DONE && (Passes() == 1 || pass == Passes() - 1)) - m_ProcessState = FILTER_DONE; - - //Take special action if filtering exited prematurely. - if (fullRun != RENDER_OK) - { - if (Passes() > 1)//Since all filtering is cummulative with passes > 1, must restart the entire process. - { - m_ProcessState = NONE; - m_ProcessAction = FULL_RENDER; - } - - ResetBuckets(false, true);//Reset the accumulator, come back and try again on the next call. - success = fullRun; - goto Finish; - } - - if (m_Abort) - { - success = RENDER_ABORT; - goto Finish; - } - //t.Toc("Density estimation filtering time: ", true); + success = RENDER_ABORT; + goto Finish; } - //Only increment pass if the temporal samples loop has been completed, which could have been done incrementally. - //Also skip if rendering jumped straight here after completely finishing beforehand. - if (!filterAndAccumOnly && temporalSample >= TemporalSamples())//This may not work if filtering was prematurely exited. - pass++; + //Accumulate stats whether this batch ran to completion or exited prematurely. + m_LastIter += stats.m_Iters;//Sum of iter count of all threads, reset each temporal sample. + m_Stats.m_Iters += stats.m_Iters;//Sum of iter count of all threads, cumulative from beginning to end. + m_Stats.m_Badvals += stats.m_Badvals; + m_Stats.m_IterMs += stats.m_IterMs; - if (!filterAndAccumOnly) - m_LastPass = pass; + //After each temporal sample, accumulate these. + //Allow for incremental rendering by only taking action if the iter loop for this temporal sample is completely done. + if (m_LastIter >= itersPerTemporalSample) + { + m_Vibrancy += m_Ember.m_Vibrancy; + m_Gamma += m_Ember.m_Gamma; + m_Background.r += m_Ember.m_Background.r; + m_Background.g += m_Ember.m_Background.g; + m_Background.b += m_Ember.m_Background.b; + m_VibGamCount++; + m_LastIter = 0; + temporalSample++; + } + + m_LastTemporalSample = temporalSample; if (subBatchCountOverride > 0)//Don't keep going through this loop if only doing an incremental render. break; - }//Passes. + }//Temporal samples. + + //If we've completed all temporal samples, then it was a complete render, so report progress. + if (temporalSample >= TemporalSamples()) + { + m_ProcessState = ITER_DONE; + + if (m_Callback && !m_Callback->ProgressFunc(m_Ember, m_ProgressParameter, 100.0, 0, 0)) + { + Abort(); + success = RENDER_ABORT; + goto Finish; + } + } + +FilterAndAccum: + if (filterAndAccumOnly || temporalSample >= TemporalSamples() || forceOutput) + { + //t.Toc("Iterating and accumulating"); + //Compute k1 and k2. + eRenderStatus fullRun = RENDER_OK;//Whether density filtering was run to completion without aborting prematurely or triggering an error. + + T area = FinalRasW() * FinalRasH() / (m_PixelsPerUnitX * m_PixelsPerUnitY);//Need to use temps from field if ever implemented. + m_K1 = (Brightness() * T(268.0)) / 256; + + //When doing an interactive render, force output early on in the render process, before all iterations are done. + //This presents a problem with the normal calculation of K2 since it relies on the quality value; it will scale the colors + //to be very dark. Correct it by pretending the number of iters done is the exact quality desired and then scale according to that. + if (forceOutput) + { + T quality = ((T)m_Stats.m_Iters / (T)FinalDimensions()) * (m_Scale * m_Scale); + m_K2 = (Supersample() * Supersample()) / (area * quality * m_TemporalFilter->SumFilt()); + } + else + m_K2 = (Supersample() * Supersample()) / (area * m_ScaledQuality * m_TemporalFilter->SumFilt()); + + ResetBuckets(false, true);//Only the histogram was reset above, now reset the density filtering buffer. + //t.Tic(); + + //Apply appropriate filter if iterating is complete. + if (filterAndAccumOnly || temporalSample >= TemporalSamples()) + { + fullRun = m_DensityFilter.get() ? GaussianDensityFilter() : LogScaleDensityFilter(); + } + else + { + //Apply requested filter for a forced output during interactive rendering. + if (m_DensityFilter.get() && m_InteractiveFilter == FILTER_DE) + fullRun = GaussianDensityFilter(); + else if (!m_DensityFilter.get() || m_InteractiveFilter == FILTER_LOG) + fullRun = LogScaleDensityFilter(); + } + + //Only update state if iterating and filtering finished completely (didn't arrive here via forceOutput). + if (fullRun == RENDER_OK && m_ProcessState == ITER_DONE) + m_ProcessState = FILTER_DONE; + + //Take special action if filtering exited prematurely. + if (fullRun != RENDER_OK) + { + ResetBuckets(false, true);//Reset the accumulator, come back and try again on the next call. + success = fullRun; + goto Finish; + } + + if (m_Abort) + { + success = RENDER_ABORT; + goto Finish; + } + //t.Toc("Density estimation filtering time: ", true); + } AccumOnly: if (m_ProcessState == FILTER_DONE || forceOutput) @@ -816,57 +785,29 @@ eRenderStatus Renderer::LogScaleDensityFilter() //Timing t(4); //Original didn't parallelize this, doing so gives a 50-75% speedup. - //If there is only one pass, the value can be directly assigned, which is quicker than summing. - if (Passes() == 1) + //The value can be directly assigned, which is quicker than summing. + parallel_for(startRow, endRow, [&] (size_t j) { - parallel_for(startRow, endRow, [&] (size_t j) + size_t row = j * m_SuperRasW; + //__m128 logm128;//Figure out SSE at some point. + //__m128 bucketm128; + //__m128 scaledBucket128; + + for (size_t i = startCol; (i < endCol) && !m_Abort; i++) { - size_t row = j * m_SuperRasW; - //__m128 logm128;//Figure out SSE at some point. - //__m128 bucketm128; - //__m128 scaledBucket128; + size_t index = row + i; - for (size_t i = startCol; (i < endCol) && !m_Abort; i++) + //Check for visibility first before doing anything else to avoid all possible unnecessary calculations. + if (m_HistBuckets[index].a != 0) { - size_t index = row + i; + T logScale = (m_K1 * log(1 + m_HistBuckets[index].a * m_K2)) / m_HistBuckets[index].a; - //Check for visibility first before doing anything else to avoid all possible unnecessary calculations. - if (m_HistBuckets[index].a != 0) - { - T logScale = (m_K1 * log(1 + m_HistBuckets[index].a * m_K2)) / m_HistBuckets[index].a; - - //Original did a temporary assignment, then *= logScale, then passed the result to bump_no_overflow(). - //Combine here into one operation for a slight speedup. - m_AccumulatorBuckets[index] = (m_HistBuckets[index] * (bucketT)logScale); - } + //Original did a temporary assignment, then *= logScale, then passed the result to bump_no_overflow(). + //Combine here into one operation for a slight speedup. + m_AccumulatorBuckets[index] = m_HistBuckets[index] * (bucketT)logScale; } - }); - } - else//Passes > 1, so sum. - { - parallel_for(startRow, endRow, [&] (size_t j) - { - size_t row = j * m_SuperRasW; - - for (size_t i = startCol; (i < endCol) && !m_Abort; i++) - { - size_t index = row + i; - - //Check for visibility first before doing anything else to avoid all possible unnecessary calculations. - if (m_HistBuckets[index].a != 0) - { - //Figure out SSE at some point. - //__declspec(align(16)) - T logScale = (m_K1 * log(1 + m_HistBuckets[index].a * m_K2)) / m_HistBuckets[index].a; - //logm128 = _mm_load1_ps(&logScale); - //bucketm128 = _mm_load_ps(m_HistBuckets[index].Channels); - //scaledBucket128 = _mm_mul_ps(logm128, bucketm128); - - m_AccumulatorBuckets[index] += (m_HistBuckets[index] * bucketT(logScale)); - } - } - }); - } + } + }); //t.Toc(__FUNCTION__); return m_Abort ? RENDER_ABORT : RENDER_OK; @@ -1216,11 +1157,10 @@ eRenderStatus Renderer::AccumulatorToFinalImage(unsigned char* pixel /// which by default is 10,000 iterations. /// /// The number of iterations to run -/// The pass this is running for -/// The temporal sample within the current pass this is running for +/// The temporal sample this is running for /// Rendering statistics template -EmberStats Renderer::Iterate(size_t iterCount, size_t pass, size_t temporalSample) +EmberStats Renderer::Iterate(size_t iterCount, size_t temporalSample) { //Timing t2(4); m_IterTimer.Tic(); @@ -1245,7 +1185,7 @@ EmberStats Renderer::Iterate(size_t iterCount, size_t pass, size_t t m_BadVals[threadIndex] = 0; - //Sub batch iterations, loop 3. + //Sub batch iterations, loop 2. for (m_SubBatch[threadIndex] = 0; (m_SubBatch[threadIndex] < totalItersPerThread) && !m_Abort; m_SubBatch[threadIndex] += subBatchSize) { //Must recalculate the number of iters to run on each sub batch because the last batch will most likely have less than m_SubBatchSize iters. @@ -1262,7 +1202,7 @@ EmberStats Renderer::Iterate(size_t iterCount, size_t pass, size_t t //Finally, iterate. //t.Tic(); - //Iterating, loop 4. + //Iterating, loop 3. m_BadVals[threadIndex] += m_Iterator->Iterate(m_Ember, subBatchSize, fuse, m_Samples[threadIndex].data(), m_Rand[threadIndex]); //iterationTime += t.Toc(); @@ -1278,21 +1218,19 @@ EmberStats Renderer::Iterate(size_t iterCount, size_t pass, size_t t if (m_Callback && threadIndex == 0) { percent = 100.0 * + + double + ( double ( double ( - double - ( - double - ( - //Takes progress of current thread and multiplies by thread count. - //This assumes the threads progress at roughly the same speed. - double(m_LastIter + (m_SubBatch[threadIndex] * m_ThreadsToUse)) / double(ItersPerTemporalSample()) - ) + temporalSample - ) / (double)TemporalSamples() - ) + (double)pass - ) / (double)Passes(); + //Takes progress of current thread and multiplies by thread count. + //This assumes the threads progress at roughly the same speed. + double(m_LastIter + (m_SubBatch[threadIndex] * m_ThreadsToUse)) / double(ItersPerTemporalSample()) + ) + temporalSample + ) / (double)TemporalSamples() + ); double percentDiff = percent - m_LastIterPercent; double toc = m_ProgressTimer.Toc(); @@ -1406,7 +1344,6 @@ template ePaletteMode Renderer:: /// Virtual ember wrappers overridden from RendererBase, getters only. /// -template size_t Renderer::Passes() const { return m_Ember.m_Passes; } template size_t Renderer::TemporalSamples() const { return m_Ember.m_TemporalSamples; } template size_t Renderer::FinalRasW() const { return m_Ember.m_FinalRasW; } template size_t Renderer::FinalRasH() const { return m_Ember.m_FinalRasH; } diff --git a/Source/Ember/Renderer.h b/Source/Ember/Renderer.h index 80494f5..8772eb1 100644 --- a/Source/Ember/Renderer.h +++ b/Source/Ember/Renderer.h @@ -74,7 +74,7 @@ protected: virtual eRenderStatus GaussianDensityFilter(); virtual eRenderStatus AccumulatorToFinalImage(vector& pixels, size_t finalOffset); virtual eRenderStatus AccumulatorToFinalImage(unsigned char* pixels, size_t finalOffset); - virtual EmberStats Iterate(size_t iterCount, size_t pass, size_t temporalSample); + virtual EmberStats Iterate(size_t iterCount, size_t temporalSample); public: //Non-virtual render properties, getters and setters. @@ -131,7 +131,6 @@ public: inline ePaletteMode PaletteMode() const; //Virtual ember wrappers overridden from RendererBase, getters only. - virtual size_t Passes() const override; virtual size_t TemporalSamples() const override; virtual size_t FinalRasW() const override; virtual size_t FinalRasH() const override; diff --git a/Source/Ember/RendererBase.cpp b/Source/Ember/RendererBase.cpp index 8b14263..2a4c9df 100644 --- a/Source/Ember/RendererBase.cpp +++ b/Source/Ember/RendererBase.cpp @@ -23,7 +23,6 @@ RendererBase::RendererBase() ThreadCount(Timing::ProcessorCount()); m_Callback = nullptr; m_ProgressParameter = nullptr; - m_LastPass = 0; m_LastTemporalSample = 0; m_LastIter = 0; m_LastIterPercent = 0; @@ -65,7 +64,7 @@ void RendererBase::ChangeVal(std::function func, eProcessAction acti //new and old quality values. else if (action == KEEP_ITERATING) { - if (m_ProcessState == ACCUM_DONE && TemporalSamples() == 1 && Passes() == 1) + if (m_ProcessState == ACCUM_DONE && TemporalSamples() == 1) { m_ProcessState = ITER_STARTED; m_ProcessAction = KEEP_ITERATING; @@ -84,11 +83,11 @@ void RendererBase::ChangeVal(std::function func, eProcessAction acti m_ProcessState = NONE; m_ProcessAction = FULL_RENDER; } - //If passes == 1, set the state to ITER_DONE and the next process action to FILTER_AND_ACCUM. + //Set the state to ITER_DONE and the next process action to FILTER_AND_ACCUM. else { - m_ProcessState = Passes() == 1 ? ITER_DONE : NONE; - m_ProcessAction = Passes() == 1 ? FILTER_AND_ACCUM : FULL_RENDER;//Cannot just filter if passes > 1 because filtering is done with each pass. + m_ProcessState = ITER_DONE; + m_ProcessAction = FILTER_AND_ACCUM; } } //Run accum only. @@ -283,7 +282,7 @@ size_t RendererBase::PixelSize() const { return NumChannels() * BytesP size_t RendererBase::GutterWidth() const { return m_GutterWidth; } size_t RendererBase::DensityFilterOffset() const { return m_DensityFilterOffset; } size_t RendererBase::TotalIterCount(size_t strips) const { return (size_t)((size_t)Round(ScaledQuality()) * FinalRasW() * FinalRasH() * strips); }//Use Round() because there can be some roundoff error when interpolating. -size_t RendererBase::ItersPerTemporalSample() const { return (size_t)ceil(double(TotalIterCount(1)) / double(Passes() * TemporalSamples())); }//Temporal samples is used with animation, which doesn't support strips, so pass 1. +size_t RendererBase::ItersPerTemporalSample() const { return (size_t)ceil(double(TotalIterCount(1)) / double(TemporalSamples())); }//Temporal samples is used with animation, which doesn't support strips, so pass 1. eProcessState RendererBase::ProcessState() const { return m_ProcessState; } eProcessAction RendererBase::ProcessAction() const { return m_ProcessAction; } EmberStats RendererBase::Stats() const { return m_Stats; } diff --git a/Source/Ember/RendererBase.h b/Source/Ember/RendererBase.h index d83438f..01c390f 100644 --- a/Source/Ember/RendererBase.h +++ b/Source/Ember/RendererBase.h @@ -165,7 +165,6 @@ public: virtual eRendererType RendererType() const; //Abstract render properties, getters only. - virtual size_t Passes() const = 0; virtual size_t TemporalSamples() const = 0; virtual size_t HistBucketSize() const = 0; virtual size_t FinalRasW() const = 0; diff --git a/Source/Ember/SheepTools.h b/Source/Ember/SheepTools.h index f869474..a7b0ba4 100644 --- a/Source/Ember/SheepTools.h +++ b/Source/Ember/SheepTools.h @@ -872,7 +872,6 @@ public: adjustedEmber.m_FinalRasW = (size_t)(ember.m_FinalRasW * scalar); adjustedEmber.m_FinalRasH = (size_t)(ember.m_FinalRasH * scalar); adjustedEmber.m_PixelsPerUnit *= scalar; - adjustedEmber.m_Passes = 1; adjustedEmber.m_TemporalSamples = 1; m_Renderer->SetEmber(adjustedEmber); @@ -1181,9 +1180,6 @@ public: if (templ.m_Quality > 0) ember.m_Quality = templ.m_Quality; - if (templ.m_Passes > 0) - ember.m_Passes = templ.m_Passes; - if (templ.m_TemporalSamples > 0) ember.m_TemporalSamples = templ.m_TemporalSamples; @@ -1209,9 +1205,6 @@ public: if (templ.m_GammaThresh >= 0) ember.m_GammaThresh = templ.m_GammaThresh; - if (templ.m_Passes > 0) - ember.m_Passes = templ.m_Passes; - if (templ.m_SpatialFilterType > 0) ember.m_SpatialFilterType = templ.m_SpatialFilterType; diff --git a/Source/Ember/TemporalFilter.h b/Source/Ember/TemporalFilter.h index 693ae71..4931d1c 100644 --- a/Source/Ember/TemporalFilter.h +++ b/Source/Ember/TemporalFilter.h @@ -44,14 +44,12 @@ public: /// Derived class constructors will complete the final part of filter setup. /// /// Type of the filter. - /// The number of passes used in the ember being rendered /// The number of temporal samples in the ember being rendered /// The width of the filter. - TemporalFilter(eTemporalFilterType filterType, size_t passes, size_t temporalSamples, T filterWidth) + TemporalFilter(eTemporalFilterType filterType, size_t temporalSamples, T filterWidth) { - size_t i, steps = passes * temporalSamples; + size_t i, steps = temporalSamples; - m_Passes = passes; m_TemporalSamples = temporalSamples; m_FilterWidth = filterWidth; m_Deltas.resize(steps); @@ -98,7 +96,6 @@ public: { if (this != &filter) { - m_Passes = filter.m_Passes; m_TemporalSamples = filter.m_TemporalSamples; m_FilterWidth = filter.m_FilterWidth; m_FilterExp = filter.m_FilterExp; @@ -146,7 +143,6 @@ public: /// Accessors. /// size_t Size() const { return m_Filter.size(); } - size_t Passes() const { return m_Passes; } size_t TemporalSamples() const { return m_TemporalSamples; } T FilterWidth() const { return m_FilterWidth; } T FilterExp() const { return m_FilterExp; } @@ -176,7 +172,6 @@ protected: T m_SumFilt;//The sum of all filter values. T m_FilterWidth; T m_FilterExp; - size_t m_Passes; size_t m_TemporalSamples; vector m_Deltas;//Delta vector. vector m_Filter;//Filter vector. @@ -194,12 +189,11 @@ public: /// /// Constructor to create an Exp filter. /// - /// The number of passes used in the ember being rendered /// The number of temporal samples in the ember being rendered /// The width of the filter. /// The filter exp. - ExpTemporalFilter(size_t passes, size_t temporalSamples, T filterWidth, T filterExp) - : TemporalFilter(BOX_TEMPORAL_FILTER, passes, temporalSamples, filterWidth) + ExpTemporalFilter(size_t temporalSamples, T filterWidth, T filterExp) + : TemporalFilter(BOX_TEMPORAL_FILTER, temporalSamples, filterWidth) { if (Size() > 1) { @@ -237,11 +231,10 @@ public: /// /// Constructor to create a Gaussian filter. /// - /// The number of passes used in the ember being rendered /// The number of temporal samples in the ember being rendered /// The width of the filter. - GaussianTemporalFilter(size_t passes, size_t temporalSamples, T filterWidth) - : TemporalFilter(GAUSSIAN_TEMPORAL_FILTER, passes, temporalSamples, filterWidth) + GaussianTemporalFilter(size_t temporalSamples, T filterWidth) + : TemporalFilter(GAUSSIAN_TEMPORAL_FILTER, temporalSamples, filterWidth) { if (Size() > 1) { @@ -273,11 +266,10 @@ public: /// /// Constructor to create a Box filter. /// - /// The number of passes used in the ember being rendered /// The number of temporal samples in the ember being rendered /// The width of the filter. - BoxTemporalFilter(size_t passes, size_t temporalSamples, T filterWidth) - : TemporalFilter(BOX_TEMPORAL_FILTER, passes, temporalSamples, filterWidth) + BoxTemporalFilter(size_t temporalSamples, T filterWidth) + : TemporalFilter(BOX_TEMPORAL_FILTER, temporalSamples, filterWidth) { if (Size() > 1) { @@ -300,23 +292,22 @@ public: /// Creates the specified filter type based on the filterType enum parameter. /// /// Type of the filter - /// The number of passes used in the ember being rendered /// The number of temporal samples in the ember being rendered /// The width of the filter /// The filter exp, only used with Exp filter, otherwise ignored. /// A pointer to the newly created filter object - static TemporalFilter* Create(eTemporalFilterType filterType, size_t passes, size_t temporalSamples, T filterWidth, T filterExp = 1) + static TemporalFilter* Create(eTemporalFilterType filterType, size_t temporalSamples, T filterWidth, T filterExp = 1) { TemporalFilter* filter = nullptr; if (filterType == BOX_TEMPORAL_FILTER) - filter = new BoxTemporalFilter(passes, temporalSamples, filterWidth); + filter = new BoxTemporalFilter(temporalSamples, filterWidth); else if (filterType == GAUSSIAN_TEMPORAL_FILTER) - filter = new GaussianTemporalFilter(passes, temporalSamples, filterWidth); + filter = new GaussianTemporalFilter(temporalSamples, filterWidth); else if (filterType == EXP_TEMPORAL_FILTER) - filter = new ExpTemporalFilter(passes, temporalSamples, filterWidth, filterExp); + filter = new ExpTemporalFilter(temporalSamples, filterWidth, filterExp); else - filter = new BoxTemporalFilter(passes, temporalSamples, filterWidth);//Default to box if bad enum passed in. + filter = new BoxTemporalFilter(temporalSamples, filterWidth);//Default to box if bad enum passed in. return filter; } diff --git a/Source/Ember/Xform.h b/Source/Ember/Xform.h index 1a3e34c..a044a21 100644 --- a/Source/Ember/Xform.h +++ b/Source/Ember/Xform.h @@ -584,8 +584,6 @@ public: outPoint->m_VizAdjusted = m_VizAdjusted; iterHelper.m_Color.x = outPoint->m_ColorX = m_ColorSpeedCache + (m_OneMinusColorCache * inPoint->m_ColorX); - //This modification returns the affine transformed points if no variations are present. - //Note this differs from flam3, which would just return zero in that scenario. if (m_HasPreOrRegularVars) { //Compute the pre affine portion of the transform. @@ -637,6 +635,8 @@ public: outPoint->m_Z = iterHelper.m_TransZ; } } + //Return the affine transformed points if no variations are present. + //Note this differs from flam3, which would just return zero in that scenario. else { //There are no variations, so the affine transformed points can be assigned directly to the output points. diff --git a/Source/EmberAnimate/EmberAnimate.rc b/Source/EmberAnimate/EmberAnimate.rc index 8dcb8de..09e4dc1 100644 --- a/Source/EmberAnimate/EmberAnimate.rc +++ b/Source/EmberAnimate/EmberAnimate.rc @@ -49,8 +49,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,4,1,3 - PRODUCTVERSION 0,4,1,3 + FILEVERSION 0,4,1,4 + PRODUCTVERSION 0,4,1,4 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Renders fractal flames as animations with motion blur" - VALUE "FileVersion", "0.4.1.3" + VALUE "FileVersion", "0.4.1.4" VALUE "InternalName", "EmberAnimate.rc" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3" VALUE "OriginalFilename", "EmberAnimate.rc" VALUE "ProductName", "Ember Animate" - VALUE "ProductVersion", "0.4.1.3" + VALUE "ProductVersion", "0.4.1.4" END END BLOCK "VarFileInfo" diff --git a/Source/EmberCL/RendererCL.cpp b/Source/EmberCL/RendererCL.cpp index 0fab12d..eebb711 100644 --- a/Source/EmberCL/RendererCL.cpp +++ b/Source/EmberCL/RendererCL.cpp @@ -601,11 +601,10 @@ eRenderStatus RendererCL::AccumulatorToFinalImage(unsigned char* pixels, size /// needed, run on the CPU. /// /// The number of iterations to run -/// The pass this is running for /// The temporal sample within the current pass this is running for /// Rendering statistics template -EmberStats RendererCL::Iterate(size_t iterCount, size_t pass, size_t temporalSample) +EmberStats RendererCL::Iterate(size_t iterCount, size_t temporalSample) { bool b = true; EmberStats stats;//Do not record bad vals with with GPU. If the user needs to investigate bad vals, use the CPU. @@ -636,7 +635,7 @@ EmberStats RendererCL::Iterate(size_t iterCount, size_t pass, size_t temporal if (m_Stats.m_Iters == 0)//Only reset the call count on the beginning of a new render. Do not reset on KEEP_ITERATING. m_Calls = 0; - b = RunIter(iterCount, pass, temporalSample, stats.m_Iters); + b = RunIter(iterCount, temporalSample, stats.m_Iters); if (!b || stats.m_Iters == 0)//If no iters were executed, something went catastrophically wrong. m_Abort = true; @@ -695,12 +694,11 @@ bool RendererCL::BuildIterProgramForEmber(bool doAccum) /// between quality of the final image and performance. /// /// The number of iterations to run -/// The pass this is running for -/// The temporal sample within the current pass this is running for +/// The temporal sample this is running for /// The storage for the number of iterations ran /// True if success, else false. template -bool RendererCL::RunIter(size_t iterCount, size_t pass, size_t temporalSample, size_t& itersRan) +bool RendererCL::RunIter(size_t iterCount, size_t temporalSample, size_t& itersRan) { Timing t;//, t2(4); bool b = true; @@ -795,13 +793,10 @@ bool RendererCL::RunIter(size_t iterCount, size_t pass, size_t temporalSample ( double ( - double - ( - double(m_LastIter + itersRan) / double(ItersPerTemporalSample()) - ) + temporalSample - ) / (double)TemporalSamples() - ) + (double)pass - ) / (double)Passes(); + double(m_LastIter + itersRan) / double(ItersPerTemporalSample()) + ) + temporalSample + ) / (double)TemporalSamples() + ); double percentDiff = percent - m_LastIterPercent; double toc = m_ProgressTimer.Toc(); @@ -838,15 +833,10 @@ eRenderStatus RendererCL::RunLogScaleFilter() { //Timing t(4); bool b = true; - int kernelIndex; + int kernelIndex = m_Wrapper.FindKernelIndex(m_DEOpenCLKernelCreator.LogScaleAssignDEEntryPoint()); const char* loc = __FUNCTION__; eRenderStatus status = RENDER_OK; - if (Passes() == 1) - kernelIndex = m_Wrapper.FindKernelIndex(m_DEOpenCLKernelCreator.LogScaleAssignDEEntryPoint()); - else - kernelIndex = m_Wrapper.FindKernelIndex(m_DEOpenCLKernelCreator.LogScaleSumDEEntryPoint()); - if (kernelIndex != -1) { m_DensityFilterCL = ConvertDensityFilter(); diff --git a/Source/EmberCL/RendererCL.h b/Source/EmberCL/RendererCL.h index 2829765..1ef9760 100644 --- a/Source/EmberCL/RendererCL.h +++ b/Source/EmberCL/RendererCL.h @@ -88,12 +88,12 @@ protected: virtual eRenderStatus LogScaleDensityFilter() override; virtual eRenderStatus GaussianDensityFilter() override; virtual eRenderStatus AccumulatorToFinalImage(unsigned char* pixels, size_t finalOffset) override; - virtual EmberStats Iterate(size_t iterCount, size_t pass, size_t temporalSample) override; + virtual EmberStats Iterate(size_t iterCount, size_t temporalSample) override; private: //Private functions for making and running OpenCL programs. bool BuildIterProgramForEmber(bool doAccum = true); - bool RunIter(size_t iterCount, size_t pass, size_t temporalSample, size_t& itersRan); + bool RunIter(size_t iterCount, size_t temporalSample, size_t& itersRan); eRenderStatus RunLogScaleFilter(); eRenderStatus RunDensityFilter(); eRenderStatus RunFinalAccum(); diff --git a/Source/EmberGenome/EmberGenome.cpp b/Source/EmberGenome/EmberGenome.cpp index 92860d1..2d76ef3 100644 --- a/Source/EmberGenome/EmberGenome.cpp +++ b/Source/EmberGenome/EmberGenome.cpp @@ -27,7 +27,6 @@ void SetDefaultTestValues(Ember& ember) ember.m_SpatialFilterType = GAUSSIAN_SPATIAL_FILTER; ember.m_Zoom = 0; ember.m_Quality = 1; - ember.m_Passes = 1; ember.m_TemporalSamples = 1; ember.m_MaxRadDE = 0; ember.m_MinRadDE = 0; diff --git a/Source/EmberGenome/EmberGenome.rc b/Source/EmberGenome/EmberGenome.rc index b14d08d..6e8d76d 100644 --- a/Source/EmberGenome/EmberGenome.rc +++ b/Source/EmberGenome/EmberGenome.rc @@ -49,8 +49,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,4,1,3 - PRODUCTVERSION 0,4,1,3 + FILEVERSION 0,4,1,4 + PRODUCTVERSION 0,4,1,4 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Manipulates fractal flames parameter files" - VALUE "FileVersion", "0.4.1.3" + VALUE "FileVersion", "0.4.1.4" VALUE "InternalName", "EmberGenome.rc" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3" VALUE "OriginalFilename", "EmberGenome.rc" VALUE "ProductName", "Ember Genome" - VALUE "ProductVersion", "0.4.1.3" + VALUE "ProductVersion", "0.4.1.4" END END BLOCK "VarFileInfo" diff --git a/Source/EmberRender/EmberRender.rc b/Source/EmberRender/EmberRender.rc index 41b75a6..786c4b5 100644 --- a/Source/EmberRender/EmberRender.rc +++ b/Source/EmberRender/EmberRender.rc @@ -49,8 +49,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 0,4,1,3 - PRODUCTVERSION 0,4,1,3 + FILEVERSION 0,4,1,4 + PRODUCTVERSION 0,4,1,4 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -67,12 +67,12 @@ BEGIN BEGIN VALUE "CompanyName", "Open Source" VALUE "FileDescription", "Renders fractal flames as single images" - VALUE "FileVersion", "0.4.1.3" + VALUE "FileVersion", "0.4.1.4" VALUE "InternalName", "EmberRender.rc" VALUE "LegalCopyright", "Copyright (C) Matt Feemster 2013, GPL v3" VALUE "OriginalFilename", "EmberRender.rc" VALUE "ProductName", "Ember Render" - VALUE "ProductVersion", "0.4.1.3" + VALUE "ProductVersion", "0.4.1.4" END END BLOCK "VarFileInfo" diff --git a/Source/Fractorium/AboutDialog.ui b/Source/Fractorium/AboutDialog.ui index 0ec6449..9202d7c 100644 --- a/Source/Fractorium/AboutDialog.ui +++ b/Source/Fractorium/AboutDialog.ui @@ -52,7 +52,7 @@ - <html><head/><body><p align="center"><br/><span style=" font-size:12pt;">Fractorium 0.4.1.3 Beta</span></p><p align="center"><span style=" font-size:10pt;"><br/>A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><span style=" font-size:10pt;">Matt Feemster</span></p></body></html> + <html><head/><body><p align="center"><br/><span style=" font-size:12pt;">Fractorium 0.4.1.4 Beta</span></p><p align="center"><span style=" font-size:10pt;"><br/>A Qt-based fractal flame editor which uses a C++ re-write of the flam3 algorithm named Ember and a GPU capable version named EmberCL which implements a portion of the cuburn algorithm in OpenCL.</span></p><p align="center"><span style=" font-size:10pt;">Matt Feemster</span></p></body></html> Qt::RichText diff --git a/Source/Fractorium/FinalRenderDialog.ui b/Source/Fractorium/FinalRenderDialog.ui index 602ec80..fc6484d 100644 --- a/Source/Fractorium/FinalRenderDialog.ui +++ b/Source/Fractorium/FinalRenderDialog.ui @@ -356,13 +356,13 @@ 0 - 44 + 46 16777215 - 44 + 46 @@ -565,13 +565,13 @@ 0 - 198 + 200 16777215 - 198 + 200 diff --git a/Source/Fractorium/Fractorium.cpp b/Source/Fractorium/Fractorium.cpp index fd86bdf..dc6c307 100644 --- a/Source/Fractorium/Fractorium.cpp +++ b/Source/Fractorium/Fractorium.cpp @@ -573,7 +573,6 @@ void Fractorium::SetTabOrders() w = SetTabOrder(this, w, m_DEFilterMaxRadiusSpin); w = SetTabOrder(this, w, m_DECurveSpin); - w = SetTabOrder(this, w, m_PassesSpin); w = SetTabOrder(this, w, m_TemporalSamplesSpin); w = SetTabOrder(this, w, m_QualitySpin); w = SetTabOrder(this, w, m_SupersampleSpin); diff --git a/Source/Fractorium/Fractorium.h b/Source/Fractorium/Fractorium.h index b9a36fd..b3f3e19 100644 --- a/Source/Fractorium/Fractorium.h +++ b/Source/Fractorium/Fractorium.h @@ -152,8 +152,7 @@ public slots: void OnDEFilterMinRadiusWidthChanged(double d); void OnDEFilterMaxRadiusWidthChanged(double d); void OnDEFilterCurveWidthChanged(double d); - void OnPassesChanged(int d);//Iteration. - void OnTemporalSamplesChanged(int d); + void OnTemporalSamplesChanged(int d);//Iteration. void OnQualityChanged(double d); void OnSupersampleChanged(int d); void OnAffineInterpTypeComboCurrentIndexChanged(int index); @@ -332,8 +331,7 @@ private: DoubleSpinBox* m_DEFilterMinRadiusSpin; DoubleSpinBox* m_DEFilterMaxRadiusSpin; DoubleSpinBox* m_DECurveSpin; - SpinBox* m_PassesSpin;//Iteration. - SpinBox* m_TemporalSamplesSpin; + SpinBox* m_TemporalSamplesSpin;//Iteration. DoubleSpinBox* m_QualitySpin; SpinBox* m_SupersampleSpin; StealthComboBox* m_AffineInterpTypeCombo; diff --git a/Source/Fractorium/Fractorium.rc b/Source/Fractorium/Fractorium.rc index fe3d5b5eb325267161783435a9a3a5b750b0dbd3..d6dabf4e711e1c8045ca9bc11b194513ff2e5168 100644 GIT binary patch delta 46 wcmcbod{23U7YC!sWN!{bMw8989PG?Mjv|-%WC32W&6~KHm>}HEXLyBJ04}x*xBvhE delta 46 wcmcbod{23U7YC#9WN!{bM&r%39PG?Mjv|-%WC32W&6~KHm>}HEXLyBJ04_}nv;Y7A diff --git a/Source/Fractorium/Fractorium.ui b/Source/Fractorium/Fractorium.ui index aecbdc9..0108ced 100644 --- a/Source/Fractorium/Fractorium.ui +++ b/Source/Fractorium/Fractorium.ui @@ -944,13 +944,13 @@ 0 - 140 + 117 16777215 - 140 + 117 @@ -1031,11 +1031,6 @@ false - - - Passes - - Temporal Samples @@ -1073,7 +1068,7 @@ - Passes + Temporal Samples @@ -1083,7 +1078,7 @@ - Temporal Samples + Quality @@ -1093,7 +1088,7 @@ - Quality + Supersample @@ -1103,7 +1098,7 @@ - Supersample + Affine Interpolation @@ -1112,21 +1107,11 @@ - - Affine Interpolation - - - - - 0 - - - Interpolation - + 0 @@ -2835,8 +2820,8 @@ SpinBox 0 0 - 238 - 747 + 118 + 597 diff --git a/Source/Fractorium/FractoriumEmberController.h b/Source/Fractorium/FractoriumEmberController.h index 003c50c..0fa2e8a 100644 --- a/Source/Fractorium/FractoriumEmberController.h +++ b/Source/Fractorium/FractoriumEmberController.h @@ -126,7 +126,6 @@ public: virtual void DEFilterMinRadiusWidthChanged(double d) { } virtual void DEFilterMaxRadiusWidthChanged(double d) { } virtual void DEFilterCurveWidthChanged(double d) { } - virtual void PassesChanged(int i) { } virtual void TemporalSamplesChanged(int d) { } virtual void QualityChanged(double d) { } virtual void SupersampleChanged(int d) { } @@ -341,7 +340,6 @@ public: virtual void DEFilterMinRadiusWidthChanged(double d) override; virtual void DEFilterMaxRadiusWidthChanged(double d) override; virtual void DEFilterCurveWidthChanged(double d) override; - virtual void PassesChanged(int d) override; virtual void TemporalSamplesChanged(int d) override; virtual void QualityChanged(double d) override; virtual void SupersampleChanged(int d) override; diff --git a/Source/Fractorium/FractoriumParams.cpp b/Source/Fractorium/FractoriumParams.cpp index 8201fc0..b1266dc 100644 --- a/Source/Fractorium/FractoriumParams.cpp +++ b/Source/Fractorium/FractoriumParams.cpp @@ -85,7 +85,6 @@ void Fractorium::InitParamsUI() //Iteration. row = 0; table = ui.IterationTable; - SetupSpinner (table, this, row, 1, m_PassesSpin, spinHeight, 1, 3, 1, SIGNAL(valueChanged(int)), SLOT(OnPassesChanged(int)), true, 1, 1, 1); SetupSpinner (table, this, row, 1, m_TemporalSamplesSpin, spinHeight, 1, 5000, 50, SIGNAL(valueChanged(int)), SLOT(OnTemporalSamplesChanged(int)), true, 1000); SetupSpinner(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, 10, 10, 10); SetupSpinner (table, this, row, 1, m_SupersampleSpin, spinHeight, 1, 4, 1, SIGNAL(valueChanged(int)), SLOT(OnSupersampleChanged(int)), true, 1, 1, 1); @@ -389,16 +388,6 @@ void Fractorium::OnDEFilterCurveWidthChanged(double d) { m_Controller->DEFilterC /// Iteration. /// -/// -/// Set the number of passes. -/// This is a feature that is mostly useless and unused, and may even be removed soon. -/// It should never be set to a value greater than 1. -/// Resets the rendering process. -/// -/// The passes value -template void FractoriumEmberController::PassesChanged(int i) { Update([&] { m_Ember.m_Passes = i; }); } -void Fractorium::OnPassesChanged(int d) { m_Controller->PassesChanged(d); } - /// /// Set the temporal samples to be used with animation. /// Called when the temporal samples spinner is changed. @@ -534,8 +523,7 @@ void FractoriumEmberController::FillParamTablesAndPalette() m_Fractorium->m_DEFilterMinRadiusSpin->SetValueStealth(m_Ember.m_MinRadDE); m_Fractorium->m_DEFilterMaxRadiusSpin->SetValueStealth(m_Ember.m_MaxRadDE); m_Fractorium->m_DECurveSpin->SetValueStealth(m_Ember.m_CurveDE); - m_Fractorium->m_PassesSpin->SetValueStealth(m_Ember.m_Passes);//Iteration. - m_Fractorium->m_TemporalSamplesSpin->SetValueStealth(m_Ember.m_TemporalSamples); + m_Fractorium->m_TemporalSamplesSpin->SetValueStealth(m_Ember.m_TemporalSamples);//Iteration. m_Fractorium->m_QualitySpin->SetValueStealth(m_Ember.m_Quality); m_Fractorium->m_SupersampleSpin->SetValueStealth(m_Ember.m_Supersample); m_Fractorium->m_AffineInterpTypeCombo->SetCurrentIndexStealth(m_Ember.m_AffineInterp); @@ -597,7 +585,6 @@ void FractoriumEmberController::ParamsToEmber(Ember& ember) ember.m_MinRadDE = m_Fractorium->m_DEFilterMinRadiusSpin->value(); ember.m_MaxRadDE = m_Fractorium->m_DEFilterMaxRadiusSpin->value(); ember.m_CurveDE = m_Fractorium->m_DECurveSpin->value(); - ember.m_Passes = m_Fractorium->m_PassesSpin->value(); ember.m_TemporalSamples = m_Fractorium->m_TemporalSamplesSpin->value(); ember.m_Quality = m_Fractorium->m_QualitySpin->value(); ember.m_Supersample = m_Fractorium->m_SupersampleSpin->value(); diff --git a/Source/Fractorium/FractoriumXforms.cpp b/Source/Fractorium/FractoriumXforms.cpp index 5c43ec6..cef5f08 100644 --- a/Source/Fractorium/FractoriumXforms.cpp +++ b/Source/Fractorium/FractoriumXforms.cpp @@ -305,7 +305,7 @@ void FractoriumEmberController::SetNormalizedWeightText(Xform* xform) m_Ember.CalcNormalizedWeights(m_NormalizedWeights); if (index != -1 && index < m_NormalizedWeights.size()) - m_Fractorium->m_XformWeightSpin->setSuffix(QString(" (") + QString::number((double)m_NormalizedWeights[index], 'g', 3) + ")"); + m_Fractorium->m_XformWeightSpin->setSuffix(QString(" (") + QLocale::system().toString((double)m_NormalizedWeights[index], 'g', 3) + ")"); } } diff --git a/Source/Fractorium/OptionsDialog.ui b/Source/Fractorium/OptionsDialog.ui index 3e267a5..cec1cc8 100644 --- a/Source/Fractorium/OptionsDialog.ui +++ b/Source/Fractorium/OptionsDialog.ui @@ -324,13 +324,13 @@ in interactive mode for each mouse movement 0 - 66 + 68 16777215 - 66 + 68 @@ -507,13 +507,13 @@ in interactive mode for each mouse movement 120 - 66 + 68 16777215 - 66 + 68