図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つの三角形を作成しています。