collada_scene: implement directional lighting

This commit is contained in:
Zack Buhman 2026-01-28 22:36:12 -06:00
parent 4d952b0a90
commit b9cfcde9c7
5 changed files with 122 additions and 18 deletions

View File

@ -9,6 +9,7 @@
#include "new.hpp" #include "new.hpp"
extern ID3D10Device * g_pd3dDevice; extern ID3D10Device * g_pd3dDevice;
extern XMVECTOR g_Eye;
extern XMMATRIX g_View; extern XMMATRIX g_View;
extern XMMATRIX g_Projection; extern XMMATRIX g_Projection;
@ -22,6 +23,11 @@ namespace collada_scene {
ID3D10EffectMatrixVariable * g_pViewVariable = NULL; ID3D10EffectMatrixVariable * g_pViewVariable = NULL;
ID3D10EffectMatrixVariable * g_pProjectionVariable = 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_pEmissionVariable = NULL;
ID3D10EffectVectorVariable * g_pAmbientVariable = NULL; ID3D10EffectVectorVariable * g_pAmbientVariable = NULL;
ID3D10EffectVectorVariable * g_pDiffuseVariable = NULL; ID3D10EffectVectorVariable * g_pDiffuseVariable = NULL;
@ -67,8 +73,52 @@ namespace collada_scene {
return S_OK; 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<XMFLOAT4>(m_lightInstancesCount);
m_lightDirections = New<XMFLOAT4>(m_lightInstancesCount);
m_lightColors = New<XMFLOAT4>(m_lightInstancesCount);
}
static void initialize_node_transforms(node const * const node, 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++) { for (int i = 0; i < node->transforms_count; i++) {
transform& transform = node_instance->transforms[i]; transform& transform = node_instance->transforms[i];
@ -98,7 +148,7 @@ namespace collada_scene {
} }
void scene_state::allocate_node_instance(node const * const node, void scene_state::allocate_node_instance(node const * const node,
node_instance * node_instance) node_instance * const node_instance)
{ {
node_instance->transforms = New<transform>(node->transforms_count); node_instance->transforms = New<transform>(node->transforms_count);
initialize_node_transforms(node, node_instance); initialize_node_transforms(node, node_instance);
@ -133,6 +183,7 @@ namespace collada_scene {
return E_FAIL; return E_FAIL;
allocate_node_instances(); allocate_node_instances();
allocate_light_instances();
return S_OK; return S_OK;
} }
@ -143,6 +194,7 @@ namespace collada_scene {
D3D10_INPUT_ELEMENT_DESC layout[inputs.elements_count]; D3D10_INPUT_ELEMENT_DESC layout[inputs.elements_count];
assert(inputs.elements_count == 3);
int 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;
@ -200,6 +252,11 @@ namespace collada_scene {
g_pViewVariable = g_pEffect->GetVariableByName("View")->AsMatrix(); g_pViewVariable = g_pEffect->GetVariableByName("View")->AsMatrix();
g_pProjectionVariable = g_pEffect->GetVariableByName("Projection")->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_pEmissionVariable = g_pEffect->GetVariableByName("Emission")->AsVector();
g_pAmbientVariable = g_pEffect->GetVariableByName("Ambient")->AsVector(); g_pAmbientVariable = g_pEffect->GetVariableByName("Ambient")->AsVector();
g_pDiffuseVariable = g_pEffect->GetVariableByName("Diffuse")->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); t = loop(t / 2.0f, 3.333333f);
// animate and update all world transforms
for (int i = 0; i < m_descriptor->nodes_count; i++) { for (int i = 0; i < m_descriptor->nodes_count; i++) {
node const& node = *m_descriptor->nodes[i]; node const& node = *m_descriptor->nodes[i];
node_instance& node_instance = m_nodeInstances[i]; node_instance& node_instance = m_nodeInstances[i];
animate_node(node, node_instance, t); animate_node(node, node_instance, t);
node_world_transform(node, node_instance); 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 // joints aren't rendered
if (node.type != node_type::NODE) if (node.type != node_type::NODE)
continue; continue;
g_pWorldVariable->SetMatrix((float *)&node_instance.world);
render_geometries(node.instance_geometries, node.instance_geometries_count); render_geometries(node.instance_geometries, node.instance_geometries_count);
} }
} }

View File

@ -2,6 +2,12 @@ cbuffer cbEveryFrame
{ {
matrix View; matrix View;
matrix Projection; matrix Projection;
float4 ViewEye;
float4 LightPos[2];
float4 LightDir[2];
float4 LightColor[2];
}; };
cbuffer cbMultiplePerFrame cbuffer cbMultiplePerFrame
@ -30,30 +36,39 @@ struct PS_INPUT
float4 Pos : SV_POSITION; float4 Pos : SV_POSITION;
float3 Norm : NORMAL; float3 Norm : NORMAL;
float2 Tex : TEXCOORD0; float2 Tex : TEXCOORD0;
float4 WPos : POSITION;
}; };
PS_INPUT VS(VS_INPUT input) PS_INPUT VS(VS_INPUT input)
{ {
PS_INPUT output; PS_INPUT output;
output.Pos = mul(float4(input.Pos, 1), World); float4 world_pos = mul(float4(input.Pos, 1), World);
output.Pos = mul(output.Pos, View); output.Pos = mul(world_pos, View);
output.Pos = mul(output.Pos, Projection); output.Pos = mul(output.Pos, Projection);
output.Norm = mul(input.Norm, (float3x3)World); output.Norm = mul(input.Norm, (float3x3)World);
output.Tex = input.Tex; output.Tex = input.Tex;
output.WPos = world_pos;
return output; return output;
} }
float4 PS(PS_INPUT input) : SV_Target 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(color.xyz, 1);
//return float4(input.Normal * 0.5 + 0.5, 1);
//return float4(input.Tex.xy, 0, 1);
} }
BlendState DisableBlending BlendState DisableBlending

View File

@ -20,7 +20,7 @@
#include "collada.hpp" #include "collada.hpp"
#include "collada_scene.hpp" #include "collada_scene.hpp"
#include "scenes/curve_interpolation.hpp" #include "scenes/curve_interpolation/curve_interpolation.hpp"
HINSTANCE g_hInstance = NULL; HINSTANCE g_hInstance = NULL;
HWND g_hWnd = NULL; HWND g_hWnd = NULL;
@ -1843,7 +1843,8 @@ void Render(float t, float dt)
//collada::Render(t); //collada::Render(t);
g_SceneState.render(t); g_SceneState.update(t);
g_SceneState.render();
RenderFont(dt); RenderFont(dt);

View File

@ -1008,8 +1008,8 @@ instance_light const instance_lights_node_cube[] = {
}; };
channel const * const node_channels_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_y,
&node_channel_node_cube_translation_x,
}; };
node const node_node_cube = { node const node_node_cube = {