Skip to content

Commit

Permalink
GRAPHICS: Add support for Soft Shadows with rounded squares
Browse files Browse the repository at this point in the history
  • Loading branch information
rundfunk47 committed Aug 16, 2013
1 parent 887a99e commit 5c00dbb
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 62 deletions.
14 changes: 13 additions & 1 deletion graphics/VectorRenderer.h
Expand Up @@ -73,6 +73,8 @@ struct DrawStep {
uint8 shadow, stroke, factor, radius, bevel; /**< Misc options... */

uint8 fillMode; /**< active fill mode */
uint8 shadowFillMode; /**< fill mode of the shadow used */

uint32 extraData; /**< Generic parameter for extra options (orientation/bevel) */

uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */
Expand Down Expand Up @@ -103,7 +105,7 @@ VectorRenderer *createRenderer(int mode);
*/
class VectorRenderer {
public:
VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0),
VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0), _shadowFillMode(kShadowExponential),
_disableShadows(false), _strokeWidth(1), _gradientFactor(1) {

}
Expand All @@ -126,6 +128,11 @@ class VectorRenderer {
kTriangleRight
};

enum ShadowFillMode {
kShadowLinear = 0,
kShadowExponential = 1
};

/**
* Draws a line by considering the special cases for optimization.
*
Expand Down Expand Up @@ -292,6 +299,10 @@ class VectorRenderer {
_fillMode = mode;
}

virtual void setShadowFillMode(ShadowFillMode mode) {
_shadowFillMode = mode;
}

/**
* Sets the stroke width. All shapes drawn with a stroke will
* have that width. Pass 0 to disable shape stroking.
Expand Down Expand Up @@ -485,6 +496,7 @@ class VectorRenderer {
Surface *_activeSurface; /**< Pointer to the surface currently being drawn */

FillMode _fillMode; /**< Defines in which way (if any) are filled the drawn shapes */
ShadowFillMode _shadowFillMode;

int _shadowOffset; /**< offset for drawn shadows */
int _bevel; /**< amount of fake bevel */
Expand Down
120 changes: 74 additions & 46 deletions graphics/VectorRendererSpec.cpp
Expand Up @@ -883,7 +883,8 @@ drawRoundedSquare(int x, int y, int r, int w, int h) {

if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
&& x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
&& y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h) {
&& y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
&& h > (Base::_shadowOffset + 1) * 2) {
drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
}

Expand Down Expand Up @@ -1704,85 +1705,112 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f
********************************************************************/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawSquareShadow(int x, int y, int w, int h, int blur) {
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur);
drawSquareShadow(int x, int y, int w, int h, int offset) {
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int i, j;

i = h - blur;
i = h - offset;

while (i--) {
j = blur;
j = offset;
while (j--)
blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur);
blendPixelPtr(ptr + j, 0, ((offset - j) << 8) / offset);
ptr += pitch;
}

ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1);
ptr = (PixelType *)_activeSurface->getBasePtr(x + offset, y + h - 1);

while (i++ < blur) {
j = w - blur;
while (i++ < offset) {
j = w - offset;
while (j--)
blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur);
blendPixelPtr(ptr + j, 0, ((offset - i) << 8) / offset);
ptr += pitch;
}

ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);

i = 0;
while (i++ < blur) {
j = blur - 1;
while (i++ < offset) {
j = offset - 1;
while (j--)
blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur));
blendPixelPtr(ptr + j, 0, (((offset - j) * (offset - i)) << 8) / (offset * offset));
ptr += pitch;
}
}

template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) {
int f, ddF_x, ddF_y;
int x, y, px, py;
drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int alpha = 102;

x1 += blur;
y1 += blur;

PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r);
PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r);
PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r);
PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - blur, y1 + r);
// "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
double expFactor = (_activeSurface->format.bytesPerPixel > 2) ? 1.60 : 1.25;
double alpha = (_activeSurface->format.bytesPerPixel > 2) ? 1 : 8;

// These constants ensure a border of 2px on the left and of each rounded square
int xstart = (x1 > 2) ? x1 - 2 : x1;
int ystart = y1;
int width = w + offset + 2;
int height = h + offset + 1;

for (int i = offset; i >= 0; i--) {
int f, ddF_x, ddF_y;
int x, y, px, py;

PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + height - r);
PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + height - r);
PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);

int short_h = height - (2 * r) + 2;
PixelType color = _format.RGBToColor(0, 0, 0);

int short_h = h - (2 * r) + 1;
BE_RESET();

BE_RESET();
// HACK: As we are drawing circles exploting 8-axis symmetry,
// there are 4 pixels on each circle which are drawn twice.
// this is ok on filled circles, but when blending on surfaces,
// we cannot let it blend twice. awful.
uint32 hb = 0;

while (x++ < y) {
BE_ALGORITHM();

// HACK: As we are drawing circles exploting 8-axis symmetry,
// there are 4 pixels on each circle which are drawn twice.
// this is ok on filled circles, but when blending on surfaces,
// we cannot let it blend twice. awful.
uint32 hb = 0;

while (x++ < y) {
BE_ALGORITHM();
if (((1 << x) & hb) == 0) {
blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);

// Will create a dark line of pixles if left out
if (hb > 0) {
blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
}
hb |= (1 << x);
}

if (((1 << x) & hb) == 0) {
blendFill(ptr_tr - px - r, ptr_tr + y - px, 0, alpha);
blendFill(ptr_bl - y + px, ptr_br + y + px, 0, alpha);
hb |= (1 << x);
if (((1 << y) & hb) == 0) {
blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
blendFill(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha);
hb |= (1 << y);
}
}

if (((1 << y) & hb) == 0) {
blendFill(ptr_tr - r - py, ptr_tr + x - py, 0, alpha);
blendFill(ptr_bl - x + py, ptr_br + x + py, 0, alpha);
hb |= (1 << y);
ptr_fill += pitch * r;
while (short_h--) {
blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
ptr_fill += pitch;
}
}

while (short_h--) {
blendFill(ptr_fill - r, ptr_fill + blur, 0, alpha);
ptr_fill += pitch;
// Make shadow smaller each iteration, and move it one pixel inward
xstart += 1;
ystart += 1;
width -= 2;
height -= 2;

if (_shadowFillMode == kShadowExponential)
// Multiply with expfactor
alpha = alpha * expFactor;
}
}

Expand Down
12 changes: 5 additions & 7 deletions graphics/VectorRendererSpec.h
Expand Up @@ -186,10 +186,10 @@ class VectorRendererSpec : public VectorRenderer {
* There functions may be overloaded in inheriting classes to improve performance
* in the slowest platforms where pixel alpha blending just doesn't cut it.
*
* @param blur Intensity/size of the shadow.
* @param offset Intensity/size of the shadow.
*/
virtual void drawSquareShadow(int x, int y, int w, int h, int blur);
virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur);
virtual void drawSquareShadow(int x, int y, int w, int h, int offset);
virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset);

/**
* Calculates the color gradient on a given point.
Expand Down Expand Up @@ -292,10 +292,8 @@ class VectorRendererAA : public VectorRendererSpec<PixelType> {
*/
virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m);

virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur) {
Base::drawRoundedSquareShadow(x, y, r, w, h, blur);
// VectorRenderer::applyConvolutionMatrix(VectorRenderer::kConvolutionHardBlur,
// Common::Rect(x, y, x + w + blur * 2, y + h + blur * 2));
virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset) {
Base::drawRoundedSquareShadow(x, y, r, w, h, offset);
}

virtual void drawTabAlg(int x, int y, int w, int h, int r,
Expand Down
Binary file modified gui/themes/scummclassic.zip
Binary file not shown.
Binary file modified gui/themes/scummmodern.zip
Binary file not shown.
16 changes: 8 additions & 8 deletions gui/themes/scummmodern/scummmodern_gfx.stx
Expand Up @@ -73,7 +73,7 @@
rgb = '255, 255, 255'
/>
<color name = 'shadowcolor'
rgb = '63, 60, 17'
rgb = '105, 101, 86'
/>
<color name = 'darkgray'
rgb = '176, 168, 144'
Expand Down Expand Up @@ -232,7 +232,7 @@
stroke = '0'
gradient_start = 'darkorange'
gradient_end = 'brightorange'
shadow = '3'
shadow = '7'
gradient_factor = '3'
/>
</drawdata>
Expand Down Expand Up @@ -466,7 +466,7 @@
fg_color = 'lightgray2'
fill = 'background'
bg_color = 'xtrabrightred'
shadow = '2'
shadow = '1'
/>

<drawstep func = 'triangle'
Expand Down Expand Up @@ -505,7 +505,7 @@
fg_color = 'lightgray2'
fill = 'background'
bg_color = 'xtrabrightred'
shadow = '2'
shadow = '1'
/>

<drawstep func = 'triangle'
Expand Down Expand Up @@ -663,7 +663,7 @@
fg_color = 'lightgray2'
fill = 'background'
bg_color = 'xtrabrightred'
shadow = '2'
shadow = '1'
/>

<drawstep func = 'triangle'
Expand Down Expand Up @@ -716,7 +716,7 @@
gradient_start = 'blandyellow'
gradient_end = 'xtrabrightred'
fill = 'gradient'
shadow = '3'
shadow = '7'
/>
</drawdata>

Expand All @@ -737,7 +737,7 @@
gradient_start = 'blandyellow'
gradient_end = 'xtrabrightred'
gradient_factor = '4'
shadow = '3'
shadow = '7'
/>
</drawdata>

Expand Down Expand Up @@ -915,7 +915,7 @@
gradient_factor = '6'
fill = 'gradient'
bg_color = 'xtrabrightred'
shadow = '3'
shadow = '7'
/>
</drawdata>

Expand Down

0 comments on commit 5c00dbb

Please sign in to comment.