【ゲーム制作】No.13: VPDファイルの読み込みと描画(Direct3D11)

今回はMMDファイル関連であるVPDファイルの読み込みと描画になります。
MMDファイルでいうと、モデル(PMDファイル/PMXファイル)、モーション(VMDファイル)、ポーズ(VPDファイル)の中で
三番目のポーズ機能(VPDファイル)になります。

 

①VPDファイルの読み込み(VPDパーサー)の実装

VPDファイル読み込みの為のVPDパーサーは今回新規に作りました。
設計はstd::wifstreamの標準C++ストリームとstd::getline()による1行読み出しによる
標準なもの。トータル400行ぐらいでした。

 

途中のトラブルは文字化けが出たぐらい。
理由はわかってないですけど、以下の1行で治りました。


std::wifstream ifs;
ifs.open( vpd_file_name, std::ios::in | std::ios::binary);
ifs.imbue(std::locale("", LC_CTYPE));    // これを入れないと文字化けになる


②VPDファイルの描画

結論からいうと、VPDファイルの実装はまったくありませんでした。
元々PMXファイルへの描画機能とVMDファイルによるモーションは

既に実装済みだった為、そこにVPDファイルを変換することで描画は出来ました。


図でいうと以下のような形です。

 ①VMD描画 VMDファイル → VMDパーサー(既存)→ モーション管理クラス(pmx_motion_t) → D3D描画クラス → 描画
 ②VPD描画 VPDファイル → VPDパーサー(新規) → モーション管理クラス(pmx_motion_t) → D3D描画クラス → 描画

 

自分のようにPMXファイルによる描画とVMDファイルによるモーションが既に

実装済みだったなら、MMDなどのアプリでVPDファイルからVMDファイルに変換し、

VMDファイルでポーズ画像を描画することでも実装無しで実装可能です。

 

③VPDファイルの仕様

VPDファイルの描画をするにあたってVPDファイルの仕様やフォーマットを
いろいろ調査したのですが、それらしき情報がまったく無くて

これが一番苦労しました。
MMDはとても素晴らしいものですが、仕様となると途端に無くなる。
勝手にやれの一点張り。こういうところが弱点だなぁと思いました。

 

VPDファイルは基本的に以下の繰り返しですが、

 

Bone1{上半身
  0.000000,0.000000,0.000000;                // trans x,y,z
  0.088801,0.153755,0.013875,0.984011;        // Quaternion x,y,z,w
}
// 以下これが続く・・

 

「Vaporlock V1.00.zip」の「球体ポーズ.vpd」には、

 

Morph0{まばたき
  1;
}

のようなブロックもあります。


グループモーフが最も近いですが、仕様がわからず・・

 

また「Vaporlock V1.00.zip」ですが、
readmeには「そぼろ様のAutoLuminusに対応しており・・」とありますが
詳細がわからない・・発光する機能だろうけど・・

 

④画像比較

以下MMDと自作のポーズ画像の比較になります。

 

MMD側は「MikuMikuDance_v926x64」「自作」

 

モデルは「初音ミク イミテーションv1ミニマム2.pmx」「Vaporlock V1.00t.pmx」

 

ポーズは順に「miku.vpd(sm18628875)」「四脚ポーズ.vpd(Vaporlock V1.00)」「球体ポーズ.vpd(Vaporlock V1.00)」

 

【ゲーム制作】No.12: 無限平面の描画(Direct3D11)

今回は無限平面の描画エフェクトの実装になります。
以下みたいな実装のことですね。

 

自分が勝手に思っているだけなんですが、
無限平面の描画というのは、
ゲームプログラミングにおいて必ず通る道みたいなものであり
ただ実装するには必要となる数学も結構必要で
手ごわい中ボスって感じです。
これをこなすことでゲームプログラマーの四天王最弱になれる!!って
感じです。皆さんも是非試してください。

 

実装するにあたっての資料をネット上から探したところ、
有名どころとして以下の3点がありました。

 

①[Unity]無限平面を描画する過程でGPUの理解を深める

日本語で図も複数あり、丁寧に説明してあります。
ただ、環境がUnityだったので、デバッグ環境が無く
Unity専用の関数UnityWorldToClipPos()やTRANSFORM_TEXマクロ
なども複数使われており、チャレンジしてみましたが

私の技術が足りず、実装までは至りませんでした。

 

②【Unity道場 2月】シェーダを書けるプログラマになろう

これも技術的には①と同様。より説明メインで
とても勉強にはなりましたが、これで実装はちょっと無理でした。

 

③How to make an infinite grid.

英語ですが、説明が最小限でシンプル、1ステップ1ステップ
丁寧に説明されているのでわかりやすいです。
GLSLなのが残念でしたが、私は今回この資料で実装しました。
調べてみると多くの人が参考にしているようで
大人気(?)だと思いました。

以下にフルソースもあるので参考にしてください。
内容も100%同じではなく多少改善しているみたいです。

 

実際の実装は以下です。
Direct3D11への移植は、特に問題なくストレートに移植出来た様に

思います。

ソース全てのアップは難しいのでエフェクトファイルのみ

載せておきます。

--------------------------------------------

infinite_plane_effect.fx

--------------------------------------------

#include "common_definition.hlsl"
#include "math.hlsl"

//--------------------------------------------------------------------------------------
// Constant buffers
//--------------------------------------------------------------------------------------
cbuffer cb_view_transform
{
    float4x4_t    g_mView;
    float4x4_t    g_mProj;
    float4x4_t    g_m_inv_view;
    float4x4_t    g_m_inv_proj;
};

static const float3_t g_grid_plane[6] = 
{
    float3_t(1, 1, 0),   float3_t(-1, -1, 0), float3_t(-1, 1, 0),
    float3_t(-1, -1, 0), float3_t(1, 1, 0),   float3_t(1, -1, 0)
};

static const float_t x_axis_width    = 10.0;
static const float_t z_axis_width    = 10.0;
static const float_t near_plane    = 0.1;
static const float_t far_plane    = 100;
static const float_t plane_width_scale_0    = 0.1;        // plane四角形のサイズを指定。0.1がデフォルト。0.1→0.05で四角形のサイズが増える。;
static const float_t plane_width_scale_1    = 0.1;        // グリッド線の中のテクスチャ個数を指定。0.1がデフォルト。0.1→0.05でテクスチャ個数が増える。;
static const float_t plane_color_intensity    = 0.75;    // テクスチャ画像の色の濃さを指定。0.75がデフォルト。0.75→0.5→0.25で白→黒;

//--------------------------------------------------------------------------------------
// State
//--------------------------------------------------------------------------------------
RasterizerState g_state_render_solid
{
    FillMode                = SOLID;
    CullMode                = NONE;
    FrontCounterClockwise    = FALSE;
    DepthBias                = 0;
    SlopeScaledDepthBias    = 0.0f; 
    DepthBiasClamp            = 0.0f;
    DepthClipEnable            = FALSE; 
    ScissorEnable            = FALSE;
    MultisampleEnable        = FALSE;
    AntialiasedLineEnable    = FALSE;
};

BlendState g_state_no_blend
{
    AlphaToCoverageEnable        = FALSE;
    BlendEnable[0]                = FALSE;
    SrcBlend[0]                    = ONE;
    DestBlend[0]                = ZERO;
    BlendOp[0]                    = ADD;
    SrcBlendAlpha[0]            = ONE;
    DestBlendAlpha[0]            = ZERO;
    BlendOpAlpha[0]                = ADD;
    RenderTargetWriteMask[0]    = 0x0f;
    BlendEnable[1]                = FALSE;
    RenderTargetWriteMask[1]    = 0x00;
};

BlendState g_state_blend_alphablend_on
{
    AlphaToCoverageEnable        = FALSE;
    BlendEnable[0]                = TRUE;
    SrcBlend[0]                    = SRC_ALPHA;
    DestBlend[0]                = INV_SRC_ALPHA;
    BlendOp[0]                    = ADD;
    SrcBlendAlpha[0]            = ONE;
    DestBlendAlpha[0]            = ONE;
    BlendOpAlpha[0]                = ADD;
    RenderTargetWriteMask[0]    = 0x0f;
    BlendEnable[1]                = FALSE;
    RenderTargetWriteMask[1]    = 0x00;
};

DepthStencilState g_state_disable_depth
{
    DepthEnable        = FALSE;
    StencilEnable    = FALSE;
};

DepthStencilState g_state_enable_depth
{
    DepthEnable        = TRUE;
    DepthWriteMask    = ALL;
    DepthFunc        = LESS;
    StencilEnable    = FALSE;
};

//--------------------------------------------------------------------------------------
// Textures
//--------------------------------------------------------------------------------------
Texture2D    g_tex_decal;

//--------------------------------------------------------------------------------------
// Texture samplers
//--------------------------------------------------------------------------------------
SamplerState g_sam_linear
{
    Filter = ANISOTROPIC;
    AddressU = WRAP;
    AddressV = WRAP;
    //AddressU = Border;
    //AddressV = Border;
    //BorderColor    = float4_t(1,1,1,1);
};

struct draw_infinite_grid__VS_input_t
{
    float4_t    position    : POSITION;
    uint_t        vertex_id    : SV_VertexID;
};

struct draw_infinite_grid__VS_output_t
{
    float4_t    vertex_position_inWVP    : SV_POSITION;
    float3_t    near_point                : TEXCOORD0;
    float3_t    far_point                : TEXCOORD1;
};

//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------
float3_t unproject_point(    const in float_t    x,
                            const in float_t    y,
                            const in float_t    z,
                            const in float4x4_t    inv_view,
                            const in float4x4_t    inv_proj)
{
    const float4x4_t    inv_view_inv_proj    = mul(inv_proj, inv_view);
    const float4_t        unprojected_point    = mul( float4_t(x, y, z, 1.0), inv_view_inv_proj);
    return unprojected_point.xyz / unprojected_point.w;
}

draw_infinite_grid__VS_output_t VS_main( const in    draw_infinite_grid__VS_input_t input)
{
    draw_infinite_grid__VS_output_t output = (draw_infinite_grid__VS_output_t)0;

    float3_t    p        = g_grid_plane[input.vertex_id].xyz;
    output.near_point    = unproject_point(p.x, p.y, 0.0, g_m_inv_view, g_m_inv_proj).xyz; // unprojecting on the near plane
    output.far_point    = unproject_point(p.x, p.y, 1.0, g_m_inv_view, g_m_inv_proj).xyz; // unprojecting on the far plane
    output.vertex_position_inWVP    = float4_t(p, 1.0);

    return output;
}

//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------


float4_t    grid(const in float3_t fragPos3D, const in float_t scale)
{
    const float2_t    coord        = fragPos3D.xz * scale; // use the scale variable to set the distance between the lines
    const float2_t    derivative    = fwidth(coord);
    const float2_t    grid        = abs( frac(coord - 0.5) - 0.5) / derivative;
    const float_t    line_        = min(grid.x, grid.y);
    const float_t    minimumz    = min(derivative.y, 1);
    const float_t    minimumx    = min(derivative.x, 1);
    float4_t        color        = float4_t(0.2, 0.2, 0.2, 1.0 - min(line_, 1.0));
    // z axis
    if(fragPos3D.x > -z_axis_width * minimumx && fragPos3D.x < z_axis_width * minimumx)
        color.z = 1.0;
    // x axis
    if(fragPos3D.z > -z_axis_width * minimumz && fragPos3D.z < z_axis_width * minimumz)
        color.x = 1.0;
    
    return color;
}

float_t computeDepth(const in float3_t pos)
{
    const float4x4_t    view_proj    = mul(g_mView, g_mProj);

    const float4_t        unprojected_point    = mul( float4_t(pos.xyz, 1.0), view_proj);
    return (unprojected_point.z / unprojected_point.w);
}

float_t computeLinearDepth(const in float3_t pos)
{
    const float4x4_t    view_proj    = mul(g_mView, g_mProj);
    const float4_t        clip_space_pos    = mul( float4_t(pos.xyz, 1.0), view_proj);

    float_t clip_space_depth    = (clip_space_pos.z / clip_space_pos.w) * 2.0 - 1.0; // put back between -1 and 1
    float_t linearDepth            = (2.0 * near_plane * far_plane) / (far_plane + near_plane - clip_space_depth * (far_plane - near_plane)); // get linear value between 0.01 and 100
    return linearDepth / far_plane; // normalize
}

//[earlydepthstencil]
float4_t PS_main( draw_infinite_grid__VS_output_t input, out float_t depth : SV_Depth) : SV_Target
//float4_t PS_main( draw_infinite_grid__VS_output_t input) : SV_Target
{
    //// 「 Step 3 : Draw the plane when it intersects the floor 」の描画
    //const float_t    t            = -input.near_point.y / (input.far_point.y - input.near_point.y);
    //return float4_t(1.0, 0.0, 0.0, 1.0 * float(t > 0)); // opacity = 1 when t > 0, opacity = 0 otherwise

    //// 「 Step 4 : Draw the actual grid 」+ 「 Step 5 : Output depth 」の描画
    //const float_t    t            = -input.near_point.y / (input.far_point.y - input.near_point.y);
    //const float3_t    fragPos3D    = input.near_point + t * (input.far_point - input.near_point);
    //depth    = computeDepth(fragPos3D);
    //return grid(fragPos3D, plane_width_scale_1) * float(t > 0);

    //// 「 Step 4 : Draw the actual grid 」+ 「 Step 5 : Output depth 」+ テクスチャの描画
    //const float_t    t            = -input.near_point.y / (input.far_point.y - input.near_point.y);
    //const float3_t    fragPos3D    = input.near_point + t * (input.far_point - input.near_point);
    //const float4_t    tex_decal    = g_tex_decal.Sample( g_sam_linear, fragPos3D.xz * float2_t(plane_width_scale_0,-plane_width_scale_0));
    //depth    = computeDepth(fragPos3D);
    //return (tex_decal * plane_color_intensity + grid(fragPos3D, plane_width_scale_1)) * float(t > 0);

    //「 Step 6 : Fade out the grid 」+ テクスチャの描画
    const float_t    t            = -input.near_point.y / (input.far_point.y - input.near_point.y);
    const float3_t    fragPos3D    = input.near_point + t * (input.far_point - input.near_point);
    const float4_t    tex_decal    = g_tex_decal.Sample( g_sam_linear, fragPos3D.xz * float2_t(plane_width_scale_0,-plane_width_scale_0));
    depth    = computeDepth(fragPos3D);
    float_t linearDepth = computeLinearDepth(fragPos3D);
    float_t fading = max(0, (0.5 - linearDepth));

    float4_t    outColor;
    outColor = (tex_decal * plane_color_intensity + grid(fragPos3D, plane_width_scale_1)) * float(t > 0); // adding multiple resolution for the grid
    outColor.a *= fading;
    return outColor;
}

VertexShader    g_VS_main    = CompileShader(vs_5_0, VS_main());
PixelShader        g_PS_main    = CompileShader(ps_5_0, PS_main());

//--------------------------------------------------------------------------------------
// technique
//--------------------------------------------------------------------------------------
technique11 t0
{
    pass p0
    {
        SetVertexShader( g_VS_main);
        SetHullShader(NULL);
        SetDomainShader(NULL);
        SetGeometryShader( NULL);
        SetPixelShader( g_PS_main);
        //SetBlendState( g_state_no_blend, float4_t(0,0,0,0), 0xFFFFFFFF);
        SetBlendState( g_state_blend_alphablend_on, float4_t(0,0,0,0), 0xFFFFFFFF);
        SetDepthStencilState( g_state_enable_depth, 0);
        SetRasterizerState( g_state_render_solid);
    }
}

--------------------------------------------

 

最後に③ですが、テクスチャ画像の貼り付けが無かったので
その実装を載せておきます。

 

    static const float_t plane_width_scale_0    = 0.1;        // plane四角形のサイズを指定。0.1がデフォルト。0.1→0.05で四角形のサイズが増える。;
    static const float_t plane_width_scale_1    = 0.1;        // グリッド線の中のテクスチャ個数を指定。0.1がデフォルト。0.1→0.05でテクスチャ個数が増える。;
    const float4_t    tex_decal    = g_tex_decal.Sample( g_sam_linear, fragPos3D.xz * float2_t(plane_width_scale_0,-plane_width_scale_0));
    return (tex_decal * plane_color_intensity + grid(fragPos3D, plane_width_scale_1)) * float(t > 0);

 

【ゲーム制作】No.11: 動的LOD(レベルオブディテール)

今回は動的LOD(レベルオブディテール)の実装になります。
DirectXでいうDirect3D8のプログレッシブメッシュですね。
実装方法については以下の書籍に実装方法があり
それをそのまま実装しています。(20年も経ってる!!古っ!!
個人的にこの書籍にはとても役に立ちました。どうもありがとう)

 

実際の表示は以下
ワイヤーフレーム=OFF、LOD=100(%)


ワイヤーフレーム=OFF、LOD=50(%)

 

ワイヤーフレーム=ON、LOD=100(%)


ワイヤーフレーム=ON、LOD=50(%)


作ってみた感想ですが、残念ながら使い物にはならない、
ボツかなぁってところです。
そもそもMESHモデルをLOD化するのにも処理に時間がかかります。
だったらあらかじめLOD化されたモデルを複数用意するって方向になりますよね。
ならUnitiyなどのエンジンで静的にLODモデルを用意すればいいってなっちゃうんですよね。

 

【ゲーム制作】No.10: 動的頂点バッファ/インデックスバッファの設定について

お久しぶりです。前回の更新が2021年10月13日ですから、約17ヶ月ぶりの更新になってしまいました。
いろいろ生活は代わりましたが、ゲーム開発はそのまま続けています。

環境もDirectX11( Microsoft DirectX SDK (June 2010) ) + Windows11のままです。
今後も定期的に更新をしていきたいと思っています。

今日のテーマは動的な頂点バッファとインデックスバッファの設定方法についてです。

自分は今、動的LOD機能の制作を進めており(これも近いうちに公開したいと思っています)、

その為に頂点バッファとインデックスバッファの動的な読み取りと書込みが必要だったのですが、

これをどう設定するのが良いのかいろいろ苦労した為、それの備忘録になります。

!!注意!!:これは自分の環境での設定です。他の環境での動作は未確認です。


【パターン1】頂点バッファとインデックスバッファで動的な読み取りと書込みを行う場合(イレギュラーな方法)

下記の設定でバッファを作ると、バッファは動的な読み取りと書込みを行うことが出来ます。

D3D11_BUFFER_DESC    buffer_desc = { 0 };
buffer_desc.ByteWidth         = バッファのサイズ;
buffer_desc.Usage                = D3D11_USAGE_DEFAULT;
buffer_desc.BindFlags           = D3D11_BIND_UNORDERED_ACCESS;
buffer_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
buffer_desc.MiscFlags           = 0;
buffer_desc.StructureByteStride = 0;

D3D11_SUBRESOURCE_DATA subresource = { 0 };
subresource.pSysMem          = 開始アドレス;
subresource.SysMemPitch      = 0;
subresource.SysMemSlicePitch = 0;

p_d3ddevice->CreateBuffer(&buffer_desc, &subresource, &m_p_vertex_buffer);


特徴として、

①D3D11_BIND_UNORDERED_ACCESSという正しくない設定を使っています。
 動いたから良いかレベルのイレギュラーな設定です。

②D3D11_BIND_VERTEX_BUFFERやD3D11_BIND_INDEX_BUFFERと合わせて使うことは出来ません。

その為、ID3D11DeviceContext::IASetVertexBuffers()やID3D11DeviceContext::IASetIndexBuffer()を使うと
D3D11_BIND_VERTEX_BUFFERやD3D11_BIND_INDEX_BUFFERが立っていない為に、デバッグウインドウに以下のような警告が出るようになります。

D3D11 ERROR: ID3D11DeviceContext::IASetVertexBuffers: A Buffer trying to be bound to slot 0 did not have the appropriate bind flag set at creation time to allow the Buffer to be bound as a VertexBuffer. [ STATE_SETTING ERROR #238: IASETVERTEXBUFFERS_INVALIDBUFFER]

デバッグビルトでは表示コスト以外に影響はありませんが、リファレンスドライバー(D3D_DRIVER_TYPE_REFERENCE)などで作成していると警告ではなくエラーになります。
この警告を修正する為には次のパターン2の方法に切り替える必要があります。


【パターン2】頂点バッファとインデックスバッファで動的な読み取りと書込みを行う場合(より一般的な方法)

上記設定を踏まえて、より一般的な方法として動的に読み取りと書込みを行う頂点バッファとインデックスバッファを作る為には、
動的な読み取りと動的な書込みに分けて設計する必要があります。

動的な読み取り:D3D10_USAGE_STAGINGを使用してバッファを作成します。読み取り前にGPU→CPUにメモリをコピーし、このバッファのMap()でデータの読み取りを行います。

動的な書き込み:D3D11_USAGE_DYNAMICを使用してバッファを作成します。このバッファのMap()でデータの書き込みを行います。


// 1,D3D11_USAGE_DYNAMICを使用してバッファーを作成

D3D11_BUFFER_DESC    buffer_desc = { 0 };
buffer_desc.ByteWidth           = バッファのサイズ;
buffer_desc.Usage               = D3D11_USAGE_DYNAMIC;
buffer_desc.BindFlags           = D3D11_BIND_INDEX_BUFFER;    // 警告を修正する為
buffer_desc.CPUAccessFlags      = D3D11_CPU_ACCESS_WRITE;    // 書き込みを行う為
buffer_desc.MiscFlags           = 0;
buffer_desc.StructureByteStride = 0;

D3D11_SUBRESOURCE_DATA subresource = { 0 };
subresource.pSysMem          = 開始アドレス;
subresource.SysMemPitch      = 0;
subresource.SysMemSlicePitch = 0;

p_d3ddevice->CreateBuffer(&buffer_desc, &subresource, &p_index_buffer);


// 動的な読み取りを行う場合
//
// 2,D3D11_USAGE_STAGINGを使用してバッファーを作成
ID3D11BufferPtr    p_index_buffer_cpu_staging    = NULL;

D3D11_BUFFER_DESC    buffer_desc = { 0 };
buffer_desc.ByteWidth            = バッファのサイズ;
buffer_desc.Usage                = D3D11_USAGE_STAGING;    // GPU→CPUメモリコピーの為
buffer_desc.BindFlags            = 0;
buffer_desc.CPUAccessFlags        = D3D11_CPU_ACCESS_READ;// 読み取りを行う為
buffer_desc.MiscFlags            = 0;
buffer_desc.StructureByteStride    = 0;

uint8_collection    NULL_buffer( バッファのサイズ, 0);

D3D11_SUBRESOURCE_DATA    subresource = { 0 };
subresource.pSysMem = &NULL_buffer.front();
subresource.SysMemPitch = 0;
subresource.SysMemSlicePitch = 0;

hr = p_d3ddevice->CreateBuffer(&buffer_desc, &subresource, &p_index_buffer_cpu_staging);

// 3,頂点バッファからD3D11_USAGE_STAGINGバッファへ頂点データをコピー

p_device_context->CopyResource( p_index_buffer_cpu_staging, p_index_buffer);

// 4,頂点データをコピーされたD3D11_USAGE_STAGINGバッファをMap()し読み出す

D3D11_MAPPED_SUBRESOURCE    mapped_resource    = { 0 };

hr = p_device_context->Map(
    p_index_buffer_cpu_staging,
    0,
    D3D11_MAP_READ,
    0,
    &mapped_resource);


// 動的な書込みを行う場合
//
// 5,D3D11_USAGE_DYNAMICバッファをMap()し書き込む

D3D11_MAPPED_SUBRESOURCE    mapped_resource    = { 0 };

hr = p_device_context->Map(
    p_index_buffer,
    0,
    D3D11_MAP_WRITE_DISCARD,
    0,
    &mapped_resource);


注意点として、動的な書込みはD3D11_MAP_WRITE_DISCARDかD3D11_MAP_WRITE_NO_OVERWRITEになります。
D3D11_MAP_READ_WRITEは使用できずエラーになります。

【ゲーム制作】No.9: シャドウマッピング①

シャドウマッピングによる影生成の整備を行っています。

ただしシャドウマッピングはDirect3D9時代に作ったソースが既にありますので、作業はそれの移植がメインになります。

今はUniformShadowmap_Spotlightのシャドウマッピングは完成済で、PerspectiveShadowmap_Spotlightの移植を行っていますが、影の品質があまりよくありません。

PerspectiveShadowmapって論文で言うような高品質になるケースは少なくて大抵はUniformShadowmapの方が綺麗なんですよね。

問題点ばかりで実際には使い物になるのか?って感じです。

シャドウマッピング構築は時間がかかると思いますのでちょこちょこ進めていければと思います。

 

  • PerspectiveShadowmapの場合。あ、粗いです。

f:id:houz12345:20211013171618p:plain

 

  • UniformShadowmapの場合。解像度2048x2048ということもありとても綺麗です。

f:id:houz12345:20211013171624p:plain

 

【日記】2021年10月8日

今日は、 脳神経外科へ外来受診の日でした。

  • 次回入院して行う手術の内容を説明して頂きました。腫瘍の除去を行う手術だが言語に関わる箇所が腫瘍に沿うように存在する為、適当に取ると言語機能に障害が残る可能性がある。そのリスクを下げる為、意識を覚醒したまま脳機能のテストを行いなら腫瘍の除去を行う覚醒下手術を行う、とのことでした。

  • 気紛れで病院から徒歩で帰ったのですが(13kmほど)、途中で足の裏が痛くてギブアップ、結局電車で帰りました。

【ゲーム制作】No.8: 動的環境マッピング⑤

PMD/PMXモデルでの動的キューブ環境マッピングに対応しました。

屈折モデルへの対応などやるべき課題はまだいろいろありますが環境マップ対応は今回で終了にしたいと思います。

次回からは別課題への対応を行います。

 

f:id:houz12345:20211007202317p:plain