図0405a
中心にある茶色い球体は自作シェーダによる描画です。内容的にはPNTStatic描画コンポーネントの簡略版となります。1、頂点シェーダの準備と記述 2、ピクセルシェーダの準備と記述 3、インクルードファイルの準備と記述 4、シェーダクラスの作成(コンスタントバッファ、頂点、ピクセル) 5、描画処理
図0405b
図0405c
続いて、作成したShaderSourcesフィルタに追加・新しい項目の追加を選びます。
図0405d
すると以下のような画面がでますので頂点シェーダを選びます。シェーダ名をVSTest.hlslとし、作成するディレクトリをGameSourcesディレクトリにShaderSourcesのサブディレクトリを作成し、指定します。
図0405e
ファイルが作成されます。
図0405f
作成したファイルのプロパティを選びます。
図0405g
構成プロパティのHLSLコンパイラの出力ファイルが、$(SolutionDir)media\Shaders\%(Filename).cso
struct VSPNTInput { float4 position : SV_POSITION; float3 norm : NORMAL; float2 tex : TEXCOORD; }; struct PSPNTInput { float4 position : SV_POSITION; float3 norm : NORMAL; float2 tex : TEXCOORD; }; cbuffer ParametersBuffer : register(b0) { float4x4 World : packoffset(c0); float4x4 View : packoffset(c4); float4x4 Projection : packoffset(c8); float4 Emissive : packoffset(c12); float4 Diffuse : packoffset(c13); float4 LightDir : packoffset(c14); }; PSPNTInput main(VSPNTInput input) { PSPNTInput result; //頂点の位置を変換 float4 pos = float4(input.position.xyz, 1.0f); //ワールド変換 pos = mul(pos, World); //ビュー変換 pos = mul(pos, View); //射影変換 pos = mul(pos, Projection); //ピクセルシェーダに渡す変数に設定 result.position = pos; //ライティング result.norm = mul(input.norm, (float3x3)World); result.norm = normalize(result.norm); //テクスチャUV result.tex = input.tex; return result; }
図0405h
以下がコードです。struct VSPNTInput { float4 position : SV_POSITION; float3 norm : NORMAL; float2 tex : TEXCOORD; }; struct PSPNTInput { float4 position : SV_POSITION; float3 norm : NORMAL; float2 tex : TEXCOORD; }; cbuffer ParametersBuffer : register(b0) { float4x4 World : packoffset(c0); float4x4 View : packoffset(c4); float4x4 Projection : packoffset(c8); float4 Emissive : packoffset(c12); float4 Diffuse : packoffset(c13); float4 LightDir : packoffset(c14); }; Texture2D g_texture : register(t0); SamplerState g_sampler : register(s0); float4 main(PSPNTInput input) : SV_TARGET { //ライティング float3 lightdir = normalize(LightDir.xyz); float4 Light = (saturate(dot(input.norm, -lightdir)) * Diffuse) + Emissive; Light.a = Diffuse.a; Light = g_texture.Sample(g_sampler, input.tex) * Light; return Light; }
図0405i
そしてそのファイルに以下のように記述します。struct VSPNTInput { float4 position : SV_POSITION; float3 norm : NORMAL; float2 tex : TEXCOORD; }; struct PSPNTInput { float4 position : SV_POSITION; float3 norm : NORMAL; float2 tex : TEXCOORD; }; cbuffer ParametersBuffer : register(b0) { float4x4 World : packoffset(c0); float4x4 View : packoffset(c4); float4x4 Projection : packoffset(c8); float4 Emissive : packoffset(c12); float4 Diffuse : packoffset(c13); float4 LightDir : packoffset(c14); };
//共通の項目をインクルード
#include "INCTest.hlsli"
PSPNTInput main(VSPNTInput input)
{
PSPNTInput result;
//頂点の位置を変換
float4 pos = float4(input.position.xyz, 1.0f);
//ワールド変換
pos = mul(pos, World);
//ビュー変換
pos = mul(pos, View);
//射影変換
pos = mul(pos, Projection);
//ピクセルシェーダに渡す変数に設定
result.position = pos;
//ライティング
result.norm = mul(input.norm, (float3x3)World);
result.norm = normalize(result.norm);
//テクスチャUV
result.tex = input.tex;
return result;
}
//共通の項目をインクルード
#include "INCTest.hlsli"
Texture2D g_texture : register(t0);
SamplerState g_sampler : register(s0);
float4 main(PSPNTInput input) : SV_TARGET
{
//ライティング
float3 lightdir = normalize(LightDir.xyz);
float4 Light = (saturate(dot(input.norm, -lightdir)) * Diffuse) + Emissive;
Light.a = Diffuse.a;
Light = g_texture.Sample(g_sampler, input.tex) * Light;
return Light;
}
//-------------------------------------------------------------------------------------- /// コンスタントバッファ構造体 //-------------------------------------------------------------------------------------- struct TestConstants { /// ワールド行列 Mat4x4 World; /// ビュー行列 Mat4x4 View; /// 射影行列 Mat4x4 Projection; /// エミッシブ色 Col4 Emissive; /// デフューズ色 Col4 Diffuse; /// ライイト方向 Vec4 LightDir; TestConstants() { memset(this, 0, sizeof(TestConstants)); Diffuse = Col4(1.0f, 1.0f, 1.0f, 1.0f); }; }; //コンスタントバッファ用マクロ DECLARE_DX11_CONSTANT_BUFFER(CBTest, TestConstants) //頂点シェーダ用マクロ DECLARE_DX11_VERTEX_SHADER(VSTest, VertexPositionNormalTexture) //ピクセルシェーダ用マクロ DECLARE_DX11_PIXEL_SHADER(PSTest)
//コンスタントバッファ用マクロ DECLARE_DX11_CONSTANT_BUFFER(CBTest, TestConstants)
//頂点シェーダ用マクロ DECLARE_DX11_VERTEX_SHADER(VSTest, VertexPositionNormalTexture)
//ピクセルシェーダ用マクロ DECLARE_DX11_PIXEL_SHADER(PSTest)
//コンスタントバッファ実体マクロ IMPLEMENT_DX11_CONSTANT_BUFFER(CBTest) //頂点シェーダ実体マクロ IMPLEMENT_DX11_VERTEX_SHADER(VSTest, App::GetApp()->GetShadersPath() + L"VSTest.cso") //ピクセルシェーダ実体マクロ IMPLEMENT_DX11_PIXEL_SHADER(PSTest, App::GetApp()->GetShadersPath() + L"PSTest.cso")
void PntSphere::OnDraw() { //メッシュの取得 auto MeshRes = App::GetApp()->GetResource<MeshResource>(L"DEFAULT_SPHERE"); //デバイスの取得 auto Dev = App::GetApp()->GetDeviceResources(); //デバイスコンテキストの取得 auto pD3D11DeviceContext = Dev->GetD3DDeviceContext(); //レンダーステートの取得 auto RenderState = Dev->GetRenderState(); //コンスタントバッファの準備 TestConstants Cb; //行列の定義 auto PtrTrans = GetComponent<Transform>(); //行列の定義 Mat4x4 World, ViewMat, ProjMat; //ワールド行列の決定 World = PtrTrans->GetWorldMatrix(); //転置する World.transpose(); //カメラを得る auto CameraPtr = OnGetDrawCamera(); //ビューと射影行列を得る ViewMat = CameraPtr->GetViewMatrix(); //転置する ViewMat.transpose(); ProjMat = CameraPtr->GetProjMatrix(); //転置する ProjMat.transpose(); Cb.World = World; Cb.View = ViewMat; Cb.Projection = ProjMat; //エミッシブ Cb.Emissive = Col4(0.5f, 0.5f, 0.5f,0); //デフィーズ Cb.Diffuse = Col4(1, 1, 1, 1); //ライティング auto StageLight = OnGetDrawLight(); Cb.LightDir = StageLight.m_Directional; Cb.LightDir.w = 1.0f; //テクスチャ(シェーダリソース)の取得 auto Res = App::GetApp()->GetResource<TextureResource>(L"WALL_TX"); pD3D11DeviceContext->PSSetShaderResources(0, 1, Res->GetShaderResourceView().GetAddressOf()); auto pSampler = RenderState->GetLinearClamp(); //サンプラーを設定 pD3D11DeviceContext->PSSetSamplers(0, 1, &pSampler); //コンスタントバッファの更新 pD3D11DeviceContext->UpdateSubresource(CBTest::GetPtr()->GetBuffer(), 0, nullptr, &Cb, 0, 0); //ストライドとオフセット UINT stride = MeshRes->GetNumStride(); UINT offset = 0; //頂点バッファのセット pD3D11DeviceContext->IASetVertexBuffers(0, 1, MeshRes->GetVertexBuffer().GetAddressOf(), &stride, &offset); //インデックスバッファのセット pD3D11DeviceContext->IASetIndexBuffer(MeshRes->GetIndexBuffer().Get(), DXGI_FORMAT_R16_UINT, 0); //描画方法(3角形) pD3D11DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); //コンスタントバッファの設定 ID3D11Buffer* pConstantBuffer = CBTest::GetPtr()->GetBuffer(); //頂点シェーダに渡す pD3D11DeviceContext->VSSetConstantBuffers(0, 1, &pConstantBuffer); //ピクセルシェーダに渡す pD3D11DeviceContext->PSSetConstantBuffers(0, 1, &pConstantBuffer); //シェーダの設定 pD3D11DeviceContext->VSSetShader(VSTest::GetPtr()->GetShader(), nullptr, 0); pD3D11DeviceContext->PSSetShader(PSTest::GetPtr()->GetShader(), nullptr, 0); //インプットレイアウトの設定 pD3D11DeviceContext->IASetInputLayout(VSTest::GetPtr()->GetInputLayout()); //デプスステンシルステート pD3D11DeviceContext->OMSetDepthStencilState(RenderState->GetDepthDefault(), 0); //ブレンドステート pD3D11DeviceContext->OMSetBlendState(RenderState->GetOpaque(), nullptr, 0xffffffff); //ラスタライザステート pD3D11DeviceContext->RSSetState(RenderState->GetCullBack()); //描画 pD3D11DeviceContext->DrawIndexed(MeshRes->GetNumIndicis(), 0, 0); //後始末 Dev->InitializeStates(); }