• Direct3D 11のカリング設定

    2011年07月13日 22時55分
    前回の続き。

    影が真っ黒になる問題がありましたが、結局原因は解らず諦めました。
    Specularの計算中powを使うのですが、これの結果がやたらとマイナスの値になるため、
    最終的に合算した色が真っ黒になるようです。

    ただ、powに渡している引数を何度確認してもそんな結果になるはずはなく、
    コンパイラかドライバの問題ではないだろうか・・・と思います。

    if文で切ったりすると、powの累乗数の方に渡している変数が0でおかしくなっているような気がするのですが、
    0を直接書くと正常に動いたりするのでもうわけわからんです。

    powの累乗数に0を指定すると不正なのでコンパイラが関数ごとカットしていたりするのかもしれません。
    コンパイル後のバイトコードを確認すればわかるかもしれませんが日曜プログラマがそこまで出来るわけありません。


    とりあえず回避は出来るのでそれで良しとしました。正常に表示されています。
    真っ黒修正版



    次に気になるのは髪の毛ですね。消えてしまっています。
    これはカリングのせいでしょう。MMDはカリングを無効化する必要があるようです。

    Direct3D 11でカリングを設定する方法ですが、
    Direct3D 9のように、SetRenderStateで設定してはい終わり。というわけには行きません。

    次の手順が必要です。
    1. D3D11_RASTERIZER_DESCにラスタライザの設定を入れる
    2. D3D11_RASTERIZER_DESCをID3D11Device.CreateRasterizerStateに渡してID3D11RasterizerStateを生成
    3. ID3D11DeviceContext.RSSetStateにID3D11RasterizerStateをセット
    4. ID3D11RasterizerStateは終了時にReleaseを忘れずに

    超面倒くさいです。
    予めID3D11RasterizerStateを複数生成しておいて、切り替えて使用することを想定した実装なのでしょうが、
    ちょいとカリング設定すっか!というノリで調べ始めたボクはくじけそうです。

    今回はカリング無しに設定しました。
    1D3D11_RASTERIZER_DESC rasterizerDesc;
    2rasterizerDesc.FillMode = D3D11_FILL_MODE.D3D11_FILL_SOLID;
    3rasterizerDesc.CullMode = D3D11_CULL_MODE.D3D11_CULL_NONE;
    4rasterizerDesc.DepthClipEnable = FALSE;
    5rasterizerDesc.MultisampleEnable = FALSE;
    6rasterizerDesc.DepthBiasClamp = 0;
    7rasterizerDesc.SlopeScaledDepthBias = 0;



    裏面がレンダリングされるようになったため、髪の毛が表示されています。
    カリング修正版
  • CentOS5.6(32bit)でdmd2.053を使う話

    2011年07月03日 11時35分
    dmd2.053に付属するlinuxバイナリは、GLIBC 2.11を要求してきます。

    しかし、CentOS5.6(32bit)に入っているGLIBCはだいぶ古いので、
    そのままでは動作させることが出来ません。

    最初GLIBCをバージョンアップしようとしたのですが、
    RPMは無いようですし、ソースからビルドする方法もよくわかりませんでした。


    そこで、dmdの方をCentOS上でビルドしなおしました。


    makeを叩いて出来たファイルで上書きするだけです。
    # cd dmd2/src/dmd/
    # make -f linux.mak
    # mv dmd ../../linux/bin32/



    druntimeも同様です
    # cd dmd2/src/druntime/
    # make -f linux.mak
    # mv libdruntime.a ../../linux/lib32/



    普段はダウンロードしたバイナリをそのまま使っているだけなので、
    自分でビルドするという発想はなかなか出てこないものです。
  • SysTimeとimmutable

    2011年06月29日 23時16分
    日付型は自作のclassを使っていたのですが、
    せっかくstd.datetimeが入ったので置き換えました。

    その中にimmutableなclass内にSysTimeが入るケースがありまして、ここでエラーが出ました。
    1import std.datetime;
    2
    3immutable
    4class Homuhomu
    5{
    6    SysTime time;
    7
    8    this(SysTime t)
    9    {
    10        time = t;
    11    }
    12}


    test.d(10): Error: function std.datetime.SysTime.opAssign (ref const const(SysTime) rhs) is not callable using argument types (SysTime) immutable
    test.d(8): Error: constructor test.Homuhomu.this missing initializer for final field time


    コンストラクタではなくopAssignが呼ばれてしまい、エラーになるようです。


    C++のように初期化リストが有ったか?と思ったけど、これは無かった。
    1this(SysTime t) : time(t) // この書き方は無い



    仕様として合ってるかは不明ですが、一応次の様に書くとコンストラクタが呼ばれるような気がします。
    (コピーコンストラクタは無いのでstdTimeを介して渡す)
    1this(SysTime t)
    2{
    3    time(t.stdTime);
    4}


    でも、コンストラクタを呼べと怒られてしまいます。実際は呼べてないのかもしれません。
    test.d(8): Error: constructor test.Homuhomu.this missing initializer for final field time



    困り果てた僕は救いを求めてD言語スレに書き込みました。

    (#゚Д゚) < immutableがクサッテル!!



    すると心優しい住人が答えてくれました。

    (゜Д゜)< immutableなんか使う奴は池沼



    おかげで僕のガラスハートはブロークンですが、
    なんやかんやで回避方法を思いつきました。

    1import std.datetime;
    2
    3//immutable
    4class Homuhomu_
    5{
    6    SysTime time;
    7
    8    this(SysTime t)
    9    {
    10        time = t;
    11    }
    12}
    13alias immutable(Homuhomu_) Homuhomu;


    これで試した範囲では正常に動いています。
    1auto homuhomu = new Homuhomu(Clock.currTime());


    回避は出来たけどそもそもどこが悪いのかよくわからない。
  • SDLモジュールをさらに更新

    2011年04月13日 23時15分
    情報をいただいたので修正しました。

    SDL for D version 1.2.14.4

    • ttfのUnicode系関数の引数をUint16からwcharに変更しました
    • mixerとimageのenumにaliasを追加しました
  • SDL_imageとSDL_ttfとSDL_netを追加

    2011年04月12日 00時25分
    あと使いそうなのがimage、ttf、netあたりでしょうか。とりあえず入れておきました。


    SDL for D version 1.2.14.3


    3つ同時に試したのでごちゃごちゃしてますが、
    一応基本的なとこは動くのを確認しましたってことで。
    1import core.runtime;
    2import std.c.windows.windows;
    3import org.libsdl.sdl;
    4import org.libsdl.image;
    5import org.libsdl.ttf;
    6import org.libsdl.net;
    7
    8extern (Windows)
    9int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
    10{
    11    void exceptionHandler(Throwable e)
    12    {
    13        throw e;
    14    }
    15
    16    int result;
    17    try
    18    {
    19        Runtime.initialize(&exceptionHandler);
    20        scope (exit) Runtime.terminate(&exceptionHandler);
    21
    22        dmain();
    23    }
    24    catch (Throwable o)
    25    {
    26        MessageBoxA(nullcast(char*)(o.toString() ~ '\0').ptr, "Error\0".ptr, MB_OK | MB_ICONEXCLAMATION);
    27        result = 1;
    28    }
    29
    30    return result;
    31}
    32
    33// 画面サイズ
    34immutable int SCREEN_WIDTH = 640;
    35immutable int SCREEN_HEIGHT = 680;
    36
    37void dmain()
    38{
    39    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) < 0)
    40        throw new Error("SDL_Init failed.");
    41    scope(exit) SDL_Quit();
    42
    43    SDL_Surface* screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 32, SDL_HWSURFACE);
    44    if (screen is null)
    45        throw new Error("SDL_SetVideoMode failed.");
    46
    47
    48    // 画像の読み込みと解放
    49    SDL_Surface* image = IMG_Load("hoge.png");
    50    if (image is null)
    51        throw new Error("IMG_Load failed.");
    52    scope(exit) SDL_FreeSurface(image);
    53
    54
    55    // SDL_netの初期化と解放
    56    if(SDLNet_Init() != 0)
    57        throw new Error("SDLNet_Init failed.");
    58    scope(exit) SDLNet_Quit();
    59
    60    // ホスト名からIPアドレスを取得
    61    IPaddress address;
    62    if(SDLNet_ResolveHost(&address, "ku6.jp\0".ptr, 80))
    63        throw new Error("SDLNet_Init failed.");
    64
    65    // TCP接続のオープンとクローズ
    66    TCPsocket socket = SDLNet_TCP_Open(&address);
    67    if (socket is null)
    68        throw new Error("SDLNet_TCP_Open failed.");
    69    scope(exit) SDLNet_TCP_Close(socket);
    70
    71    // HTTPリクエストを送信
    72    string message = "GET /SDL_net.txt HTTP/1.0\r\n\r\n";
    73    SDLNet_TCP_Send(socket, message.ptr, message.length);
    74
    75    // 結果を受信
    76    char[] buffer = new char[64 * 1024];
    77    SDLNet_TCP_Recv(socket, buffer.ptr, buffer.length - 1);
    78
    79    // 各行の先頭ポインタを収集しつつ改行コードを文字終端とする
    80    char*[] lines = [buffer.ptr];
    81    for (uint i; i < buffer.length - 1; ++i)
    82    {
    83        if (buffer[i] == '\r')
    84        {
    85            buffer[i] = 0;
    86            if (buffer[i + 1] == '\n')
    87                lines ~= &buffer[i + 2];
    88            ++i;
    89        }
    90        else if (buffer[i] == '\n')
    91        {
    92            buffer[i] = 0;
    93            lines ~= &buffer[i + 1];
    94        }
    95    }
    96
    97
    98    // TTFの初期化と解放
    99    if(TTF_Init() != 0)
    100        throw new Error("TTF_Init failed.");
    101    scope(exit) TTF_Quit();
    102
    103    // フォントの取得と解放
    104    TTF_Font* font = TTF_OpenFont("ipam.ttf", 16);
    105    if (font is null)
    106        throw new Error("TTF_OpenFont failed.");
    107    scope(exit) TTF_CloseFont(font);
    108
    109    // 各行のテキストサーフェスの作成
    110    SDL_Color color = SDL_Color(128, 255, 128);
    111    SDL_Surface*[] textSurfaces;
    112    foreach (line; lines)
    113        textSurfaces ~= TTF_RenderUTF8_Solid(font, line, color);
    114
    115
    116    for (;;)
    117    {
    118        SDL_Event event;
    119        while (SDL_PollEvent(&event))
    120        {
    121            if (event.type == SDL_QUIT)
    122                return;
    123        }
    124
    125        // 画像の表示
    126        SDL_BlitSurface(image, null, screen, null);
    127
    128        // テキストの表示
    129        SDL_Rect rect;
    130        for (uint i; i < textSurfaces.length; ++i)
    131        {
    132            rect.y = cast(short)(18 * i);
    133            SDL_BlitSurface(textSurfaces[i], null, screen, &rect);
    134        }
    135
    136        // 画面の更新
    137        SDL_UpdateRect(screen, 0, 0, 0, 0);
    138    }
    139}


    SDL_Netがイマイチ使い方よくわからんのですが、一応上のコードで動いてはいます。


    あと、SDL_xxxをいっぱい足していったら、DLLが15個も並びました。
    なんかドキドキします。