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 { struct scene_state {
const UINT m_numBuffers = 1; // FIXME ID3D10Buffer * m_pVertexBuffers[2] = { NULL, NULL };
const UINT m_strides[1] = {3 * 3 * 4}; // FIXME
const UINT m_offsets[1] = {0}; // FIXME
ID3D10Buffer * m_pVertexBuffers[1] = {}; // FIXME
ID3D10Buffer * m_pIndexBuffer = NULL; ID3D10Buffer * m_pIndexBuffer = NULL;
ID3D10InputLayout ** m_pVertexLayouts = NULL; ID3D10InputLayout ** m_pVertexLayouts = NULL;
ID3D10InputLayout ** m_pSkinnedVertexLayouts = NULL;
UINT * m_iVertexLayoutStrides = NULL;
node_instance * m_nodeInstances = NULL; node_instance * m_nodeInstances = NULL;
@ -70,16 +68,22 @@ namespace collada_scene {
int const instance_materials_count); int const instance_materials_count);
void render_instance_geometries(collada::instance_geometry const * const instance_geometries, void render_instance_geometries(collada::instance_geometry const * const instance_geometries,
int const instance_geometries_count); 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, void render_instance_controllers(collada::instance_controller const * const instance_controllers,
int const instance_controllers_count); 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, void set_color_or_texture(collada::color_or_texture const& color_or_texture,
ID3D10EffectVectorVariable * pVectorVariable, ID3D10EffectVectorVariable * pVectorVariable,
ID3D10EffectShaderResourceVariable * pShaderResourceVariable); ID3D10EffectShaderResourceVariable * pShaderResourceVariable);
}; };
HRESULT LoadEffect(); 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 LoadVertexBuffer(LPCWSTR name, ID3D10Buffer ** ppVertexBuffer);
HRESULT LoadIndexBuffer(LPCWSTR name, ID3D10Buffer ** ppIndexBuffer); 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::FLOAT2: return DXGI_FORMAT_R32G32_FLOAT;
case input_format::FLOAT3: return DXGI_FORMAT_R32G32B32_FLOAT; case input_format::FLOAT3: return DXGI_FORMAT_R32G32B32_FLOAT;
case input_format::FLOAT4: return DXGI_FORMAT_R32G32B32A32_FLOAT; case input_format::FLOAT4: return DXGI_FORMAT_R32G32B32A32_FLOAT;
case input_format::INT4: return DXGI_FORMAT_R32G32B32A32_SINT;
default: default:
assert(false); assert(false);
} }
} }
static inline int format_size(input_format format) static inline UINT format_size(input_format format)
{ {
switch (format) { switch (format) {
case input_format::FLOAT1: return 1 * 4; case input_format::FLOAT1: return 1 * 4;
case input_format::FLOAT2: return 2 * 4; case input_format::FLOAT2: return 2 * 4;
case input_format::FLOAT3: return 3 * 4; case input_format::FLOAT3: return 3 * 4;
case input_format::FLOAT4: return 4 * 4; case input_format::FLOAT4: return 4 * 4;
case input_format::INT4: return 4 * 4;
default: default:
assert(false); assert(false);
} }
@ -71,9 +73,14 @@ namespace collada_scene {
HRESULT hr; HRESULT hr;
m_pVertexLayouts = New<ID3D10InputLayout *>(m_descriptor->inputs_list_count); 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++) { 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)) if (FAILED(hr))
return hr; return hr;
} }
@ -203,6 +210,10 @@ namespace collada_scene {
if (FAILED(hr)) if (FAILED(hr))
return E_FAIL; 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); hr = LoadIndexBuffer(L"RES_MODELS_CURVE_INTERPOLATION_IDX", &m_pIndexBuffer);
if (FAILED(hr)) if (FAILED(hr))
return E_FAIL; return E_FAIL;
@ -217,14 +228,34 @@ namespace collada_scene {
return S_OK; 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; HRESULT hr;
D3D10_INPUT_ELEMENT_DESC layout[inputs.elements_count]; D3D10_INPUT_ELEMENT_DESC layout[inputs.elements_count + 2];
assert(inputs.elements_count == 3); UINT byte_offset = 0;
int byte_offset = 0;
for (int i = 0; i < inputs.elements_count; i++) { for (int i = 0; i < inputs.elements_count; i++) {
layout[i].SemanticName = inputs.elements[i].semantic; layout[i].SemanticName = inputs.elements[i].semantic;
layout[i].SemanticIndex = inputs.elements[i].semantic_index; layout[i].SemanticIndex = inputs.elements[i].semantic_index;
@ -236,6 +267,7 @@ namespace collada_scene {
byte_offset += format_size(inputs.elements[i].format); byte_offset += format_size(inputs.elements[i].format);
} }
*iVertexLayoutStride = byte_offset;
D3D10_PASS_DESC passDesc; D3D10_PASS_DESC passDesc;
g_pTechniqueBlinn->GetPassByIndex(0)->GetDesc(&passDesc); g_pTechniqueBlinn->GetPassByIndex(0)->GetDesc(&passDesc);
@ -249,6 +281,33 @@ namespace collada_scene {
return hr; 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; 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) { switch (effect.type) {
case effect_type::BLINN: case effect_type::BLINN:
set_color_or_texture(effect.blinn.emission, g_pEmissionVariable, g_pTexEmissionVariable); set_color_or_texture(effect.blinn.emission, g_pEmissionVariable, g_pTexEmissionVariable);
@ -420,6 +480,14 @@ namespace collada_scene {
default: default:
break; 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, void scene_state::render_geometry(geometry const& geometry,
@ -427,10 +495,6 @@ namespace collada_scene {
int const instance_materials_count) int const instance_materials_count)
{ {
mesh const& mesh = geometry.mesh; 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); g_pd3dDevice->IASetIndexBuffer(m_pIndexBuffer, DXGI_FORMAT_R32_UINT, mesh.index_buffer_offset);
D3D10_TECHNIQUE_DESC techDesc; D3D10_TECHNIQUE_DESC techDesc;
@ -439,17 +503,43 @@ namespace collada_scene {
for (int j = 0; j < instance_materials_count; j++) { for (int j = 0; j < instance_materials_count; j++) {
instance_material const& instance_material = instance_materials[j]; instance_material const& instance_material = instance_materials[j];
triangles const& triangles = mesh.triangles[instance_material.element_index]; triangles const& triangles = mesh.triangles[instance_material.element_index];
set_material(*instance_material.material->effect);
int texture_channels[4] = { set_instance_material(instance_material);
instance_material.emission.input_set,
instance_material.ambient.input_set, UINT numBuffers = 1;
instance_material.diffuse.input_set, UINT offsets[1] = { (UINT)mesh.vertex_buffer_offset };
instance_material.specular.input_set, UINT strides[1] = { m_iVertexLayoutStrides[triangles.inputs_index] };
}; g_pd3dDevice->IASetVertexBuffers(0, numBuffers, m_pVertexBuffers, strides, offsets);
g_pTextureChannelVariable->SetIntVector(texture_channels); 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_pTechniqueBlinn->GetPassByIndex(0)->Apply(0);
g_pd3dDevice->IASetInputLayout(m_pVertexLayouts[triangles.inputs_index]);
g_pd3dDevice->DrawIndexed(triangles.count * 3, triangles.index_offset, 0); 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++) { for (int i = 0; i < instance_geometries_count; i++) {
instance_geometry const &instance_geometry = instance_geometries[i]; instance_geometry const &instance_geometry = instance_geometries[i];
geometry const& geometry = *instance_geometry.geometry; render_geometry(*instance_geometry.geometry,
render_geometry(geometry,
instance_geometry.instance_materials, instance_geometry.instance_materials,
instance_geometry.instance_materials_count); instance_geometry.instance_materials_count);
} }
@ -472,9 +560,7 @@ namespace collada_scene {
{ {
for (int i = 0; i < instance_controllers_count; i++) { for (int i = 0; i < instance_controllers_count; i++) {
instance_controller const &instance_controller = instance_controllers[i]; instance_controller const &instance_controller = instance_controllers[i];
geometry const& geometry = *instance_controller.controller->skin.geometry; render_skin(instance_controller.controller->skin,
render_geometry(geometry,
instance_controller.instance_materials, instance_controller.instance_materials,
instance_controller.instance_materials_count); instance_controller.instance_materials_count);
} }