--Code changes

-Bump to version 1.0.0.3
 -Remove all code for opacity adjustment, it's no longer needed.
 -Small optimization on accumulating to the histogram on the CPU.
This commit is contained in:
Person
2017-03-27 18:05:06 -07:00
parent 71abee0396
commit dea12ee96a
19 changed files with 81 additions and 96 deletions

View File

@ -37,7 +37,7 @@ static void sincos(float x, float* s, float* c)
namespace EmberNs
{
#define EMBER_VERSION "1.0.0.2"
#define EMBER_VERSION "1.0.0.3"
#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

@ -213,7 +213,7 @@ protected:
firstBadPoint.m_Y = rand.Frand11<T>();
firstBadPoint.m_Z = 0;
firstBadPoint.m_ColorX = point->m_ColorX;
firstBadPoint.m_VizAdjusted = point->m_VizAdjusted;
firstBadPoint.m_Opacity = point->m_Opacity;
xformIndex = NextXformFromIndex(rand.Rand());
if (!xforms[xformIndex].Apply(&firstBadPoint, point, rand))
@ -245,9 +245,9 @@ protected:
{
if (IsClose<T>(ember.FinalXform()->m_Opacity, 1) || rand.Frand01<T>() < ember.FinalXform()->m_Opacity)
{
T tempVizAdjusted = tempPoint.m_VizAdjusted;
T tempOpacity = tempPoint.m_Opacity;
ember.NonConstFinalXform()->Apply(&tempPoint, sample, rand);
sample->m_VizAdjusted = tempVizAdjusted;
sample->m_Opacity = tempOpacity;
}
else
{
@ -433,7 +433,7 @@ public:
firstBadPoint.m_Y = rand.Frand11<T>();
firstBadPoint.m_Z = 0;
firstBadPoint.m_ColorX = point->m_ColorX;
firstBadPoint.m_VizAdjusted = point->m_VizAdjusted;
firstBadPoint.m_Opacity = point->m_Opacity;
xformIndex = NextXformFromIndex(rand.Rand(), lastXformUsed);
if (!xforms[xformIndex].Apply(&firstBadPoint, point, rand))

View File

@ -72,7 +72,7 @@ public:
m_Z = point.m_Z;
m_ColorX = point.m_ColorX;
//m_ColorY = point.m_ColorY;
m_VizAdjusted = point.m_VizAdjusted;
m_Opacity = point.m_Opacity;
return *this;
}
@ -82,7 +82,7 @@ public:
T m_Z = 0;
T m_ColorX = 0;
//T m_ColorY;
T m_VizAdjusted = 1;
T m_Opacity = 1;
};
/// <summary>

View File

@ -1516,21 +1516,21 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
{
Point<T> p(samples[i]);//Slightly faster to cache this.
if (Rotate() != 0)
if (p.m_Opacity != 0)
{
T p00 = p.m_X - CenterX();
T p11 = p.m_Y - m_Ember.m_RotCenterY;
p.m_X = (p00 * m_RotMat.A()) + (p11 * m_RotMat.B()) + CenterX();
p.m_Y = (p00 * m_RotMat.D()) + (p11 * m_RotMat.E()) + m_Ember.m_RotCenterY;
}
if (Rotate() != 0)
{
T p00 = p.m_X - CenterX();
T p11 = p.m_Y - m_Ember.m_RotCenterY;
p.m_X = (p00 * m_RotMat.A()) + (p11 * m_RotMat.B()) + CenterX();
p.m_Y = (p00 * m_RotMat.D()) + (p11 * m_RotMat.E()) + m_Ember.m_RotCenterY;
}
//Checking this first before converting gives better performance than converting and checking a single value, which the original did.
//Second, an interesting optimization observation is that when keeping the bounds vars within m_CarToRas and calling its InBounds() member function,
//rather than here as members, about a 7% speedup is achieved. This is possibly due to the fact that data from m_CarToRas is accessed
//right after the call to Convert(), so some caching efficiencies get realized.
if (m_CarToRas.InBounds(p))
{
if (p.m_VizAdjusted != 0)
//Checking this first before converting gives better performance than converting and checking a single value, which the original did.
//Second, an interesting optimization observation is that when keeping the bounds vars within m_CarToRas and calling its InBounds() member function,
//rather than here as members, about a 7% speedup is achieved. This is possibly due to the fact that data from m_CarToRas is accessed
//right after the call to Convert(), so some caching efficiencies get realized.
if (m_CarToRas.InBounds(p))
{
m_CarToRas.Convert(p, histIndex);
@ -1563,7 +1563,7 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
auto cifm1 = bucketT(1) - colorIndexFrac;
//Loops are unrolled to allow auto vectorization.
if (p.m_VizAdjusted == 1)
if (p.m_Opacity == 1)
{
hist[0] += (pal[0] * cifm1) + (pal2[0] * colorIndexFrac);
hist[1] += (pal[1] * cifm1) + (pal2[1] * colorIndexFrac);
@ -1572,7 +1572,7 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
}
else
{
auto va = bucketT(p.m_VizAdjusted);
auto va = bucketT(p.m_Opacity);
hist[0] += ((pal[0] * cifm1) + (pal2[0] * colorIndexFrac)) * va;
hist[1] += ((pal[1] * cifm1) + (pal2[1] * colorIndexFrac)) * va;
hist[2] += ((pal[2] * cifm1) + (pal2[2] * colorIndexFrac)) * va;
@ -1589,17 +1589,17 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
{
Point<T> p(samples[i]);//Slightly faster to cache this.
if (Rotate() != 0)
if (p.m_Opacity != 0)
{
T p00 = p.m_X - CenterX();
T p11 = p.m_Y - m_Ember.m_RotCenterY;
p.m_X = (p00 * m_RotMat.A()) + (p11 * m_RotMat.B()) + CenterX();
p.m_Y = (p00 * m_RotMat.D()) + (p11 * m_RotMat.E()) + m_Ember.m_RotCenterY;
}
if (Rotate() != 0)
{
T p00 = p.m_X - CenterX();
T p11 = p.m_Y - m_Ember.m_RotCenterY;
p.m_X = (p00 * m_RotMat.A()) + (p11 * m_RotMat.B()) + CenterX();
p.m_Y = (p00 * m_RotMat.D()) + (p11 * m_RotMat.E()) + m_Ember.m_RotCenterY;
}
if (m_CarToRas.InBounds(p))
{
if (p.m_VizAdjusted != 0)
if (m_CarToRas.InBounds(p))
{
m_CarToRas.Convert(p, histIndex);
@ -1609,7 +1609,7 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
bucketT* __restrict hist = glm::value_ptr(m_HistBuckets[histIndex]);//Vectorizer can't tell these point to different locations.
const bucketT* __restrict pal = glm::value_ptr(palette->m_Entries[intColorIndex]);
if (p.m_VizAdjusted == 1)
if (p.m_Opacity == 1)
{
hist[0] += pal[0];
hist[1] += pal[1];
@ -1618,7 +1618,7 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
}
else
{
auto va = bucketT(p.m_VizAdjusted);
auto va = bucketT(p.m_Opacity);
hist[0] += pal[0] * va;
hist[1] += pal[1] * va;
hist[2] += pal[2] * va;

View File

@ -474,7 +474,7 @@ public:
m_ParentEmber = nullptr;
m_ColorSpeedCache = 0;
m_OneMinusColorCache = 0;
m_VizAdjusted = 0;
m_Opacity = 0;
m_Animate = 0;
m_Wind[0] = 0;
m_Wind[1] = 0;
@ -482,7 +482,7 @@ public:
}
/// <summary>
/// Compute color cache values: color speed, one minus color speed and adjusted visibility.
/// Compute color cache values: color speed and one minus color speed.
/// </summary>
void CacheColorVals()
{
@ -491,7 +491,6 @@ public:
//m_OneMinusColorCache = (1 + m_ColorSpeed) / 2;
m_ColorSpeedCache = m_ColorSpeed * m_ColorX;//Flam3 style.
m_OneMinusColorCache = T(1.0) - m_ColorSpeed;
m_VizAdjusted = AdjustOpacityPercentage(m_Opacity);
}
/// <summary>
@ -598,7 +597,7 @@ public:
//to the histogram. Calculate this value by interpolating between the index value of the
//last iteration with the one specified in this xform. Note that some cached values are used
//to reduce the amount of processing.
outPoint->m_VizAdjusted = m_VizAdjusted;
outPoint->m_Opacity = m_Opacity;
iterHelper.m_Color.x = outPoint->m_ColorX = m_ColorSpeedCache + (m_OneMinusColorCache * inPoint->m_ColorX);
if (m_HasPreOrRegularVars)
@ -788,7 +787,6 @@ public:
size_t PostVariationCount() const { return m_PostVariations.size(); }
size_t TotalVariationCount() const { return PreVariationCount() + VariationCount() + PostVariationCount(); }
bool Empty() const { return TotalVariationCount() == 0 && m_Affine.IsID(); }//Use this instead of padding like the original did.
T VizAdjusted() const { return m_VizAdjusted; }
T ColorSpeedCache() const { return m_ColorSpeedCache; }
T OneMinusColorCache() const { return m_OneMinusColorCache; }
const vector<T>& XaosVec() const { return m_Xaos; }
@ -1133,7 +1131,6 @@ public:
ss << "\nColor Speed: " << m_ColorSpeed;
ss << "\nAnimate: " << m_Animate;
ss << "\nOpacity: " << m_Opacity;
ss << "\nViz Adjusted: " << m_VizAdjusted;
ss << "\nWind: " << m_Wind[0] << ", " << m_Wind[1];
ss << "\nMotion Frequency: " << m_MotionFreq;
ss << "\nMotion Func: " << m_MotionFunc;
@ -1165,7 +1162,6 @@ public:
private:
bool m_HasPreOrRegularVars;//Whethere there are any pre or regular variations present.
T m_VizAdjusted;//Adjusted visibility for better transitions.
public:
//Color coordinates for this function. This is the index into the palette used to look up a color and add to the histogram for each iter.
@ -1237,20 +1233,6 @@ private:
func(m_PostVariations, keepGoing);
}
/// <summary>
/// Adjust opacity.
/// </summary>
/// <param name="in">The opacity to adjust, range 0-1.</param>
/// <returns>The adjusted opacity</returns>
static T AdjustOpacityPercentage(T in)
{
return in;
/* if (in == 0)
return 0;
else
return std::pow(T(10.0), -std::log(T(1.0) / T(in)) / std::log(T(2)));*/
}
vector<T> m_Xaos;//Xaos vector which affects the probability that this xform is chosen. Usually empty.
Ember<T>* m_ParentEmber;//The parent ember that contains this xform.
bool m_NeedPrecalcSumSquares;//Whether any variation uses the precalc sum squares value in its calculations.

View File

@ -168,7 +168,6 @@ struct ALIGN XformCL
T m_ColorSpeedCache;//88 (176)
T m_OneMinusColorCache;//92 (184)
T m_Opacity;//96 (192)
T m_VizAdjusted;//100 (200)
};
/// <summary>
@ -184,7 +183,6 @@ static const char* XformCLStructString =
" real_t m_ColorSpeedCache;\n"
" real_t m_OneMinusColorCache;\n"
" real_t m_Opacity;\n"
" real_t m_VizAdjusted;\n"
"} XformCL;\n"
"\n";

View File

@ -490,15 +490,15 @@ string IterOpenCLKernelCreator<T>::CreateIterKernelString(const Ember<T>& ember,
if (lockAccum)
{
os <<
" AtomicAdd(&(histogram[histIndex].m_Reals[0]), palColor1.x * (real_bucket_t)xforms[secondPoint.m_LastXfUsed].m_VizAdjusted);\n"//Always apply opacity, even though it's usually 1.
" AtomicAdd(&(histogram[histIndex].m_Reals[1]), palColor1.y * (real_bucket_t)xforms[secondPoint.m_LastXfUsed].m_VizAdjusted);\n"
" AtomicAdd(&(histogram[histIndex].m_Reals[2]), palColor1.z * (real_bucket_t)xforms[secondPoint.m_LastXfUsed].m_VizAdjusted);\n"
" AtomicAdd(&(histogram[histIndex].m_Reals[3]), palColor1.w * (real_bucket_t)xforms[secondPoint.m_LastXfUsed].m_VizAdjusted);\n";
" AtomicAdd(&(histogram[histIndex].m_Reals[0]), palColor1.x * (real_bucket_t)xforms[secondPoint.m_LastXfUsed].m_Opacity);\n"//Always apply opacity, even though it's usually 1.
" AtomicAdd(&(histogram[histIndex].m_Reals[1]), palColor1.y * (real_bucket_t)xforms[secondPoint.m_LastXfUsed].m_Opacity);\n"
" AtomicAdd(&(histogram[histIndex].m_Reals[2]), palColor1.z * (real_bucket_t)xforms[secondPoint.m_LastXfUsed].m_Opacity);\n"
" AtomicAdd(&(histogram[histIndex].m_Reals[3]), palColor1.w * (real_bucket_t)xforms[secondPoint.m_LastXfUsed].m_Opacity);\n";
}
else
{
os <<
" histogram[histIndex].m_Real4 += (palColor1 * (real_bucket_t)xforms[secondPoint.m_LastXfUsed].m_VizAdjusted);\n";//real_bucket_t should always be float.
" histogram[histIndex].m_Real4 += (palColor1 * (real_bucket_t)xforms[secondPoint.m_LastXfUsed].m_Opacity);\n";//real_bucket_t should always be float.
}
os <<

View File

@ -1781,7 +1781,6 @@ void RendererCL<T, bucketT>::ConvertEmber(Ember<T>& ember, EmberCL<T>& emberCL,
xformsCL[i].m_ColorSpeedCache = xform->ColorSpeedCache();
xformsCL[i].m_OneMinusColorCache = xform->OneMinusColorCache();
xformsCL[i].m_Opacity = xform->m_Opacity;
xformsCL[i].m_VizAdjusted = xform->VizAdjusted();
for (size_t varIndex = 0; varIndex < xform->TotalVariationCount() && varIndex < MAX_CL_VARS; varIndex++)//Assign all variation weights for this xform, with a max of MAX_CL_VARS.
xformsCL[i].m_VariationWeights[varIndex] = xform->GetVariation(varIndex)->m_Weight;

View File

@ -1140,7 +1140,7 @@ void TestXformsInOutPoints()
orig.m_Y = rand.Frand11<float>();
orig.m_Z = rand.Frand11<float>();
orig.m_ColorX = rand.Frand01<float>();
orig.m_VizAdjusted = rand.Frand01<float>();
orig.m_Opacity = rand.Frand01<float>();
Point<float> p1 = orig, p2 = orig, p3;
xforms[i].Apply(&p1, &p1, rand);
xforms[i].Apply(&p2, &p3, rand);
@ -1148,12 +1148,12 @@ void TestXformsInOutPoints()
badVals |= (p1.m_Y != p1.m_Y);
badVals |= (p1.m_Z != p1.m_Z);
badVals |= (p1.m_ColorX != p1.m_ColorX);
badVals |= (p1.m_VizAdjusted != p1.m_VizAdjusted);
badVals |= (p1.m_Opacity != p1.m_Opacity);
badVals |= (p3.m_X != p3.m_X);
badVals |= (p3.m_Y != p3.m_Y);
badVals |= (p3.m_Z != p3.m_Z);
badVals |= (p3.m_ColorX != p3.m_ColorX);
badVals |= (p3.m_VizAdjusted != p3.m_VizAdjusted);
badVals |= (p3.m_Opacity != p3.m_Opacity);
if (badVals)
cout << "Variation " << regVar->Name() << ": Bad value detected" << endl;
@ -1172,8 +1172,8 @@ void TestXformsInOutPoints()
if (p1.m_ColorX != p3.m_ColorX)
cout << "Variation " << regVar->Name() << ": p1.m_ColorX " << p1.m_ColorX << " != p3.m_ColorX " << p3.m_ColorX << endl;
if (p1.m_VizAdjusted != p3.m_VizAdjusted)
cout << "Variation " << regVar->Name() << ": p1.m_VizAdjusted " << p1.m_VizAdjusted << " != p3.m_VizAdjusted " << p3.m_VizAdjusted << endl;
if (p1.m_Opacity != p3.m_Opacity)
cout << "Variation " << regVar->Name() << ": p1.m_Opacity " << p1.m_Opacity << " != p3.m_Opacity " << p3.m_Opacity << endl;
}
}
}
@ -1221,7 +1221,7 @@ void TestVarTime()
helper.In.y = helper.m_TransY = (xform.m_Affine.D() * p.m_X) + (xform.m_Affine.E() * p.m_Y) + xform.m_Affine.F();
helper.In.z = helper.m_TransZ = p.m_Z;
helper.m_Color.x = p.m_ColorX = rand.Frand01<T>();
p.m_VizAdjusted = rand.Frand01<T>();
p.m_Opacity = rand.Frand01<T>();
helper.m_PrecalcSumSquares = SQR(helper.m_TransX) + SQR(helper.m_TransY);
helper.m_PrecalcSqrtSumSquares = sqrt(helper.m_PrecalcSumSquares);
helper.m_PrecalcSina = helper.m_TransX / helper.m_PrecalcSqrtSumSquares;
@ -1346,7 +1346,7 @@ void TestVarsSimilar()
helper.In.y = helper.m_TransY = (xform.m_Affine.D() * p.m_X) + (xform.m_Affine.E() * p.m_Y) + xform.m_Affine.F();
helper.In.z = helper.m_TransZ = p.m_Z;
helper.m_Color.x = p.m_ColorX = rand.Frand01<T>();
p.m_VizAdjusted = rand.Frand01<T>();
p.m_Opacity = rand.Frand01<T>();
pComp = p;
helper.m_PrecalcSumSquares = SQR(helper.m_TransX) + SQR(helper.m_TransY);
helper.m_PrecalcSqrtSumSquares = sqrt(helper.m_PrecalcSumSquares);
@ -1501,7 +1501,7 @@ void TestCpuGpuResults(size_t platform, size_t device)
p.m_Y = rand.Frand<T>(-5, 5);
p.m_Z = rand.Frand<T>(-5, 5);
p.m_ColorX = rand.Frand01<T>();
p.m_VizAdjusted = rand.Frand01<T>();
p.m_Opacity = rand.Frand01<T>();
varCopy->Random(rand);
xform.AddVariation(varCopy);
ember.AddXform(xform);
@ -1579,7 +1579,7 @@ void TestGpuVectorRead(size_t platform, size_t device)
p.m_Y = rand.Frand<T>(-5, 5);
p.m_Z = rand.Frand<T>(-5, 5);
p.m_ColorX = rand.Frand01<T>();
p.m_VizAdjusted = rand.Frand01<T>();
p.m_Opacity = rand.Frand01<T>();
varCopy->Random(rand);
xform.AddVariation(varCopy);
ember.AddXform(xform);

View File

@ -58,7 +58,7 @@
<enum>QFrame::NoFrame</enum>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p align=&quot;center&quot;&gt;Fractorium 1.0.0.2&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&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;a href=&quot;http://fractorium.com&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;fractorium.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&gt;Lead: Matt Feemster&lt;br/&gt;Contributors: Simon Detheridge, Michel Mastriani&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;Fractorium 1.0.0.3&lt;/p&gt;&lt;p align=&quot;center&quot;&gt;&lt;span style=&quot; font-size:10pt;&quot;&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;a href=&quot;http://fractorium.com&quot;&gt;&lt;span style=&quot; text-decoration: underline; color:#0000ff;&quot;&gt;fractorium.com&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot; font-size:10pt;&quot;&gt;&lt;br/&gt;Lead: Matt Feemster&lt;br/&gt;Contributors: Simon Detheridge, Michel Mastriani&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="textFormat">
<enum>Qt::RichText</enum>

View File

@ -471,10 +471,13 @@ void Fractorium::OnTemporalFilterTypeComboCurrentIndexChanged(const QString& tex
template <typename T>
void FractoriumEmberController<T>::DEFilterMinRadiusWidthChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
if (m_Ember.m_MinRadDE != d)
{
ember.m_MinRadDE = d;
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
UpdateAll([&](Ember<T>& ember)
{
ember.m_MinRadDE = d;
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
}
}
void Fractorium::OnDEFilterMinRadiusWidthChanged(double d)
@ -491,10 +494,13 @@ void Fractorium::OnDEFilterMinRadiusWidthChanged(double d)
template <typename T>
void FractoriumEmberController<T>::DEFilterMaxRadiusWidthChanged(double d)
{
UpdateAll([&](Ember<T>& ember)
if (m_Ember.m_MaxRadDE != d)
{
ember.m_MaxRadDE = d;
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
UpdateAll([&](Ember<T>& ember)
{
ember.m_MaxRadDE = d;
}, true, eProcessAction::FILTER_AND_ACCUM, m_Fractorium->ApplyAll());
}
}
void Fractorium::OnDEFilterMaxRadiusWidthChanged(double d)