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:
kerwizzy
2018-12-12 22:17:24 +00:00
committed by waddlesplash
parent 2e7e161dfb
commit e5aeaa8d03
3 changed files with 67 additions and 12 deletions
+31 -9
View File
@@ -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)
int16 totalR = 0;
int16 totalG = 0;
int16 totalB = 0;
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. // Didn't escape.
loc = 999; sampleLoc = 999;
else else
loc = 998 - (iterToEscape % 999); 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];
} }
+4
View File
@@ -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;
+30 -1
View File
@@ -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