サンプルプログラム 3Dアクション基本+深度値を利用した影表現基本
に、モデルをスフィアマップ付きで表示したいのですが、やり方が分かりません。
(目標は、↓のようにスフィアマップでモデルを表示させて、なおかつセルフシャドウを付与させることです。)
MMD互換のトゥーンレンダリング スキニングメッシュでディレクショナルライト一つとスフィアマップのフォンシェーディング
http://homepage2.nifty.com/natupaji/DxL ... .html#R5N5
おそらく、これを参考にして、SkinMesh4_DirLight_DepthShadow_Step2VSとDirLight_DepthShadow_Step2PSを変えれば良いんじゃないかなという気はします。(ステップ1は影の深度画像作成のためのシェーダと思われるため)
ということで、この2つをいじっていたのですが、シェーダをコンパイルすると以下のようなエラーが出てしまいました。
3DAction_DepthShadow\DirLight_DepthShadow_Step2PS.fx(172,1
5): warning X3206: implicit truncation of vector type
3DAction_DepthShadow\DirLight_DepthShadow_Step2PS.fx(104,9
): error X5200: (Third source param) Invalid register number: 33. Max allowed fo
r this type is 31.
以下が、そのfxファイルです。
SkinMesh4_DirLight_DepthShadow_Step2VS.fx
// 頂点シェーダーの入力
struct VS_INPUT
{
float4 Position : POSITION ; // 座標( ローカル空間 )
int4 BlendIndices0 : BLENDINDICES0 ; // スキニング処理用 Float型定数配列インデックス
float4 BlendWeight0 : BLENDWEIGHT0 ; // スキニング処理用ウエイト値
float3 Normal : NORMAL0 ; // 法線( ローカル空間 )
float4 Diffuse : COLOR0 ; // ディフューズカラー
float4 Specular : COLOR1 ; // スペキュラカラー
float4 TexCoords0 : TEXCOORD0 ; // テクスチャ座標
} ;
// 頂点シェーダーの出力
struct VS_OUTPUT
{
float4 Position : POSITION ; // 座標( 射影空間 )
float2 TexCoords0 : TEXCOORD0 ; // テクスチャ座標
float3 VPosition : TEXCOORD1 ; // 座標( ビュー空間 )
float3 VNormal : TEXCOORD2 ; // 法線( ビュー空間 )
float4 LPPosition : TEXCOORD3 ; // ライトからみた座標( ライトの射影空間 )
} ;
// マテリアルパラメータ
struct VS_CONST_MATERIAL
{
float4 Diffuse ; // マテリアルディフューズカラー
float4 Specular ; // マテリアルスペキュラカラー
float4 Power ; // マテリアルスペキュラハイライトの強さ
} ;
// ライトパラメータ
struct VS_CONST_LIGHT
{
float4 Position ; // 座標( ビュー空間 )
float3 Direction ; // 方向( ビュー空間 )
float4 Diffuse ; // ディフューズカラー
float4 Specular ; // スペキュラカラー
float4 Ambient ; // アンビエントカラーとマテリアルのアンビエントカラーを乗算したもの
float4 Range_FallOff_AT0_AT1 ; // x:有効距離 y:スポットライト用FallOff z:距離による減衰処理用パラメータ0 w:距離による減衰処理用パラメータ1
float4 AT2_SpotP0_SpotP1 ; // x:距離による減衰処理用パラメータ2 y:スポットライト用パラメータ0( cos( Phi / 2.0f ) ) z:スポットライト用パラメータ1( 1.0f / ( cos( Theta / 2.0f ) - cos( Phi / 2.0f ) ) )
} ;
// C++ 側で設定する定数の定義
float4 cfAmbient_Emissive : register( c1 ) ; // マテリアルエミッシブカラー + マテリアルアンビエントカラー * グローバルアンビエントカラー
float4 cfProjectionMatrix[ 4 ] : register( c2 ) ; // ビュー → 射影行列
float4 cfViewMatrix[ 3 ] : register( c6 ) ; // ワールド → ビュー行列
float4 cfLocalWorldMatrix[ 162 ] : register( c94 ) ; // ローカル → ワールド行列
VS_CONST_MATERIAL cfMaterial : register( c11 ) ; // マテリアルパラメータ
VS_CONST_LIGHT cfLight : register( c14 ) ; // 有効ライト0番のパラメータ
matrix cfLightViewMatrix : register( c43 ) ; // ライトのワールド → ビュー行列
matrix cfLightProjectionMatrix : register( c47 ) ; // ライトのビュー → 射影行列
// main関数
VS_OUTPUT main( VS_INPUT VSInput )
{
VS_OUTPUT VSOutput ;
float4 lWorldPosition ;
float4 lViewPosition ;
float4 lLViewPosition ;
float3 lWorldNrm ;
float3 lViewNrm ;
float3 lLightHalfVec ;
float4 lLightLitParam ;
float4 lLightLitDest ;
float4 lLocalWorldMatrix[ 3 ] ;
// 複数のフレームのブレンド行列の作成
lLocalWorldMatrix[ 0 ] = cfLocalWorldMatrix[ VSInput.BlendIndices0.x + 0 ] * VSInput.BlendWeight0.x;
lLocalWorldMatrix[ 1 ] = cfLocalWorldMatrix[ VSInput.BlendIndices0.x + 1 ] * VSInput.BlendWeight0.x;
lLocalWorldMatrix[ 2 ] = cfLocalWorldMatrix[ VSInput.BlendIndices0.x + 2 ] * VSInput.BlendWeight0.x;
lLocalWorldMatrix[ 0 ] += cfLocalWorldMatrix[ VSInput.BlendIndices0.y + 0 ] * VSInput.BlendWeight0.y;
lLocalWorldMatrix[ 1 ] += cfLocalWorldMatrix[ VSInput.BlendIndices0.y + 1 ] * VSInput.BlendWeight0.y;
lLocalWorldMatrix[ 2 ] += cfLocalWorldMatrix[ VSInput.BlendIndices0.y + 2 ] * VSInput.BlendWeight0.y;
lLocalWorldMatrix[ 0 ] += cfLocalWorldMatrix[ VSInput.BlendIndices0.z + 0 ] * VSInput.BlendWeight0.z;
lLocalWorldMatrix[ 1 ] += cfLocalWorldMatrix[ VSInput.BlendIndices0.z + 1 ] * VSInput.BlendWeight0.z;
lLocalWorldMatrix[ 2 ] += cfLocalWorldMatrix[ VSInput.BlendIndices0.z + 2 ] * VSInput.BlendWeight0.z;
lLocalWorldMatrix[ 0 ] += cfLocalWorldMatrix[ VSInput.BlendIndices0.w + 0 ] * VSInput.BlendWeight0.w;
lLocalWorldMatrix[ 1 ] += cfLocalWorldMatrix[ VSInput.BlendIndices0.w + 1 ] * VSInput.BlendWeight0.w;
lLocalWorldMatrix[ 2 ] += cfLocalWorldMatrix[ VSInput.BlendIndices0.w + 2 ] * VSInput.BlendWeight0.w;
// 頂点座標変換 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 開始 )
// ローカル座標をワールド座標に変換
lWorldPosition.x = dot( VSInput.Position, lLocalWorldMatrix[ 0 ] ) ;
lWorldPosition.y = dot( VSInput.Position, lLocalWorldMatrix[ 1 ] ) ;
lWorldPosition.z = dot( VSInput.Position, lLocalWorldMatrix[ 2 ] ) ;
lWorldPosition.w = 1.0f ;
// ワールド座標をビュー座標に変換
lViewPosition.x = dot( lWorldPosition, cfViewMatrix[ 0 ] ) ;
lViewPosition.y = dot( lWorldPosition, cfViewMatrix[ 1 ] ) ;
lViewPosition.z = dot( lWorldPosition, cfViewMatrix[ 2 ] ) ;
lViewPosition.w = 1.0f ;
// ビュー座標を射影座標に変換
VSOutput.Position.x = dot( lViewPosition, cfProjectionMatrix[ 0 ] ) ;
VSOutput.Position.y = dot( lViewPosition, cfProjectionMatrix[ 1 ] ) ;
VSOutput.Position.z = dot( lViewPosition, cfProjectionMatrix[ 2 ] ) ;
VSOutput.Position.w = dot( lViewPosition, cfProjectionMatrix[ 3 ] ) ;
// 頂点座標変換 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 終了 )
// ライトの処理 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 開始 )
// 法線をビュー空間の角度に変換 =========================================( 開始 )
// ローカルベクトルをワールドベクトルに変換
lWorldNrm.x = dot( VSInput.Normal, lLocalWorldMatrix[ 0 ].xyz ) ;
lWorldNrm.y = dot( VSInput.Normal, lLocalWorldMatrix[ 1 ].xyz ) ;
lWorldNrm.z = dot( VSInput.Normal, lLocalWorldMatrix[ 2 ].xyz ) ;
// ワールドベクトルをビューベクトルに変換
lViewNrm.x = dot( lWorldNrm, cfViewMatrix[ 0 ].xyz ) ;
lViewNrm.y = dot( lWorldNrm, cfViewMatrix[ 1 ].xyz ) ;
lViewNrm.z = dot( lWorldNrm, cfViewMatrix[ 2 ].xyz ) ;
// 法線をビュー空間の角度に変換 =========================================( 終了 )
// ライトディフューズカラーとライトスペキュラカラーの角度減衰計算 =======( 開始 )
// 法線とライトの逆方向ベクトルとの内積を lLightLitParam.x にセット
lLightLitParam.x = dot( lViewNrm, -cfLight.Direction ) ;
// ハーフベクトルの計算 norm( ( norm( 頂点位置から視点へのベクトル ) + ライトの方向 ) )
lLightHalfVec = normalize( normalize( -lViewPosition.xyz ) - cfLight.Direction ) ;
// 法線とハーフベクトルの内積を lLightLitParam.y にセット
lLightLitParam.y = dot( lLightHalfVec, lViewNrm ) ;
// スペキュラ反射率を lLightLitParam.w にセット
lLightLitParam.w = cfMaterial.Power.x ;
// ライトパラメータ計算
lLightLitDest = lit( lLightLitParam.x, lLightLitParam.y, lLightLitParam.w ) ;
// ライトディフューズカラーとライトスペキュラカラーの角度減衰計算 =======( 終了 )
// ライトの処理 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 終了 )
// 出力パラメータセット ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 開始 )
// 頂点座標を保存
VSOutput.VPosition = lViewPosition.xyz ;
// 法線を保存
VSOutput.VNormal = lViewNrm ;
// テクスチャ座標のセット
VSOutput.TexCoords0 = VSInput.TexCoords0;
// 出力パラメータセット ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 終了 )
// 深度影用のライトから見た射影座標を算出 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 開始 )
// ワールド座標をライトのビュー座標に変換
lLViewPosition = mul( cfLightViewMatrix, lWorldPosition ) ;
// ライトのビュー座標をライトの射影座標に変換
VSOutput.LPPosition = mul( cfLightProjectionMatrix, lLViewPosition ) ;
// 深度影用のライトから見た射影座標を算出 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 終了 )
// 出力パラメータを返す
return VSOutput ;
}
// ピクセルシェーダーの入力
struct PS_INPUT
{
float4 Diffuse : COLOR0 ; // ディフューズカラー
float4 Specular : COLOR1 ; // スペキュラカラー
float2 TexCoords0 : TEXCOORD0 ; // テクスチャ座標
float3 VPosition : TEXCOORD1 ; // 座標( ビュー空間 )
float3 VNormal : TEXCOORD2 ; // 法線( ビュー空間 )
float4 LPPosition : TEXCOORD3 ; // ライトからみた座標( ライトの射影空間 )
} ;
// ピクセルシェーダーの出力
struct PS_OUTPUT
{
float4 Color0 : COLOR0 ;
} ;
// マテリアルパラメータ
struct MATERIAL
{
float4 Diffuse ; // ディフューズカラー
float4 Specular ; // スペキュラカラー
float4 Power ; // スペキュラの強さ
} ;
// ライトパラメータ
struct LIGHT
{
float4 Position ; // 座標( ビュー空間 )
float3 Direction ; // 方向( ビュー空間 )
float4 Diffuse ; // ディフューズカラー
float4 Specular ; // スペキュラカラー
float4 Ambient ; // アンビエントカラーとマテリアルのアンビエントカラーを乗算したもの
float4 Range_FallOff_AT0_AT1 ; // x:有効距離 y:スポットライト用FallOff z:距離による減衰処理用パラメータ0 w:距離による減衰処理用パラメータ1
float4 AT2_SpotP0_SpotP1 ; // x:距離による減衰処理用パラメータ2 y:スポットライト用パラメータ0( cos( Phi / 2.0f ) ) z:スポットライト用パラメータ1( 1.0f / ( cos( Theta / 2.0f ) - cos( Phi / 2.0f ) ) )
} ;
// C++ 側で設定する定数やテクスチャの定義
sampler DiffuseMapTexture : register( s0 ) ; // ディフューズマップテクスチャ
sampler DepthMapTexture : register( s10 ) ; // 深度バッファテクスチャ
sampler ToonTexture : register( s1 ) ; // トゥーンテクスチャ
sampler ToonSphereMapTexture : register( s5 ) ; // トゥーンレンダリング用スフィアマップテクスチャ
float4 cfAmbient_Emissive : register( c1 ) ; // エミッシブカラー + マテリアルアンビエントカラー * グローバルアンビエントカラー
MATERIAL cfMaterial : register( c2 ) ; // マテリアルパラメータ
float4 cfFactorColor : register( c5 ) ; // 不透明度等
LIGHT cfLight[ 1 ] : register( c32 ) ; // ライトパラメータ
// main関数
PS_OUTPUT main( PS_INPUT PSInput )
{
PS_OUTPUT PSOutput ;
float4 TextureDiffuseColor ;
float TextureDepth ;
float2 DepthTexCoord ;
float4 lToonSphereMapColor ;
float4 lSpecularColor ;
float4 lDiffuseColor ;
float3 Normal ;
float lDiffuseAngleGen ;
float4 lTotalDiffuse ;
float4 lTotalSpecular ;
float4 lTotalAmbient ;
float4 lToonColor ;
float lTotalLightGen ;
float3 V_to_Eye ;
float3 TempF3 ;
float Temp ;
float3 lLightTemp ;
float3 lLightDir ;
// 法線の準備
Normal = normalize( PSInput.VNormal ) ;
// 頂点座標から視点へのベクトルを正規化
V_to_Eye = normalize( -PSInput.VPosition ) ;
// ディフューズカラーとスペキュラカラーとアンビエントカラーの合計値を初期化
lTotalDiffuse = float4( 0.0f, 0.0f, 0.0f, 0.0f ) ;
lTotalSpecular = float4( 0.0f, 0.0f, 0.0f, 0.0f ) ;
lTotalAmbient = float4( 0.0f, 0.0f, 0.0f, 0.0f ) ;
// ライトの減衰率合計値の初期化
lTotalLightGen = 0.0f ;
// ディレクショナルライトの処理 +++++++++++++++++++++++++++++++++++++++++++++++++++++( 開始 )
// ライト方向ベクトルのセット
lLightDir = cfLight[ 0 ].Direction ;
// ディフューズ角度減衰率計算
lDiffuseAngleGen = saturate( dot( Normal, -lLightDir ) ) ;
// ディフューズ減衰率を合計値に加算
lTotalLightGen += lDiffuseAngleGen ;
// スペキュラカラー計算
// ハーフベクトルの計算
TempF3 = normalize( V_to_Eye - lLightDir ) ;
// Temp = pow( max( 0.0f, N * H ), cfMaterial.Power.x )
Temp = pow( max( 0.0f, dot( Normal, TempF3 ) ), cfMaterial.Power.x ) ;
// スペキュラライト合計値 += スペキュラ角度減衰計算結果 * ライトのスペキュラカラー
lTotalSpecular += Temp * cfLight[ 0 ].Specular ;
// ライトのディフューズカラーを合計値に加算
lTotalDiffuse += cfLight[ 0 ].Diffuse ;
// ライトのアンビエントカラーを合計値に加算
lTotalAmbient += cfLight[ 0 ].Ambient ;
// ディレクショナルライトの処理 +++++++++++++++++++++++++++++++++++++++++++++++++++++( 終了 )
// アンビエントカラーの蓄積値 += マテリアルのアンビエントカラーとグローバルアンビエントカラーを乗算したものとマテリアルエミッシブカラーを加算したもの
lTotalAmbient += cfAmbient_Emissive ;
// 出力カラー計算 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 開始 )
// テクスチャカラーの読み込み
TextureDiffuseColor = tex2D( DiffuseMapTexture, PSInput.TexCoords0.xy ) ;
// トゥーンテクスチャカラーをライトのディフューズ減衰率から取得
lToonColor = tex2D( ToonTexture, lTotalLightGen ) ;
// ディフューズカラー = ライトのディフューズカラー蓄積値 * マテリアルのディフューズカラー
lDiffuseColor = lTotalDiffuse * cfMaterial.Diffuse ;
// スペキュラカラー = ライトのスペキュラカラー蓄積値 * マテリアルのスペキュラカラー
lSpecularColor = lTotalSpecular * cfMaterial.Specular ;
// 出力 = saturate( saturate( ディフューズカラー * アンビエントカラーの蓄積値 ) * トゥーンテクスチャカラー + スペキュラカラー ) * テクスチャカラー
PSOutput.Color0.rgb = saturate( saturate( lDiffuseColor.rgb + lTotalAmbient.rgb ) * lToonColor.rgb + lSpecularColor.rgb ) * TextureDiffuseColor.rgb ;
// スフィアマップの色を取得
TempF3 = Normal * float3( 0.5f, -0.5f, 0.0f ) + float3( 0.5f, 0.5f, 0.5f ) ;
lToonSphereMapColor = tex2D( ToonSphereMapTexture, TempF3.xy ) ;
/* スフィアマップの効果が乗算の場合はこちらを加算の2行の代わりに使います
// スフィアマップの色を出力に乗算
PSOutput.Color0.rgb *= lToonSphereMapColor.rgb ;
*/
// スフィアマップの色を出力に加算
PSOutput.Color0.rgb += lToonSphereMapColor.rgb ;
// アルファ値 = ディフューズアルファ * マテリアルのディフューズアルファ * 不透明度
PSOutput.Color0.a = TextureDiffuseColor.a * cfMaterial.Diffuse.a * cfFactorColor.a ;
// 出力カラー計算 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++( 終了 )
// 深度テクスチャの座標を算出
// PSInput.LPPosition.xy は -1.0f ~ 1.0f の値なので、これを 0.0f ~ 1.0f の値にする
DepthTexCoord.x = ( PSInput.LPPosition.x + 1.0f ) / 2.0f;
// yは更に上下反転
DepthTexCoord.y = 1.0f - ( PSInput.LPPosition.y + 1.0f ) / 2.0f;
// 深度バッファテクスチャから深度を取得
TextureDepth = tex2D( DepthMapTexture, DepthTexCoord );
// テクスチャに記録されている深度( +補正値 )よりZ値が大きかったら奥にあるということで輝度を半分にする
if( PSInput.LPPosition.z > TextureDepth + 0.0016f )
{
PSOutput.Color0.rgb *= 0.8f;
if(PSOutput.Color0.r>PSOutput.Color0.g && PSOutput.Color0.r >PSOutput.Color0.b)PSOutput.Color0.r*=1.2f;
if(PSOutput.Color0.g>PSOutput.Color0.r && PSOutput.Color0.g >PSOutput.Color0.b)PSOutput.Color0.g*=1.1f;
if(PSOutput.Color0.b>PSOutput.Color0.r && PSOutput.Color0.b >PSOutput.Color0.g)PSOutput.Color0.b*=1.1f;
}
// 出力パラメータを返す
return PSOutput ;
}
// 3Dアクション基本
#include "DxLib.h"
#include <math.h>
// 固定値定義 -------------------------------------------------------------------------------------
// ゲームデータ
#define CUSTOM_FPS (60.0f)
#define DEBUG_MODE true
// キャラクターの情報
#define KOTORI_MODEL_TYPE 0
#define CHARA_PLAY_ANIM_SPEED 0.5f // アニメーション速度
#define KOTORI_PHISICS_RUNFRAME 2 // 物理演算の計算回数(大きくなればなるほど、揺れなくなり、揺れから戻るのが早くなる。最小は1)
#define KOTORI_SCALE (50.0f)
#define MODEL1_TAG_PLUS_Y (8.0f*KOTORI_SCALE)
#define MODEL2_TAG_PLUS_Y (12.0f*KOTORI_SCALE)
#define MODEL3_TAG_PLUS_Y (8.0f*KOTORI_SCALE)
#define STAGE_SCALE (20.0f*KOTORI_SCALE)
// カメラ関係の定義
#define CAMERA_ANGLE_SPEED 0.025f // 旋回速度
#define CAMERA_PLAYER_LENGTH 800.0f // プレイヤーとの距離
// ライトのベクトル
#define LIGHT_VEC_X (0)
#define LIGHT_VEC_Y (-0.3f)
#define LIGHT_VEC_Z (0.5f)
// クラス定義 -------------------------------------------------------------------------------------
class Fps{
int mStartTime; //測定開始時刻
int mCount; //カウンタ
float mFps; //fps
static const int N = 60;//平均を取るサンプル数
static const int FPS = (int)CUSTOM_FPS; //設定したFPS
LONGLONG mTime, mRefT, mNowT, mFpsUpdateTime ;
int mRunFrame;
public:
Fps(){
mStartTime = 0;
mCount = 0;
mFps = CUSTOM_FPS;
mRunFrame = 1 ;
mRefT = GetNowHiPerformanceCount() ;
mFpsUpdateTime = 0 ;
mTime = 0 ;
}
bool Update(){
if( mCount == 0 ){ //1フレーム目なら時刻を記憶
mStartTime = GetNowCount();
}
if( mCount == N ){ //60フレーム目なら平均を計算する
int t = GetNowCount();
//mFps = 1000.f/((t-mStartTime)/(float)N);
mCount = 0;
mStartTime = t;
}
mCount++;
return true;
}
void Draw(){
DrawFormatString(0, 0, GetColor(255,255,255), "[FPS %.1f]", mFps);
}
void Wait(){
int tookTime = GetNowCount() - mStartTime; //かかった時間
int waitTime = mCount*1000/FPS - tookTime; //待つべき時間
if( waitTime > 0 ){
Sleep(waitTime); //待機
}
// 経過時間から実行するフレーム数を決定
mNowT = GetNowHiPerformanceCount() ;
mTime = mNowT - mRefT ;
mRunFrame = ( int )( mTime / ( 1000000 / 60 ) ) ;
if( mRunFrame == 0 ) mRunFrame = 1 ;
mRefT = mNowT ;
// FPSを計算
if( mRefT - mFpsUpdateTime > 250000 )
{
mFpsUpdateTime = mRefT ;
mFps = 1000000.0f / mTime ;
}
}
float FpsReturn(){
return mFps;
}
int ConstFpsReturn(){
return FPS;
}
};
// 構造体定義 -------------------------------------------------------------------------------------
// 入力情報構造体
struct PADINPUT
{
int NowInput ; // 現在の入力
int EdgeInput ; // 現在のフレームで押されたボタンのみビットが立っている入力値
} ;
// プレイヤー情報構造体
struct PLAYER
{
VECTOR Position ; // 座標
VECTOR TargetMoveDirection ; // モデルが向くべき方向のベクトル
float Angle ; // モデルが向いている方向の角度
float JumpPower ; // Y軸方向の速度
int ModelHandle ; // モデルハンドル
int State ; // 状態( 0:立ち止まり 1:走り 2:ジャンプ )
int PlayAnim1 ; // 再生しているアニメーション1のアタッチ番号( -1:何もアニメーションがアタッチされていない )
float AnimPlayCount1 ; // 再生しているアニメーション1の再生時間
int PlayAnim2 ; // 再生しているアニメーション2のアタッチ番号( -1:何もアニメーションがアタッチされていない )
float AnimPlayCount2 ; // 再生しているアニメーション2の再生時間
float AnimBlendRate ; // 再生しているアニメーション1と2のブレンド率
} ;
// ステージ情報構造体
struct STAGE
{
int ModelHandle ; // モデルハンドル
} ;
// カメラ情報構造体
struct CAMERA
{
float AngleH ; // 水平角度
float AngleV ; // 垂直角度
VECTOR Eye ; // カメラ座標
VECTOR Target ; // 注視点座標
float EyeHeight;
float Length;
} ;
// 関数プロトタイプ宣言 ---------------------------------------------------------------------------
void Input_Process( void ) ; // 入力処理
void Player_Initialize( void ) ; // プレイヤーの初期化
void Player_Terminate( void ) ; // プレイヤーの後始末
void Player_Process( void ) ; // プレイヤーの処理
void Stage_Initialize( void ) ; // ステージの初期化処理
void Stage_Terminate( void ) ; // ステージの後始末処理
void Camera_Initialize( void ) ; // カメラの初期化処理
void Camera_Process( void ) ; // カメラの処理
void SetupDepthImage( void ) ; // 影描画用の深度記録画像を準備する
void DrawModelWithDepthShadow( void ) ; // 影用の深度記録画像を使った影を落とす処理も含めたモデルの描画
void Render_Process( void ) ; // 描画処理
// 実体宣言 ---------------------------------------------------------------------------------------
PADINPUT inp ; // 入力情報の実体宣言
PLAYER pl ; // プレイヤー情報の実体宣言
STAGE stg ; // ステージ情報の実体宣言
CAMERA cam ; // カメラ情報の実体宣言
Fps fps ; // FPSクラスの実態宣言
// グローバル変数宣言 ---------------------------------------------------------------------------------------
LONG cnt=0;bool debugMode=DEBUG_MODE;
// 影用の深度値を保存する描画可能グラフィック
int DepthBufferGraphHandle ;
// 影用の深度記録画像を作成した際のカメラのビュー行列と射影行列
MATRIX LightCamera_ViewMatrix ;
MATRIX LightCamera_ProjectionMatrix ;
// 深度記録画像への描画用の剛体メッシュ用頂点シェーダーと
// スキニングメッシュ用の頂点シェーダー
int Skin4_DepthShadow_Step1_VertexShader ;
int Normal_DepthShadow_Step1_VertexShader ;
// 深度記録画像への描画用のピクセルシェーダー
int DepthShadow_Step1_PixelShader ;
// 深度記録画像を使ったディレクショナルライト一つ付きの描画用の剛体メッシュ用頂点シェーダーと
// スキニングメッシュ用の頂点シェーダー
int Skin4_DirLight_DepthShadow_Step2_VertexShader ;
int Normal_DirLight_DepthShadow_Step2_VertexShader ;
// 深度記録画像を使ったディレクショナルライト一つ付きの描画用のピクセルシェーダー
int DirLight_DepthShadow_Step2_PixelShader ;
// 関数実体 ---------------------------------------------------------------------------------------
// 入力処理
void Input_Process( void )
{
int Old ;
// ひとつ前のフレームの入力を変数にとっておく
Old = inp.NowInput ;
// 現在の入力状態を取得
inp.NowInput = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;
// 今のフレームで新たに押されたボタンのビットだけ立っている値を EdgeInput に代入する
inp.EdgeInput = inp.NowInput & ~Old ;
}
// プレイヤーの初期化
void Player_Initialize( void )
{
// 初期座標は原点
pl.Position = VGet(0,0,0);
// 次に読み込むモデルの物理演算モードをリアルタイム物理演算にする
MV1SetLoadModelUsePhysicsMode( DX_LOADMODEL_PHYSICS_REALTIME ) ;
// モデルハンドルの作成
switch(KOTORI_MODEL_TYPE)
{
case 0:
pl.ModelHandle = MV1LoadModel( "音無小鳥モデル/音無小鳥 UN18.mv1" ) ;
break;
case 1:
pl.ModelHandle = MV1LoadModel( "15セーラーミズギ/15SM-Kot2.mv1" ) ;
break;
case 2:
pl.ModelHandle = MV1LoadModel( "アイマス ラフタイムスクール ver.1.4/音無小鳥 RTS14.mv1" ) ;
break;
default:break;
}
//MV1SetScale(pl.ModelHandle,VGet(KOTORI_SCALE,KOTORI_SCALE,KOTORI_SCALE));
int MaterialNum = MV1GetMaterialNum( pl.ModelHandle ) ;
for( int i = 0 ; i < MaterialNum ; i ++ )
{
// マテリアルの輪郭線の太さを取得
float dotwidth = MV1GetMaterialOutLineDotWidth( pl.ModelHandle, i ) ;
// マテリアルの輪郭線の太さを拡大した分小さくする
MV1SetMaterialOutLineDotWidth( pl.ModelHandle, i, dotwidth/KOTORI_SCALE ) ;
}
// ただ立っているアニメーションを再生
pl.PlayAnim1=MV1AttachAnim( pl.ModelHandle, 0, -1, FALSE ) ;
// 物理演算の状態をリセット
MV1PhysicsResetState( pl.ModelHandle ) ;
}
// プレイヤーの処理
void Player_Process( void )
{
float TotalTime = MV1GetAttachAnimTotalTime( pl.ModelHandle, pl.PlayAnim1 ) ;
// 再生時間を進める
// 物理演算をmFPS分の1秒経過したという設定で実行
for(int i=0;i<KOTORI_PHISICS_RUNFRAME;i++)
{
pl.AnimPlayCount1 += CHARA_PLAY_ANIM_SPEED / (float)KOTORI_PHISICS_RUNFRAME;
// 再生時間がアニメーションの総再生時間に達したら再生時間を0に戻す
if( pl.AnimPlayCount1 >= TotalTime )
{
pl.AnimPlayCount1 = 0.0f ;
// 再生時間をセットする
MV1SetAttachAnimTime( pl.ModelHandle,pl.PlayAnim1, pl.AnimPlayCount1 ) ;
// モーションがループしたときに位置が移動することがあるので物理演算の状態をリセット
MV1PhysicsResetState( pl.ModelHandle ) ;
}
else
{
// 再生時間をセットする
MV1SetAttachAnimTime( pl.ModelHandle,pl.PlayAnim1, pl.AnimPlayCount1 ) ;
}
MV1PhysicsCalculation( pl.ModelHandle, 1000.0f / fps.FpsReturn() / (float)KOTORI_PHISICS_RUNFRAME ) ;
}
}
// ステージの初期化処理
void Stage_Initialize( void )
{
// ステージモデルの読み込み
stg.ModelHandle = MV1LoadModel( "背景モデル/S4Uドームベース.mv1" ) ;
MV1SetScale(stg.ModelHandle,VGet(STAGE_SCALE,STAGE_SCALE,STAGE_SCALE));
// 作成する画像のフォーマットを不動小数点型で1チャンネル、16ビットにする
SetDrawValidFloatTypeGraphCreateFlag( TRUE ) ;
SetCreateDrawValidGraphChannelNum( 1 ) ;
SetCreateGraphColorBitDepth( 16 ) ;
// 影用深度記録画像の作成
DepthBufferGraphHandle = MakeScreen( 4096, 4096, FALSE ) ;
// 設定を元に戻す
SetDrawValidFloatTypeGraphCreateFlag( FALSE ) ;
SetCreateDrawValidGraphChannelNum( 4 ) ;
SetCreateGraphColorBitDepth( 32 ) ;
// 深度記録画像描画用の頂点シェーダーを読み込む
Skin4_DepthShadow_Step1_VertexShader = LoadVertexShader( "SkinMesh4_DepthShadow_Step1VS.vso" ) ;
Normal_DepthShadow_Step1_VertexShader = LoadVertexShader( "NormalMesh_DepthShadow_Step1VS.vso" ) ;
// 深度記録画像描画用のピクセルシェーダーを読み込む
DepthShadow_Step1_PixelShader = LoadPixelShader( "DepthShadow_Step1PS.pso" ) ;
// 深度記録画像を使ったディレクショナルライト一つの描画用頂点シェーダーを読み込む
Skin4_DirLight_DepthShadow_Step2_VertexShader = LoadVertexShader( "SkinMesh4_DirLight_DepthShadow_Step2VS.vso" ) ;
Normal_DirLight_DepthShadow_Step2_VertexShader = LoadVertexShader( "NormalMesh_DirLight_DepthShadow_Step2VS.vso" ) ;
// 深度記録画像を使ったディレクショナルライト一つの描画用ピクセルシェーダーを読み込む
DirLight_DepthShadow_Step2_PixelShader = LoadPixelShader( "DirLight_DepthShadow_Step2PS.pso" ) ;
}
// ステージの後始末処理
void Stage_Terminate( void )
{
// ステージモデルの後始末
MV1DeleteModel( stg.ModelHandle ) ;
}
// カメラの初期化処理
void Camera_Initialize( void )
{
// カメラの初期水平角度は180度
cam.AngleH = DX_PI_F*3/2 ;
// 垂直角度は0度
cam.AngleV = 0.0f ;
cam.EyeHeight = 0;
cam.Length = CAMERA_PLAYER_LENGTH;
SetLightDirection(VGet(LIGHT_VEC_X,LIGHT_VEC_Y,LIGHT_VEC_Z));
}
// カメラの処理
void Camera_Process( void )
{
// パッドの3ボタンか、シフトキーが押されている場合のみ角度変更操作を行う
//if( CheckHitKey( KEY_INPUT_LSHIFT ) || ( inp.NowInput & PAD_INPUT_C ) )
{
// 「←」ボタンが押されていたら水平角度をマイナスする
if( inp.NowInput & PAD_INPUT_LEFT )
{
cam.AngleH -= CAMERA_ANGLE_SPEED ;
// -180度以下になったら角度値が大きくなりすぎないように360度を足す
if( cam.AngleH < -DX_PI_F )
{
cam.AngleH += DX_TWO_PI_F ;
}
}
// 「→」ボタンが押されていたら水平角度をプラスする
if( inp.NowInput & PAD_INPUT_RIGHT )
{
cam.AngleH += CAMERA_ANGLE_SPEED ;
// 180度以上になったら角度値が大きくなりすぎないように360度を引く
if( cam.AngleH > DX_PI_F )
{
cam.AngleH -= DX_TWO_PI_F ;
}
}
// 「↑」ボタンが押されていたら垂直角度をマイナスする
if( inp.NowInput & PAD_INPUT_UP )
{
cam.AngleV -= CAMERA_ANGLE_SPEED ;
// ある一定角度以下にはならないようにする
if( cam.AngleV < -DX_PI_F / 2.0f + 0.6f )
{
cam.AngleV = -DX_PI_F / 2.0f + 0.6f ;
}
}
// 「↓」ボタンが押されていたら垂直角度をプラスする
if( inp.NowInput & PAD_INPUT_DOWN )
{
cam.AngleV += CAMERA_ANGLE_SPEED ;
// ある一定角度以上にはならないようにする
if( cam.AngleV > DX_PI_F / 2.0f - 0.6f )
{
cam.AngleV = DX_PI_F / 2.0f - 0.6f ;
}
}
// カメラ近づける
if( inp.NowInput & PAD_INPUT_Z )
{
cam.Length-=5;
}
// カメラ離す
if( inp.NowInput & PAD_INPUT_X )
{
cam.Length+=5;
}
// カメラ上に移動
if( inp.NowInput & PAD_INPUT_Y )
{
cam.EyeHeight+=5;
}
// カメラ下に移動
if( inp.NowInput & PAD_INPUT_R )
{
cam.EyeHeight-=5;
}
}
// カメラの注視点はプレイヤー座標から規定値分高い座標
cam.Target = MV1GetFramePosition( pl.ModelHandle, 2 ) ;
if(KOTORI_MODEL_TYPE==0)cam.Target.y+=MODEL1_TAG_PLUS_Y;
if(KOTORI_MODEL_TYPE==1)cam.Target.y+=MODEL2_TAG_PLUS_Y;
if(KOTORI_MODEL_TYPE==2)cam.Target.y+=MODEL3_TAG_PLUS_Y;
// カメラの座標を決定する
{
MATRIX RotZ, RotY ;
float Camera_Player_Length ;
MV1_COLL_RESULT_POLY_DIM HRes ;
int HitNum ;
// 水平方向の回転はY軸回転
RotY = MGetRotY( cam.AngleH ) ;
// 垂直方向の回転はZ軸回転 )
RotZ = MGetRotZ( cam.AngleV ) ;
// カメラからプレイヤーまでの初期距離をセット
Camera_Player_Length = CAMERA_PLAYER_LENGTH ;
// カメラの座標を算出
// X軸にカメラとプレイヤーとの距離分だけ伸びたベクトルを
// 垂直方向回転( Z軸回転 )させたあと水平方向回転( Y軸回転 )して更に
// 注視点の座標を足したものがカメラの座標
cam.Eye = VAdd( VTransform( VTransform( VGet( -cam.Length, 0.0f, 0.0f ), RotZ ), RotY ), cam.Target ) ;
cam.Eye.y+=cam.EyeHeight;
}
}
// 影用の深度記録画像の準備を行う
void SetupDepthImage( void )
{
int i ;
VECTOR LightDirection ;
VECTOR LightPosition ;
VECTOR LightTarget ;
// 描画先を影用深度記録画像にする
SetDrawScreen( DepthBufferGraphHandle ) ;
// 影用深度記録画像を真っ白にクリア
SetBackgroundColor( 255, 255, 255 ) ;
ClearDrawScreen() ;
SetBackgroundColor( 0, 0, 0 ) ;
// カメラのタイプを正射影タイプにセット、描画範囲も指定
SetupCamera_Ortho( 1600.0f ) ;
// 描画する奥行き範囲をセット
SetCameraNearFar( 10.0f, 1500.0f ) ;
// カメラの向きはライトの向き
LightDirection = GetLightDirection() ;
// カメラの位置と注視点はステージ全体が見渡せる位置
LightTarget.x = pl.Position.x;//3620.0f ;
LightTarget.y = pl.Position.y ;
LightTarget.z = pl.Position.z;//3830.0f ;
LightPosition = VAdd( LightTarget, VScale( LightDirection, -1400.0f ) ) ;
SetCameraPositionAndTarget_UpVecY( LightPosition, LightTarget ) ;
// 設定したカメラのビュー行列と射影行列を取得しておく
LightCamera_ViewMatrix = GetCameraViewMatrix() ;
LightCamera_ProjectionMatrix = GetCameraProjectionMatrix() ;
// モデルの描画にオリジナルのシェーダーを使用するように設定する
MV1SetUseOrigShader( TRUE ) ;
// 深度記録画像への描画用のピクセルシェーダーをセット
SetUsePixelShader( DepthShadow_Step1_PixelShader ) ;
// 深度記録画像への剛体メッシュ描画用の頂点シェーダーをセット
SetUseVertexShader( Normal_DepthShadow_Step1_VertexShader ) ;
// ステージを描画
//MV1DrawModel( stg.ModelHandle ) ;
// 深度記録画像へのスキニングメッシュ描画用の頂点シェーダーをセット
SetUseVertexShader( Skin4_DepthShadow_Step1_VertexShader ) ;
// プレイヤーモデルの描画
MV1DrawModel( pl.ModelHandle ) ;
// モデルの描画にオリジナルのシェーダーを使用するようにした設定を解除
MV1SetUseOrigShader( FALSE ) ;
// 描画先を裏画面に戻す
SetDrawScreen( DX_SCREEN_BACK ) ;
}
// 影用の深度記録画像を使った影を落とす処理も含めたモデルの描画
void DrawModelWithDepthShadow( void )
{
int i ;
// カメラの設定を行う
SetCameraPositionAndTarget_UpVecY( cam.Eye, cam.Target ) ;
MV1SetMeshCategoryVisible( pl.ModelHandle, DX_MV1_MESHCATEGORY_NORMAL, FALSE ) ;
MV1SetMeshCategoryVisible( pl.ModelHandle, DX_MV1_MESHCATEGORY_OUTLINE, TRUE ) ;
MV1DrawModel( pl.ModelHandle ) ;
// モデルの描画にオリジナルのシェーダーを使用するように設定する
MV1SetUseOrigShader( TRUE ) ;
MV1SetMeshCategoryVisible( pl.ModelHandle, DX_MV1_MESHCATEGORY_NORMAL, TRUE ) ;
MV1SetMeshCategoryVisible( pl.ModelHandle, DX_MV1_MESHCATEGORY_OUTLINE_ORIG_SHADER, FALSE ) ;
// 深度記録画像を使った影+ディレクショナルライト一つ描画用のピクセルシェーダーをセット
SetUsePixelShader( DirLight_DepthShadow_Step2_PixelShader ) ;
// 影用深度記録画像を描画したときのカメラのビュー行列と射影行列を定数に設定する
SetVSConstFMtx( 43, LightCamera_ViewMatrix ) ;
SetVSConstFMtx( 47, LightCamera_ProjectionMatrix ) ;
// 影用深度記録画像をテクスチャ10にセット
SetUseTextureToShader( 10, DepthBufferGraphHandle ) ;
// 深度記録画像を使った影+ディレクショナルライト一つの剛体メッシュ描画用の頂点シェーダーをセット
SetUseVertexShader( Normal_DirLight_DepthShadow_Step2_VertexShader ) ;
// 深度記録画像を使った影+ディレクショナルライト一つのスキニングメッシュ描画用の頂点シェーダーをセット
SetUseVertexShader( Skin4_DirLight_DepthShadow_Step2_VertexShader ) ;
// プレイヤーモデルの描画
MV1DrawModel( pl.ModelHandle ) ;
// モデルの描画にオリジナルのシェーダーを使用するようにした設定を解除
MV1SetUseOrigShader( FALSE ) ;
// 使用テクスチャの設定を解除
SetUseTextureToShader( 1, -1 ) ;
// 設定した定数を解除
ResetVSConstF( 43, 8 ) ;
ChangeLightTypePoint( cam.Target, 20000, 1.0f, 0.0006f , 0.0f ) ;
//SetGlobalAmbientLight( GetColorF(1.0f,1.0f,1.0f,1.0f ) );
// ステージモデルの描画
MV1DrawModel( stg.ModelHandle ) ;
}
// 描画処理
void Render_Process( void )
{
// 影用の深度記録画像の準備を行う
SetupDepthImage() ;
// 影用の深度記録画像を使った影を落とす処理も含めたモデルの描画
DrawModelWithDepthShadow() ;
/* セルフシャドウ使わない描画
SetCameraPositionAndTarget_UpVecY( cam.Eye, cam.Target ) ;
MV1DrawModel( stg.ModelHandle ) ;
// 物理演算を60分の1秒経過したという設定で実行
MV1PhysicsCalculation( pl.ModelHandle, 1000.0f / fps.FpsReturn() ) ;
// プレイヤーモデルの描画
MV1DrawModel( pl.ModelHandle ) ;
*/
if(debugMode==true)
DrawFormatString(300,0,GetColor(0,255,0),"DEBUG_MODE(未実装)");
VECTOR vec;
vec=MV1GetFramePosition( pl.ModelHandle, 2 );
DrawFormatString(0,30,GetColor(255,255,255),"モデル座標 x %.1f, y %.1f, z %.1f",vec.x,vec.y,vec.z);
}
// WinMain
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow )
{
// ウインドウモードで起動
ChangeWindowMode( TRUE ) ;
// ライブラリの初期化
if( DxLib_Init() < 0 )
return -1 ;
// プレイヤーの初期化
Player_Initialize() ;
// ステージの初期化
Stage_Initialize() ;
// カメラの初期化
Camera_Initialize() ;
// 描画先を裏画面にする
SetDrawScreen( DX_SCREEN_BACK ) ;
// ESCキーが押されるか、ウインドウが閉じられるまでループ
while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
{
// FPS更新
fps.Update();
// 画面をクリア
ClearDrawScreen() ;
// 入力処理
Input_Process() ;
// プレイヤーの処理
Player_Process() ;
// カメラの処理
Camera_Process() ;
// 描画処理
Render_Process() ;
// FPS描画
fps.Draw();
//printfDx("CNT%d\n",cnt);
// 裏画面の内容を表画面に反映
ScreenFlip() ;
// cnt++
cnt++;
// FPS待機
fps.Wait();
}
// ステージの後始末
Stage_Terminate() ;
// ライブラリの後始末
DxLib_End() ;
// ソフト終了
return 0 ;
}