Add FixedFunctionState to keep track of D3D fixed function lights

This commit is contained in:
Anthony Miles 2020-10-27 20:43:19 +13:00 committed by Anthony
parent ddc62ad00e
commit 99a96e675d
3 changed files with 115 additions and 0 deletions

View File

@ -121,6 +121,7 @@ file (GLOB CXBXR_HEADER_EMU
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/VertexShader.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/VertexShaderSource.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/WalkIndexBuffer.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/FixedFunctionState.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/ResourceTracker.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbConvert.h"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbD3D8Logging.h"
@ -266,6 +267,7 @@ file (GLOB CXBXR_SOURCE_EMU
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/VertexShader.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/VertexShaderSource.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/Direct3D9/WalkIndexBuffer.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/FixedFunctionState.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/ResourceTracker.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbConvert.cpp"
"${CXBXR_ROOT_DIR}/src/core/hle/D3D8/XbD3D8Logging.cpp"

View File

@ -0,0 +1,87 @@
#define LOG_PREFIX CXBXR_MODULE::D3D8
#include "FixedFunctionState.h"
#include "Logging.h"
D3DCOLORVALUE colorValue(float r, float g, float b, float a) {
auto value = D3DCOLORVALUE();
value.r = r;
value.g = g;
value.b = b;
value.a = a;
return value;
}
D3DVECTOR toVector(float x, float y, float z) {
auto value = D3DVECTOR();
value.x = x;
value.y = y;
value.z = z;
return value;
}
D3D8LightState::D3D8LightState() {
// Define the default light
// When unset lights are enabled, they're set to the default light
auto defaultLight = xbox::X_D3DLIGHT8();
defaultLight.Type = D3DLIGHT_DIRECTIONAL;
defaultLight.Diffuse = colorValue(1, 1, 1, 0);
defaultLight.Specular = colorValue(0, 0, 0, 0);
defaultLight.Ambient = colorValue(0, 0, 0, 0);
defaultLight.Position = toVector(0, 0, 0);
defaultLight.Direction = toVector(0, 0, 1);
defaultLight.Range = 0;
defaultLight.Falloff = 0;
defaultLight.Attenuation0 = 0;
defaultLight.Attenuation1 = 0;
defaultLight.Attenuation2 = 0;
defaultLight.Theta = 0;
defaultLight.Phi = 0;
// We'll just preset every light to the default light
Lights.fill(defaultLight);
EnabledLights.fill(-1);
}
void D3D8LightState::EnableLight(uint32_t index, bool enable) {
// Since Xbox only supports 8 lights, we keep track of the 8 most recently enabled lights
// Lights are ordered oldest to newest, with disabled lights at the end
// Check to see if the light is already enabled
for (size_t i = 0; i < EnabledLightCount; i++) {
// If the light is already in the enabled lights
if (EnabledLights[i] == index) {
// Either way we move this light to the end
std::rotate(std::begin(EnabledLights) + i, std::begin(EnabledLights) + i + 1, std::begin(EnabledLights) + EnabledLightCount);
if (enable) {
// Don't need to do anything
EmuLog(LOG_LEVEL::INFO, "Enabled light %d but it was already enabled", index);
}
else {
// Disable the light
EnabledLights[EnabledLightCount - 1] = -1;
EnabledLightCount--;
}
return;
}
}
if (enable) {
// The light was not in the enabled lights. Let's add it
if (EnabledLightCount < EnabledLights.size()) {
EnabledLights[EnabledLightCount] = index; // add it to the end
EnabledLightCount++;
}
else {
// Replace the oldest element and move to end
EmuLog(LOG_LEVEL::INFO, "Can't enable any more lights. Replacing the oldest light %i", EnabledLights[0]);
EnabledLights[0] = index;
std::rotate(std::begin(EnabledLights), std::begin(EnabledLights) + 1, std::end(EnabledLights));
}
}
else {
EmuLog(LOG_LEVEL::INFO, "Could not disable light %d because it wasn't enabled", index);
}
}

View File

@ -0,0 +1,26 @@
#ifndef FIXEDFUNCTIONSTATE_H
#define FIXEDFUNCTIONSTATE_H
#include "XbD3D8Types.h"
#include <array>
class D3D8LightState {
public:
std::array<xbox::X_D3DLIGHT8, 4096> Lights;
// The indices of last 8 enabled lights
// From least recently to most recently enabled
// -1 represents empty light slots
// which always appear after enabled lights
std::array<int, 8> EnabledLights;
// The number of enabled lights
uint32_t EnabledLightCount = 0;
D3D8LightState();
// Enable a light
void EnableLight(uint32_t index, bool enable);
};
#endif