Remove passes.

Fix some table dimensions.
Proper locale for normalized weight.
This commit is contained in:
mfeemster 2014-11-02 23:16:34 -08:00
parent 6b2b6ede7f
commit b2600f0fff
28 changed files with 257 additions and 394 deletions

View File

@ -6,7 +6,7 @@
<ProductVersion>3.7</ProductVersion>
<ProjectGuid>{c8096c47-e358-438c-a520-146d46b0637d}</ProjectGuid>
<SchemaVersion>2.0</SchemaVersion>
<OutputName>Fractorium_Beta_0.4.1.3</OutputName>
<OutputName>Fractorium_Beta_0.4.1.4</OutputName>
<OutputType>Package</OutputType>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' AND '$(MSBuildExtensionsPath32)' != '' ">$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets</WixTargetsPath>

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define ProductVersion="0.4.1.3" ?>
<?define ProductVersion="0.4.1.4" ?>
<?define ProductName="Fractorium Beta $(var.ProductVersion) ($(var.GpuType))" ?>
<?define UpgradeCode="{4714cd15-bfba-44f6-8059-9e1466ebfa6e}"?>
<?define Manufacturer="Fractorium"?>

View File

@ -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<T>::m_CamDepthBlur>(embers, coefs, size);
InterpX<m3T, &Ember<T>::m_CamMat>(embers, coefs, size);
InterpT<&Ember<T>::m_Rotate>(embers, coefs, size);
InterpI<&Ember<T>::m_Passes>(embers, coefs, size);
InterpI<&Ember<T>::m_TemporalSamples>(embers, coefs, size);
InterpT<&Ember<T>::m_MaxRadDE>(embers, coefs, size);
InterpT<&Ember<T>::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.

View File

@ -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<T>::epsilon()//Apoplugin.h uses -20, but it's more mathematically correct to do it this way.
#define ISAAC_SIZE 4

View File

@ -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 << "\"";

View File

@ -265,14 +265,13 @@ bool Renderer<T, bucketT>::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<TemporalFilter<T>>(
TemporalFilterCreator<T>::Create(m_Ember.m_TemporalFilterType, m_Ember.m_Passes, m_Ember.m_TemporalSamples, m_Ember.m_TemporalFilterWidth, m_Ember.m_TemporalFilterExp));
TemporalFilterCreator<T>::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<T, bucketT>::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<T, bucketT>::Run(vector<unsigned char>& 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<T, bucketT>::Run(vector<unsigned char>& 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<T, bucketT>::Run(vector<unsigned char>& 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<T, bucketT>::Run(vector<unsigned char>& 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<T, bucketT>::Run(vector<unsigned char>& 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<T>::Interpolate(m_Embers, deTime, 0, m_Ember);
//it.Toc("Interp 2");
ClampGte<T>(m_Ember.m_MinRadDE, 0);
ClampGte<T>(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<T>::Interpolate(m_Embers, deTime, 0, m_Ember);
//it.Toc("Interp 2");
Interpolater<T>::Interpolate(m_Embers, temporalTime, 0, m_Ember);//This will perform all necessary precalcs via the ember/xform/variation assignment operators.
ClampGte<T>(m_Ember.m_MinRadDE, 0);
ClampGte<T>(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<T>::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<T, bucketT>::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<T, bucketT>::AccumulatorToFinalImage(unsigned char* pixel
/// which by default is 10,000 iterations.
/// </summary>
/// <param name="iterCount">The number of iterations to run</param>
/// <param name="pass">The pass this is running for</param>
/// <param name="temporalSample">The temporal sample within the current pass this is running for</param>
/// <param name="temporalSample">The temporal sample this is running for</param>
/// <returns>Rendering statistics</returns>
template <typename T, typename bucketT>
EmberStats Renderer<T, bucketT>::Iterate(size_t iterCount, size_t pass, size_t temporalSample)
EmberStats Renderer<T, bucketT>::Iterate(size_t iterCount, size_t temporalSample)
{
//Timing t2(4);
m_IterTimer.Tic();
@ -1245,7 +1185,7 @@ EmberStats Renderer<T, bucketT>::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<T, bucketT>::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<T, bucketT>::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 <typename T, typename bucketT> ePaletteMode Renderer<T, bucketT>::
/// Virtual ember wrappers overridden from RendererBase, getters only.
/// </summary>
template <typename T, typename bucketT> size_t Renderer<T, bucketT>::Passes() const { return m_Ember.m_Passes; }
template <typename T, typename bucketT> size_t Renderer<T, bucketT>::TemporalSamples() const { return m_Ember.m_TemporalSamples; }
template <typename T, typename bucketT> size_t Renderer<T, bucketT>::FinalRasW() const { return m_Ember.m_FinalRasW; }
template <typename T, typename bucketT> size_t Renderer<T, bucketT>::FinalRasH() const { return m_Ember.m_FinalRasH; }

View File

@ -74,7 +74,7 @@ protected:
virtual eRenderStatus GaussianDensityFilter();
virtual eRenderStatus AccumulatorToFinalImage(vector<unsigned char>& 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;

View File

@ -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<void(void)> 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<void(void)> 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; }

View File

@ -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;

View File

@ -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;

View File

@ -44,14 +44,12 @@ public:
/// Derived class constructors will complete the final part of filter setup.
/// </summary>
/// <param name="filterType">Type of the filter.</param>
/// <param name="passes">The number of passes used in the ember being rendered</param>
/// <param name="temporalSamples">The number of temporal samples in the ember being rendered</param>
/// <param name="filterWidth">The width of the filter.</param>
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.
/// </summary>
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<T> m_Deltas;//Delta vector.
vector<T> m_Filter;//Filter vector.
@ -194,12 +189,11 @@ public:
/// <summary>
/// Constructor to create an Exp filter.
/// </summary>
/// <param name="passes">The number of passes used in the ember being rendered</param>
/// <param name="temporalSamples">The number of temporal samples in the ember being rendered</param>
/// <param name="filterWidth">The width of the filter.</param>
/// <param name="filterExp">The filter exp.</param>
ExpTemporalFilter(size_t passes, size_t temporalSamples, T filterWidth, T filterExp)
: TemporalFilter<T>(BOX_TEMPORAL_FILTER, passes, temporalSamples, filterWidth)
ExpTemporalFilter(size_t temporalSamples, T filterWidth, T filterExp)
: TemporalFilter<T>(BOX_TEMPORAL_FILTER, temporalSamples, filterWidth)
{
if (Size() > 1)
{
@ -237,11 +231,10 @@ public:
/// <summary>
/// Constructor to create a Gaussian filter.
/// </summary>
/// <param name="passes">The number of passes used in the ember being rendered</param>
/// <param name="temporalSamples">The number of temporal samples in the ember being rendered</param>
/// <param name="filterWidth">The width of the filter.</param>
GaussianTemporalFilter(size_t passes, size_t temporalSamples, T filterWidth)
: TemporalFilter<T>(GAUSSIAN_TEMPORAL_FILTER, passes, temporalSamples, filterWidth)
GaussianTemporalFilter(size_t temporalSamples, T filterWidth)
: TemporalFilter<T>(GAUSSIAN_TEMPORAL_FILTER, temporalSamples, filterWidth)
{
if (Size() > 1)
{
@ -273,11 +266,10 @@ public:
/// <summary>
/// Constructor to create a Box filter.
/// </summary>
/// <param name="passes">The number of passes used in the ember being rendered</param>
/// <param name="temporalSamples">The number of temporal samples in the ember being rendered</param>
/// <param name="filterWidth">The width of the filter.</param>
BoxTemporalFilter(size_t passes, size_t temporalSamples, T filterWidth)
: TemporalFilter<T>(BOX_TEMPORAL_FILTER, passes, temporalSamples, filterWidth)
BoxTemporalFilter(size_t temporalSamples, T filterWidth)
: TemporalFilter<T>(BOX_TEMPORAL_FILTER, temporalSamples, filterWidth)
{
if (Size() > 1)
{
@ -300,23 +292,22 @@ public:
/// Creates the specified filter type based on the filterType enum parameter.
/// </summary>
/// <param name="filterType">Type of the filter</param>
/// <param name="passes">The number of passes used in the ember being rendered</param>
/// <param name="temporalSamples">The number of temporal samples in the ember being rendered</param>
/// <param name="filterWidth">The width of the filter</param>
/// <param name="filterExp">The filter exp, only used with Exp filter, otherwise ignored.</param>
/// <returns>A pointer to the newly created filter object</returns>
static TemporalFilter<T>* Create(eTemporalFilterType filterType, size_t passes, size_t temporalSamples, T filterWidth, T filterExp = 1)
static TemporalFilter<T>* Create(eTemporalFilterType filterType, size_t temporalSamples, T filterWidth, T filterExp = 1)
{
TemporalFilter<T>* filter = nullptr;
if (filterType == BOX_TEMPORAL_FILTER)
filter = new BoxTemporalFilter<T>(passes, temporalSamples, filterWidth);
filter = new BoxTemporalFilter<T>(temporalSamples, filterWidth);
else if (filterType == GAUSSIAN_TEMPORAL_FILTER)
filter = new GaussianTemporalFilter<T>(passes, temporalSamples, filterWidth);
filter = new GaussianTemporalFilter<T>(temporalSamples, filterWidth);
else if (filterType == EXP_TEMPORAL_FILTER)
filter = new ExpTemporalFilter<T>(passes, temporalSamples, filterWidth, filterExp);
filter = new ExpTemporalFilter<T>(temporalSamples, filterWidth, filterExp);
else
filter = new BoxTemporalFilter<T>(passes, temporalSamples, filterWidth);//Default to box if bad enum passed in.
filter = new BoxTemporalFilter<T>(temporalSamples, filterWidth);//Default to box if bad enum passed in.
return filter;
}

View File

@ -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.

View File

@ -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"

View File

@ -601,11 +601,10 @@ eRenderStatus RendererCL<T>::AccumulatorToFinalImage(unsigned char* pixels, size
/// needed, run on the CPU.
/// </summary>
/// <param name="iterCount">The number of iterations to run</param>
/// <param name="pass">The pass this is running for</param>
/// <param name="temporalSample">The temporal sample within the current pass this is running for</param>
/// <returns>Rendering statistics</returns>
template <typename T>
EmberStats RendererCL<T>::Iterate(size_t iterCount, size_t pass, size_t temporalSample)
EmberStats RendererCL<T>::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<T>::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<T>::BuildIterProgramForEmber(bool doAccum)
/// between quality of the final image and performance.
/// </summary>
/// <param name="iterCount">The number of iterations to run</param>
/// <param name="pass">The pass this is running for</param>
/// <param name="temporalSample">The temporal sample within the current pass this is running for</param>
/// <param name="temporalSample">The temporal sample this is running for</param>
/// <param name="itersRan">The storage for the number of iterations ran</param>
/// <returns>True if success, else false.</returns>
template <typename T>
bool RendererCL<T>::RunIter(size_t iterCount, size_t pass, size_t temporalSample, size_t& itersRan)
bool RendererCL<T>::RunIter(size_t iterCount, size_t temporalSample, size_t& itersRan)
{
Timing t;//, t2(4);
bool b = true;
@ -795,13 +793,10 @@ bool RendererCL<T>::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<T>::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();

View File

@ -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();

View File

@ -27,7 +27,6 @@ void SetDefaultTestValues(Ember<T>& 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;

View File

@ -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"

View File

@ -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"

View File

@ -52,7 +52,7 @@
</font>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Fractorium 0.4.1.3 Beta&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&gt;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.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Matt Feemster&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;&lt;br/&gt;&lt;span style=&quot; font-size:12pt;&quot;&gt;Fractorium 0.4.1.4 Beta&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&gt;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.&lt;/span&gt;&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;Matt Feemster&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>

View File

@ -356,13 +356,13 @@
<property name="minimumSize">
<size>
<width>0</width>
<height>44</height>
<height>46</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>44</height>
<height>46</height>
</size>
</property>
<property name="focusPolicy">
@ -565,13 +565,13 @@
<property name="minimumSize">
<size>
<width>0</width>
<height>198</height>
<height>200</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>198</height>
<height>200</height>
</size>
</property>
<property name="focusPolicy">

View File

@ -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);

View File

@ -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;

Binary file not shown.

View File

@ -944,13 +944,13 @@
<property name="minimumSize">
<size>
<width>0</width>
<height>140</height>
<height>117</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>140</height>
<height>117</height>
</size>
</property>
<property name="focusPolicy">
@ -1031,11 +1031,6 @@
<attribute name="verticalHeaderStretchLastSection">
<bool>false</bool>
</attribute>
<row>
<property name="text">
<string>Passes</string>
</property>
</row>
<row>
<property name="text">
<string>Temporal Samples</string>
@ -1073,7 +1068,7 @@
</column>
<item row="0" column="0">
<property name="text">
<string>Passes</string>
<string>Temporal Samples</string>
</property>
</item>
<item row="0" column="1">
@ -1083,7 +1078,7 @@
</item>
<item row="1" column="0">
<property name="text">
<string>Temporal Samples</string>
<string>Quality</string>
</property>
</item>
<item row="1" column="1">
@ -1093,7 +1088,7 @@
</item>
<item row="2" column="0">
<property name="text">
<string>Quality</string>
<string>Supersample</string>
</property>
</item>
<item row="2" column="1">
@ -1103,7 +1098,7 @@
</item>
<item row="3" column="0">
<property name="text">
<string>Supersample</string>
<string>Affine Interpolation</string>
</property>
</item>
<item row="3" column="1">
@ -1112,21 +1107,11 @@
</property>
</item>
<item row="4" column="0">
<property name="text">
<string>Affine Interpolation</string>
</property>
</item>
<item row="4" column="1">
<property name="text">
<string>0</string>
</property>
</item>
<item row="5" column="0">
<property name="text">
<string>Interpolation</string>
</property>
</item>
<item row="5" column="1">
<item row="4" column="1">
<property name="text">
<string>0</string>
</property>
@ -2835,8 +2820,8 @@ SpinBox
<rect>
<x>0</x>
<y>0</y>
<width>238</width>
<height>747</height>
<width>118</width>
<height>597</height>
</rect>
</property>
<property name="palette">

View File

@ -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;

View File

@ -85,7 +85,6 @@ void Fractorium::InitParamsUI()
//Iteration.
row = 0;
table = ui.IterationTable;
SetupSpinner<SpinBox, int> (table, this, row, 1, m_PassesSpin, spinHeight, 1, 3, 1, SIGNAL(valueChanged(int)), SLOT(OnPassesChanged(int)), true, 1, 1, 1);
SetupSpinner<SpinBox, int> (table, this, row, 1, m_TemporalSamplesSpin, spinHeight, 1, 5000, 50, SIGNAL(valueChanged(int)), SLOT(OnTemporalSamplesChanged(int)), true, 1000);
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_QualitySpin, spinHeight, 1, dmax, 50, SIGNAL(valueChanged(double)), SLOT(OnQualityChanged(double)), true, 10, 10, 10);
SetupSpinner<SpinBox, int> (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.
/// </summary>
/// <summary>
/// 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.
/// </summary>
/// <param name="d">The passes value</param>
template <typename T> void FractoriumEmberController<T>::PassesChanged(int i) { Update([&] { m_Ember.m_Passes = i; }); }
void Fractorium::OnPassesChanged(int d) { m_Controller->PassesChanged(d); }
/// <summary>
/// Set the temporal samples to be used with animation.
/// Called when the temporal samples spinner is changed.
@ -534,8 +523,7 @@ void FractoriumEmberController<T>::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<T>::ParamsToEmber(Ember<T>& 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();

View File

@ -305,7 +305,7 @@ void FractoriumEmberController<T>::SetNormalizedWeightText(Xform<T>* 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) + ")");
}
}

View File

@ -324,13 +324,13 @@ in interactive mode for each mouse movement</string>
<property name="minimumSize">
<size>
<width>0</width>
<height>66</height>
<height>68</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>66</height>
<height>68</height>
</size>
</property>
<property name="focusPolicy">
@ -507,13 +507,13 @@ in interactive mode for each mouse movement</string>
<property name="minimumSize">
<size>
<width>120</width>
<height>66</height>
<height>68</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>66</height>
<height>68</height>
</size>
</property>
<property name="focusPolicy">