図0407a
この画面は、FullSample4071の画面です。ここでは、ジオメトリックシェーダを使って、3つ描画していいます。
cbuffer SimpleConstantBuffer : register(b0)
{
float4x4 World[3] : packoffset(c0);
float4x4 View : packoffset(c12);
float4x4 Projection : packoffset(c16);
float4 LightDir : packoffset(c20);
float4 Param : packoffset(c21);
};
struct VertexShaderInput
{
float4 pos : SV_Position;
float3 norm : NORMAL;
float4 color : COLOR0;
};
typedef VertexShaderInput GeometryShaderInput;
struct PixelShaderInput
{
float4 pos : SV_POSITION;
float3 norm : NORMAL;
float4 color : COLOR0;
};
#include "SimpleInc.hlsli"
GeometryShaderInput main(VertexShaderInput input)
{
//ジオメトリシェーダーに渡す変数
//入力をそのまま出力する
GeometryShaderInput vertexShaderOutput
= (GeometryShaderInput)input;
return vertexShaderOutput;
}
#include "SimpleInc.hlsli" [maxvertexcount(9)] void main( triangle GeometryShaderInput input[3], inout TriangleStream< PixelShaderInput > output ) { for (uint count = 0; count < 3; count++){ for (uint i = 0; i < 3; i++) { PixelShaderInput element; //頂点の位置を変換 float4 pos = float4(input[i].pos.xyz, 1.0f); float4 Col; if (pos.y > 0){ switch (count){ case 0: Col = float4(1.0f, 0.0f, 0.0f, 0.0f); break; case 1: Col = float4(0.0f, 1.0f, 0.0f, 0.0f); break; case 2: Col = float4(0.0f, 0.0f, 1.0f, 0.0f); break; default: Col = float4(1.0f, 1.0f, 1.0f, 1.0f); break; } } else if (pos.y < 0){ switch (count){ case 0: Col = float4(0.0f, 1.0f, 0.0f, 0.0f); break; case 1: Col = float4(0.0f, 0.0f, 1.0f, 0.0f); break; case 2: Col = float4(1.0f, 0.0f, 0.0f, 0.0f); break; default: Col = float4(1.0f, 1.0f, 1.0f, 1.0f); break; } } else{ Col = float4(1.0f, 1.0f, 1.0f, 1.0f); } //ワールド変換 pos = mul(pos, World[count]); //ビュー変換 pos = mul(pos, View); //射影変換 pos = mul(pos, Projection); //ピクセルシェーダに渡す変数に設定 element.pos = pos; //ライティング用に法線をワールド変換して設定 element.norm = mul(input[i].norm, (float3x3)World[count]); //頂点色を設定 element.color = Col; //頂点を追加 output.Append(element); } //一つの三角形をストリームに送る output.RestartStrip(); } }
[maxvertexcount(9)]
void main(
triangle GeometryShaderInput input[3],
inout TriangleStream< PixelShaderInput > output
)
//頂点を追加
output.Append(element);
//一つの三角形をストリームに送る
output.RestartStrip();
//カスタムシャドウマップ用コンスタントバッファ構造体
struct CustomShadowmapConstantBuffer
{
Mat4x4 mWorld[3];
Mat4x4 mView;
Mat4x4 mProj;
CustomShadowmapConstantBuffer() {
memset(this, 0, sizeof(CustomShadowmapConstantBuffer));
};
};
//シェーダ宣言(マクロ使用)
DECLARE_DX11_CONSTANT_BUFFER(CBCustomShadowmap, CustomShadowmapConstantBuffer)
DECLARE_DX11_VERTEX_SHADER(VSCustomShadowmap, VertexPositionNormalColor)
DECLARE_DX11_GEOMETRY_SHADER(GSCustomShadowmap)
//カスタム描画コンスタントバッファ構造体
struct CustomDrawConstantBuffer
{
Mat4x4 World[3];
Mat4x4 View;
Mat4x4 Projection;
Vec4 LightDir;
Vec4 Param; //汎用パラメータ
CustomDrawConstantBuffer() {
memset(this, 0, sizeof(CustomDrawConstantBuffer));
};
};
//シェーダ宣言(マクロ使用)
DECLARE_DX11_CONSTANT_BUFFER(CBCustomDraw, CustomDrawConstantBuffer)
DECLARE_DX11_VERTEX_SHADER(VSCustomDraw, VertexPositionNormalColor)
DECLARE_DX11_GEOMETRY_SHADER(GSCustomDraw)
DECLARE_DX11_PIXEL_SHADER(PSCustomDraw)
//シェーダ定義(マクロ使用)
IMPLEMENT_DX11_CONSTANT_BUFFER(CBCustomShadowmap)
IMPLEMENT_DX11_VERTEX_SHADER(VSCustomShadowmap,
App::GetApp()->GetShadersPath() + L"VSCustomShadowmap.cso")
IMPLEMENT_DX11_GEOMETRY_SHADER(GSCustomShadowmap,
App::GetApp()->GetShadersPath() + L"GSCustomShadowmap.cso")
IMPLEMENT_DX11_CONSTANT_BUFFER(CBCustomDraw)
IMPLEMENT_DX11_VERTEX_SHADER(VSCustomDraw,
App::GetApp()->GetShadersPath() + L"VSSimpleBase.cso")
IMPLEMENT_DX11_GEOMETRY_SHADER(GSCustomDraw,
App::GetApp()->GetShadersPath() + L"GSSimpleBase.cso")
IMPLEMENT_DX11_PIXEL_SHADER(PSCustomDraw,
App::App::GetApp()->GetShadersPath() + L"PSSimpleBase.cso")
//--------------------------------------------------------------------------------------
// ジオメトリシェーダを使った独自の描画コンポーネント
//--------------------------------------------------------------------------------------
class CustomPNCStaticDraw : public StaticBaseDraw {
public:
//--------------------------------------------------------------------------------------
/*!
@brief コンストラクタ
@param[in] GameObjectPtr ゲームオブジェクト
*/
//--------------------------------------------------------------------------------------
explicit CustomPNCStaticDraw(const shared_ptr<GameObject>& GameObjectPtr);
//--------------------------------------------------------------------------------------
/*!
@brief デストラクタ
*/
//--------------------------------------------------------------------------------------
virtual ~CustomPNCStaticDraw() {}
//--------------------------------------------------------------------------------------
/*!
@brief OnCreate処理
@return なし
*/
//--------------------------------------------------------------------------------------
virtual void OnCreate()override {}
//--------------------------------------------------------------------------------------
/*!
@brief OnUpdate処理(空関数)
@return なし
*/
//--------------------------------------------------------------------------------------
virtual void OnUpdate()override {}
//--------------------------------------------------------------------------------------
/*!
@brief OnDraw処理
@return なし
*/
//--------------------------------------------------------------------------------------
virtual void OnDraw()override;
};
void CustomPNCStaticDraw::OnDraw() {
auto PtrGameObject = GetGameObject();
//メッシュがなければ描画しない
auto MeshRes = GetMeshResource();
if (!MeshRes) {
throw BaseException(
L"メッシュが作成されていません",
L"if (!MeshRes)",
L"CustomPNCStaticDraw::OnDraw()"
);
}
auto Dev = App::GetApp()->GetDeviceResources();
auto pID3D11DeviceContext = Dev->GetD3DDeviceContext();
auto RenderState = Dev->GetRenderState();
auto PtrT = PtrGameObject->GetComponent<Transform>();
//カメラを得る
auto PtrCamera = PtrGameObject->OnGetDrawCamera();
//カメラの取得
Mat4x4 View, Proj, WorldViewProj;
View = PtrCamera->GetViewMatrix();
Proj = PtrCamera->GetProjMatrix();
//コンスタントバッファの設定
CustomDrawConstantBuffer cb1;
//行列の設定(転置する)
cb1.World[0] = transpose(PtrT->GetWorldMatrix());
Mat4x4 Left;
Left.translation(Vec3(-5.0f, 0, 0));
Left = PtrT->GetWorldMatrix() * Left;
cb1.World[1] = transpose(Left);
Mat4x4 Right;
Right.translation(Vec3(5.0f, 0, 0));
Right = PtrT->GetWorldMatrix() * Right;
cb1.World[2] = transpose(Right);
cb1.View = transpose(View);
cb1.Projection = transpose(Proj);
//ライトの設定
auto PtrLight = PtrGameObject->OnGetDrawLight();
cb1.LightDir = PtrLight.m_Directional;
cb1.LightDir.w = 1.0f;
//コンスタントバッファの更新
pID3D11DeviceContext->UpdateSubresource(CBCustomDraw::GetPtr()->GetBuffer(), 0, nullptr, &cb1, 0, 0);
//ストライドとオフセット
UINT stride = MeshRes->GetNumStride();
UINT offset = 0;
//頂点バッファの設定
pID3D11DeviceContext->IASetVertexBuffers(0, 1, MeshRes->GetVertexBuffer().GetAddressOf(), &stride, &offset);
//インデックスバッファのセット
pID3D11DeviceContext->IASetIndexBuffer(MeshRes->GetIndexBuffer().Get(), DXGI_FORMAT_R16_UINT, 0);
//描画方法(3角形)
pID3D11DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
//ステータスのポインタ
//テクスチャを取得
ID3D11ShaderResourceView* pNull[1] = { 0 };
ID3D11SamplerState* pNullSR[1] = { 0 };
//半透明処理
pID3D11DeviceContext->OMSetBlendState(RenderState->GetAlphaBlendEx(), nullptr, 0xffffffff);
//デプスステンシルは使用する
pID3D11DeviceContext->OMSetDepthStencilState(RenderState->GetDepthDefault(), 0);
//シェーダの設定
pID3D11DeviceContext->VSSetShader(VSCustomDraw::GetPtr()->GetShader(), nullptr, 0);
pID3D11DeviceContext->GSSetShader(GSCustomDraw::GetPtr()->GetShader(), nullptr, 0);
pID3D11DeviceContext->PSSetShader(PSCustomDraw::GetPtr()->GetShader(), nullptr, 0);
//インプットレイアウトの設定
pID3D11DeviceContext->IASetInputLayout(VSCustomDraw::GetPtr()->GetInputLayout());
//コンスタントバッファの設定
ID3D11Buffer* pConstantBuffer = CBCustomDraw::GetPtr()->GetBuffer();
pID3D11DeviceContext->VSSetConstantBuffers(0, 1, &pConstantBuffer);
pID3D11DeviceContext->GSSetConstantBuffers(0, 1, &pConstantBuffer);
pID3D11DeviceContext->PSSetConstantBuffers(0, 1, &pConstantBuffer);
//レンダリングステート
pID3D11DeviceContext->RSSetState(RenderState->GetCullFront());
//描画
pID3D11DeviceContext->DrawIndexed(MeshRes->GetNumIndicis(), 0, 0);
//レンダリングステート
pID3D11DeviceContext->RSSetState(RenderState->GetCullBack());
//描画
pID3D11DeviceContext->DrawIndexed(MeshRes->GetNumIndicis(), 0, 0);
//後始末
Dev->InitializeStates();
}
void CustomDrawOctahedron::OnCreate() {
auto Ptr = AddComponent<Transform>();
Ptr->SetScale(m_StartScale);
Ptr->SetPosition(m_StartPos);
Ptr->SetRotation(m_StartRotation);
vector<VertexPositionNormalTexture> vertices;
vector<uint16_t> indices;
//正8面体
MeshUtill::CreateOctahedron(1.0f, vertices, indices);
for (size_t i = 0; i < vertices.size(); i++) {
VertexPositionNormalColor new_v;
new_v.position = vertices[i].position;
new_v.normal = vertices[i].normal;
new_v.color = Col4(1.0f, 1.0f, 1.0f, 1.0f);
m_BackupVertices.push_back(new_v);
}
auto PtrDraw = AddComponent<CustomPNCStaticDraw>();
PtrDraw->CreateOriginalMesh(m_BackupVertices, indices);
PtrDraw->SetOriginalMeshUse(true);
//影をつける(シャドウマップを描画する)
auto ShadowPtr = AddComponent<CustomShadowmap>();
ShadowPtr->SetMeshResource(PtrDraw->GetMeshResource());
//透明処理(描画順制御のため)
SetAlphaActive(true);
}
図0407b
このシェーダはマイクロソフト社のジオメトリシェーダのサンプルを引用したものです。各三角形を分割して4つの三角形を作成しています。