簡介 倒影可以為 UI 界面帶來立體感,在 UI 中用的很多,如 homescreen、coverflow 等,如下圖所示。 | from 參考資料1 | 實作 reflection 特效可以使用 3D 方法,也可以使用 2D 方法,下面将分别介紹。 2D 方法 用 2D 方法實作倒影(mirror)需要從兩個方面考慮: - 倒影(mirror)是将原來的圖像上、下翻轉過來;
- 從上到下半透明度的漸變效果。
以 QT 為例,生成一幅圖像的 mirror 的僞代碼如下所示: ... ...
QImage mirrorImage (const QImage &img,
MirrorStyle mirrorStyle=MirrorOverX,
FadeStyle fadeStyle=FadeDown)
{
/* Reverse image */
QImage tmpImage = img;
if (mirrorStyle != NoMirror)
tmpImage = tmpImage.mirrored(mirrorStyle == MirrorOverY,
mirrorStyle == MirrorOverX);
/*Add gradient to mirrored image.*/
if (fadeStyle != NoFade) {
QPoint p1, p2;
if (fadeStyle == FadeDown)
p2.setY(tmpImage.height());
else if (fadeStyle == FadeUp)
p1.setY(tmpImage.height());
else if (fadeStyle == FadeRight)
p2.setX(tmpImage.width());
else if (fadeStyle == FadeLeft)
p1.setX(tmpImage.width());
QLinearGradient gradient(p1, p2);
gradient.setColorAt(0, QColor(0, 0, 0, 100));
gradient.setColorAt(1, Qt::transparent);
QPainter p(&tmpImage);
p.setCompositionMode(QPainter::CompositionMode_DestinationIn);
p.fillRect(0, 0, tmpImage.width(), tmpImage.height(), gradient);
p.end();
}
return tmpImage;
}
在上面的代碼中用到了 QImage 的一個方法 mirrored,它的功能是将 image 的 資料按行上下對換,比如一幅 MxN 的圖像,第 0 行與第 m-1 行對換,第 1 行 與第 m-2 行對換,依此類推,得到的結果是圖像翻轉過來,也就是 mirror。以 24 位色的圖像為例,算法實作如下所示: QImage QImage::mirrored(bool horizontal, bool vertical) const
{
... ...
// Create result image, copy colormap
QImage result(d->width, d->height, d->format);
result.d->colortable = d->colortable;
result.d->has_alpha_clut = d->has_alpha_clut;
int dxi = horizontal ? -1 : 1;
int dxs = horizontal ? w-1 : 0;
int dyi = vertical ? -1 : 1;
int dy = vertical ? h-1: 0;
... ...
// 24 bit
if (d->depth == 24) {
for (int sy = 0; sy < h; sy++, dy += dyi) {
quint24* ssl = (quint24*)(d->data + sy*d->bytes_per_line);
quint24* dsl = (quint24*)(result.d->data + dy*result.d->bytes_per_line);
int dx = dxs;
for (int sx = 0; sx < w; sx++, dx += dxi)
dsl[dx] = ssl[sx];
}
}
... ...
return result;
}
把 mirror 顯示在 image 的下方就産生了 reflection 效果,僞代碼如下所示: void drawItemAt (QPainter *p, const QImage &img, ...)
{
p->save ();
const QImage mirror = mirrored (image);
QPointF pt(-img.height()/2, -img.height()/2);
... ...
QPointF pt2(pt.x(), img.height()/2);
p->save();
p->setCompositionMode(QPainter::CompositionMode_Source);
p->drawImage(pt2, mirror);
p->restore();
p->drawImage(pt, img);
p->restore();
}
3D 方法 效果圖如下所示: | from 參考資料3 | 在 OpenGL 中實作 mirror 效果使用如下技術: - blend
- 紋理坐标自動生成
- 球體紋理
僞代碼如下所示3 : void DrawObject()
{
glColor3f(1.0f, 1.0f, 1.0f); // Set Color To White
glBindTexture(GL_TEXTURE_2D, texture[1]); // Select Texture 2 (1)
gluSphere(q, 0.35f, 32, 16); // Draw First Sphere
glBindTexture(GL_TEXTURE_2D, texture[2]); // Select Texture 3 (2)
glColor4f(1.0f, 1.0f, 1.0f, 0.4f); // Set Color To White With 40% Alpha
glEnable(GL_BLEND); // Enable Blending
glBlendFunc(GL_SRC_ALPHA, GL_ONE); // Set Blending Mode To Mix Based On SRC Alpha
glEnable(GL_TEXTURE_GEN_S); // Enable Sphere Mapping
glEnable(GL_TEXTURE_GEN_T); // Enable Sphere Mapping
gluSphere(q, 0.35f, 32, 16); // Draw Another Sphere Using New Texture
// Textures Will Mix Creating A MultiTexture Effect (Reflection)
glDisable(GL_TEXTURE_GEN_S); // Disable Sphere Mapping
glDisable(GL_TEXTURE_GEN_T); // Disable Sphere Mapping
glDisable(GL_BLEND); // Disable Blending
}
Reference - reflections
- 使用 2D 方法實作倒影特效
- Nehe Lesson 26
|