diff --git a/scenes/curve_interpolation/curve_interpolation.max b/scenes/curve_interpolation/curve_interpolation.max index f660dd7..1a8671c 100755 Binary files a/scenes/curve_interpolation/curve_interpolation.max and b/scenes/curve_interpolation/curve_interpolation.max differ diff --git a/src/collada_scene.cpp b/src/collada_scene.cpp index 41f5821..9297b8a 100644 --- a/src/collada_scene.cpp +++ b/src/collada_scene.cpp @@ -9,6 +9,7 @@ #include "new.hpp" extern ID3D10Device * g_pd3dDevice; +extern XMVECTOR g_Eye; extern XMMATRIX g_View; extern XMMATRIX g_Projection; @@ -22,6 +23,11 @@ namespace collada_scene { ID3D10EffectMatrixVariable * g_pViewVariable = NULL; ID3D10EffectMatrixVariable * g_pProjectionVariable = NULL; + ID3D10EffectVectorVariable * g_pViewEyeVariable = NULL; + ID3D10EffectVectorVariable * g_pLightPosVariable = NULL; + ID3D10EffectVectorVariable * g_pLightDirVariable = NULL; + ID3D10EffectVectorVariable * g_pLightColorVariable = NULL; + ID3D10EffectVectorVariable * g_pEmissionVariable = NULL; ID3D10EffectVectorVariable * g_pAmbientVariable = NULL; ID3D10EffectVectorVariable * g_pDiffuseVariable = NULL; @@ -67,8 +73,52 @@ namespace collada_scene { return S_OK; } + void scene_state::update_light_instance_vectors(light const& light, + node_instance const& node_instance, + int light_index) + { + const XMVECTOR position = XMVectorSet(0, 0, 0, 1); + const XMVECTOR direction = XMVectorSet(0, 0, -1, 0); + XMVECTOR light_position = XMVector3Transform(position, node_instance.world); + XMVECTOR light_direction = XMVector3TransformNormal(direction, node_instance.world); + XMVECTOR light_color = XMLoadFloat3((XMFLOAT3 *)&light.color); + + XMStoreFloat4(&m_lightPositions[light_index], light_position); + XMStoreFloat4(&m_lightDirections[light_index], light_direction); + XMStoreFloat4(&m_lightColors[light_index], light_color); + } + + void scene_state::update_light_instances() + { + int light_index = 0; + for (int i = 0; i < m_descriptor->nodes_count; i++) { + node const& node = *m_descriptor->nodes[i]; + node_instance const& node_instance = m_nodeInstances[i]; + for (int j = 0; j < node.instance_lights_count; j++) { + light const& light = *node.instance_lights[j].light; + update_light_instance_vectors(light, node_instance, light_index); + light_index += 1; + } + } + } + + void scene_state::allocate_light_instances() + { + // count light instances + int count = 0; + for (int i = 0; i < m_descriptor->nodes_count; i++) { + count += m_descriptor->nodes[i]->instance_lights_count; + } + + // allocate + m_lightInstancesCount = count; + m_lightPositions = New(m_lightInstancesCount); + m_lightDirections = New(m_lightInstancesCount); + m_lightColors = New(m_lightInstancesCount); + } + static void initialize_node_transforms(node const * const node, - node_instance * node_instance) + node_instance * const node_instance) { for (int i = 0; i < node->transforms_count; i++) { transform& transform = node_instance->transforms[i]; @@ -98,7 +148,7 @@ namespace collada_scene { } void scene_state::allocate_node_instance(node const * const node, - node_instance * node_instance) + node_instance * const node_instance) { node_instance->transforms = New(node->transforms_count); initialize_node_transforms(node, node_instance); @@ -133,6 +183,7 @@ namespace collada_scene { return E_FAIL; allocate_node_instances(); + allocate_light_instances(); return S_OK; } @@ -143,6 +194,7 @@ namespace collada_scene { D3D10_INPUT_ELEMENT_DESC layout[inputs.elements_count]; + assert(inputs.elements_count == 3); int byte_offset = 0; for (int i = 0; i < inputs.elements_count; i++) { layout[i].SemanticName = inputs.elements[i].semantic; @@ -200,6 +252,11 @@ namespace collada_scene { g_pViewVariable = g_pEffect->GetVariableByName("View")->AsMatrix(); g_pProjectionVariable = g_pEffect->GetVariableByName("Projection")->AsMatrix(); + g_pViewEyeVariable = g_pEffect->GetVariableByName("ViewEye")->AsVector(); + g_pLightPosVariable = g_pEffect->GetVariableByName("LightPos")->AsVector(); + g_pLightDirVariable = g_pEffect->GetVariableByName("LightDir")->AsVector(); + g_pLightColorVariable = g_pEffect->GetVariableByName("LightColor")->AsVector(); + g_pEmissionVariable = g_pEffect->GetVariableByName("Emission")->AsVector(); g_pAmbientVariable = g_pEffect->GetVariableByName("Ambient")->AsVector(); g_pDiffuseVariable = g_pEffect->GetVariableByName("Diffuse")->AsVector(); @@ -559,28 +616,59 @@ namespace collada_scene { } } - void scene_state::render(float t) + void scene_state::update(float t) { - g_pViewVariable->SetMatrix((float *)&g_View); - g_pProjectionVariable->SetMatrix((float *)&g_Projection); - - g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - t = loop(t / 2.0f, 3.333333f); + // animate and update all world transforms for (int i = 0; i < m_descriptor->nodes_count; i++) { node const& node = *m_descriptor->nodes[i]; node_instance& node_instance = m_nodeInstances[i]; animate_node(node, node_instance, t); node_world_transform(node, node_instance); + } - g_pWorldVariable->SetMatrix((float *)&node_instance.world); + // update all lights (after world transforms are computed) + update_light_instances(); + } + + static int min(int a, int b) + { + return a < b ? a : b; + } + + void scene_state::render() + { + XMFLOAT4 eye; + XMFLOAT4X4 projection; + XMFLOAT4X4 view; + XMStoreFloat4(&eye, g_Eye); + XMStoreFloat4x4(&view, g_View); + XMStoreFloat4x4(&projection, g_Projection); + + g_pViewVariable->SetMatrix((float *)&view); + g_pProjectionVariable->SetMatrix((float *)&projection); + + g_pViewEyeVariable->SetFloatVector((float *)&eye); + + int lights = min(2, m_lightInstancesCount); + g_pLightPosVariable->SetFloatVectorArray((float *)m_lightPositions, 0, lights); + g_pLightDirVariable->SetFloatVectorArray((float *)m_lightDirections, 0, lights); + g_pLightColorVariable->SetFloatVectorArray((float *)m_lightColors, 0, lights); + + g_pd3dDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + for (int i = 0; i < m_descriptor->nodes_count; i++) { + node const& node = *m_descriptor->nodes[i]; + node_instance& node_instance = m_nodeInstances[i]; // joints aren't rendered if (node.type != node_type::NODE) continue; + g_pWorldVariable->SetMatrix((float *)&node_instance.world); + render_geometries(node.instance_geometries, node.instance_geometries_count); } } diff --git a/src/effect/collada_scene.fx b/src/effect/collada_scene.fx index c683dde..0c593b5 100644 --- a/src/effect/collada_scene.fx +++ b/src/effect/collada_scene.fx @@ -2,6 +2,12 @@ cbuffer cbEveryFrame { matrix View; matrix Projection; + + float4 ViewEye; + + float4 LightPos[2]; + float4 LightDir[2]; + float4 LightColor[2]; }; cbuffer cbMultiplePerFrame @@ -30,30 +36,39 @@ struct PS_INPUT float4 Pos : SV_POSITION; float3 Norm : NORMAL; float2 Tex : TEXCOORD0; + float4 WPos : POSITION; }; PS_INPUT VS(VS_INPUT input) { PS_INPUT output; - output.Pos = mul(float4(input.Pos, 1), World); - output.Pos = mul(output.Pos, View); + float4 world_pos = mul(float4(input.Pos, 1), World); + output.Pos = mul(world_pos, View); output.Pos = mul(output.Pos, Projection); output.Norm = mul(input.Norm, (float3x3)World); output.Tex = input.Tex; + output.WPos = world_pos; + return output; } float4 PS(PS_INPUT input) : SV_Target { - float4 color = Emission + Diffuse * 1.0 + Specular * 0.0; + float3 normal = normalize(input.Norm); + float3 view_dir = normalize(ViewEye.xyz - input.Pos.xyz); + + float3 color = Emission.xyz; + + for (int i = 0; i < 2; i++) { + float3 light_dir = normalize(-LightDir[i].xyz); + float diffuse_intensity = max(dot(normal, light_dir), 0.0); + color += Diffuse.xyz * diffuse_intensity * LightColor[i].xyz; + } return float4(color.xyz, 1); - - //return float4(input.Normal * 0.5 + 0.5, 1); - //return float4(input.Tex.xy, 0, 1); } BlendState DisableBlending diff --git a/src/main.cpp b/src/main.cpp index e6273c8..cc25f9e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -20,7 +20,7 @@ #include "collada.hpp" #include "collada_scene.hpp" -#include "scenes/curve_interpolation.hpp" +#include "scenes/curve_interpolation/curve_interpolation.hpp" HINSTANCE g_hInstance = NULL; HWND g_hWnd = NULL; @@ -1843,7 +1843,8 @@ void Render(float t, float dt) //collada::Render(t); - g_SceneState.render(t); + g_SceneState.update(t); + g_SceneState.render(); RenderFont(dt); diff --git a/src/scenes/curve_interpolation/curve_interpolation.cpp b/src/scenes/curve_interpolation/curve_interpolation.cpp index b26354c..e47226c 100644 --- a/src/scenes/curve_interpolation/curve_interpolation.cpp +++ b/src/scenes/curve_interpolation/curve_interpolation.cpp @@ -1008,8 +1008,8 @@ instance_light const instance_lights_node_cube[] = { }; channel const * const node_channels_node_cube[] = { - &node_channel_node_cube_translation_x, &node_channel_node_cube_translation_y, + &node_channel_node_cube_translation_x, }; node const node_node_cube = {