トップページ > 記事閲覧
シェーダーを使用したモデルの描画がされない
名前:猫の湯飲み 日時: 2023/05/25 16:23

モデルの描画に SetUseVertexShader, SetUsePixelShader で指定したシェーダーを使用した際、モデルが描画されず行き詰まっています どこら辺が間違っているなど教えてもらえるとありがたいです。よろしくお願いいたします。 <main.cpp>------------------------ #include <DxLib.h> // プログラムは WinMain から始まります int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { SetUseDirect3DVersion(DX_DIRECT3D_11); ChangeWindowMode(TRUE); if (DxLib_Init() == -1) // DXライブラリ初期化処理 { return -1; // エラーが起きたら直ちに終了 } SetBackgroundColor(200,200, 200); SetDrawScreen(DX_SCREEN_BACK); int modelHande = MV1LoadModel("./bin/grass.mv1"); // 頂点シェーダーを読み込む int vshandle = LoadVertexShader("./bin/VertexShaderTestVS.vso"); // ピクセルシェーダーを読み込む int pshandle = LoadPixelShader("./bin/VertexShaderTestPS.pso"); int vscbhandle = CreateShaderConstantBuffer(sizeof(float) * 4); FLOAT4* f4; int startTime= GetNowCount(); int processTime; // モデルの見える位置にカメラを配置 SetCameraPositionAndTarget_UpVecY(VGet(100, 0, -500), VGet(0.0f, 0.0f, 0.0f)); while (ScreenFlip() == 0 && ProcessMessage() == 0 && ClearDrawScreen() == 0) { processTime = GetNowCount() - startTime; DrawFormatString(0,0,GetColor(0,0,0),"ProcessTime:%d",processTime); // 頂点シェーダー用の定数バッファのアドレスを取得 f4 = (FLOAT4*)GetBufferShaderConstantBuffer(vscbhandle); // 座標値を取得したアドレスに書き込み f4->x = (float)processTime/1000.0f; f4->y = 0.0f; f4->z = 0.0f; f4->w = 0.0f; // 頂点シェーダー用の定数バッファを更新して書き込んだ内容を反映する UpdateShaderConstantBuffer(vscbhandle); // 頂点シェーダーの定数バッファを定数バッファレジスタ4にセット SetShaderConstantBuffer(vscbhandle, DX_SHADERTYPE_VERTEX, 4); // 使用する頂点シェーダーのセット SetUseVertexShader(vshandle); // 使用するピクセルシェーダーをセット SetUsePixelShader(pshandle); MV1SetPosition(modelHande, VGet(0, 0, 0)); MV1SetScale(modelHande, VGet(20, 20, 20)); MV1SetUseOrigShader(TRUE); MV1DrawModel(modelHande); MV1SetUseOrigShader(FALSE); } WaitKey(); // キー入力待ち // 読み込んだ頂点シェーダーの削除 DeleteShader(vshandle); DeleteShader(pshandle); // 頂点シェーダー用定数バッファを削除 DeleteShaderConstantBuffer(vscbhandle); DxLib_End(); // DXライブラリ使用の終了処理 return 0; // ソフトの終了 } <VertexShaderTestVS.fx>------------------------ // 基本パラメータ struct DX_D3D11_VS_CONST_BUFFER_BASE { float4 AntiViewportMatrix[ 4 ] ; // アンチビューポート行列 float4 ProjectionMatrix[ 4 ] ; // ビュー → プロジェクション行列 float4 ViewMatrix[ 3 ] ; // ワールド → ビュー行列 float4 LocalWorldMatrix[ 3 ] ; // ローカル → ワールド行列 float4 ToonOutLineSize ; // トゥーンの輪郭線の大きさ float DiffuseSource ; // ディフューズカラー( 0.0f:マテリアル 1.0f:頂点 ) float SpecularSource ; // スペキュラカラー( 0.0f:マテリアル 1.0f:頂点 ) float MulSpecularColor ; // スペキュラカラー値に乗算する値( スペキュラ無効処理で使用 ) float Padding ; } ; // 基本パラメータ cbuffer cbD3D11_CONST_BUFFER_VS_BASE : register( b1 ) { DX_D3D11_VS_CONST_BUFFER_BASE g_Base ; } ; // 頂点座標に加算する値 cbuffer cbTime : register( b4 ) { float4 g_time ; } ; // 頂点シェーダーの入力 struct VS_INPUT { float3 Position : POSITION0 ; // 座標( ローカル空間 ) float4 SubPosition : POSITION1 ; // 補助座標 float3 Normal : NORMAL ; // 法線 float3 Tangent : TANGENT ; // 接線 float3 Binormal : BINORMAL ; // 従法線 float4 Diffuse : COLOR0 ; // ディフューズカラー float4 Specular : COLOR1 ; // スペキュラカラー float2 TexCoords0 : TEXCOORD0 ; // テクスチャ座標0 float2 TexCoords1 : TEXCOORD1 ; // テクスチャ座標1 } ; // 頂点シェーダーの出力 struct VS_OUTPUT { float4 Position : SV_POSITION ; // 座標( プロジェクション空間 ) float4 Diffuse : COLOR0 ; // ディフューズカラー float2 TexCoords0 : TEXCOORD0 ; // テクスチャ座標0 float2 TexCoords1 : TEXCOORD1 ; // テクスチャ座標1 } ; // main関数 VS_OUTPUT main( VS_INPUT VSInput ) { VS_OUTPUT VSOutput ; float4 lWorldPosition ; float4 lViewPosition ; // 入力の頂点座標にC++プログラム側で設定した頂点座標を加算する lWorldPosition.x = sin(g_time.x) * VSInput.Position.y * 0.3; lWorldPosition.yz = VSInput.Position.yz; lWorldPosition.w = 1.0f ; // 頂点座標をビュー空間の座標に変換する lViewPosition.x = dot( lWorldPosition, g_Base.ViewMatrix[ 0 ] ) ; lViewPosition.y = dot( lWorldPosition, g_Base.ViewMatrix[ 1 ] ) ; lViewPosition.z = dot( lWorldPosition, g_Base.ViewMatrix[ 2 ] ) ; lViewPosition.w = 1.0f ; // ビュー空間の座標を射影空間の座標に変換する VSOutput.Position.x = dot( lViewPosition, g_Base.ProjectionMatrix[ 0 ] ) ; VSOutput.Position.y = dot( lViewPosition, g_Base.ProjectionMatrix[ 1 ] ) ; VSOutput.Position.z = dot( lViewPosition, g_Base.ProjectionMatrix[ 2 ] ) ; VSOutput.Position.w = dot( lViewPosition, g_Base.ProjectionMatrix[ 3 ] ) ; // テクスチャ座標はそのまま代入 VSOutput.TexCoords0 = VSInput.TexCoords0; // 頂点カラーはそのまま代入 VSOutput.Diffuse = VSInput.Diffuse ; // 関数の戻り値がピクセルシェーダーに渡される return VSOutput ; } <VertexShaderTestPS.fx>------------------------------- // ピクセルシェーダーの入力 struct PS_INPUT { float4 Diffuse : COLOR0; // ディフューズカラー float4 Specular : COLOR1; // スペキュラカラー float2 TexCoords0 : TEXCOORD0; // テクスチャ座標 }; // ピクセルシェーダーの出力 struct PS_OUTPUT { float4 Color0 : SV_TARGET0; // 色 }; // 定数バッファピクセルシェーダー基本パラメータ struct DX_D3D11_PS_CONST_BUFFER_BASE { float4 FactorColor; // アルファ値等 float MulAlphaColor; // カラーにアルファ値を乗算するかどうか( 0.0f:乗算しない 1.0f:乗算する ) float AlphaTestRef; // アルファテストで使用する比較値 float2 Padding1; int AlphaTestCmpMode; // アルファテスト比較モード( DX_CMP_NEVER など ) int3 Padding2; float4 IgnoreTextureColor; // テクスチャカラー無視処理用カラー }; // 基本パラメータ cbuffer cbD3D11_CONST_BUFFER_PS_BASE : register(b1) { DX_D3D11_PS_CONST_BUFFER_BASE g_Base; }; SamplerState g_DiffuseMapSampler : register(s0); // ディフューズマップテクスチャ Texture2D g_DiffuseMapTexture : register(t0); // ディフューズマップテクスチャ // main関数 PS_OUTPUT main(PS_INPUT PSInput) { PS_OUTPUT PSOutput; float4 TextureDiffuseColor; // テクスチャカラーの読み込み TextureDiffuseColor = g_DiffuseMapTexture.Sample(g_DiffuseMapSampler, PSInput.TexCoords0); // 出力カラー = テクスチャカラー PSOutput.Color0 = TextureDiffuseColor; // 出力アルファ = テクスチャアルファ * 不透明度 PSOutput.Color0.a = TextureDiffuseColor.a * g_Base.FactorColor.a; // 出力パラメータを返す return PSOutput; }
メンテ

Page: 1 |

Re: シェーダーを使用したモデルの描画がされない ( No.1 )
名前:管理人 日時:2023/05/26 02:04

少し拝見した限りでは頂点シェーダーの出力とピクセルシェーダーの入力が一致していないのが原因の一つかと思います ( VS_OUTPUT には Specular が無いのに PS_INPUT には Specular がある、  VS_OUTPUT には TexCoords1 があるのに PS_INPUT には TexCoords1 が無い ) 頂点シェーダーの出力の構造体とピクセルシェーダーの入力の構造体は全く同じでないと 正常に動作しませんので、まずは頂点シェーダーの出力の構造体とピクセルシェーダーの入力の 構造体のメンバー変数を全く同じにしてみてください
メンテ
Re: シェーダーを使用したモデルの描画がされない ( No.2 )
名前:猫の湯飲み 日時:2023/05/26 20:39

頂点シェーダーの出力の構造体とピクセルシェーダーの入力の 構造体のメンバー変数を同じにしてみましたが描画されませんでした。 <VertexShaderTestVS.fx>------------------------ // 基本パラメータ struct DX_D3D11_VS_CONST_BUFFER_BASE { float4 AntiViewportMatrix[ 4 ] ; // アンチビューポート行列 float4 ProjectionMatrix[ 4 ] ; // ビュー → プロジェクション行列 float4 ViewMatrix[ 3 ] ; // ワールド → ビュー行列 float4 LocalWorldMatrix[ 3 ] ; // ローカル → ワールド行列 float4 ToonOutLineSize ; // トゥーンの輪郭線の大きさ float DiffuseSource ; // ディフューズカラー( 0.0f:マテリアル 1.0f:頂点 ) float SpecularSource ; // スペキュラカラー( 0.0f:マテリアル 1.0f:頂点 ) float MulSpecularColor ; // スペキュラカラー値に乗算する値( スペキュラ無効処理で使用 ) float Padding ; } ; // 基本パラメータ cbuffer cbD3D11_CONST_BUFFER_VS_BASE : register( b1 ) { DX_D3D11_VS_CONST_BUFFER_BASE g_Base ; } ; // 頂点シェーダーの入力 struct VS_INPUT { float3 Position : POSITION; // 座標( ローカル空間 ) float3 Normal : NORMAL; // 法線( ローカル空間 ) float4 Diffuse : COLOR0; // ディフューズカラー float4 Specular : COLOR1; // スペキュラカラー float4 TexCoords0 : TEXCOORD0; // テクスチャ座標 float4 TexCoords1 : TEXCOORD1; // サブテクスチャ座標 }; // 頂点シェーダーの出力 struct VS_OUTPUT { float4 Position : SV_POSITION; // 座標( プロジェクション空間 ) float2 TexCoords0 : TEXCOORD0; // テクスチャ座標0 }; // 頂点座標に加算する値 cbuffer cbTime : register( b4 ) { float4 g_time ; } ; // main関数 VS_OUTPUT main( VS_INPUT VSInput ) { VS_OUTPUT VSOutput ; float4 lWorldPosition ; float4 lViewPosition ; // 入力の頂点座標にC++プログラム側で設定した頂点座標を加算する lWorldPosition.x = sin(g_time.x) * VSInput.Position.y * 0.3; lWorldPosition.yz = VSInput.Position.yz; //lWorldPosition.xyz = VSInput.Position.xyz; lWorldPosition.w = 1.0f ; // 頂点座標をビュー空間の座標に変換する lViewPosition.x = dot( lWorldPosition, g_Base.ViewMatrix[ 0 ] ) ; lViewPosition.y = dot( lWorldPosition, g_Base.ViewMatrix[ 1 ] ) ; lViewPosition.z = dot( lWorldPosition, g_Base.ViewMatrix[ 2 ] ) ; lViewPosition.w = 1.0f ; // ビュー空間の座標を射影空間の座標に変換する VSOutput.Position.x = dot( lViewPosition, g_Base.ProjectionMatrix[ 0 ] ) ; VSOutput.Position.y = dot( lViewPosition, g_Base.ProjectionMatrix[ 1 ] ) ; VSOutput.Position.z = dot( lViewPosition, g_Base.ProjectionMatrix[ 2 ] ) ; VSOutput.Position.w = dot( lViewPosition, g_Base.ProjectionMatrix[ 3 ] ) ; // テクスチャ座標はそのまま代入 VSOutput.TexCoords0 = VSInput.TexCoords0; // 関数の戻り値がピクセルシェーダーに渡される return VSOutput ; } <VertexShaderTestPS.fx>------------------------------- // ピクセルシェーダーの入力 struct PS_INPUT { float4 Position : SV_POSITION ; float2 TexCoords0 : TEXCOORD0 ; }; // ピクセルシェーダーの出力 struct PS_OUTPUT { float4 Output : SV_TARGET0 ; } ; // 定数バッファピクセルシェーダー基本パラメータ struct DX_D3D11_PS_CONST_BUFFER_BASE { float4 FactorColor; // アルファ値等 float MulAlphaColor; // カラーにアルファ値を乗算するかどうか( 0.0f:乗算しない 1.0f:乗算する ) float AlphaTestRef; // アルファテストで使用する比較値 float2 Padding1; int AlphaTestCmpMode; // アルファテスト比較モード( DX_CMP_NEVER など ) int3 Padding2; float4 IgnoreTextureColor; // テクスチャカラー無視処理用カラー }; // 基本パラメータ cbuffer cbD3D11_CONST_BUFFER_PS_BASE : register(b1) { DX_D3D11_PS_CONST_BUFFER_BASE g_Base; }; // C++ 側で設定する定数の定義 // 描画するテクスチャ SamplerState g_SrcSampler : register( s0 ) ; Texture2D g_SrcTexture : register( t0 ) ; // main関数 PS_OUTPUT main( PS_INPUT PSInput ) { PS_OUTPUT PSOutput ; float4 TextureDiffuseColor; // テクスチャカラーの読み込み TextureDiffuseColor = g_SrcTexture.Sample(g_SrcSampler, PSInput.TexCoords0); // 出力カラー = テクスチャカラー PSOutput.Output = TextureDiffuseColor; // 出力アルファ = テクスチャアルファ * 不透明度 PSOutput.Output.a = TextureDiffuseColor.a * g_Base.FactorColor.a; // 関数の戻り値がラスタライザに渡される return PSOutput ; }
メンテ
Re: シェーダーを使用したモデルの描画がされない ( No.3 )
名前:管理人 日時:2023/05/27 00:57

駄目でしたか… 載せていただいている頂点シェーダーのコードは 『スペキュラマップ付き剛体モデル』用となっていますが( struct VS_INPUT に『接線』『従法線』が含まれるため )、 MV1LoadModel で読み込んでいる grass.mv1 は『スペキュラマップ付き剛体モデル』でしょうか? ともあれ、色々細かい部分を拝見しないと何が原因か突き止められそうにないので よろしければ grass.mv1 と、grass.mv1 で使用しているテクスチャを纏めて zip圧縮などしてこちらのメールアドレスに送って頂けないでしょうか? m(_ _)m BQE00322(あっとまーく)nifty.com ( (あっとまーく) を @ に置き換えてください ) 手元で試すことができれば原因も比較的容易に突き止めることができると思います
メンテ
Re: シェーダーを使用したモデルの描画がされない ( No.4 )
名前:管理人 日時:2023/05/28 02:00

メールありがとうございます アップしていただいたファイルを手元で実行したところ、原因が分かりました 頂点シェーダーのワールド座標を代入しているこちらの処理ですが float4 lWorldPosition ; float4 lViewPosition ; // 入力の頂点座標にC++プログラム側で設定した頂点座標を加算する lWorldPosition.x = sin(g_time.x) * VSInput.Position.y * 0.3; lWorldPosition.yz = VSInput.Position.yz; //lWorldPosition.xyz = VSInput.Position.xyz; lWorldPosition.w = 1.0f ; 3Dモデルの場合はワールド座標の前に3Dモデルのローカル座標があり、 ローカル座標からワールド座標に変換する処理が入るのでした、なので以下のように ローカル座標をまず代入して、それをワールド座標に変換する処理に変更したところ正常に描画されました float4 lLocalPosition ; float4 lWorldPosition ; float4 lViewPosition ; // 入力の頂点座標にC++プログラム側で設定した頂点座標を加算する lLocalPosition.x = sin(g_time.x) * VSInput.Position.y * 0.3; lLocalPosition.yz = VSInput.Position.yz; //lLocalPosition.xyz = VSInput.Position.xyz; lLocalPosition.w = 1.0f ; // ローカル空間の座標をワールド空間の座標に変換する lWorldPosition.x = dot( lLocalPosition, g_Base.LocalWorldMatrix[ 0 ] ) ; lWorldPosition.y = dot( lLocalPosition, g_Base.LocalWorldMatrix[ 1 ] ) ; lWorldPosition.z = dot( lLocalPosition, g_Base.LocalWorldMatrix[ 2 ] ) ; lWorldPosition.w = 1.0f ; よろしければお試しください m(_ _)m
メンテ
Re: シェーダーを使用したモデルの描画がされない ( No.5 )
名前:猫の湯飲み 日時:2023/05/29 23:03

返信ありがとうございます。 正しく描画することが出来ました。 一つ質問なのですが 頂点シェーダーの出力の構造体とピクセルシェーダーの入力の構造体が同じであれば構造体の内容(COLOR0,COLOR1,TEXCOORD0 etc...)は自由に決めてもいいのでしょうか? それとも頂点シェーダーの入力のようにモデルによって構造体の内容が決まっているのでしょうか?
メンテ
Re: シェーダーを使用したモデルの描画がされない ( No.6 )
名前:管理人 日時:2023/05/30 01:54

正常に描画できたようで何よりです > 一つ質問なのですが > 頂点シェーダーの出力の構造体とピクセルシェーダーの入力の構造体が同じであれば構造体の内容(COLOR0,COLOR1,TEXCOORD0 etc...)は自由に決めてもいいのでしょうか? はい、頂点シェーダーもピクセルシェーダーも自作の場合は頂点シェーダーの出力の構造体の内容は自由に決めることができます ( 頂点シェーダーの出力はピクセルシェーダーの入力としてしか使用されないので、ピクセルシェーダーも自作の場合はどのような定義にしても大丈夫です )
メンテ
Re: シェーダーを使用したモデルの描画がされない ( No.7 )
名前:猫の湯飲み 日時:2023/06/01 21:46

返信が遅れて申し訳ありません 無事、シェーダーで表現したいことが出来ました。 重ねての質問にお付き合いいただきありがとうございました。
メンテ

Page: 1 |

題名
名前
コメント
パスワード (記事メンテ時に使用)

   クッキー保存