Mandelbrot: Implement subsampling
* Added subsampling. This makes the render look less noisy and generally nicer. Change-Id: I1dd667c8799bd97fb84e1401976da12ecf74ea8c Reviewed-on: https://review.haiku-os.org/732 Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
@@ -91,6 +91,9 @@ void FractalEngine::MessageReceived(BMessage* msg)
|
|||||||
case MSG_SET_ITERATIONS:
|
case MSG_SET_ITERATIONS:
|
||||||
fIterations = msg->GetUInt16("iterations", 0);
|
fIterations = msg->GetUInt16("iterations", 0);
|
||||||
break;
|
break;
|
||||||
|
case MSG_SET_SUBSAMPLING:
|
||||||
|
fSubsampling = msg->GetUInt8("subsampling", 1);
|
||||||
|
break;
|
||||||
|
|
||||||
case MSG_RESIZE: {
|
case MSG_RESIZE: {
|
||||||
TRACE("Got MSG_RESIZE threads rendering\n");
|
TRACE("Got MSG_RESIZE threads rendering\n");
|
||||||
@@ -251,19 +254,38 @@ void FractalEngine::RenderPixel(uint32 x, uint32 y)
|
|||||||
double real = (x * fSize + fLocationX) - (fWidth / 2 * fSize);
|
double real = (x * fSize + fLocationX) - (fWidth / 2 * fSize);
|
||||||
double imaginary = (y * -(fSize) + fLocationY) - (fHeight / 2 * -(fSize));
|
double imaginary = (y * -(fSize) + fLocationY) - (fHeight / 2 * -(fSize));
|
||||||
|
|
||||||
int32 iterToEscape = (this->*fDoSet)(real, imaginary);
|
double subsampleDelta = fSize / fSubsampling;
|
||||||
uint16 loc = 0;
|
uint16 nSamples = fSubsampling * fSubsampling;
|
||||||
if (iterToEscape == -1)
|
|
||||||
// Didn't escape.
|
int16 totalR = 0;
|
||||||
loc = 999;
|
int16 totalG = 0;
|
||||||
else
|
int16 totalB = 0;
|
||||||
loc = 998 - (iterToEscape % 999);
|
for (uint8 subX = 0; subX < fSubsampling; subX++) {
|
||||||
|
for (uint8 subY = 0; subY < fSubsampling; subY++) {
|
||||||
|
double sampleReal = real + subX * subsampleDelta;
|
||||||
|
double sampleImaginary = imaginary + subY * subsampleDelta;
|
||||||
|
|
||||||
|
int32 sampleIterToEscape = (this->*fDoSet)(sampleReal, sampleImaginary);
|
||||||
|
|
||||||
|
uint16 sampleLoc = 0;
|
||||||
|
if (sampleIterToEscape == -1)
|
||||||
|
// Didn't escape.
|
||||||
|
sampleLoc = 999;
|
||||||
|
else
|
||||||
|
sampleLoc = 998 - (sampleIterToEscape % 999);
|
||||||
|
sampleLoc *= 3;
|
||||||
|
|
||||||
|
totalR += fColorset[sampleLoc + 0];
|
||||||
|
totalG += fColorset[sampleLoc + 1];
|
||||||
|
totalB += fColorset[sampleLoc + 2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32 offsetBase = fWidth * y * 3 + x * 3;
|
uint32 offsetBase = fWidth * y * 3 + x * 3;
|
||||||
loc *= 3;
|
fRenderBuffer[offsetBase + 2] = totalR / nSamples; // fRenderBuffer is BGR
|
||||||
fRenderBuffer[offsetBase + 2] = fColorset[loc + 0]; // fRenderBuffer is BGR
|
fRenderBuffer[offsetBase + 1] = totalG / nSamples;
|
||||||
fRenderBuffer[offsetBase + 1] = fColorset[loc + 1];
|
fRenderBuffer[offsetBase + 0] = totalB / nSamples;
|
||||||
fRenderBuffer[offsetBase + 0] = fColorset[loc + 2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ public:
|
|||||||
MSG_CHANGE_SET = 'Frct',
|
MSG_CHANGE_SET = 'Frct',
|
||||||
MSG_SET_PALETTE,
|
MSG_SET_PALETTE,
|
||||||
MSG_SET_ITERATIONS,
|
MSG_SET_ITERATIONS,
|
||||||
|
MSG_SET_SUBSAMPLING,
|
||||||
MSG_RESIZE,
|
MSG_RESIZE,
|
||||||
MSG_BUFFER_CREATED,
|
MSG_BUFFER_CREATED,
|
||||||
MSG_RENDER,
|
MSG_RENDER,
|
||||||
@@ -45,6 +46,9 @@ private:
|
|||||||
uint8* fRenderBuffer;
|
uint8* fRenderBuffer;
|
||||||
uint32 fRenderBufferLen;
|
uint32 fRenderBufferLen;
|
||||||
|
|
||||||
|
uint8 fSubsampling = 2;
|
||||||
|
// 1 disables subsampling.
|
||||||
|
|
||||||
BMessenger fMessenger;
|
BMessenger fMessenger;
|
||||||
|
|
||||||
uint8 fThreadCount;
|
uint8 fThreadCount;
|
||||||
|
|||||||
@@ -358,7 +358,12 @@ public:
|
|||||||
MSG_ITER_4096,
|
MSG_ITER_4096,
|
||||||
MSG_ITER_8192,
|
MSG_ITER_8192,
|
||||||
MSG_ITER_12288,
|
MSG_ITER_12288,
|
||||||
MSG_ITER_16384
|
MSG_ITER_16384,
|
||||||
|
|
||||||
|
MSG_SUBSAMPLING_1,
|
||||||
|
MSG_SUBSAMPLING_2,
|
||||||
|
MSG_SUBSAMPLING_3,
|
||||||
|
MSG_SUBSAMPLING_4
|
||||||
};
|
};
|
||||||
MandelbrotWindow(BRect frame);
|
MandelbrotWindow(BRect frame);
|
||||||
~MandelbrotWindow() {}
|
~MandelbrotWindow() {}
|
||||||
@@ -381,6 +386,7 @@ MandelbrotWindow::MandelbrotWindow(BRect frame)
|
|||||||
BMenu* setMenu;
|
BMenu* setMenu;
|
||||||
BMenu* paletteMenu;
|
BMenu* paletteMenu;
|
||||||
BMenu* iterMenu;
|
BMenu* iterMenu;
|
||||||
|
BMenu* subsamplingMenu;
|
||||||
BLayoutBuilder::Menu<>(menuBar)
|
BLayoutBuilder::Menu<>(menuBar)
|
||||||
.AddMenu(B_TRANSLATE("File"))
|
.AddMenu(B_TRANSLATE("File"))
|
||||||
.AddItem(B_TRANSLATE("About"), B_ABOUT_REQUESTED)
|
.AddItem(B_TRANSLATE("About"), B_ABOUT_REQUESTED)
|
||||||
@@ -417,6 +423,13 @@ MandelbrotWindow::MandelbrotWindow(BRect frame)
|
|||||||
.AddItem("12288", MSG_ITER_12288)
|
.AddItem("12288", MSG_ITER_12288)
|
||||||
.AddItem("16384", MSG_ITER_16384)
|
.AddItem("16384", MSG_ITER_16384)
|
||||||
.End()
|
.End()
|
||||||
|
.AddMenu(B_TRANSLATE("Subsampling"))
|
||||||
|
.GetMenu(subsamplingMenu)
|
||||||
|
.AddItem(B_TRANSLATE("1 (none)"), MSG_SUBSAMPLING_1)
|
||||||
|
.AddItem("4", MSG_SUBSAMPLING_2)
|
||||||
|
.AddItem("9", MSG_SUBSAMPLING_3)
|
||||||
|
.AddItem("16", MSG_SUBSAMPLING_4)
|
||||||
|
.End()
|
||||||
.End();
|
.End();
|
||||||
setMenu->SetRadioMode(true);
|
setMenu->SetRadioMode(true);
|
||||||
setMenu->FindItem(MSG_MANDELBROT_SET)->SetMarked(true);
|
setMenu->FindItem(MSG_MANDELBROT_SET)->SetMarked(true);
|
||||||
@@ -424,6 +437,8 @@ MandelbrotWindow::MandelbrotWindow(BRect frame)
|
|||||||
paletteMenu->FindItem(MSG_ROYAL_PALETTE)->SetMarked(true);
|
paletteMenu->FindItem(MSG_ROYAL_PALETTE)->SetMarked(true);
|
||||||
iterMenu->SetRadioMode(true);
|
iterMenu->SetRadioMode(true);
|
||||||
iterMenu->FindItem(MSG_ITER_1024)->SetMarked(true);
|
iterMenu->FindItem(MSG_ITER_1024)->SetMarked(true);
|
||||||
|
subsamplingMenu->SetRadioMode(true);
|
||||||
|
subsamplingMenu->FindItem(MSG_SUBSAMPLING_2)->SetMarked(true);
|
||||||
|
|
||||||
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
|
BLayoutBuilder::Group<>(this, B_VERTICAL, 0)
|
||||||
.SetInsets(0)
|
.SetInsets(0)
|
||||||
@@ -458,6 +473,14 @@ MandelbrotWindow::MandelbrotWindow(BRect frame)
|
|||||||
fFractalView->RedrawFractal(); \
|
fFractalView->RedrawFractal(); \
|
||||||
break; \
|
break; \
|
||||||
}
|
}
|
||||||
|
#define HANDLE_SUBSAMPLING(uiwhat, id) \
|
||||||
|
case uiwhat: { \
|
||||||
|
BMessage msg(FractalEngine::MSG_SET_SUBSAMPLING); \
|
||||||
|
msg.AddUInt8("subsampling", id); \
|
||||||
|
fFractalView->fFractalEngine->PostMessage(&msg); \
|
||||||
|
fFractalView->RedrawFractal(); \
|
||||||
|
break; \
|
||||||
|
}
|
||||||
void
|
void
|
||||||
MandelbrotWindow::MessageReceived(BMessage* msg)
|
MandelbrotWindow::MessageReceived(BMessage* msg)
|
||||||
{
|
{
|
||||||
@@ -487,6 +510,11 @@ MandelbrotWindow::MessageReceived(BMessage* msg)
|
|||||||
HANDLE_ITER(MSG_ITER_12288, 12288)
|
HANDLE_ITER(MSG_ITER_12288, 12288)
|
||||||
HANDLE_ITER(MSG_ITER_16384, 16384)
|
HANDLE_ITER(MSG_ITER_16384, 16384)
|
||||||
|
|
||||||
|
HANDLE_SUBSAMPLING(MSG_SUBSAMPLING_1, 1)
|
||||||
|
HANDLE_SUBSAMPLING(MSG_SUBSAMPLING_2, 2)
|
||||||
|
HANDLE_SUBSAMPLING(MSG_SUBSAMPLING_3, 3)
|
||||||
|
HANDLE_SUBSAMPLING(MSG_SUBSAMPLING_4, 4)
|
||||||
|
|
||||||
case B_ABOUT_REQUESTED: {
|
case B_ABOUT_REQUESTED: {
|
||||||
BAboutWindow* wind = new BAboutWindow("Mandelbrot",
|
BAboutWindow* wind = new BAboutWindow("Mandelbrot",
|
||||||
"application/x-vnd.Haiku-Mandelbrot");
|
"application/x-vnd.Haiku-Mandelbrot");
|
||||||
@@ -510,6 +538,7 @@ MandelbrotWindow::MessageReceived(BMessage* msg)
|
|||||||
#undef HANDLE_SET
|
#undef HANDLE_SET
|
||||||
#undef HANDLE_PALETTE
|
#undef HANDLE_PALETTE
|
||||||
#undef HANDLE_ITER
|
#undef HANDLE_ITER
|
||||||
|
#undef HANDLE_SUBSAMPLING
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|||||||
Reference in New Issue
Block a user