> こちらのリンクで解説されているソフトで出力されたような感じを想定しています。
なるほど、了解しました
> > 法線マップとライティングを行う自作シェーダーをすねさんがご用意されて、
> > 法線マップと自作シェーダーのファイルパスを関数に渡すと、その法線マップと自作シェーダーを使用して Live2D の描画が行なわれる、
> > というような形の機能でしたら追加することが可能かもしれません…
> はい、それで大丈夫ですので是非お願いしたいです!
ちょっとお話した内容とは異なる実装となりましたが、機能を追加できましたのでよろしければ
こちらの機能追加版の暫定最新バージョンをダウンロードしてください m(_ _)m
https://dxlib.xsrv.jp/temp/DxLibVCTest.zip // Windows版 VisualC++ 用
https://dxlib.xsrv.jp/temp/DxLibBCCTest.zip // Windows版 BorlandC++ 用
https://dxlib.xsrv.jp/temp/DxLibBCC2Test.zip // Windows版 C++ Builder 10.3 用
https://dxlib.xsrv.jp/temp/DxLibGCC_MinGWTest.zip // Windows版 MinGW 用
https://dxlib.xsrv.jp/temp/DxLibDotNet.zip // Windows版 .NET用
https://dxlib.xsrv.jp/temp/DxLibMakeTest.zip // ソース
(中身を既存のライブラリのファイルに上書きして『リビルド』をして下さい)
以下の関数を追加しました
// Live2D のモデル描画で使用するシェーダーを設定する
// TargetShader : 設定対象のシェーダー
// DX_LIVE2D_SHADER_SETUP_MASK_VERTEX : マスク画像生成用頂点シェーダー
// DX_LIVE2D_SHADER_SETUP_MASK_PIXEL : マスク画像生成用ピクセルシェーダー
// DX_LIVE2D_SHADER_NORMAL_VERTEX : 標準の頂点シェーダー
// DX_LIVE2D_SHADER_NORMAL_VERTEX_MASKED : 標準の頂点シェーダー + マスク画像
// DX_LIVE2D_SHADER_NORMAL_PIXEL : 標準のピクセルシェーダー
// DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED : 標準のピクセルシェーダー + マスク画像
// DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED_INVERTED : 標準のピクセルシェーダー + マスク画像( マスク画像の値を反転して使用 )
// DX_LIVE2D_SHADER_NORMAL_PIXEL_PREMULALPHA : 標準のピクセルシェーダー + テクスチャ画像が乗算済みアルファ
// DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED_PREMULALPHA : 標準のピクセルシェーダー + テクスチャ画像が乗算済みアルファ + マスク画像
// DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED_INVERTEX_PREMULALPHA : 標準のピクセルシェーダー + テクスチャ画像が乗算済みアルファ + マスク画像( マスク画像の値を反転して使用 )
// ShaderHandle : 設定するシェーダーのハンドル( LoadVertexShader や LoadPixelShader で取得できるシェーダーハンドル )、-1を指定すると設定解除
int Live2D_SetUserShader( int TargetShader, int ShaderHandle ) ;
// Live2D のモデル描画の前に呼ばれるコールバック関数を設定する
// Callback : 描画の前に呼ばれるコールバック関数( NULL を指定すると設定解除 )
// UserData : コールバック関数の第三引数として渡される void 型のアドレス
int Live2D_DrawCallback( void ( *Callback )( int Live2DModelHandle, int TextureIndex, void *UserData ), void *UserData ) ;
Live2D_SetUserShader でオリジナルのシェーダーを設定します
標準の状態でも種類が 10個もあるので、オリジナルシェーダーに変更する場合は、オリジナルのシェーダーも10個用意することになります
( ただ、DX_LIVE2D_SHADER_SETUP_MASK_VERTEX と DX_LIVE2D_SHADER_SETUP_MASK_PIXEL はデフォルトのままでも良いかもしれません )
法線マップは恐らく描画に使用されるテクスチャに応じて変更する必要があると思いますので、描画前に呼ばれるコールバック関数を
Live2D_DrawCallback でセットして、コールバック関数の中で SetUseTextureToShader でシェーダー内で使用するテクスチャを変更します
上記の関数を使用して『テクスチャ番号0の箇所は緑色を、テクスチャ番号1の箇所は赤色を加算する』サンプルを
作成してみましたので、よろしければダウンロードしてください m(_ _)m
https://dxlib.xsrv.jp/temp/Live2D_UserShader.zip
中に含まれている Live2D_UserShader.cpp の内容は以下のようになっています
#include "DxLib.h"
int AddColorSpeed = 2 ;
int AddColor = 0 ;
int ConstantBuffer ;
// Live2D の描画処理の前に呼ばれるコールバック関数
void Live2DDrawCallback( int Live2DModelHandle, int TextureIndex, void *UserData )
{
FLOAT4 TempAddColor ;
// 使用するテクスチャーによって加算色を変更する
if( TextureIndex == 0 )
{
// テクスチャー No.0 の場合は緑に反映
TempAddColor.x = 0.0f ;
TempAddColor.y = AddColor / 255.0f ;
TempAddColor.z = 0.0f ;
TempAddColor.w = 0.0f ;
}
else
{
// テクスチャー No.1 の場合は赤に反映
TempAddColor.x = AddColor / 255.0f ;
TempAddColor.y = 0.0f ;
TempAddColor.z = 0.0f ;
TempAddColor.w = 0.0f ;
}
if( GetUseDirect3DVersion() == DX_DIRECT3D_11 )
{
// Direct3D 11 の場合は定数バッファに加算色をセット
FLOAT4 *ConstantBuffer_AddColor = ( FLOAT4 * )GetBufferShaderConstantBuffer( ConstantBuffer ) ;
// 加算色を定数バッファに書き込み
*ConstantBuffer_AddColor = TempAddColor ;
// 定数バッファへの変更を反映
UpdateShaderConstantBuffer( ConstantBuffer ) ;
// 定数バッファをピクセルシェーダーのスロット4にセット
SetShaderConstantBuffer( ConstantBuffer, DX_SHADERTYPE_PIXEL, 4 ) ;
}
else
{
// Direct3D 9 の場合はピクセルシェーダーの定数レジスタ16番に加算色をセット
SetPSConstF( 16, TempAddColor ) ;
}
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
int ModelHandle ;
int ShaderHandle[ DX_LIVE2D_SHADER_NUM ] ;
// ウィンドウモードで起動
ChangeWindowMode( TRUE ) ;
// 画面解像度を設定
SetGraphMode( 1920, 1080, 32 ) ;
// Live2D Cubism Core DLL の読み込み( 64bit アプリの場合と 32bit アプリの場合で読み込む dll を変更 )
#ifdef _WIN64
Live2D_SetCubism3CoreDLLPath( "D:/Live2D/Cubism3SDKforNative-beta12-1/Core/dll/windows/x86_64/Live2DCubismCore.dll" ) ;
#else
Live2D_SetCubism3CoreDLLPath( "D:/Live2D/Cubism3SDKforNative-beta12-1/Core/dll/windows/x86/Live2DCubismCore.dll" ) ;
#endif
// DXライブラリ初期化処理
if( DxLib_Init() == -1 )
{
return -1 ;
}
// 独自シェーダーの読み込み
if( GetUseDirect3DVersion() == DX_DIRECT3D_11 )
{
// Direct3D 11 の場合は Direct3D 11 用のシェーダーバイナリを読み込む
ShaderHandle[ DX_LIVE2D_SHADER_SETUP_MASK_VERTEX ] = LoadVertexShader( "Direct3D11\\Live2DShader_VertSetupMask.vso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_SETUP_MASK_PIXEL ] = LoadPixelShader( "Direct3D11\\Live2DShader_PixelSetupMask.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_VERTEX ] = LoadVertexShader( "Direct3D11\\Live2DShader_VertNormal.vso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_VERTEX_MASKED ] = LoadVertexShader( "Direct3D11\\Live2DShader_VertMasked.vso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL ] = LoadPixelShader( "Direct3D11\\Live2DShader_PixelNormal.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED ] = LoadPixelShader( "Direct3D11\\Live2DShader_PixelMasked.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED_INVERTED ] = LoadPixelShader( "Direct3D11\\Live2DShader_PixelMaskedInverted.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL_PREMULALPHA ] = LoadPixelShader( "Direct3D11\\Live2DShader_PixelNormalPremult.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED_PREMULALPHA ] = LoadPixelShader( "Direct3D11\\Live2DShader_PixelMaskedPremult.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED_INVERTEX_PREMULALPHA ] = LoadPixelShader( "Direct3D11\\Live2DShader_PixelMaskedInvertedPremult.pso" ) ;
}
else
{
// Direct3D 9 の場合は Direct3D 9 用のシェーダーバイナリを読み込む
ShaderHandle[ DX_LIVE2D_SHADER_SETUP_MASK_VERTEX ] = LoadVertexShader( "Direct3D9\\Live2DShader_VertSetupMask.vso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_SETUP_MASK_PIXEL ] = LoadPixelShader( "Direct3D9\\Live2DShader_PixelSetupMask.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_VERTEX ] = LoadVertexShader( "Direct3D9\\Live2DShader_VertNormal.vso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_VERTEX_MASKED ] = LoadVertexShader( "Direct3D9\\Live2DShader_VertMasked.vso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL ] = LoadPixelShader( "Direct3D9\\Live2DShader_PixelNormal.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED ] = LoadPixelShader( "Direct3D9\\Live2DShader_PixelMasked.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED_INVERTED ] = LoadPixelShader( "Direct3D9\\Live2DShader_PixelMaskedInverted.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL_PREMULALPHA ] = LoadPixelShader( "Direct3D9\\Live2DShader_PixelNormalPremult.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED_PREMULALPHA ] = LoadPixelShader( "Direct3D9\\Live2DShader_PixelMaskedPremult.pso" ) ;
ShaderHandle[ DX_LIVE2D_SHADER_NORMAL_PIXEL_MASKED_INVERTEX_PREMULALPHA ] = LoadPixelShader( "Direct3D9\\Live2DShader_PixelMaskedInvertedPremult.pso" ) ;
}
// 独自シェーダーを Live2D の描画用にセット
for( int i = 0 ; i < DX_LIVE2D_SHADER_NUM ; i ++ )
{
Live2D_SetUserShader( i, ShaderHandle[ i ] ) ;
}
// 定数バッファの作成( Direct3D 11 の場合だけ作成 )
if( GetUseDirect3DVersion() == DX_DIRECT3D_11 )
{
ConstantBuffer = CreateShaderConstantBuffer( sizeof( FLOAT4 ) ) ;
}
// Live2D の描画時に呼ばれるコールバック関数をセット
Live2D_DrawCallback( Live2DDrawCallback, NULL ) ;
// Live2Dモデルの読み込み
ModelHandle = Live2D_LoadModel( "D:/Live2D/Cubism3SDKforNative-beta12-1/Samples/Res/Hiyori/Hiyori.model3.json" ) ;
// 描画先を裏画面に変更
SetDrawScreen( DX_SCREEN_BACK ) ;
// メインループ
while( ProcessMessage() == 0 )
{
// 画面の初期化
ClearDrawScreen() ;
// モーション再生が終了していたらアイドリングモーションをランダムで再生
if( Live2D_Model_IsMotionFinished( ModelHandle ) == TRUE )
{
Live2D_Model_StartMotion( ModelHandle, "Idle", GetRand( 8 ) ) ;
}
// モデルの状態を60分の1秒分進める
Live2D_Model_Update( ModelHandle, 1 / 60.0f ) ;
// Live2D描画の開始
Live2D_RenderBegin() ;
// 加算色の推移
AddColor += AddColorSpeed ;
if( AddColor >= 255 )
{
AddColor = 255 ;
AddColorSpeed = -AddColorSpeed ;
}
else if( AddColor <= 0 )
{
AddColor = 0 ;
AddColorSpeed = -AddColorSpeed ;
}
// Live2Dモデルの描画
Live2D_Model_Draw( ModelHandle ) ;
// Live2D描画の終了
Live2D_RenderEnd() ;
// 裏画面の内容を表画面に反映
ScreenFlip() ;
}
// Live2D モデルの削除
Live2D_DeleteModel( ModelHandle ) ;
// DXライブラリ使用の終了処理
DxLib_End() ;
// ソフトの終了
return 0 ;
}
Live2D SDK のフォルダとして D:/Live2D/Cubism3SDKforNative-beta12-1 を指定していますので、
この部分はすねさんの環境に合わせて書き換えてください
まずオリジナルのシェーダーコードバイナリを LoadVertexShader や LoadPixelShader で読み込むのですが、
DXライブラリは Direct3D 11 を使用する場合と、Direct3D 9 を使用する場合があり、それぞれのバージョンで
シェーダーの仕様が異なるので、GetUseDirect3DVersion() の戻り値が DX_DIRECT3D_11 かどうかで
読み込むシェーダーコードバイナリファイルを分けています
その後 Live2D_SetUserShader で読み込んだシェーダーコードを Live2D の描画用に設定します
このサンプルは緑色や赤色を画像に加算する処理をシェーダーの定数機能を使用して実現しているのですが、
Direct3D 9 は定数レジスタ、Direct3D 11 は定数バッファを使用することになるので、Direct3D 11 の場合のみ
CreateShaderConstantBuffer で定数バッファハンドルを作成しています
Live2D_DrawCallback で Live2D の描画前に呼ばれるように設定している関数 Live2DDrawCallback の中では
引数のテクスチャ番号( TextureIndex ) に応じて緑色 or 赤色を SetShaderConstantBuffer や SetPSConstF を使用して
定数バッファや定数レジスタに設定しています
ライティングを行う場合は、恐らくこの関数の中で法線マップのテクスチャを SetUseTextureToShader で
設定することになると思います
シェーダーコードバイナリファイルは Live2D_UserShader.zip の中にある
Direct3D9\ShaderCompile.bat
Direct3D11\ShaderCompile.bat
を実行することで作成します
Direct3D 9 用のシェーダーコードは Direct3D9\ShaderCode.fx
Direct3D 11 用のシェーダーコードは Direct3D11\ShaderCode.hlsl
となっています
こちらの2つのファイルは Live2D SDK のサンプルにある標準シェーダーコードに、定数の addColor を
加算する処理を追加しただけとなっていますので、基本的にはこちらの2つのファイルを改造する形で
ライティングの処理を追加していただくのが良いと思います
もし不明な点や不足している機能などありましたら言ってください m(_ _)m