天天看點

/LGC圖形渲染/倒影(reflection)特效的實作

倒影(reflection)特效的實作 作者: 劉鵬 日期: 2010-06-09 本文詳細介紹了如何實作 reflection 特效。

簡介

倒影可以為 UI 界面帶來立體感,在 UI 中用的很多,如 homescreen、coverflow 等,如下圖所示。
/LGC圖形渲染/倒影(reflection)特效的實作
from 參考資料1
實作 reflection 特效可以使用 3D 方法,也可以使用 2D 方法,下面将分别介紹。

2D 方法

用 2D 方法實作倒影(mirror)需要從兩個方面考慮:
  1. 倒影(mirror)是将原來的圖像上、下翻轉過來;
  2. 從上到下半透明度的漸變效果。
以 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 方法

效果圖如下所示:
/LGC圖形渲染/倒影(reflection)特效的實作
from 參考資料3
在 OpenGL 中實作 mirror 效果使用如下技術:
  1. blend
  2. 紋理坐标自動生成
  3. 球體紋理
僞代碼如下所示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

  1. reflections
  2. 使用 2D 方法實作倒影特效
  3. Nehe Lesson 26