collada_scene: render skins using skin vertex layouts

This commit is contained in:
Zack Buhman 2026-01-30 11:29:25 -06:00
parent a672190459
commit b72f978f6a
2 changed files with 125 additions and 35 deletions

View File

@ -26,14 +26,12 @@ namespace collada_scene {
};
struct scene_state {
const UINT m_numBuffers = 1; // FIXME
const UINT m_strides[1] = {3 * 3 * 4}; // FIXME
const UINT m_offsets[1] = {0}; // FIXME
ID3D10Buffer * m_pVertexBuffers[1] = {}; // FIXME
ID3D10Buffer * m_pVertexBuffers[2] = { NULL, NULL };
ID3D10Buffer * m_pIndexBuffer = NULL;
ID3D10InputLayout ** m_pVertexLayouts = NULL;
ID3D10InputLayout ** m_pSkinnedVertexLayouts = NULL;
UINT * m_iVertexLayoutStrides = NULL;
node_instance * m_nodeInstances = NULL;
@ -70,16 +68,22 @@ namespace collada_scene {
int const instance_materials_count);
void render_instance_geometries(collada::instance_geometry const * const instance_geometries,
int const instance_geometries_count);
void render_skin(collada::skin const& skin,
collada::instance_material const * const instance_materials,
int const instance_materials_count);
void render_instance_controllers(collada::instance_controller const * const instance_controllers,
int const instance_controllers_count);
void set_material(collada::effect const& effect);
void set_instance_material(collada::instance_material const& instance_material);
void set_color_or_texture(collada::color_or_texture const& color_or_texture,
ID3D10EffectVectorVariable * pVectorVariable,
ID3D10EffectShaderResourceVariable * pShaderResourceVariable);
};
HRESULT LoadEffect();
HRESULT LoadLayout(collada::inputs const& inputs, ID3D10InputLayout ** ppVertexLayout);
HRESULT LoadLayout(collada::inputs const& inputs,
ID3D10InputLayout ** ppVertexLayout,
ID3D10InputLayout ** ppSkinnedVertexLayout,
UINT * iVertexLayoutStride);
HRESULT LoadVertexBuffer(LPCWSTR name, ID3D10Buffer ** ppVertexBuffer);
HRESULT LoadIndexBuffer(LPCWSTR name, ID3D10Buffer ** ppIndexBuffer);
}

View File

@ -49,18 +49,20 @@ namespace collada_scene {
case input_format::FLOAT2: return DXGI_FORMAT_R32G32_FLOAT;
case input_format::FLOAT3: return DXGI_FORMAT_R32G32B32_FLOAT;
case input_format::FLOAT4: return DXGI_FORMAT_R32G32B32A32_FLOAT;
case input_format::INT4: return DXGI_FORMAT_R32G32B32A32_SINT;
default:
assert(false);
}
}
static inline int format_size(input_format format)
static inline UINT format_size(input_format format)
{
switch (format) {
case input_format::FLOAT1: return 1 * 4;
case input_format::FLOAT2: return 2 * 4;
case input_format::FLOAT3: return 3 * 4;
case input_format::FLOAT4: return 4 * 4;
case input_format::INT4: return 4 * 4;
default:
assert(false);
}
@ -71,9 +73,14 @@ namespace collada_scene {
HRESULT hr;
m_pVertexLayouts = New<ID3D10InputLayout *>(m_descriptor->inputs_list_count);
m_pSkinnedVertexLayouts = New<ID3D10InputLayout *>(m_descriptor->inputs_list_count);
m_iVertexLayoutStrides = New<UINT>(m_descriptor->inputs_list_count);
for (int i = 0; i < m_descriptor->inputs_list_count; i++) {
hr = LoadLayout(m_descriptor->inputs_list[i], &m_pVertexLayouts[i]);
hr = LoadLayout(m_descriptor->inputs_list[i],
&m_pVertexLayouts[i],
&m_pSkinnedVertexLayouts[i],
&m_iVertexLayoutStrides[i]);
if (FAILED(hr))
return hr;
}
@ -203,6 +210,10 @@ namespace collada_scene {
if (FAILED(hr))
return E_FAIL;
hr = LoadVertexBuffer(L"RES_MODELS_CURVE_INTERPOLATION_VJW", &m_pVertexBuffers[1]);
if (FAILED(hr))
return E_FAIL;
hr = LoadIndexBuffer(L"RES_MODELS_CURVE_INTERPOLATION_IDX", &m_pIndexBuffer);
if (FAILED(hr))
return E_FAIL;
@ -217,14 +228,34 @@ namespace collada_scene {
return S_OK;
}
HRESULT LoadLayout(inputs const& inputs, ID3D10InputLayout ** ppVertexLayout)
input_element const input_elements_blendindices_0_4_blendweight_0_4[] = {
{
.semantic = "BLENDINDICES",
.semantic_index = 0,
.format = input_format::INT4,
},
{
.semantic = "BLENDWEIGHT",
.semantic_index = 0,
.format = input_format::FLOAT4,
},
};
inputs const skin_inputs = {
.elements = input_elements_blendindices_0_4_blendweight_0_4,
.elements_count = 2,
};
HRESULT LoadLayout(inputs const& inputs,
ID3D10InputLayout ** ppVertexLayout,
ID3D10InputLayout ** ppSkinnedVertexLayout,
UINT * iVertexLayoutStride)
{
HRESULT hr;
D3D10_INPUT_ELEMENT_DESC layout[inputs.elements_count];
D3D10_INPUT_ELEMENT_DESC layout[inputs.elements_count + 2];
assert(inputs.elements_count == 3);
int byte_offset = 0;
UINT byte_offset = 0;
for (int i = 0; i < inputs.elements_count; i++) {
layout[i].SemanticName = inputs.elements[i].semantic;
layout[i].SemanticIndex = inputs.elements[i].semantic_index;
@ -236,6 +267,7 @@ namespace collada_scene {
byte_offset += format_size(inputs.elements[i].format);
}
*iVertexLayoutStride = byte_offset;
D3D10_PASS_DESC passDesc;
g_pTechniqueBlinn->GetPassByIndex(0)->GetDesc(&passDesc);
@ -249,6 +281,33 @@ namespace collada_scene {
return hr;
}
//////////////////////////////////////////////////////////////////////
// skinned layout
//////////////////////////////////////////////////////////////////////
UINT skin_byte_offset = 0;
for (int i = 0; i < skin_inputs.elements_count; i++) {
int ix = inputs.elements_count + i;
layout[ix].SemanticName = skin_inputs.elements[i].semantic;
layout[ix].SemanticIndex = skin_inputs.elements[i].semantic_index;
layout[ix].Format = dxgi_format(skin_inputs.elements[i].format);
layout[ix].InputSlot = 0;
layout[ix].AlignedByteOffset = skin_byte_offset;
layout[ix].InputSlotClass = D3D10_INPUT_PER_VERTEX_DATA;
layout[ix].InstanceDataStepRate = 0;
skin_byte_offset += format_size(skin_inputs.elements[i].format);
}
hr = g_pd3dDevice->CreateInputLayout(layout, inputs.elements_count + skin_inputs.elements_count,
passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize,
ppSkinnedVertexLayout);
if (FAILED(hr)) {
print("CreateInputLayout\n");
return hr;
}
return S_OK;
}
@ -392,8 +451,9 @@ namespace collada_scene {
}
}
void scene_state::set_material(effect const& effect)
void scene_state::set_instance_material(instance_material const& instance_material)
{
effect const& effect = *instance_material.material->effect;
switch (effect.type) {
case effect_type::BLINN:
set_color_or_texture(effect.blinn.emission, g_pEmissionVariable, g_pTexEmissionVariable);
@ -420,6 +480,14 @@ namespace collada_scene {
default:
break;
}
int texture_channels[4] = {
instance_material.emission.input_set,
instance_material.ambient.input_set,
instance_material.diffuse.input_set,
instance_material.specular.input_set,
};
g_pTextureChannelVariable->SetIntVector(texture_channels);
}
void scene_state::render_geometry(geometry const& geometry,
@ -427,10 +495,6 @@ namespace collada_scene {
int const instance_materials_count)
{
mesh const& mesh = geometry.mesh;
UINT strides[1] = { 3 * 3 * 4 };
UINT offsets[1] = { (UINT)mesh.vertex_buffer_offset };
g_pd3dDevice->IASetVertexBuffers(0, m_numBuffers, m_pVertexBuffers, strides, offsets);
g_pd3dDevice->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, mesh.index_buffer_offset);
D3D10_TECHNIQUE_DESC techDesc;
@ -439,17 +503,43 @@ namespace collada_scene {
for (int j = 0; j < instance_materials_count; j++) {
instance_material const& instance_material = instance_materials[j];
triangles const& triangles = mesh.triangles[instance_material.element_index];
set_material(*instance_material.material->effect);
int texture_channels[4] = {
instance_material.emission.input_set,
instance_material.ambient.input_set,
instance_material.diffuse.input_set,
instance_material.specular.input_set,
};
g_pTextureChannelVariable->SetIntVector(texture_channels);
set_instance_material(instance_material);
UINT numBuffers = 1;
UINT offsets[1] = { (UINT)mesh.vertex_buffer_offset };
UINT strides[1] = { m_iVertexLayoutStrides[triangles.inputs_index] };
g_pd3dDevice->IASetVertexBuffers(0, numBuffers, m_pVertexBuffers, strides, offsets);
g_pd3dDevice->IASetInputLayout(m_pVertexLayouts[triangles.inputs_index]);
g_pTechniqueBlinn->GetPassByIndex(0)->Apply(0);
g_pd3dDevice->DrawIndexed(triangles.count * 3, triangles.index_offset, 0);
}
}
void scene_state::render_skin(skin const& skin,
instance_material const * const instance_materials,
int const instance_materials_count)
{
mesh const& mesh = skin.geometry->mesh;
g_pd3dDevice->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, mesh.index_buffer_offset);
D3D10_TECHNIQUE_DESC techDesc;
g_pTechniqueBlinn->GetDesc(&techDesc);
for (int j = 0; j < instance_materials_count; j++) {
instance_material const& instance_material = instance_materials[j];
triangles const& triangles = mesh.triangles[instance_material.element_index];
set_instance_material(instance_material);
UINT numBuffers = 2;
UINT offsets[2] = { (UINT)mesh.vertex_buffer_offset, (UINT)skin.vertex_buffer_offset };
UINT strides[2] = { m_iVertexLayoutStrides[triangles.inputs_index], 2 * 4 * 4 };
g_pd3dDevice->IASetVertexBuffers(0, numBuffers, m_pVertexBuffers, strides, offsets);
g_pd3dDevice->IASetInputLayout(m_pSkinnedVertexLayouts[triangles.inputs_index]);
g_pTechniqueBlinn->GetPassByIndex(0)->Apply(0);
g_pd3dDevice->IASetInputLayout(m_pVertexLayouts[triangles.inputs_index]);
g_pd3dDevice->DrawIndexed(triangles.count * 3, triangles.index_offset, 0);
}
}
@ -459,9 +549,7 @@ namespace collada_scene {
{
for (int i = 0; i < instance_geometries_count; i++) {
instance_geometry const &instance_geometry = instance_geometries[i];
geometry const& geometry = *instance_geometry.geometry;
render_geometry(geometry,
render_geometry(*instance_geometry.geometry,
instance_geometry.instance_materials,
instance_geometry.instance_materials_count);
}
@ -472,11 +560,9 @@ namespace collada_scene {
{
for (int i = 0; i < instance_controllers_count; i++) {
instance_controller const &instance_controller = instance_controllers[i];
geometry const& geometry = *instance_controller.controller->skin.geometry;
render_geometry(geometry,
instance_controller.instance_materials,
instance_controller.instance_materials_count);
render_skin(instance_controller.controller->skin,
instance_controller.instance_materials,
instance_controller.instance_materials_count);
}
}