サンプル

プロジェクションシャドウ

プロジェクションシャドウ - MascotCapsule eruption

ここではプロジェクションシャドウについて解説します。




※ BREW 3.1は非対応となります。

目次


モデルの影を描画する手法で、影生成方向から見たモデルのシルエットを影用テクスチャに描画し、影用テクスチャを射影対象のモデルにマッピングすることで影を表現します。


1. 影生成の初期化

影生成のためには、プロジェクタとして使用する mceCamera 、テクスチャを生成する mceTexture 、カメラやテクスチャを設定する mceAppearance を用意する必要があります。 ここで注意する点は、mceTexture_create( gID, format, width, height, useMipmap, exception ) で影用テクスチャを生成し、引数 format は必ず、mcePixelFormat_DPY を指定することです。

#define ANGLE        (360)                /* 角度 */

    (中略)

typedef struct tagWork
{
    (中略)

    mceGraphics3D *G3d;                   /* Graphics3D        */

    (中略)

    mceFigure        *Figure0;            /* Figure0           */
    mceFigure        *Figure1;            /* Figure1           */

    (中略)

    mceAppearance   *Appe0;               /* Appearance    */
    mceAppearance   *Appe1;               /* Appearance    */

    (中略)

    mceCamera        *ShadowCamera;       /* ShadowCamera      */
    mceTexture       *ShadowTexture;      /* ShadowTexture     */
    mceAppearance    *ShadowAppe;         /* ShadowAppearance  */
    mceAppearance    *BlackAppe;          /* ShadowAppearance  */

    (中略)
} WORK;
hi_exception exception;

    (中略)

/* プロジェクタとして使用するカメラを生成 */
work->ShadowCamera = mceCamera_create (&exception);
if ((work->ShadowCamera == NULL) || (exception != hi_NoException))
{
    return 1;
}

/* 投影方法の設定 */
exception = mceCamera_setPerspectiveFov (work->ShadowCamera,
                                         work->AspectRate,
                                         work->ViewAngle / ANGLE,
                                         work->NearClip,
                                         work->FarClip);
if (exception != hi_NoException)
{
    return 1;
}

/* 影用テクスチャを生成 */
work->ShadowTexture = mceTexture_create (100, mcePixelFormat_DPY,
                                         256, 256, HI_FALSE, &exception);
if ((work->ShadowTexture == NULL) || (exception != hi_NoException))
{
    return 1;
}

/* 影用mceAppearanceを生成 */
work->ShadowAppe = mceAppearance_create (&exception);
if ((work->ShadowAppe == NULL) || (exception != hi_NoException))
{
    return 1;
}

/* 影用mceAppearanceのテクスチャを設定 */
exception = mceAppearance_setTexture (work->ShadowAppe, 0,
                                      work->ShadowTexture);
if (exception != hi_NoException)
{
    return 1;
}

/* 影用mceAppearanceのブレンドモードを設定 */
exception = mceAppearance_setBlendMode (work->ShadowAppe,
                                        mceAppearance_BlendMode_MODULATE);
if (exception != hi_NoException)
{
    return 1;
}

/* 影用mceAppearanceのテクスチャブレンドモードを設定 */
exception = mceAppearance_setTextureBlendMode (work->ShadowAppe, 0,
                                               mceAppearance_Texture_FUNC_REPLACE);
if (exception != hi_NoException)
{
    return 1;
}

/* 影用mceAppearanceに設定するテクスチャの種別を指定 */
exception = mceAppearance_setTextureType (work->ShadowAppe, 0,
                                          mceAppearance_TextureType_PROJECTIVE);
if (exception != hi_NoException)
{
    return 1;
}

/* 影用mceAppearanceに設定するテクスチャのラッピングモードを指定 */
exception = mceAppearance_setTextureWrapMode (work->ShadowAppe, 0,
                                              MCE_TEXTURE_WRAP_CLAMP,
                                              MCE_TEXTURE_WRAP_CLAMP);
if (exception != hi_NoException)
{
    return 1;
}

/* プロジェクタとして使用するカメラを設定 */
exception = mceAppearance_setProjector (work->ShadowAppe, 0,
                                        work->ShadowCamera);
if (exception != hi_NoException)
{
    return 1;
}

/* 射影対象モデルと影用テクスチャの重なりをデプスオフセット値で補正 */
exception = mceAppearance_setPolygonOffset (work->ShadowAppe,
                                            MCE_F2C (-0.1f), MCE_F2C (-0.1f));
if (exception != hi_NoException)
{
    return 1;
}

/* 影用mceAppearanceのプロパティにMCE_APPEARANCE_DEPTHOFFSETを追加 */
exception = mceAppearance_setProperties (work->ShadowAppe,
                                         mceAppearance_getProperties (work->ShadowAppe) |
                                         MCE_APPEARANCE_DEPTHOFFSET);
if (exception != hi_NoException)
{
    return 1;
}

/* 射影対象モデルに生成した影用mceAppearanceを設定 */
mceFigure_setAppearance (work->Figure0, work->ShadowAppe);

work->BlackAppe = mceAppearance_create (&exception);
if ((work->BlackAppe == NULL) || (exception != hi_NoException))
{
    return 1;
}

exception = mceAppearance_setColor(work->BlackAppe,
                                   mceAppearance_MaterialType_DIFFUSE, 0xff000000);
if (exception != hi_NoException)
{
    return 1;
}

mceFigure_setAppearance (work->Figure1, work->BlackAppe);

work->Appe0 = (mceAppearance *)mceObject3D_findObject3D (
                              (mceObject3D *)work->Figure0, ClassId_Appearance, 0);
if (work->Appe0 == NULL)
{
    return 1;
}

work->Appe1 = (mceAppearance *)mceObject3D_findObject3D (
                              (mceObject3D *)work->Figure1, ClassId_Appearance, 0);
if (work->Appe1 == NULL)
{
    return 1;
}



2. 影生成

レンダリングターゲットの設定、プロジェクタの設定、影用テクスチャの描画クリア、影生成したいモデルの描画、そしてレンダリングターゲットの解除の順で行います。
レンダリングターゲットの設定と解除以外は、「3D モデルの描画」のドキュメントページに記述されている通常のモデル描画処理と変わりありませんが、必ず影生成したいモデルの描画は設定したプロジェクタ内に収まる位置に描画するようにしてください。

#define ANGLE        (360)                 /* 角度 */

    (中略)

typedef struct tagWork
{
    (中略)

    mceGraphics3D *G3d;                    /* Graphics3D */

    (中略)

    mceFigure       *Figure1;              /* Figure1       */

    (中略)

    mceAppearance   *Appe1;                /* Appearance    */

    (中略)

    mceCamera       *ShadowCamera;         /* ShadowCamera     */
    mceTexture      *ShadowTexture;        /* ShadowTexture    */

    (中略)
} WORK;
hi_exception exception;

Transform matrix;
Transform matrix2;
Vector3D  rotate;

    (中略)

/* 影用テクスチャをレンダリングターゲットにする */
exception = mceGraphics3D_bindRenderTarget (work->G3d,
                                            work->ShadowTexture);
if (exception != hi_NoException)
{
    return 1;
}

    (中略)

/* カメラを設定 */
exception = mceGraphics3D_setCamera (work->G3d, work->ShadowCamera,
                                     &matrix);
if (exception != hi_NoException)
{
    return 1;
}

/* プロジェクタのワールド変換 */
exception = mceGraphics3D_setProjectorTransform (work->G3d, 0,
                                                 &matrix);
if (exception != hi_NoException)
{
    return 1;
}

exception = mceAppearance_setProperties (work->Appe1,
                                         mceAppearance_getProperties (work->Appe1) |
                                         MCE_APPEARANCE_USE_FIGURE_APPEARANCE);
if (exception != hi_NoException)
{
    return 1;
}

/* 影用テクスチャの描画クリア */
exception = mceGraphics3D_clear (work->G3d,
                                 MCE_GRAPHICS3D_CLEAR_DEPTH |
                                 MCE_GRAPHICS3D_CLEAR_COLOR,
                                 0xffffffff);
if (exception != hi_NoException)
{
    return 1;
}

/* 影生成したいモデルの描画位置を設定 */
mceTransform_setTranslate (&matrix,
                           MCE_F2C (0.0f), MCE_F2C (0.0f), MCE_F2C (0.0f));

mceVector3D_set           (&rotate,
                           MCE_F2C (0.0f), MCE_F2C (1.0f), MCE_F2C (0.0f));
mceTransform_setRotate    (&matrix2, &rotate, work->ObjRy / ANGLE);
mceTransform_multiply     (&matrix, &matrix2);

/* 影生成したいモデルを影用テクスチャへ描画 */
exception = mceGraphics3D_drawFigure (work->G3d, work->Figure1,
                                      &matrix, 0);
if (exception != hi_NoException)
{
    return 1;
}

exception = mceGraphics3D_flush (work->G3d);
if (exception != hi_NoException)
{
    return 1;
}

/* 影用テクスチャをレンダリングターゲットから外す */
mceGraphics3D_releaseRenderTarget (work->G3d);


3. 影の描画

生成した影用テクスチャを射影対象モデルにマッピングするには、まず射影対象モデルに対して mceAppearance_setProperties( This, properties ) を用いてプロパティに MCE_APPEARANCE_USE_FIGURE_APPEARANCE を適用します。その結果、射影対象モデルに設定していた影用mceAppearance が使用できるようになり、射影対象モデルを描画することで影用テクスチャがマッピングされます。
なお、実際には影用mceAppearance を適用していない射影対象モデルと適用した射影対象モデルの 2 つを描画することで影を表現します。

#define ANGLE        (360)           /* 角度 */

    (中略)

typedef struct tagWork
{
    (中略)

    mceGraphics3D   *G3d;            /* Graphics3D */

    (中略)

    mceFigure       *Figure0;        /* Figure0       */

    (中略)

    mceAppearance   *Appe0;         /* Appearance    */
    mceAppearance   *Appe1;         /* Appearance    */

    (中略)

    hi_coord ObjRy;                  /* オブジェクトY軸回転 */

    (中略)
} WORK;
hi_exception exception;

mceTransform matrix;
mceTransform matrix2;
mceVector3D  rotate;

    (中略)

/* 射影対象モデルの位置設定 */
mceTransform_setTranslate (&matrix,
                           MCE_F2C (0.0f), MCE_F2C (0.0f), MCE_F2C (0.0f));

mceVector3D_set           (&rotate,
                           MCE_F2C (0.0f), MCE_F2C (1.0f), MCE_F2C (0.0f));
mceTransform_setRotate    (&matrix2, &rotate, work->ObjRy / ANGLE);
mceTransform_multiply     (&matrix, &matrix2);

/*影用mceAppearanceを適用していない射影対象モデルを描画 */
exception = mceGraphics3D_drawFigure (work->G3d, work->Figure0,
                                      &matrix, 0);
if (exception != hi_NoException)
{
    return 1;
}

/*射影対象モデルに影用mceAppearanceを適用する */
exception = mceAppearance_setProperties (work->Appe0,
                                         mceAppearance_getProperties (work->Appe0) |
                                         MCE_APPEARANCE_USE_FIGURE_APPEARANCE);
if (exception != hi_NoException)
{
    return 1;
}

/*影用mceAppearanceを適用した射影対象モデルを描画 */
exception = mceGraphics3D_drawFigure (work->G3d, work->Figure0,
                                      &matrix, 0);
if (exception != hi_NoException)
{
    return 1;
}

/* 射影対象モデルに影用mceAppearanceを適用しない */
exception = mceAppearance_setProperties (work->Appe0,
                                         mceAppearance_getProperties (work->Appe0) &
                                         ~MCE_APPEARANCE_USE_FIGURE_APPEARANCE);
if (exception != hi_NoException)
{
    return 1;
}

exception = mceAppearance_setProperties (work->Appe1,
                                         mceAppearance_getProperties (work->Appe1) &
                                         ~MCE_APPEARANCE_USE_FIGURE_APPEARANCE);
if (exception != hi_NoException)
{
    return 1;
}
描画結果 影用mceAppearanceを 適用していない床モデル 描画結果 影用mceAppearanceを 適用した床モデル
影用mceAppearanceを
適用していない床モデル
影用mceAppearanceを
適用した床モデル
描画結果 影生成
影生成
描画結果



このページの先頭へ戻る