0.4.1.1 Beta 08/03/2014

--Bug Fixes
Spatial filter would not be correctly recreated on subsequent runs of
differing supersample values during final render.
Fix DCBubble, Funnel, SphericalN,
Wrong logic with some usage of DO_DOUBLE. Only relevant for testing.
Use uint64 for iters/sec calculation on final render dialog. int was
overflowing on extremely fast GPU renders.

--Code Changes
Make density, spatial and temporal filters preserve the values they were
created with. This helps in determining when a new instance is needed.
Better NULL checks when copying embers and xforms.
Rename members in FractoriumEmberControllerBase.h to omit duplicating
the members declared in the base.
This commit is contained in:
mfeemster
2014-08-03 16:16:10 -07:00
parent 152318a567
commit 570d3bcf1d
21 changed files with 135 additions and 80 deletions

View File

@ -312,6 +312,7 @@ public:
inline T MinRad() const { return m_MinRad; }
inline T MaxRad() const { return m_MaxRad; }
inline T Curve() const { return m_Curve; }
inline unsigned int Supersample() const { return m_Supersample; }
inline unsigned int KernelSize() const { return m_KernelSize; }
inline unsigned int MaxFilterIndex() const { return m_MaxFilterIndex; }
inline unsigned int MaxFilteredCounts() const { return m_MaxFilteredCounts; }

View File

@ -143,9 +143,12 @@ public:
for (unsigned int i = 0; i < ember.XformCount(); i++)
{
Xform<T> xform = *ember.GetXform(i);//Will call assignment operator to convert between types T and U.
if (Xform<U>* p = ember.GetXform(i))
{
Xform<T> xform = *p;//Will call assignment operator to convert between types T and U.
AddXform(xform);
AddXform(xform);
}
}
Xform<T> finalXform = *ember.FinalXform();//Will call assignment operator to convert between types T and U.

View File

@ -25,7 +25,7 @@ namespace EmberNs
extern void sincos(double x, double *s, double *c);
#endif
#define EMBER_VERSION "0.4.1.0"
#define EMBER_VERSION "0.4.1.1"
#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

@ -263,12 +263,12 @@ bool Renderer<T, bucketT>::CreateTemporalFilter(bool& newAlloc)
newAlloc = false;
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ((m_TemporalFilter.get() == NULL) ||
(m_Ember.m_Passes != m_LastEmber.m_Passes) ||
(m_Ember.m_TemporalSamples != m_LastEmber.m_TemporalSamples) ||
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_LastEmber.m_TemporalFilterWidth) ||
(m_Ember.m_TemporalFilterExp != m_LastEmber.m_TemporalFilterExp))
(m_Ember.m_TemporalFilterWidth != m_TemporalFilter->FilterWidth()) ||
(m_Ember.m_TemporalFilterExp != m_TemporalFilter->FilterExp()))
{
m_TemporalFilter = auto_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));
@ -296,10 +296,10 @@ bool Renderer<T, bucketT>::PrepFinalAccumVector(vector<unsigned char>& pixels)
if (m_ReclaimOnResize)
{
if (pixels.size() != size)
{
pixels.resize(size);
if (m_ReclaimOnResize)
pixels.shrink_to_fit();
}
}
else
{
@ -850,11 +850,11 @@ bool Renderer<T, bucketT>::CreateDEFilter(bool& newAlloc)
if (m_Ember.m_MaxRadDE > 0)
{
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ((m_DensityFilter.get() == NULL) ||
if ((!m_DensityFilter.get()) ||
(m_Ember.m_MinRadDE != m_DensityFilter->MinRad()) ||
(m_Ember.m_MaxRadDE != m_DensityFilter->MaxRad()) ||
(m_Ember.m_CurveDE != m_DensityFilter->Curve()) ||
(m_Ember.m_Supersample != m_LastEmber.m_Supersample))
(m_Ember.m_Supersample != m_DensityFilter->Supersample()))
{
m_DensityFilter = auto_ptr<DensityFilter<T>>(new DensityFilter<T>(m_Ember.m_MinRadDE, m_Ember.m_MaxRadDE, m_Ember.m_CurveDE, m_Ember.m_Supersample));
newAlloc = true;
@ -889,10 +889,10 @@ bool Renderer<T, bucketT>::CreateSpatialFilter(bool& newAlloc)
newAlloc = false;
//Use intelligent testing so it isn't created every time a new ember is passed in.
if ((m_SpatialFilter.get() == NULL) ||
if ((!m_SpatialFilter.get()) ||
(m_Ember.m_SpatialFilterType != m_SpatialFilter->FilterType()) ||
(m_Ember.m_SpatialFilterRadius != m_SpatialFilter->FilterRadius()) ||
(m_Ember.m_Supersample != m_LastEmber.m_Supersample) ||
(m_Ember.m_Supersample != m_SpatialFilter->Supersample()) ||
(m_PixelAspectRatio != m_SpatialFilter->PixelAspectRatio()))
{
m_SpatialFilter = auto_ptr<SpatialFilter<T>>(
@ -1007,7 +1007,7 @@ void Renderer<T, bucketT>::ThreadCount(unsigned int threads, const char* seedStr
#ifdef ISAAC_FLAM3_DEBUG
QTIsaac<ISAAC_SIZE, ISAAC_INT> isaac(0, 0, 0, seeds);
#else
QTIsaac<ISAAC_SIZE, ISAAC_INT> isaac(newSize, newSize * newSize, newSize * newSize * newSize, seeds);
QTIsaac<ISAAC_SIZE, ISAAC_INT> isaac(newSize, newSize * 2, newSize * 3, seeds);
#endif
m_Rand.push_back(isaac);

View File

@ -40,9 +40,13 @@ public:
{
unsigned int i, steps = passes * temporalSamples;
m_Passes = passes;
m_TemporalSamples = temporalSamples;
m_FilterWidth = filterWidth;
m_Deltas.resize(steps);
m_Filter.resize(steps);
m_FilterType = filterType;
m_FilterExp = 1;
if (steps == 1)
{
@ -83,6 +87,10 @@ public:
{
if (this != &filter)
{
m_Passes = filter.m_Passes;
m_TemporalSamples = filter.m_TemporalSamples;
m_FilterWidth = filter.m_FilterWidth;
m_FilterExp = filter.m_FilterExp;
m_SumFilt = filter.m_SumFilt;
m_Deltas = filter.m_Deltas;
m_Filter = filter.m_Filter;
@ -127,6 +135,10 @@ public:
/// Accessors.
/// </summary>
size_t Size() const { return m_Filter.size(); }
unsigned int Passes() const { return m_Passes; }
unsigned int TemporalSamples() const { return m_TemporalSamples; }
T FilterWidth() const { return m_FilterWidth; }
T FilterExp() const { return m_FilterExp; }
T SumFilt() const { return m_SumFilt; }
T* Deltas() { return &m_Deltas[0]; }
T* Filter() { return &m_Filter[0]; }
@ -151,6 +163,10 @@ protected:
}
T m_SumFilt;//The sum of all filter values.
T m_FilterWidth;
T m_FilterExp;
unsigned int m_Passes;
unsigned int m_TemporalSamples;
vector<T> m_Deltas;//Delta vector.
vector<T> m_Filter;//Filter vector.
eTemporalFilterType m_FilterType;//The type of filter this is.
@ -192,6 +208,7 @@ public:
maxFilt = m_Filter[i];
}
m_FilterExp = filterExp;
FinishFilter(maxFilt);
}
}

View File

@ -20,7 +20,7 @@ public:
void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
T temp = 1 / cos(helper.In.y) + m_Effect * T(M_PI);
T temp = 1 / Zeps(cos(helper.In.y)) + m_Effect * T(M_PI);
helper.Out.x = m_Weight * (tanh(helper.In.x) * temp);
helper.Out.y = m_Weight * (tanh(helper.In.y) * temp);
@ -36,7 +36,7 @@ public:
string effect = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t temp = 1 / cos(vIn.y) + " << effect << " * M_PI;\n"
<< "\t\treal_t temp = 1 / Zeps(cos(vIn.y)) + " << effect << " * M_PI;\n"
<< "\n"
<< "\t\tvOut.x = xform->m_VariationWeights[" << varIndex << "] * (tanh(vIn.x) * temp);\n"
<< "\t\tvOut.y = xform->m_VariationWeights[" << varIndex << "] * (tanh(vIn.y) * temp);\n"
@ -276,11 +276,9 @@ public:
void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
T r = pow(helper.m_PrecalcSqrtSumSquares, m_Dist);
T r = Zeps(pow(helper.m_PrecalcSqrtSumSquares, m_Dist));
int n = Floor<T>(m_Power * rand.Frand01<T>());
T alpha = helper.m_PrecalcAtanyx + n * M_2PI / Floor<T>(m_Power);
//int n = (int)floor(m_Power * rand.Frand01<T>());
//T alpha = helper.m_PrecalcAtanyx + n * M_2PI / floor(m_Power);
T alpha = helper.m_PrecalcAtanyx + n * M_2PI / Zeps<T>((T)Floor<T>(m_Power));
T sina = sin(alpha);
T cosa = cos(alpha);
@ -299,9 +297,9 @@ public:
string dist = "parVars[" + ToUpper(m_Params[i++].Name()) + index;
ss << "\t{\n"
<< "\t\treal_t r = pow(precalcSqrtSumSquares, " << dist << ");\n"
<< "\t\treal_t r = Zeps(pow(precalcSqrtSumSquares, " << dist << "));\n"
<< "\t\tint n = floor(" << power << " * MwcNext01(mwc));\n"
<< "\t\treal_t alpha = precalcAtanyx + n * M_2PI / floor(" << power << ");\n"
<< "\t\treal_t alpha = precalcAtanyx + n * M_2PI / Zeps(floor(" << power << "));\n"
<< "\t\treal_t sina = sin(alpha);\n"
<< "\t\treal_t cosa = cos(alpha);\n"
<< "\n"

View File

@ -23,7 +23,7 @@ public:
void Func(IteratorHelper<T>& helper, Point<T>& outPoint, QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand)
{
T r = helper.m_PrecalcSumSquares;
T r4_1 = r / 4 + 1;
T r4_1 = Zeps(r / 4 + 1);
r4_1 = m_Weight / r4_1;
helper.Out.x = r4_1 * helper.In.x;
@ -49,7 +49,7 @@ public:
ss << "\t{\n"
<< "\t\treal_t r = precalcSumSquares;\n"
<< "\t\treal_t r4_1 = r / 4 + 1;\n"
<< "\t\treal_t r4_1 = Zeps(r / 4 + 1);\n"
<< "\t\tr4_1 = xform->m_VariationWeights[" << varIndex << "] / r4_1;\n"
<< "\n"
<< "\t\tvOut.x = r4_1 * vIn.x;\n"

View File

@ -171,9 +171,12 @@ public:
for (unsigned int i = 0; i < xform.TotalVariationCount(); i++)
{
Variation<T>* var = NULL;
xform.GetVariation(i)->Copy(var);//Will convert from type U to type T.
AddVariation(var);//Will internally call SetPrecalcFlags().
if (Variation<U>* varOrig = xform.GetVariation(i))
{
varOrig->Copy(var);//Will convert from type U to type T.
AddVariation(var);//Will internally call SetPrecalcFlags().
}
}
if (TotalVariationCount() == 0)