From 1e0ea56efc5cd55579ca5f2b2cccb49e0100b143 Mon Sep 17 00:00:00 2001 From: Bastien Bouclet Date: Thu, 19 Jan 2012 21:04:01 +0100 Subject: [PATCH] MYST3: Implement the blur effect for J'nanin's projectors. --- engines/myst3/movie.cpp | 50 ++++++++++++++++++++++++++++++++++++----- engines/myst3/movie.h | 4 ++++ 2 files changed, 49 insertions(+), 5 deletions(-) diff --git a/engines/myst3/movie.cpp b/engines/myst3/movie.cpp index e6b324c62da..db3bdabf100 100644 --- a/engines/myst3/movie.cpp +++ b/engines/myst3/movie.cpp @@ -301,6 +301,11 @@ ProjectorMovie::ProjectorMovie(Myst3Engine *vm, uint16 id, Graphics::Surface *ba _background(background), _frame(0) { _enabled = true; + + for (uint i = 0; i < kBlurIterations; i++) { + _blurTableX[i] = sin(2 * M_PI * i / (float) kBlurIterations) * 256.0; + _blurTableY[i] = cos(2 * M_PI * i / (float) kBlurIterations) * 256.0; + } } ProjectorMovie::~ProjectorMovie() { @@ -323,22 +328,57 @@ void ProjectorMovie::update() { _frame->copyFrom(*frame); } + uint16 focus = _vm->_state->getProjectorBlur() / 10; uint16 zoom = _vm->_state->getProjectorZoom(); uint16 backgroundX = (_vm->_state->getProjectorX() - zoom / 2) / 10; uint16 backgroundY = (_vm->_state->getProjectorY() - zoom / 2) / 10; float delta = zoom / 10.0 / _frame->w; + // For each pixel in the target image for (uint i = 0; i < _frame->h; i++) { uint32 *dst = (uint32 *)_frame->getBasePtr(0, i); for (uint j = 0; j < _frame->w; j++) { - uint8 a, r, g, b; - uint32 *src = (uint32 *)_background->getBasePtr(backgroundX + j * delta, backgroundY + i * delta); + uint8 a, depth; + uint16 r = 0, g = 0, b = 0; + uint32 srcX = backgroundX + j * delta; + uint32 srcY = backgroundY + i * delta; + uint32 *src = (uint32 *)_background->getBasePtr(srcX, srcY); // Keep the alpha channel from the previous frame - Graphics::colorToARGB< Graphics::ColorMasks<8888> >(*dst, a, r, g, b); + a = *dst >> 24; - // Get the colors from the background - Graphics::colorToRGB< Graphics::ColorMasks<8888> >(*src, r, g, b); + // Get the depth from the background + depth = *src >> 24; + + // Compute the blur level from the focus point and the depth of the current point + uint8 blurLevel = abs(focus - depth) + 1; + + // No need to compute the effect for transparent pixels + if (a != 0) { + // The blur effect is done by mixing the color components from the pixel at (srcX, srcY) + // and other pixels on the same row / column + uint cnt = 0; + for (uint k = 0; k < kBlurIterations; k++) { + uint8 blurR, blurG, blurB; + uint32 blurX = srcX + ((uint32) (blurLevel * _blurTableX[k] * delta) >> 12); // >> 12 = / 256 / 16 + uint32 blurY = srcY + ((uint32) (blurLevel * _blurTableY[k] * delta) >> 12); + + if (blurX >= 0 && blurX < 1024 && blurY >= 0 && blurY < 1024) { + uint32 *blur = (uint32 *)_background->getBasePtr(blurX, blurY); + + Graphics::colorToRGB< Graphics::ColorMasks<8888> >(*blur, blurR, blurG, blurB); + r += blurR; + g += blurG; + b += blurB; + cnt++; + } + } + + // Divide the components by the number of pixels used in the blur effect + r /= cnt; + g /= cnt; + b /= cnt; + } // Draw the new frame *dst++ = Graphics::ARGBToColor< Graphics::ColorMasks<8888> >(a, r, g, b); diff --git a/engines/myst3/movie.h b/engines/myst3/movie.h index 9d78eedcdd6..ce810ee5dfc 100644 --- a/engines/myst3/movie.h +++ b/engines/myst3/movie.h @@ -141,6 +141,10 @@ public: private: Graphics::Surface *_background; Graphics::Surface *_frame; + + static const uint kBlurIterations = 30; + uint8 _blurTableX[kBlurIterations]; + uint8 _blurTableY[kBlurIterations]; }; } /* namespace Myst3 */