MYST3: Implement the blur effect for J'nanin's projectors.

This commit is contained in:
Bastien Bouclet
2012-01-19 21:04:01 +01:00
parent a37cb11f2b
commit 1e0ea56efc
2 changed files with 49 additions and 5 deletions
+45 -5
View File
@@ -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);
+4
View File
@@ -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 */