Adds fog tests.

This commit is contained in:
Erik Abair 2022-01-14 13:14:17 -08:00
parent 63de359668
commit c8270cb313
6 changed files with 299 additions and 29 deletions

View File

@ -22,6 +22,7 @@ SRCS = \
$(SRCDIR)/test_driver.cpp \
$(SRCDIR)/test_host.cpp \
$(SRCDIR)/tests/depth_format_tests.cpp \
$(SRCDIR)/tests/fog_tests.cpp \
$(SRCDIR)/tests/front_face_tests.cpp \
$(SRCDIR)/tests/image_blit_tests.cpp \
$(SRCDIR)/tests/lighting_normal_tests.cpp \

View File

@ -16,6 +16,7 @@
#include "test_driver.h"
#include "test_host.h"
#include "tests/depth_format_tests.h"
#include "tests/fog_tests.h"
#include "tests/front_face_tests.h"
#include "tests/image_blit_tests.h"
#include "tests/lighting_normal_tests.h"
@ -126,6 +127,10 @@ static void register_suites(TestHost& host, std::vector<std::shared_ptr<TestSuit
test_suites.push_back(std::dynamic_pointer_cast<TestSuite>(suite));
}
{
auto suite = std::make_shared<FogTests>(host, output_directory);
test_suites.push_back(std::dynamic_pointer_cast<TestSuite>(suite));
}
{
auto suite = std::make_shared<FrontFaceTests>(host, output_directory);
test_suites.push_back(std::dynamic_pointer_cast<TestSuite>(suite));

241
src/tests/fog_tests.cpp Normal file
View File

@ -0,0 +1,241 @@
#include "fog_tests.h"
#include <pbkit/pbkit.h>
#include "pbkit_ext.h"
#include "test_host.h"
#include "vertex_buffer.h"
// clang-format off
static constexpr FogTests::FogMode kFogModes[] = {
FogTests::FOG_LINEAR,
FogTests::FOG_EXP,
FogTests::FOG_EXP2,
// FogTests::FOG_EXP_ABS,
// FogTests::FOG_EXP2_ABS,
// FogTests::FOG_LINEAR_ABS,
};
static constexpr FogTests::FogGenMode kGenModes[] = {
// FogTests::FOG_GEN_SPEC_ALPHA,
// FogTests::FOG_GEN_RADIAL,
FogTests::FOG_GEN_PLANAR,
// FogTests::FOG_GEN_ABS_PLANAR,
// FogTests::FOG_GEN_FOG_X,
};
// clang-format on
FogTests::FogTests(TestHost& host, std::string output_dir) : TestSuite(host, std::move(output_dir), "Fog") {
for (const auto fog_mode : kFogModes) {
for (const auto gen_mode : kGenModes) {
// Alpha doesn't seem to actually have any effect.
for (auto alpha : {0xFF}) {
const std::string test_name = MakeTestName(fog_mode, gen_mode, alpha);
auto test = [this, fog_mode, gen_mode, alpha]() { this->Test(fog_mode, gen_mode, alpha); };
tests_[test_name] = test;
}
}
}
}
void FogTests::Initialize() {
TestSuite::Initialize();
host_.SetShaderProgram(nullptr);
CreateGeometry();
host_.SetXDKDefaultViewportAndFixedFunctionMatrices();
}
void FogTests::CreateGeometry() {
constexpr int kNumTriangles = 4;
auto buffer = host_.AllocateVertexBuffer(kNumTriangles * 3);
int index = 0;
{
float one[] = {-1.5f, -1.5f, 0.0f};
float two[] = {-0.5f, 0.6f, 0.0f};
float three[] = {-2.5f, 0.6f, 0.0f};
buffer->DefineTriangle(index++, one, two, three);
}
{
float one[] = {0.0f, -1.5f, 5.0f};
float two[] = {2.0f, 0.75f, 20.0f};
float three[] = {-1.0f, 0.75f, 10.0f};
buffer->DefineTriangle(index++, one, two, three);
}
{
float one[] = {5.0f, -2.0f, 30};
float two[] = {12.0f, 2.0f, 70};
float three[] = {3.0f, 2.0f, 40};
buffer->DefineTriangle(index++, one, two, three);
}
{
float one[] = {20.0f, -10.0f, 50};
float two[] = {80.0f, 10.0f, 200};
float three[] = {12.0f, 10.0f, 125};
buffer->DefineTriangle(index++, one, two, three);
}
}
void FogTests::Test(FogTests::FogMode fog_mode, FogTests::FogGenMode gen_mode, uint32_t fog_alpha) {
// See https://docs.microsoft.com/en-us/previous-versions/windows/desktop/bb324452(v=vs.85)
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/bb322857(v=vs.85)
static constexpr uint32_t kBackgroundColor = 0xFF303030;
host_.PrepareDraw(kBackgroundColor);
auto p = pb_begin();
p = pb_push1(p, NV097_SET_COMBINER_CONTROL, 1);
pb_push_to(SUBCH_3D, p++, NV097_SET_COMBINER_COLOR_ICW, 8);
*(p++) = 0x4200000;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
pb_push_to(SUBCH_3D, p++, NV097_SET_COMBINER_COLOR_OCW, 8);
*(p++) = 0xC00;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
pb_push_to(SUBCH_3D, p++, NV097_SET_COMBINER_ALPHA_ICW, 8);
*(p++) = 0x14200000;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
pb_push_to(SUBCH_3D, p++, NV097_SET_COMBINER_ALPHA_OCW, 8);
*(p++) = 0xC00;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
p = pb_push1(p, NV097_SET_FOG_ENABLE, true);
p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW0, 0x130C0300);
p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW1, 0x1c80);
// Note: Fog color is ABGR and not ARGB
p = pb_push1(p, NV097_SET_FOG_COLOR, 0x7F2030 + (fog_alpha << 24));
p = pb_push1(p, NV097_SET_FOG_GEN_MODE, gen_mode);
p = pb_push1(p, NV097_SET_FOG_MODE, fog_mode);
// Linear parameters.
// TODO: Parameterize.
// Right now these are just the near and far planes.
const float fog_start = 1.0f;
const float fog_end = 200.0f;
// Exponential parameters.
const float fog_density = 0.025f;
static constexpr float LN_256 = 5.5452f;
static constexpr float SQRT_LN_256 = 2.3548f;
float bias_param = 0.0f;
float multiplier_param = 1.0f;
switch (fog_mode) {
case FOG_LINEAR:
multiplier_param = -1.0f / (fog_end - fog_start);
bias_param = 1.0f + -fog_end * multiplier_param;
break;
case FOG_EXP:
bias_param = 1.5f;
multiplier_param = -fog_density / (2.0f * LN_256);
break;
case FOG_EXP2:
bias_param = 1.5f;
multiplier_param = -fog_density / (2.0f * SQRT_LN_256);
break;
default:
break;
}
// TODO: Figure out what the third parameter is. In all examples I've seen it's always been 0.
p = pb_push3f(p, NV097_SET_FOG_PARAMS, bias_param, multiplier_param, 0.0f);
pb_end(p);
host_.DrawArrays(host_.POSITION | host_.DIFFUSE);
std::string name = MakeTestName(fog_mode, gen_mode, fog_alpha);
pb_print("%s\n", name.c_str());
pb_draw_text_screen();
host_.FinishDrawAndSave(output_dir_, name);
}
std::string FogTests::MakeTestName(FogTests::FogMode fog_mode, FogTests::FogGenMode gen_mode, uint32_t fog_alpha) {
std::string ret;
{
char buf[8] = {0};
snprintf(buf, 7, "A%02X", fog_alpha);
ret = buf;
}
switch (fog_mode) {
case FOG_LINEAR:
ret += "-linear";
break;
case FOG_EXP:
ret += "-exp";
break;
case FOG_EXP2:
ret += "-exp2";
break;
case FOG_EXP_ABS:
ret += "-exp_abs";
break;
case FOG_EXP2_ABS:
ret += "-exp2_abs";
break;
case FOG_LINEAR_ABS:
ret += "-linear_abs";
break;
}
switch (gen_mode) {
case FOG_GEN_SPEC_ALPHA:
ret += "-spec_alpha";
break;
case FOG_GEN_RADIAL:
ret += "-radial";
break;
case FOG_GEN_PLANAR:
ret += "-planar";
break;
case FOG_GEN_ABS_PLANAR:
ret += "-abs_planar";
break;
case FOG_GEN_FOG_X:
ret += "-fog_x";
break;
}
return std::move(ret);
}

45
src/tests/fog_tests.h Normal file
View File

@ -0,0 +1,45 @@
#ifndef NXDK_PGRAPH_TESTS_FOG_TESTS_H
#define NXDK_PGRAPH_TESTS_FOG_TESTS_H
#include <memory>
#include <vector>
#include "test_host.h"
#include "test_suite.h"
#include "vertex_buffer.h"
class TestHost;
class VertexBuffer;
// Tests behavior of the Fog code.
class FogTests : public TestSuite {
public:
enum FogMode {
FOG_LINEAR = NV097_SET_FOG_MODE_V_LINEAR,
FOG_EXP = NV097_SET_FOG_MODE_V_EXP,
FOG_EXP2 = NV097_SET_FOG_MODE_V_EXP2,
FOG_EXP_ABS = NV097_SET_FOG_MODE_V_EXP_ABS,
FOG_EXP2_ABS = NV097_SET_FOG_MODE_V_EXP2_ABS,
FOG_LINEAR_ABS = NV097_SET_FOG_MODE_V_LINEAR_ABS,
};
enum FogGenMode {
FOG_GEN_SPEC_ALPHA = NV097_SET_FOG_GEN_MODE_V_SPEC_ALPHA,
FOG_GEN_RADIAL = NV097_SET_FOG_GEN_MODE_V_RADIAL,
FOG_GEN_PLANAR = NV097_SET_FOG_GEN_MODE_V_PLANAR,
FOG_GEN_ABS_PLANAR = NV097_SET_FOG_GEN_MODE_V_ABS_PLANAR,
FOG_GEN_FOG_X = NV097_SET_FOG_GEN_MODE_V_FOG_X,
};
public:
FogTests(TestHost& host, std::string output_dir);
void Initialize() override;
private:
void CreateGeometry();
void Test(FogMode fog_mode, FogGenMode gen_mode, uint32_t fog_alpha);
static std::string MakeTestName(FogMode fog_mode, FogGenMode gen_mode, uint32_t fog_alpha);
};
#endif // NXDK_PGRAPH_TESTS_FOG_TESTS_H

View File

@ -60,7 +60,7 @@ void TestSuite::Initialize() {
p = pb_push1(p, NV097_SET_FRONT_POLYGON_MODE, NV097_SET_FRONT_POLYGON_MODE_V_FILL);
p = pb_push1(p, NV097_SET_BACK_POLYGON_MODE, NV097_SET_FRONT_POLYGON_MODE_V_FILL);
p = pb_push1(p, NV097_SET_FOG_ENABLE, 0x0);
p = pb_push1(p, NV097_SET_FOG_ENABLE, false);
p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW0, 0xe);
p = pb_push1(p, NV097_SET_COMBINER_SPECULAR_FOG_CW1, 0x1c80);
@ -96,9 +96,9 @@ void TestSuite::Initialize() {
pb_push_to(SUBCH_3D, p++, NV097_SET_COMBINER_ALPHA_ICW, 8);
*(p++) = 0x14200000;
*(p++) = 0;
*(p++) = 0;
*(p++) = 0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
@ -106,9 +106,9 @@ void TestSuite::Initialize() {
pb_push_to(SUBCH_3D, p++, NV097_SET_COMBINER_ALPHA_OCW, 8);
*(p++) = 0xC00;
*(p++) = 0;
*(p++) = 0;
*(p++) = 0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;
*(p++) = 0x0;

View File

@ -2,9 +2,7 @@
#include <pbkit/pbkit.h>
#include "debug_output.h"
#include "pbkit_ext.h"
#include "shaders/precalculated_vertex_shader.h"
#include "test_host.h"
#include "vertex_buffer.h"
@ -400,23 +398,3 @@ std::string ThreeDPrimitiveTests::MakeTestName(TestHost::DrawPrimitive primitive
return std::move(ret);
}
static void CreateGeometry(TestHost& host, TestHost::DrawPrimitive primitive) {
float left = -2.75f;
float right = 2.75f;
float top = 1.75f;
float bottom = -1.75f;
float z = 1.0f;
VECTOR normal{0.0f, 0.0f, 1.0f, 1.0f};
std::shared_ptr<VertexBuffer> buffer = host.AllocateVertexBuffer(6);
buffer->DefineQuad(0, left, top, right, bottom);
// Point normals for half the quad away from the camera.
Vertex* v = buffer->Lock();
v[0].normal[2] = -1.0f;
v[1].normal[2] = -1.0f;
v[2].normal[2] = -1.0f;
buffer->Unlock();
}