mirror of
https://github.com/scummvm/scummvm.git
synced 2026-06-20 05:45:29 +00:00
MYST3: Implement the blur effect for J'nanin's projectors.
This commit is contained in:
+45
-5
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user