mirror of
https://bitbucket.org/mfeemster/fractorium.git
synced 2025-02-01 10:30:08 -05:00
--User changes
-Clear all color curves when clicking Reset while holding down Ctrl. --Code changes -No longer assume palettes are 256 elements. Can now read and write longer palettes. -Ensure OpenCL images always get written when created.
This commit is contained in:
parent
5209ead086
commit
77515aae73
@ -53,7 +53,6 @@ namespace EmberNs
|
|||||||
#define SQRT5 T(2.2360679774997896964091736687313)
|
#define SQRT5 T(2.2360679774997896964091736687313)
|
||||||
#define M_PHI T(1.61803398874989484820458683436563)
|
#define M_PHI T(1.61803398874989484820458683436563)
|
||||||
#define COLORMAP_LENGTH 256//These will need to change if 2D palette support is ever added, or variable sized palettes.
|
#define COLORMAP_LENGTH 256//These will need to change if 2D palette support is ever added, or variable sized palettes.
|
||||||
#define COLORMAP_LENGTH_MINUS_1 255
|
|
||||||
#define WHITE 255
|
#define WHITE 255
|
||||||
#define DEFAULT_SBS (1024 * 10)
|
#define DEFAULT_SBS (1024 * 10)
|
||||||
//#define XC(c) ((const xmlChar*)(c))
|
//#define XC(c) ((const xmlChar*)(c))
|
||||||
|
@ -259,7 +259,7 @@ string EmberToXml<T>::ToString(Ember<T>& ember, const string& extraAttributes, s
|
|||||||
//less error prone to just embed the palette.
|
//less error prone to just embed the palette.
|
||||||
if (hexPalette)
|
if (hexPalette)
|
||||||
{
|
{
|
||||||
os << " <palette count=\"256\" format=\"RGB\"";
|
os << " <palette count=\"" << ember.m_Palette.Size() << "\" format=\"RGB\"";
|
||||||
|
|
||||||
if (!ember.m_Palette.m_SourceColors.empty())
|
if (!ember.m_Palette.m_SourceColors.empty())
|
||||||
{
|
{
|
||||||
@ -279,8 +279,9 @@ string EmberToXml<T>::ToString(Ember<T>& ember, const string& extraAttributes, s
|
|||||||
|
|
||||||
os << ">\n";
|
os << ">\n";
|
||||||
os << std::uppercase;
|
os << std::uppercase;
|
||||||
|
auto rows = ember.m_Palette.Size() / 8;
|
||||||
|
|
||||||
for (i = 0; i < 32; i++)
|
for (i = 0; i < rows; i++)
|
||||||
{
|
{
|
||||||
os << " ";
|
os << " ";
|
||||||
|
|
||||||
@ -300,7 +301,7 @@ string EmberToXml<T>::ToString(Ember<T>& ember, const string& extraAttributes, s
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (i = 0; i < 256; i++)
|
for (i = 0; i < ember.m_Palette.Size(); i++)
|
||||||
{
|
{
|
||||||
double r = ember.m_Palette[i][0] * 255;
|
double r = ember.m_Palette[i][0] * 255;
|
||||||
double g = ember.m_Palette[i][1] * 255;
|
double g = ember.m_Palette[i][1] * 255;
|
||||||
|
@ -246,7 +246,7 @@ public:
|
|||||||
|
|
||||||
for (size_t i = 0; i < Size(); i++)
|
for (size_t i = 0; i < Size(); i++)
|
||||||
{
|
{
|
||||||
size_t ii = (i * 256) / COLORMAP_LENGTH;
|
size_t ii = (i * Size()) / Size();
|
||||||
T rgb[3], hsv[3];
|
T rgb[3], hsv[3];
|
||||||
rgb[0] = m_Entries[ii].r;
|
rgb[0] = m_Entries[ii].r;
|
||||||
rgb[1] = m_Entries[ii].g;
|
rgb[1] = m_Entries[ii].g;
|
||||||
@ -279,6 +279,7 @@ public:
|
|||||||
void MakeAdjustedPalette(Palette<T>& palette, int rot, T hue, T sat, T bright, T cont, uint blur, uint freq)
|
void MakeAdjustedPalette(Palette<T>& palette, int rot, T hue, T sat, T bright, T cont, uint blur, uint freq)
|
||||||
{
|
{
|
||||||
T rgb[3], hsv[3];
|
T rgb[3], hsv[3];
|
||||||
|
palette.m_Entries.resize(Size());
|
||||||
|
|
||||||
if (freq > 1)
|
if (freq > 1)
|
||||||
{
|
{
|
||||||
@ -306,13 +307,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto tempPal = palette;
|
auto tempPal = palette;
|
||||||
|
intmax_t iSize = intmax_t(Size());
|
||||||
|
|
||||||
for (size_t i = 0; i < Size(); i++)
|
for (intmax_t i = 0; i < iSize; i++)
|
||||||
{
|
{
|
||||||
int ii = int(i);
|
rgb[0] = tempPal[std::abs(iSize + i - rot) % iSize].r;//Rotation.
|
||||||
rgb[0] = tempPal[std::abs(COLORMAP_LENGTH + ii - rot) % COLORMAP_LENGTH].r;//Rotation.
|
rgb[1] = tempPal[std::abs(iSize + i - rot) % iSize].g;
|
||||||
rgb[1] = tempPal[std::abs(COLORMAP_LENGTH + ii - rot) % COLORMAP_LENGTH].g;
|
rgb[2] = tempPal[std::abs(iSize + i - rot) % iSize].b;
|
||||||
rgb[2] = tempPal[std::abs(COLORMAP_LENGTH + ii - rot) % COLORMAP_LENGTH].b;
|
|
||||||
RgbToHsv(rgb, hsv);
|
RgbToHsv(rgb, hsv);
|
||||||
hsv[0] += hue * T(6.0);//Hue.
|
hsv[0] += hue * T(6.0);//Hue.
|
||||||
hsv[1] = Clamp<T>(hsv[1] + sat, 0, 1);//Saturation.
|
hsv[1] = Clamp<T>(hsv[1] + sat, 0, 1);//Saturation.
|
||||||
@ -335,7 +336,7 @@ public:
|
|||||||
{
|
{
|
||||||
tempPal = palette;
|
tempPal = palette;
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 0; i < iSize; i++)
|
||||||
{
|
{
|
||||||
int n = -1;
|
int n = -1;
|
||||||
rgb[0] = 0;
|
rgb[0] = 0;
|
||||||
@ -345,7 +346,7 @@ public:
|
|||||||
for (int j = i - int(blur); j <= i + int(blur); j++)
|
for (int j = i - int(blur); j <= i + int(blur); j++)
|
||||||
{
|
{
|
||||||
n++;
|
n++;
|
||||||
int k = (256 + j) % 256;
|
auto k = (iSize + j) % iSize;
|
||||||
|
|
||||||
if (k != i)
|
if (k != i)
|
||||||
{
|
{
|
||||||
|
@ -1497,6 +1497,7 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
|
|||||||
{
|
{
|
||||||
size_t histIndex, intColorIndex, histSize = m_HistBuckets.size();
|
size_t histIndex, intColorIndex, histSize = m_HistBuckets.size();
|
||||||
bucketT colorIndex, colorIndexFrac;
|
bucketT colorIndex, colorIndexFrac;
|
||||||
|
auto psm1 = m_Ember.m_Palette.Size() - 1;
|
||||||
|
|
||||||
//Linear is a linear scale for when the color index is not a whole number, which is most of the time.
|
//Linear is a linear scale for when the color index is not a whole number, which is most of the time.
|
||||||
//It uses a portion of the value of the index, and the remainder of the next index.
|
//It uses a portion of the value of the index, and the remainder of the next index.
|
||||||
@ -1506,6 +1507,8 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
|
|||||||
//Use overloaded addition and multiplication operators in vec4 to perform the accumulation.
|
//Use overloaded addition and multiplication operators in vec4 to perform the accumulation.
|
||||||
if (PaletteMode() == ePaletteMode::PALETTE_LINEAR)
|
if (PaletteMode() == ePaletteMode::PALETTE_LINEAR)
|
||||||
{
|
{
|
||||||
|
auto psm2 = psm1 - 1;
|
||||||
|
|
||||||
//It's critical to understand what's going on here as it's one of the most important parts of the algorithm.
|
//It's critical to understand what's going on here as it's one of the most important parts of the algorithm.
|
||||||
//A color value gets retrieved from the palette and
|
//A color value gets retrieved from the palette and
|
||||||
//its RGB values are added to the existing RGB values in the histogram bucket.
|
//its RGB values are added to the existing RGB values in the histogram bucket.
|
||||||
@ -1542,7 +1545,7 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
|
|||||||
//This will result in a few points at the very edges getting discarded, but prevents a crash and doesn't seem to make a speed difference.
|
//This will result in a few points at the very edges getting discarded, but prevents a crash and doesn't seem to make a speed difference.
|
||||||
if (histIndex < histSize)
|
if (histIndex < histSize)
|
||||||
{
|
{
|
||||||
colorIndex = bucketT(p.m_ColorX) * COLORMAP_LENGTH_MINUS_1;
|
colorIndex = bucketT(p.m_ColorX) * psm1;
|
||||||
intColorIndex = size_t(colorIndex);
|
intColorIndex = size_t(colorIndex);
|
||||||
|
|
||||||
if (intColorIndex < 0)
|
if (intColorIndex < 0)
|
||||||
@ -1550,9 +1553,9 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
|
|||||||
intColorIndex = 0;
|
intColorIndex = 0;
|
||||||
colorIndexFrac = 0;
|
colorIndexFrac = 0;
|
||||||
}
|
}
|
||||||
else if (intColorIndex >= COLORMAP_LENGTH_MINUS_1)
|
else if (intColorIndex >= psm1)
|
||||||
{
|
{
|
||||||
intColorIndex = COLORMAP_LENGTH_MINUS_1 - 1;
|
intColorIndex = psm2;
|
||||||
colorIndexFrac = 1;
|
colorIndexFrac = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1608,7 +1611,7 @@ void Renderer<T, bucketT>::Accumulate(QTIsaac<ISAAC_SIZE, ISAAC_INT>& rand, Poin
|
|||||||
|
|
||||||
if (histIndex < histSize)
|
if (histIndex < histSize)
|
||||||
{
|
{
|
||||||
intColorIndex = Clamp<size_t>(size_t(p.m_ColorX * COLORMAP_LENGTH_MINUS_1), 0, COLORMAP_LENGTH_MINUS_1);
|
intColorIndex = Clamp<size_t>(size_t(p.m_ColorX * psm1), 0, psm1);
|
||||||
bucketT* __restrict hist = glm::value_ptr(m_HistBuckets[histIndex]);//Vectorizer can't tell these point to different locations.
|
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]);
|
const bucketT* __restrict pal = glm::value_ptr(palette->m_Entries[intColorIndex]);
|
||||||
|
|
||||||
|
@ -1310,19 +1310,18 @@ bool XmlToEmber<T>::ParseEmberElementFromChaos(xmlNode* emberNode, Ember<T>& cur
|
|||||||
{
|
{
|
||||||
if (auto palettevalsnode = GetChildNodeByNodeName(palettenode, "values"))
|
if (auto palettevalsnode = GetChildNodeByNodeName(palettenode, "values"))
|
||||||
{
|
{
|
||||||
int i = 0;
|
|
||||||
float r = 0, g = 0, b = 0;
|
float r = 0, g = 0, b = 0;
|
||||||
auto colors = CCX(palettevalsnode->children->content);
|
auto colors = CCX(palettevalsnode->children->content);
|
||||||
istringstream istr(colors);
|
istringstream istr(colors);
|
||||||
|
currentEmber.m_Palette.m_Entries.clear();
|
||||||
|
std::vector<v4F> tempv;
|
||||||
|
tempv.reserve(256);
|
||||||
|
|
||||||
while (istr >> r && istr >> g && istr >> b && i < COLORMAP_LENGTH)
|
while (istr >> r && istr >> g && istr >> b)
|
||||||
{
|
tempv.push_back(v4F(r, g, b, 1));
|
||||||
currentEmber.m_Palette.m_Entries[i][0] = r;
|
|
||||||
currentEmber.m_Palette.m_Entries[i][1] = g;
|
if (!tempv.empty())
|
||||||
currentEmber.m_Palette.m_Entries[i][2] = b;
|
currentEmber.m_Palette.m_Entries = std::move(tempv);
|
||||||
currentEmber.m_Palette.m_Entries[i][3] = 1;
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1393,9 +1392,10 @@ bool XmlToEmber<T>::ParseEmberElementFromChaos(xmlNode* emberNode, Ember<T>& cur
|
|||||||
Spline<float> hspline(hvec);
|
Spline<float> hspline(hvec);
|
||||||
Spline<float> sspline(svec);
|
Spline<float> sspline(svec);
|
||||||
Spline<float> vspline(vvec);
|
Spline<float> vspline(vvec);
|
||||||
auto stepsize = (1.0f / (COLORMAP_LENGTH - 1));
|
currentEmber.m_Palette.m_Entries.resize(COLORMAP_LENGTH);
|
||||||
|
auto stepsize = (1.0f / (currentEmber.m_Palette.Size() - 1));
|
||||||
|
|
||||||
for (auto palindex = 0; palindex < COLORMAP_LENGTH; palindex++)
|
for (auto palindex = 0; palindex < currentEmber.m_Palette.Size(); palindex++)
|
||||||
{
|
{
|
||||||
float t = palindex * stepsize;
|
float t = palindex * stepsize;
|
||||||
auto h = hspline.Interpolate(t);
|
auto h = hspline.Interpolate(t);
|
||||||
@ -1768,22 +1768,15 @@ bool XmlToEmber<T>::ParseEmberElement(xmlNode* emberNode, Ember<T>& currentEmber
|
|||||||
xmlFree(attStr);
|
xmlFree(attStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Palette colors are [0..255], convert to [0..1].
|
while (index >= currentEmber.m_Palette.Size())
|
||||||
if (index >= 0 && index <= 255)
|
currentEmber.m_Palette.m_Entries.push_back(v4F());
|
||||||
{
|
|
||||||
float alphaPercent = a / 255.0f;//Aplha percentage in the range of 0 to 1.
|
float alphaPercent = a / 255.0f;//Aplha percentage in the range of 0 to 1.
|
||||||
//Premultiply the palette.
|
//Premultiply the palette.
|
||||||
currentEmber.m_Palette.m_Entries[index].r = alphaPercent * (r / 255.0f);
|
currentEmber.m_Palette.m_Entries[index].r = alphaPercent * (r / 255.0f);//Palette colors are [0..255], convert to [0..1].
|
||||||
currentEmber.m_Palette.m_Entries[index].g = alphaPercent * (g / 255.0f);
|
currentEmber.m_Palette.m_Entries[index].g = alphaPercent * (g / 255.0f);
|
||||||
currentEmber.m_Palette.m_Entries[index].b = alphaPercent * (b / 255.0f);
|
currentEmber.m_Palette.m_Entries[index].b = alphaPercent * (b / 255.0f);
|
||||||
currentEmber.m_Palette.m_Entries[index].a = a / 255.0f;//Will be one for RGB, and other than one if RGBA with A != 255.
|
currentEmber.m_Palette.m_Entries[index].a = a / 255.0f;//Will be one for RGB, and other than one if RGBA with A != 255.
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stringstream ss;
|
|
||||||
ss << "ParseEmberElement() : Color element with bad/missing index attribute " << index;
|
|
||||||
AddToReport(ss.str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (!Compare(childNode->name, "colors"))
|
else if (!Compare(childNode->name, "colors"))
|
||||||
{
|
{
|
||||||
@ -2487,12 +2480,16 @@ bool XmlToEmber<T>::ParseHexColors(const char* colstr, Ember<T>& ember, size_t n
|
|||||||
|
|
||||||
for (size_t strIndex = 0; strIndex < length;)
|
for (size_t strIndex = 0; strIndex < length;)
|
||||||
{
|
{
|
||||||
for (glm::length_t i = 0; i < 3 && colorCount < ember.m_Palette.Size(); i++)
|
for (glm::length_t i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
const char tmpStr[3] = { s[strIndex++], s[strIndex++], 0 };//Read out and convert the string two characters at a time.
|
const char tmpStr[3] = { s[strIndex++], s[strIndex++], 0 };//Read out and convert the string two characters at a time.
|
||||||
ss.clear();//Reset and fill the string stream.
|
ss.clear();//Reset and fill the string stream.
|
||||||
ss.str(tmpStr);
|
ss.str(tmpStr);
|
||||||
ss >> tmp;//Do the conversion.
|
ss >> tmp;//Do the conversion.
|
||||||
|
|
||||||
|
while (colorCount >= ember.m_Palette.Size())
|
||||||
|
ember.m_Palette.m_Entries.push_back(v4F());
|
||||||
|
|
||||||
ember.m_Palette.m_Entries[colorCount][i] = float(tmp) / 255.0f;//Hex palette is [0..255], convert to [0..1].
|
ember.m_Palette.m_Entries[colorCount][i] = float(tmp) / 255.0f;//Hex palette is [0..255], convert to [0..1].
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,8 +70,6 @@ static string ConstantDefinesString(bool doublePrecision)
|
|||||||
"#define NTHREADS 256u\n"
|
"#define NTHREADS 256u\n"
|
||||||
"#define THREADS_PER_WARP 32u\n"
|
"#define THREADS_PER_WARP 32u\n"
|
||||||
"#define NWARPS (NTHREADS / THREADS_PER_WARP)\n"
|
"#define NWARPS (NTHREADS / THREADS_PER_WARP)\n"
|
||||||
"#define COLORMAP_LENGTH 256u\n"
|
|
||||||
"#define COLORMAP_LENGTH_MINUS_1 255\n"
|
|
||||||
"#define DE_THRESH 100u\n"
|
"#define DE_THRESH 100u\n"
|
||||||
"#define BadVal(x) (isnan(x))\n"
|
"#define BadVal(x) (isnan(x))\n"
|
||||||
"#define SQR(x) ((x) * (x))\n"
|
"#define SQR(x) ((x) * (x))\n"
|
||||||
@ -206,6 +204,8 @@ struct ALIGN EmberCL
|
|||||||
m3T m_CamMat;
|
m3T m_CamMat;
|
||||||
T m_CenterX, m_CenterY;
|
T m_CenterX, m_CenterY;
|
||||||
T m_RotA, m_RotB, m_RotD, m_RotE;
|
T m_RotA, m_RotB, m_RotD, m_RotE;
|
||||||
|
T m_Psm1;
|
||||||
|
T m_Psm2;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -232,6 +232,8 @@ static const char* EmberCLStructString =
|
|||||||
" real_t m_C22;\n"
|
" real_t m_C22;\n"
|
||||||
" real_t m_CenterX, m_CenterY;\n"
|
" real_t m_CenterX, m_CenterY;\n"
|
||||||
" real_t m_RotA, m_RotB, m_RotD, m_RotE;\n"
|
" real_t m_RotA, m_RotB, m_RotD, m_RotE;\n"
|
||||||
|
" real_t m_Psm1;\n"
|
||||||
|
" real_t m_Psm2;\n"
|
||||||
"} EmberCL;\n"
|
"} EmberCL;\n"
|
||||||
"\n";
|
"\n";
|
||||||
|
|
||||||
|
@ -412,21 +412,21 @@ FunctionMapper::FunctionMapper()
|
|||||||
" return 0.0;\n"
|
" return 0.0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" if (w <= 4) // w in (0, 4]\n"
|
" if (w <= 4)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" real_t y = x * x;\n"
|
" real_t y = x * x;\n"
|
||||||
" r = EvalRational(P1, Q1, y, 7);\n"
|
" r = EvalRational(P1, Q1, y, 7);\n"
|
||||||
" factor = w * (w + x1) * ((w - x11 / 256) - x12);\n"
|
" factor = w * (w + x1) * ((w - x11 / 256) - x12);\n"
|
||||||
" value = factor * r;\n"
|
" value = factor * r;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" else if (w <= 8) // w in (4, 8]\n"
|
" else if (w <= 8)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" real_t y = x * x;\n"
|
" real_t y = x * x;\n"
|
||||||
" r = EvalRational(P2, Q2, y, 8);\n"
|
" r = EvalRational(P2, Q2, y, 8);\n"
|
||||||
" factor = w * (w + x2) * ((w - x21 / 256) - x22);\n"
|
" factor = w * (w + x2) * ((w - x21 / 256) - x22);\n"
|
||||||
" value = factor * r;\n"
|
" value = factor * r;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" else // w in (8, \infty)\n"
|
" else\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" real_t y = 8 / w;\n"
|
" real_t y = 8 / w;\n"
|
||||||
" real_t y2 = y * y;\n"
|
" real_t y2 = y * y;\n"
|
||||||
@ -440,7 +440,7 @@ FunctionMapper::FunctionMapper()
|
|||||||
"\n"
|
"\n"
|
||||||
" if (x < 0)\n"
|
" if (x < 0)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" value *= -1; // odd function\n"
|
" value *= -1;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" return value;\n"
|
" return value;\n"
|
||||||
|
@ -471,23 +471,24 @@ string IterOpenCLKernelCreator<T>::CreateIterKernelString(const Ember<T>& ember,
|
|||||||
{
|
{
|
||||||
os <<
|
os <<
|
||||||
" real_t colorIndexFrac;\n"
|
" real_t colorIndexFrac;\n"
|
||||||
" real_t colorIndex = secondPoint.m_ColorX * COLORMAP_LENGTH_MINUS_1;\n"
|
" real_t colorIndex = secondPoint.m_ColorX * ember->m_Psm1;\n"
|
||||||
" int intColorIndex = (int)colorIndex;\n"
|
" int intColorIndex;\n"
|
||||||
" float4 palColor2;\n"
|
" float4 palColor2;\n"
|
||||||
"\n"
|
"\n"
|
||||||
" if (intColorIndex < 0)\n"
|
" if (colorIndex < 0)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" intColorIndex = 0;\n"
|
" intColorIndex = 0;\n"
|
||||||
" colorIndexFrac = 0;\n"
|
" colorIndexFrac = 0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" else if (intColorIndex >= COLORMAP_LENGTH_MINUS_1)\n"
|
" else if (colorIndex >= ember->m_Psm1)\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" intColorIndex = COLORMAP_LENGTH_MINUS_1 - 1;\n"
|
" intColorIndex = (int)ember->m_Psm2;\n"
|
||||||
" colorIndexFrac = 1.0;\n"
|
" colorIndexFrac = 1.0;\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" else\n"
|
" else\n"
|
||||||
" {\n"
|
" {\n"
|
||||||
" colorIndexFrac = colorIndex - (real_t)intColorIndex;\n"//Interpolate between intColorIndex and intColorIndex + 1.
|
" intColorIndex = (int)colorIndex;\n"
|
||||||
|
" colorIndexFrac = colorIndex - intColorIndex;\n"//Interpolate between intColorIndex and intColorIndex + 1.
|
||||||
" }\n"
|
" }\n"
|
||||||
"\n"
|
"\n"
|
||||||
" iPaletteCoord.x = intColorIndex;\n"//Palette operations are strictly float because OpenCL does not support dp64 textures.
|
" iPaletteCoord.x = intColorIndex;\n"//Palette operations are strictly float because OpenCL does not support dp64 textures.
|
||||||
@ -499,7 +500,7 @@ string IterOpenCLKernelCreator<T>::CreateIterKernelString(const Ember<T>& ember,
|
|||||||
else if (ember.m_PaletteMode == ePaletteMode::PALETTE_STEP)
|
else if (ember.m_PaletteMode == ePaletteMode::PALETTE_STEP)
|
||||||
{
|
{
|
||||||
os <<
|
os <<
|
||||||
" iPaletteCoord.x = (int)(secondPoint.m_ColorX * COLORMAP_LENGTH_MINUS_1);\n"
|
" iPaletteCoord.x = (int)(secondPoint.m_ColorX * ember->m_Psm1);\n"
|
||||||
" palColor1 = read_imagef(palette, paletteSampler, iPaletteCoord);\n";
|
" palColor1 = read_imagef(palette, paletteSampler, iPaletteCoord);\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,12 +393,10 @@ bool OpenCLWrapper::AddAndWriteImage(const string& name, cl_mem_flags flags, con
|
|||||||
if (m_Info->CheckCL(err, "cl::ImageGL()"))
|
if (m_Info->CheckCL(err, "cl::ImageGL()"))
|
||||||
{
|
{
|
||||||
m_GLImages.push_back(namedImageGL);
|
m_GLImages.push_back(namedImageGL);
|
||||||
|
imageIndex = int(m_GLImages.size()) - 1;
|
||||||
if (data)
|
|
||||||
return WriteImage2D(m_GLImages.size() - 1, true, width, height, row_pitch, data);//OpenGL images/textures require a separate write.
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -407,8 +405,10 @@ bool OpenCLWrapper::AddAndWriteImage(const string& name, cl_mem_flags flags, con
|
|||||||
if (m_Info->CheckCL(err, "cl::Image2D()"))
|
if (m_Info->CheckCL(err, "cl::Image2D()"))
|
||||||
{
|
{
|
||||||
m_Images.push_back(namedImage);
|
m_Images.push_back(namedImage);
|
||||||
return true;
|
imageIndex = int(m_Images.size()) - 1;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else//It did exist, so create new if sizes are different. Write if data is not NULL.
|
else//It did exist, so create new if sizes are different. Write if data is not NULL.
|
||||||
@ -422,18 +422,10 @@ bool OpenCLWrapper::AddAndWriteImage(const string& name, cl_mem_flags flags, con
|
|||||||
NamedImage2DGL namedImageGL(cl::ImageGL(m_Context, flags, GL_TEXTURE_2D, 0, texName, &err), name);//Sizes are different, so create new.
|
NamedImage2DGL namedImageGL(cl::ImageGL(m_Context, flags, GL_TEXTURE_2D, 0, texName, &err), name);//Sizes are different, so create new.
|
||||||
|
|
||||||
if (m_Info->CheckCL(err, "cl::ImageGL()"))
|
if (m_Info->CheckCL(err, "cl::ImageGL()"))
|
||||||
{
|
|
||||||
m_GLImages[imageIndex] = namedImageGL;
|
m_GLImages[imageIndex] = namedImageGL;
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Write data to new image since OpenGL images/textures require a separate write, must match new size.
|
|
||||||
if (data)
|
|
||||||
return WriteImage2D(imageIndex, true, width, height, row_pitch, data);
|
|
||||||
else
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -443,17 +435,17 @@ bool OpenCLWrapper::AddAndWriteImage(const string& name, cl_mem_flags flags, con
|
|||||||
NamedImage2D namedImage(cl::Image2D(m_Context, flags, format, width, height, row_pitch, data, &err), name);
|
NamedImage2D namedImage(cl::Image2D(m_Context, flags, format, width, height, row_pitch, data, &err), name);
|
||||||
|
|
||||||
if (m_Info->CheckCL(err, "cl::Image2D()"))
|
if (m_Info->CheckCL(err, "cl::Image2D()"))
|
||||||
{
|
|
||||||
m_Images[imageIndex] = namedImage;
|
m_Images[imageIndex] = namedImage;
|
||||||
return true;
|
else
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
else if (data)
|
|
||||||
return WriteImage2D(imageIndex, false, width, height, row_pitch, data);
|
|
||||||
else//Strange case: images were same dimensions but no data was passed in, so do nothing.
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (data)
|
||||||
|
return WriteImage2D(imageIndex, shared, width, height, row_pitch, data);
|
||||||
|
else//Strange case: images were same dimensions but no data was passed in, so do nothing.
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -81,7 +81,7 @@ bool RendererCL<T, bucketT>::Init(const vector<pair<size_t, size_t>>& devices, b
|
|||||||
{
|
{
|
||||||
if (b && !(b = cld->m_Wrapper.AddProgram(m_IterOpenCLKernelCreator.ZeroizeEntryPoint(), zeroizeProgram, m_IterOpenCLKernelCreator.ZeroizeEntryPoint(), m_DoublePrecision))) { ErrorStr(loc, "Failed to init zeroize program: "s + cld->ErrorReportString(), cld.get()); }
|
if (b && !(b = cld->m_Wrapper.AddProgram(m_IterOpenCLKernelCreator.ZeroizeEntryPoint(), zeroizeProgram, m_IterOpenCLKernelCreator.ZeroizeEntryPoint(), m_DoublePrecision))) { ErrorStr(loc, "Failed to init zeroize program: "s + cld->ErrorReportString(), cld.get()); }
|
||||||
|
|
||||||
if (b && !(b = cld->m_Wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, 256, 1, 0, nullptr))) { ErrorStr(loc, "Failed to init palette buffer: "s + cld->ErrorReportString(), cld.get()); }
|
if (b && !(b = cld->m_Wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, m_Ember.m_Palette.Size(), 1, 0, nullptr))) { ErrorStr(loc, "Failed to init palette buffer: "s + cld->ErrorReportString(), cld.get()); }
|
||||||
|
|
||||||
if (b && !(b = cld->m_Wrapper.AddAndWriteBuffer(m_GlobalSharedBufferName, m_GlobalShared.second.data(), m_GlobalShared.second.size() * sizeof(m_GlobalShared.second[0])))) { ErrorStr(loc, "Failed to init global shared buffer: "s + cld->ErrorReportString(), cld.get()); }//Empty at start, will be filled in later if needed.
|
if (b && !(b = cld->m_Wrapper.AddAndWriteBuffer(m_GlobalSharedBufferName, m_GlobalShared.second.data(), m_GlobalShared.second.size() * sizeof(m_GlobalShared.second[0])))) { ErrorStr(loc, "Failed to init global shared buffer: "s + cld->ErrorReportString(), cld.get()); }//Empty at start, will be filled in later if needed.
|
||||||
|
|
||||||
@ -853,7 +853,7 @@ EmberStats RendererCL<T, bucketT>::Iterate(size_t iterCount, size_t temporalSamp
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b && !(b = wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, m_Dmap.m_Entries.size(), 1, 0, m_Dmap.m_Entries.data())))
|
if (b && !(b = wrapper.AddAndWriteImage("Palette", CL_MEM_READ_ONLY, m_PaletteFormat, m_Dmap.Size(), 1, 0, m_Dmap.m_Entries.data())))
|
||||||
{
|
{
|
||||||
ErrorStr(loc, "Write palette buffer failed", device.get());
|
ErrorStr(loc, "Write palette buffer failed", device.get());
|
||||||
break;
|
break;
|
||||||
@ -1787,6 +1787,8 @@ void RendererCL<T, bucketT>::ConvertEmber(Ember<T>& ember, EmberCL<T>& emberCL,
|
|||||||
emberCL.m_RotB = m_RotMat.B();
|
emberCL.m_RotB = m_RotMat.B();
|
||||||
emberCL.m_RotD = m_RotMat.D();
|
emberCL.m_RotD = m_RotMat.D();
|
||||||
emberCL.m_RotE = m_RotMat.E();
|
emberCL.m_RotE = m_RotMat.E();
|
||||||
|
emberCL.m_Psm1 = T(m_Dmap.Size() - 1);
|
||||||
|
emberCL.m_Psm2 = T(m_Dmap.Size() - 2);
|
||||||
|
|
||||||
for (size_t i = 0; i < ember.TotalXformCount() && i < xformsCL.size(); i++)
|
for (size_t i = 0; i < ember.TotalXformCount() && i < xformsCL.size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -248,6 +248,7 @@ public:
|
|||||||
virtual void PaletteCellClicked(int row, int col) { }
|
virtual void PaletteCellClicked(int row, int col) { }
|
||||||
virtual void SetBasePaletteAndAdjust(const Palette<float>& palette) { }
|
virtual void SetBasePaletteAndAdjust(const Palette<float>& palette) { }
|
||||||
virtual void PaletteEditorButtonClicked() { }
|
virtual void PaletteEditorButtonClicked() { }
|
||||||
|
virtual void PaletteEditorColorChanged() { }
|
||||||
QImage& FinalPaletteImage() { return m_FinalPaletteImage; }
|
QImage& FinalPaletteImage() { return m_FinalPaletteImage; }
|
||||||
|
|
||||||
//Info.
|
//Info.
|
||||||
@ -535,6 +536,7 @@ public:
|
|||||||
virtual void PaletteCellClicked(int row, int col) override;
|
virtual void PaletteCellClicked(int row, int col) override;
|
||||||
virtual void SetBasePaletteAndAdjust(const Palette<float>& palette) override;
|
virtual void SetBasePaletteAndAdjust(const Palette<float>& palette) override;
|
||||||
virtual void PaletteEditorButtonClicked() override;
|
virtual void PaletteEditorButtonClicked() override;
|
||||||
|
virtual void PaletteEditorColorChanged() override;
|
||||||
|
|
||||||
//Info.
|
//Info.
|
||||||
virtual void FillSummary() override;
|
virtual void FillSummary() override;
|
||||||
|
@ -406,7 +406,7 @@ void FractoriumEmberController<T>::PaletteEditorButtonClicked()
|
|||||||
if (auto xform = m_Ember.GetTotalXform(index.first, forceFinal))
|
if (auto xform = m_Ember.GetTotalXform(index.first, forceFinal))
|
||||||
xform->m_ColorX = index.second;
|
xform->m_ColorX = index.second;
|
||||||
|
|
||||||
edPal = ed->GetPalette(int(256));
|
edPal = ed->GetPalette(int(prevPal.Size()));
|
||||||
SetBasePaletteAndAdjust(edPal);//This will take care of updating the color index controls.
|
SetBasePaletteAndAdjust(edPal);//This will take care of updating the color index controls.
|
||||||
|
|
||||||
if (edPal.m_Filename.get() && !edPal.m_Filename->empty())
|
if (edPal.m_Filename.get() && !edPal.m_Filename->empty())
|
||||||
@ -458,10 +458,16 @@ void Fractorium::OnPaletteEditorButtonClicked(bool checked)
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Slot called every time a color is changed in the palette editor.
|
/// Slot called every time a color is changed in the palette editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
template <typename T>
|
||||||
|
void FractoriumEmberController<T>::PaletteEditorColorChanged()
|
||||||
|
{
|
||||||
|
SetBasePaletteAndAdjust(m_Fractorium->m_PaletteEditor->GetPalette(int(m_TempPalette.Size())));
|
||||||
|
}
|
||||||
|
|
||||||
void Fractorium::OnPaletteEditorColorChanged()
|
void Fractorium::OnPaletteEditorColorChanged()
|
||||||
{
|
{
|
||||||
m_PaletteChanged = true;
|
m_PaletteChanged = true;
|
||||||
m_Controller->SetBasePaletteAndAdjust(m_PaletteEditor->GetPalette(int(256)));
|
m_Controller->PaletteEditorColorChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -569,7 +575,7 @@ void Fractorium::SetPaletteFileComboIndex(const string& filename)
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reset the color curve values for the selected curve in the current ember to their default state and also update the curves control.
|
/// Reset the color curve values for the selected curve in the current ember to their default state and also update the curves control.
|
||||||
/// Called when ResetCurvesButton is clicked.
|
/// Called when ResetCurvesButton is clicked.
|
||||||
/// Note if they click Reset Curves when the "All" radio button is selected, then it clears all curves.
|
/// Note if they click Reset Curves when the ctrl is pressed, then it clears all curves.
|
||||||
/// Resets the rendering process at either ACCUM_ONLY by default, or FILTER_AND_ACCUM when using early clip.
|
/// Resets the rendering process at either ACCUM_ONLY by default, or FILTER_AND_ACCUM when using early clip.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="i">The index of the curve to be cleared, 0 to clear all.</param>
|
/// <param name="i">The index of the curve to be cleared, 0 to clear all.</param>
|
||||||
@ -578,26 +584,34 @@ void FractoriumEmberController<T>::ClearColorCurves(int i)
|
|||||||
{
|
{
|
||||||
Update([&]
|
Update([&]
|
||||||
{
|
{
|
||||||
if (i)
|
m_Ember.m_Curves.Init(i);
|
||||||
m_Ember.m_Curves.Init(i);
|
|
||||||
else
|
|
||||||
m_Ember.m_Curves.Init(0);
|
|
||||||
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
|
}, true, m_Renderer->EarlyClip() ? eProcessAction::FILTER_AND_ACCUM : eProcessAction::ACCUM_ONLY);
|
||||||
FillCurvesControl();
|
FillCurvesControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fractorium::OnResetCurvesButtonClicked(bool checked)
|
void Fractorium::OnResetCurvesButtonClicked(bool checked)
|
||||||
{
|
{
|
||||||
if (ui.CurvesAllRadio->isChecked())
|
if (!QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier))
|
||||||
m_Controller->ClearColorCurves(0);
|
{
|
||||||
else if (ui.CurvesRedRadio->isChecked())
|
if (ui.CurvesAllRadio->isChecked())
|
||||||
m_Controller->ClearColorCurves(1);
|
m_Controller->ClearColorCurves(0);
|
||||||
else if (ui.CurvesGreenRadio->isChecked())
|
else if (ui.CurvesRedRadio->isChecked())
|
||||||
m_Controller->ClearColorCurves(2);
|
m_Controller->ClearColorCurves(1);
|
||||||
else if (ui.CurvesBlueRadio->isChecked())
|
else if (ui.CurvesGreenRadio->isChecked())
|
||||||
m_Controller->ClearColorCurves(3);
|
m_Controller->ClearColorCurves(2);
|
||||||
|
else if (ui.CurvesBlueRadio->isChecked())
|
||||||
|
m_Controller->ClearColorCurves(3);
|
||||||
|
else
|
||||||
|
m_Controller->ClearColorCurves(0);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
m_Controller->ClearColorCurves(0);
|
m_Controller->ClearColorCurves(0);
|
||||||
|
m_Controller->ClearColorCurves(1);
|
||||||
|
m_Controller->ClearColorCurves(2);
|
||||||
|
m_Controller->ClearColorCurves(3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -22,12 +22,12 @@ void Fractorium::InitParamsUI()
|
|||||||
SetFixedTableHeader(ui.IterationTableHeader->horizontalHeader());
|
SetFixedTableHeader(ui.IterationTableHeader->horizontalHeader());
|
||||||
SetFixedTableHeader(ui.AnimationTableHeader->horizontalHeader());
|
SetFixedTableHeader(ui.AnimationTableHeader->horizontalHeader());
|
||||||
//Color.
|
//Color.
|
||||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_BrightnessSpin, spinHeight, 0.05, 1000, 1, SIGNAL(valueChanged(double)), SLOT(OnBrightnessChanged(double)), true, 4.0, 4.0, 4.0);
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_BrightnessSpin, spinHeight, 0.01, dmax, 1, SIGNAL(valueChanged(double)), SLOT(OnBrightnessChanged(double)), true, 4.0, 4.0, 4.0);
|
||||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaSpin, spinHeight, 1, 9999, 0.5, SIGNAL(valueChanged(double)), SLOT(OnGammaChanged(double)), true, 4.0, 4.0, 4.0);
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaSpin, spinHeight, 1, dmax, 0.5, SIGNAL(valueChanged(double)), SLOT(OnGammaChanged(double)), true, 4.0, 4.0, 4.0);
|
||||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, 10, 0.01, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.0);
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_GammaThresholdSpin, spinHeight, 0, dmax, 0.01, SIGNAL(valueChanged(double)), SLOT(OnGammaThresholdChanged(double)), true, 0.1, 0.1, 0.0);
|
||||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_VibrancySpin, spinHeight, 0, 30, 0.01, SIGNAL(valueChanged(double)), SLOT(OnVibrancyChanged(double)), true, 1.0, 1.0, 0.0);
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_VibrancySpin, spinHeight, 0, dmax, 0.01, SIGNAL(valueChanged(double)), SLOT(OnVibrancyChanged(double)), true, 1.0, 1.0, 0.0);
|
||||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, 1.0, 1.0, -1.0);
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_HighlightSpin, spinHeight, -1.0, 10, 0.1, SIGNAL(valueChanged(double)), SLOT(OnHighlightPowerChanged(double)), true, 1.0, 1.0, -1.0);
|
||||||
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_K2Spin, spinHeight, 0, 10.0, 0.0001, SIGNAL(valueChanged(double)), SLOT(OnK2Changed(double)), true, 0, 0.0001, 0);
|
SetupSpinner<DoubleSpinBox, double>(table, this, row, 1, m_K2Spin, spinHeight, 0, 99.0, 0.0001, SIGNAL(valueChanged(double)), SLOT(OnK2Changed(double)), true, 0, 0.0001, 0);
|
||||||
m_HighlightSpin->DoubleClickLowVal(-1.0);
|
m_HighlightSpin->DoubleClickLowVal(-1.0);
|
||||||
int dec = 6;
|
int dec = 6;
|
||||||
m_BrightnessSpin->setDecimals(dec);
|
m_BrightnessSpin->setDecimals(dec);
|
||||||
|
@ -229,7 +229,7 @@ void Fractorium::OnXformRefPaletteResized(int logicalIndex, int oldSize, int new
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
QColor FractoriumEmberController<T>::ColorIndexToQColor(double d)
|
QColor FractoriumEmberController<T>::ColorIndexToQColor(double d)
|
||||||
{
|
{
|
||||||
v4F entry = m_Ember.m_Palette[Clamp<size_t>(d * COLORMAP_LENGTH_MINUS_1, 0, m_Ember.m_Palette.Size())];
|
v4F entry = m_Ember.m_Palette[Clamp<size_t>(d * (m_Ember.m_Palette.Size() - 1), 0, m_Ember.m_Palette.Size())];
|
||||||
entry.r *= 255;
|
entry.r *= 255;
|
||||||
entry.g *= 255;
|
entry.g *= 255;
|
||||||
entry.b *= 255;
|
entry.b *= 255;
|
||||||
|
Loading…
Reference in New Issue
Block a user