draw instanced cubes

This commit is contained in:
Zack Buhman 2026-01-13 18:00:11 -06:00
parent 9449f3f4d7
commit efa08063c0
3 changed files with 163 additions and 48 deletions

View File

@ -11,6 +11,7 @@ struct VS_INPUT_INSTANCED
float3 Normal : NORMAL; float3 Normal : NORMAL;
float2 Tex : TEXCOORD0; float2 Tex : TEXCOORD0;
row_major float4x4 mTransform : mTransform; row_major float4x4 mTransform : mTransform;
uint InstanceID : SV_InstanceID;
}; };
struct PS_INPUT struct PS_INPUT
@ -54,17 +55,6 @@ PS_INPUT VS(VS_INPUT input)
return output; return output;
} }
PS_INPUT VSInstanced(VS_INPUT_INSTANCED input)
{
VS_INPUT input_vs = (VS_INPUT)0;
input_vs.Pos = mul(input.Pos, input.mTransform);
input_vs.Normal = input.Normal;
input_vs.Tex = input.Tex;
return VS(input_vs);
}
PS_OUTPUT PS(PS_INPUT input) PS_OUTPUT PS(PS_INPUT input)
{ {
PS_OUTPUT output; PS_OUTPUT output;
@ -73,6 +63,23 @@ PS_OUTPUT PS(PS_INPUT input)
return output; return output;
} }
PS_INPUT VSInstanced(VS_INPUT_INSTANCED input)
{
VS_INPUT input_vs = (VS_INPUT)0;
input_vs.Pos = mul(float4(input.Pos.xyz, 1), input.mTransform);
//input_vs.Pos = float4(input.Pos.xyz, 1) + float4(0, input.InstanceID * 3, 0, 0);
input_vs.Normal = input.Normal;
input_vs.Tex = input.Tex;
return VS(input_vs);
}
float4 PSInstanced(PS_INPUT input) : SV_TARGET0
{
return float4(1, 1, 1, 1);
}
BlendState DisableBlending BlendState DisableBlending
{ {
BlendEnable[0] = FALSE; BlendEnable[0] = FALSE;
@ -102,7 +109,7 @@ technique10 StaticInstanced
{ {
SetVertexShader(CompileShader(vs_4_0, VSInstanced())); SetVertexShader(CompileShader(vs_4_0, VSInstanced()));
SetGeometryShader(NULL); SetGeometryShader(NULL);
SetPixelShader(CompileShader(ps_4_0, PS())); SetPixelShader(CompileShader(ps_4_0, PSInstanced()));
SetBlendState(DisableBlending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff); SetBlendState(DisableBlending, float4(0.0, 0.0, 0.0, 0.0), 0xffffffff);
SetDepthStencilState(EnableDepth, 0); SetDepthStencilState(EnableDepth, 0);
} }

View File

@ -95,6 +95,7 @@ ID3D10Effect * g_pEffectStatic = NULL;
ID3D10EffectTechnique * g_pTechniqueStatic = NULL; ID3D10EffectTechnique * g_pTechniqueStatic = NULL;
ID3D10EffectTechnique * g_pTechniqueStaticInstanced = NULL; ID3D10EffectTechnique * g_pTechniqueStaticInstanced = NULL;
ID3D10InputLayout * g_pVertexLayoutStatic = NULL; ID3D10InputLayout * g_pVertexLayoutStatic = NULL;
ID3D10InputLayout * g_pVertexLayoutStaticInstanced = NULL;
ID3D10EffectMatrixVariable * g_pWorldVariableStatic = NULL; ID3D10EffectMatrixVariable * g_pWorldVariableStatic = NULL;
ID3D10EffectMatrixVariable * g_pViewVariableStatic = NULL; ID3D10EffectMatrixVariable * g_pViewVariableStatic = NULL;
@ -102,6 +103,10 @@ ID3D10EffectMatrixVariable * g_pProjectionVariableStatic = NULL;
ID3D10EffectMatrixVariable * g_pWorldNormalVariableStatic = NULL; ID3D10EffectMatrixVariable * g_pWorldNormalVariableStatic = NULL;
ID3D10EffectVectorVariable * g_pOutputColorVariableStatic = NULL; ID3D10EffectVectorVariable * g_pOutputColorVariableStatic = NULL;
// instance data
ID3D10Buffer * g_pVolumeMeshInstanceData = NULL;
const int g_iNumVolumeMeshInstances = 8;
// cube // cube
const DWORD g_dwVertexBufferCountCube = 3; const DWORD g_dwVertexBufferCountCube = 3;
ID3D10Buffer * g_pVertexBufferCube[g_dwVertexBufferCountCube]; ID3D10Buffer * g_pVertexBufferCube[g_dwVertexBufferCountCube];
@ -746,27 +751,57 @@ HRESULT InitStaticEffect()
g_pTechniqueStatic = g_pEffectStatic->GetTechniqueByName("Static"); g_pTechniqueStatic = g_pEffectStatic->GetTechniqueByName("Static");
g_pTechniqueStaticInstanced = g_pEffectStatic->GetTechniqueByName("StaticInstanced"); g_pTechniqueStaticInstanced = g_pEffectStatic->GetTechniqueByName("StaticInstanced");
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// layout // layout
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
D3D10_INPUT_ELEMENT_DESC layout[] = { // static
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0}, {
{"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0}, D3D10_INPUT_ELEMENT_DESC layout[] = {
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 2, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0}, {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
}; {"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
UINT numElements = (sizeof (layout)) / (sizeof (layout[0])); {"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 2, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
};
UINT numElements = (sizeof (layout)) / (sizeof (layout[0]));
D3D10_PASS_DESC passDesc; D3D10_PASS_DESC passDesc;
g_pTechniqueStatic->GetPassByIndex(0)->GetDesc(&passDesc); g_pTechniqueStatic->GetPassByIndex(0)->GetDesc(&passDesc);
hr = g_pd3dDevice->CreateInputLayout(layout, numElements, hr = g_pd3dDevice->CreateInputLayout(layout, numElements,
passDesc.pIAInputSignature, passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize, passDesc.IAInputSignatureSize,
&g_pVertexLayoutStatic); &g_pVertexLayoutStatic);
if (FAILED(hr)) { if (FAILED(hr)) {
print("CreateInputLayout\n"); print("CreateInputLayout\n");
return hr; return hr;
}
}
// static instanced
{
D3D10_INPUT_ELEMENT_DESC layout[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
{"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 2, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
{"mTransform", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 3, 0 , D3D10_INPUT_PER_INSTANCE_DATA, 1},
{"mTransform", 1, DXGI_FORMAT_R32G32B32A32_FLOAT, 3, 16, D3D10_INPUT_PER_INSTANCE_DATA, 1},
{"mTransform", 2, DXGI_FORMAT_R32G32B32A32_FLOAT, 3, 32, D3D10_INPUT_PER_INSTANCE_DATA, 1},
{"mTransform", 3, DXGI_FORMAT_R32G32B32A32_FLOAT, 3, 48, D3D10_INPUT_PER_INSTANCE_DATA, 1},
};
UINT numElements = (sizeof (layout)) / (sizeof (layout[0]));
D3D10_PASS_DESC passDesc;
g_pTechniqueStaticInstanced->GetPassByIndex(0)->GetDesc(&passDesc);
hr = g_pd3dDevice->CreateInputLayout(layout, numElements,
passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize,
&g_pVertexLayoutStaticInstanced);
if (FAILED(hr)) {
print("CreateInputLayout\n");
return hr;
}
} }
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -782,6 +817,61 @@ HRESULT InitStaticEffect()
return S_OK; return S_OK;
} }
HRESULT InitInstancedVertexBuffer()
{
HRESULT hr;
//////////////////////////////////////////////////////////////////////
// vertex buffers
//////////////////////////////////////////////////////////////////////
D3D10_BUFFER_DESC bd;
// mTransform
bd.Usage = D3D10_USAGE_DYNAMIC;
bd.ByteWidth = (sizeof (XMMATRIX)) * g_iNumVolumeMeshInstances;
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
bd.MiscFlags = 0;
hr = g_pd3dDevice->CreateBuffer(&bd, NULL, &g_pVolumeMeshInstanceData);
if (FAILED(hr)) {
print("CreateBuffer\n");
return hr;
}
//////////////////////////////////////////////////////////////////////
// vertex buffer data
//////////////////////////////////////////////////////////////////////
FontVertex * pData;
hr = g_pVolumeMeshInstanceData->Map(D3D10_MAP_WRITE_DISCARD,
0,
(void **)&pData);
if (FAILED(hr)) {
print("g_pVolumeMeshInstanceData->Map");
}
float offset = 4.0f;
XMMATRIX transforms[8] = {
XMMatrixTranslation( offset, offset, offset),
XMMatrixTranslation( offset, -offset, offset),
XMMatrixTranslation(-offset, -offset, offset),
XMMatrixTranslation(-offset, offset, offset),
XMMatrixTranslation( offset, offset, -offset),
XMMatrixTranslation( offset, -offset, -offset),
XMMatrixTranslation(-offset, -offset, -offset),
XMMatrixTranslation(-offset, offset, -offset),
};
memcpy(pData, transforms, (sizeof (XMMATRIX)) * g_iNumVolumeMeshInstances);
g_pVolumeMeshInstanceData->Unmap();
return S_OK;
}
HRESULT LoadMeshStatic(const Mesh * mesh) HRESULT LoadMeshStatic(const Mesh * mesh)
{ {
HRESULT hr; HRESULT hr;
@ -1026,6 +1116,12 @@ HRESULT InitDirect3DDevice()
return hr; return hr;
} }
hr = InitInstancedVertexBuffer();
if (FAILED(hr)) {
print("InitInstancedVertexBuffer\n");
return hr;
}
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// transform matrices // transform matrices
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
@ -1033,8 +1129,8 @@ HRESULT InitDirect3DDevice()
g_World1 = XMMatrixIdentity(); g_World1 = XMMatrixIdentity();
g_World2 = XMMatrixIdentity(); g_World2 = XMMatrixIdentity();
XMVECTOR Eye = XMVectorSet(0.0f, 1.0f, -2.0f, 0.0f); XMVECTOR Eye = XMVectorSet(0.0f, 0.0f, -2.0f, 0.0f);
XMVECTOR At = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); XMVECTOR At = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
g_View = XMMatrixLookAtLH(Eye, At, Up); g_View = XMMatrixLookAtLH(Eye, At, Up);
@ -1329,12 +1425,13 @@ static inline int sprint(LPCSTR fmt, ...)
void RenderFont() void RenderFont()
{ {
HRESULT hr;
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
// dynamic vertex buffer // dynamic vertex buffer
////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////
FontVertex * pData; FontVertex * pData;
HRESULT hr;
hr = g_pVertexBuffersFont[0]->Map(D3D10_MAP_WRITE_DISCARD, hr = g_pVertexBuffersFont[0]->Map(D3D10_MAP_WRITE_DISCARD,
0, 0,
(void **)&pData); (void **)&pData);
@ -1538,38 +1635,49 @@ void RenderVolume(float t)
void RenderVolumeMesh() void RenderVolumeMesh()
{ {
const Mesh * mesh = cube::node_0.mesh; const Mesh * mesh = cube::node_0.mesh;
int indices_length = mesh->indices_size / (sizeof (DWORD)); int index_count_per_instance = mesh->indices_size / (sizeof (DWORD));
g_pViewVariableStatic->SetMatrix((float *)&g_View); g_pViewVariableStatic->SetMatrix((float *)&g_View);
g_pProjectionVariableStatic->SetMatrix((float *)&g_Projection); g_pProjectionVariableStatic->SetMatrix((float *)&g_Projection);
ID3D10Buffer * pVB[4] = {
g_pVertexBufferCube[0],
g_pVertexBufferCube[1],
g_pVertexBufferCube[2],
g_pVolumeMeshInstanceData,
};
UINT stride[] = { UINT stride[] = {
(sizeof (mesh->position[0])), (sizeof (mesh->position[0])),
(sizeof (mesh->normal[0])), (sizeof (mesh->normal[0])),
(sizeof (mesh->texcoord_0[0])), (sizeof (mesh->texcoord_0[0])),
(sizeof (XMMATRIX)),
}; };
UINT offset[] = { 0, 0, 0 }; UINT offset[] = { 0, 0, 0, 0 };
g_pd3dDevice->IASetInputLayout(g_pVertexLayoutStatic); g_pd3dDevice->IASetInputLayout(g_pVertexLayoutStaticInstanced);
g_pd3dDevice->IASetVertexBuffers(0, g_dwVertexBufferCountCube, g_pVertexBufferCube, stride, offset); g_pd3dDevice->IASetVertexBuffers(0, 4, pVB, stride, offset);
g_pd3dDevice->IASetIndexBuffer(g_pIndexBufferCube, DXGI_FORMAT_R32_UINT, 0); g_pd3dDevice->IASetIndexBuffer(g_pIndexBufferCube, DXGI_FORMAT_R32_UINT, 0);
g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
D3D10_TECHNIQUE_DESC techDesc; D3D10_TECHNIQUE_DESC techDesc;
g_pTechniqueStatic->GetDesc(&techDesc); g_pTechniqueStaticInstanced->GetDesc(&techDesc);
XMMATRIX mWorldScale = XMMatrixScaling(0.2f, 0.2f, 0.2f); XMMATRIX mWorldScale = XMMatrixScaling(0.2f, 0.2f, 0.2f);
XMMATRIX mWorldTranslate = XMMatrixTranslation(0.5f, 0.5f, 0.5f); XMMATRIX mWorldTranslate = XMMatrixTranslation(0.0f, 0.0f, 1.5f);
XMMATRIX mWorld = mWorldScale * mWorldTranslate; XMMATRIX mWorld = mWorldScale * mWorldTranslate;
g_pWorldVariableStatic->SetMatrix((float *)&mWorld); g_pWorldVariableStatic->SetMatrix((float *)&mWorld);
XMMATRIX mWorldNormal = XMMatrixIdentity(); XMMATRIX mWorldNormal = XMMatrixIdentity();
g_pWorldNormalVariableStatic->SetMatrix((float *)&mWorldNormal); g_pWorldNormalVariableStatic->SetMatrix((float *)&mWorldNormal);
XMVECTOR vColor = XMVectorSet(0.0f, 0.9f, 0.0f, 1.0f); XMVECTOR vColor = XMVectorSet(0.0f, 0.4f, 0.3f, 1.0f);
g_pOutputColorVariableStatic->SetFloatVector((float *)&vColor); g_pOutputColorVariableStatic->SetFloatVector((float *)&vColor);
int instance_count = g_iNumVolumeMeshInstances;
for (UINT p = 0; p < techDesc.Passes; p++) { for (UINT p = 0; p < techDesc.Passes; p++) {
g_pTechniqueStatic->GetPassByIndex(p)->Apply(0); g_pTechniqueStaticInstanced->GetPassByIndex(p)->Apply(0);
g_pd3dDevice->DrawIndexed(indices_length, 0, 0); g_pd3dDevice->DrawIndexedInstanced(index_count_per_instance,
instance_count,
0, 0, 0);
} }
} }
@ -1606,7 +1714,7 @@ void Render()
//RenderBloom(); //RenderBloom();
//print("%f\n", t); //print("%f\n", t);
//RenderVolume(t); //RenderVolume(t);
//RenderVolumeMesh(); RenderVolumeMesh();
// present // present
g_pSwapChain->Present(0, 0); g_pSwapChain->Present(0, 0);

View File

@ -19,10 +19,10 @@ void print(LPCSTR fmt, ...)
args); args);
va_end(args); va_end(args);
#ifdef _DEBUG #ifdef _DEBUG
//OutputDebugStringA(buf); OutputDebugStringA(buf);
size_t length = end - &buf[0]; //size_t length = end - &buf[0];
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsoleA(hOutput, buf, (DWORD)length, NULL, NULL); //WriteConsoleA(hOutput, buf, (DWORD)length, NULL, NULL);
#endif #endif
} }
@ -42,9 +42,9 @@ void printW(LPCWSTR fmt, ...)
args); args);
va_end(args); va_end(args);
#ifdef _DEBUG #ifdef _DEBUG
//OutputDebugStringW(buf); OutputDebugStringW(buf);
size_t length = end - &buf[0]; //size_t length = end - &buf[0];
HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE); //HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
WriteConsoleW(hOutput, buf, (DWORD)length, NULL, NULL); //WriteConsoleW(hOutput, buf, (DWORD)length, NULL, NULL);
#endif #endif
} }