Skip to content

Commit

Permalink
gpu: Emulate vertex lighting (sans shininess table, for now)
Browse files Browse the repository at this point in the history
  • Loading branch information
fleroviux committed Dec 10, 2023
1 parent 53d9f02 commit 607207e
Show file tree
Hide file tree
Showing 7 changed files with 139 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ namespace dual::nds::gpu {
void cmdSetPolygonAttributes();
void cmdSetTextureParameters();
void cmdSetPaletteBase();
void cmdSetDiffuseAndAmbientMaterialColors();
void cmdSetSpecularAndEmissiveMaterialColors();
void cmdSetLightVector();
void cmdSetLightColor();
void cmdBeginVertices();
void cmdEndVertices();
void cmdSwapBuffers();
Expand Down
34 changes: 33 additions & 1 deletion src/dual/include/dual/nds/video_unit/gpu/geometry_engine.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,36 @@ namespace dual::nds::gpu {
m_vertex_color = color;
}

void SetVertexUV(const Vector2<Fixed12x4> uv) {
void SetVertexUV(Vector2<Fixed12x4> uv) {
m_vertex_uv = uv;
}

void SetNormal(Vector3<Fixed20x12> normal);

void SetMaterialDiffuseColor(const Color4& color) {
m_material_diffuse_color = color;
}

void SetMaterialAmbientColor(const Color4& color) {
m_material_ambient_color = color;
}

void SetMaterialSpecularColor(const Color4& color) {
m_material_specular_color = color;
}

void SetMaterialEmissiveColor(const Color4& color) {
m_material_emissive_color = color;
}

void SetLightDirection(int light_index, Vector3<Fixed20x12> direction) {
m_light_direction[light_index] = direction;
}

void SetLightColor(int light_index, const Color4& color) {
m_light_color[light_index] = color;
}

void SubmitVertex(Vector3<Fixed20x12> position, const Matrix4<Fixed20x12>& clip_matrix);

[[nodiscard]] std::span<const Polygon> GetPolygonsToRender() const {
Expand Down Expand Up @@ -154,6 +180,12 @@ namespace dual::nds::gpu {
u32 m_texture_palette_base{};
Color4 m_vertex_color{};
Vector2<Fixed12x4> m_vertex_uv{};
std::array<Vector3<Fixed20x12>, 4> m_light_direction{};
std::array<Color4, 4> m_light_color{};
Color4 m_material_diffuse_color{};
Color4 m_material_ambient_color{};
Color4 m_material_specular_color{};
Color4 m_material_emissive_color{};
};

} // namespace dual::nds::gpu
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,10 @@ namespace dual::nds::gpu {
case 0x29: cmdSetPolygonAttributes(); break;
case 0x2A: cmdSetTextureParameters(); break;
case 0x2B: cmdSetPaletteBase(); break;
case 0x30: cmdSetDiffuseAndAmbientMaterialColors(); break;
case 0x31: cmdSetSpecularAndEmissiveMaterialColors(); break;
case 0x32: cmdSetLightVector(); break;
case 0x33: cmdSetLightColor(); break;
case 0x40: cmdBeginVertices(); break;
case 0x41: cmdEndVertices(); break;
case 0x50: cmdSwapBuffers(); break;
Expand All @@ -220,10 +224,6 @@ namespace dual::nds::gpu {
}

if(
command != 0x30 && // DIF_AMB
command != 0x31 && // SPE_EMI
command != 0x32 && // LIGHT_VECTOR
command != 0x33 && // LIGHT_COLOR
command != 0x34 && // SHININESS
command != 0x70 && // BOX_TEST
true
Expand Down
52 changes: 51 additions & 1 deletion src/dual/src/nds/video_unit/gpu/command_processor/geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@ namespace dual::nds::gpu {
}

void CommandProcessor::cmdSetNormal() {
DequeueFIFO();
const u32 xyz = DequeueFIFO();

m_geometry_engine.SetNormal((m_direction_mtx * Vector4<Fixed20x12>{
(i32)(xyz & (0x3FFu << 0)) << 22 >> 19,
(i32)(xyz & (0x3FFu << 10)) << 12 >> 19,
(i32)(xyz & (0x3FFu << 20)) << 2 >> 19,
0
}).XYZ());
}

void CommandProcessor::cmdSetUV() {
Expand Down Expand Up @@ -73,4 +80,47 @@ namespace dual::nds::gpu {
m_geometry_engine.SetPaletteBase(DequeueFIFO() & 0x1FFFu);
}

void CommandProcessor::cmdSetDiffuseAndAmbientMaterialColors() {
const u32 param = DequeueFIFO();
const Color4 diffuse = Color4::FromRGB555((u16)(param >> 0));
const Color4 ambient = Color4::FromRGB555((u16)(param >> 16));

m_geometry_engine.SetMaterialAmbientColor(ambient);
m_geometry_engine.SetMaterialDiffuseColor(diffuse);
if(param & 0x8000u) {
m_geometry_engine.SetVertexColor(diffuse);
}
}

void CommandProcessor::cmdSetSpecularAndEmissiveMaterialColors() {
const u32 param = DequeueFIFO();
const Color4 specular = Color4::FromRGB555((u16)(param >> 0));
const Color4 emissive = Color4::FromRGB555((u16)(param >> 16));

// @todo: handle shininess table enable
m_geometry_engine.SetMaterialSpecularColor(specular);
m_geometry_engine.SetMaterialEmissiveColor(emissive);
}

void CommandProcessor::cmdSetLightVector() {
const u32 i_xyz = DequeueFIFO();

const int light_index = i_xyz >> 30;

const Vector4<Fixed20x12> light_direction = m_direction_mtx * Vector4<Fixed20x12>{
(i32)(i_xyz & (0x3FFu << 0)) << 22 >> 19,
(i32)(i_xyz & (0x3FFu << 10)) << 12 >> 19,
(i32)(i_xyz & (0x3FFu << 20)) << 2 >> 19,
0
};

m_geometry_engine.SetLightDirection(light_index, light_direction.XYZ());
}

void CommandProcessor::cmdSetLightColor() {
const u32 i_rgb555 = DequeueFIFO();

m_geometry_engine.SetLightColor(i_rgb555 >> 30, Color4::FromRGB555((u16)i_rgb555));
}

} // namespace dual::nds::gpu
45 changes: 45 additions & 0 deletions src/dual/src/nds/video_unit/gpu/geometry_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ namespace dual::nds::gpu {
m_vertex_color = {};
m_vertex_uv = {};
m_texture_parameters = {};
m_light_direction = {};
m_light_color = {};
m_material_diffuse_color = {};
m_material_ambient_color = {};
m_material_specular_color = {};
m_material_emissive_color = {};
}

void GeometryEngine::SwapBuffers() {
Expand Down Expand Up @@ -418,4 +424,43 @@ namespace dual::nds::gpu {
return dot > 0 ? +1 : -1;
}

void GeometryEngine::SetNormal(Vector3<Fixed20x12> normal) {
// @todo: texture mapping

i32 r = m_material_emissive_color.R().Raw() << 18;
i32 g = m_material_emissive_color.G().Raw() << 18;
i32 b = m_material_emissive_color.B().Raw() << 18;

const Color4 diffuse = m_material_diffuse_color;
const Color4 ambient = m_material_ambient_color;
const Color4 specular = m_material_specular_color;

for(int i = 0; i < 4; i++) {
if(!m_polygon_attributes.light_enable[i]) {
continue;
}

const Vector3<Fixed20x12> halfway{
m_light_direction[i].X().Raw() >> 1,
m_light_direction[i].Y().Raw() >> 1,
(m_light_direction[i].Z().Raw() - (1 << 12)) >> 1
};

const i32 n_dot_l = std::max<i32>(0, -normal.Dot(m_light_direction[i]).Raw());
const i32 n_dot_h = std::max<i32>(0, -normal.Dot(halfway).Raw());
const i32 n_dot_h_2 = (n_dot_h * n_dot_h) >> 12;

// @todo: implement shininess table

r += m_light_color[i].R().Raw() * (n_dot_l * diffuse.R().Raw() + n_dot_h_2 * specular.R().Raw() + ambient.R().Raw());
g += m_light_color[i].G().Raw() * (n_dot_l * diffuse.G().Raw() + n_dot_h_2 * specular.G().Raw() + ambient.G().Raw());
b += m_light_color[i].B().Raw() * (n_dot_l * diffuse.B().Raw() + n_dot_h_2 * specular.B().Raw() + ambient.B().Raw());
}

// @todo: getting some random colors which are off. figure out why this happens.
m_vertex_color.R() = std::min(r >> 18, 63);
m_vertex_color.G() = std::min(g >> 18, 63);
m_vertex_color.B() = std::min(b >> 18, 63);
}

} // namespace dual::nds::gpu
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ namespace dual::nds::gpu {
if(w == 0) {
return;
}

const i32 x = (i32)(((( (i64)position.X().Raw() + w) * viewport.width + 0x800) / two_w) + viewport.x0);
const i32 y = (i32)((((-(i64)position.Y().Raw() + w) * viewport.height + 0x800) / two_w) + viewport.y0);
const u32 depth = (u32)((((i64)position.Z().Raw() << 14) / w + 0x3FFF) << 9);
Expand Down
2 changes: 1 addition & 1 deletion src/platform/sdl/src/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ int Application::Run(int argc, char **argv) {
LoadBootROM("boot9.bin", true);
LoadBootROM("boot7.bin", false);
if(argc < 2) {
LoadROM("pokeplatin.nds");
LoadROM("pokesoulsilver.nds");
} else {
LoadROM(argv[1]);
}
Expand Down

0 comments on commit 607207e

Please sign in to comment.