図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();
}