Add FixedFunctionState to keep track of D3D fixed function lights
This commit is contained in:
parent
ddc62ad00e
commit
99a96e675d
|
@ -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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue