459 lines
18 KiB
C++
459 lines
18 KiB
C++
#include "SceneColor.h"
|
|
#include "VoxelRenderFixtures.h"
|
|
|
|
TEST_CASE("voxel.render.emptyInstanceInputsAreNoOps") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 200, 150);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
Texture *white = makeSolid(gfx, 255, 255, 255);
|
|
REQUIRE(white != nullptr);
|
|
const uint32_t packed = PackedRect::pack(0, 0, 0, 1, 1, 0).bits;
|
|
const float aspect = float(std::max(1, gfx->getPixelWidth())) / float(std::max(1, gfx->getPixelHeight()));
|
|
const glm::mat4 vp = perspectiveVulkanRH_ZO(glm::radians(50.f), aspect, 0.1f, 100.f) *
|
|
glm::lookAtRH(glm::vec3(0.5f, 0.5f, 5.f), glm::vec3(0.5f, 0.5f, 1.f), glm::vec3(0, 1, 0));
|
|
struct EmptyInput {
|
|
const uint32_t *data;
|
|
int count;
|
|
const char *direction;
|
|
Texture *atlas;
|
|
};
|
|
const EmptyInput inputs[] = {{nullptr, 0, "posZ", nullptr},
|
|
{nullptr, 10, "posY", white},
|
|
{nullptr, 0, "posY", white},
|
|
{&packed, 0, "posZ", nullptr}};
|
|
const Color background(0.1f, 0.1f, 0.12f, 1.f);
|
|
// Compare against the actual cleared frame, including the backend's display transform.
|
|
gfx->setBackgroundColor(background);
|
|
gfx->begin3DFrame();
|
|
REQUIRE(gfx->had3DThisFrame());
|
|
RenderSystem::render(*gfx);
|
|
const Color cleared = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
for (const auto &input : inputs) {
|
|
std::printf("empty input null=%d count=%d face=%s atlas=%d\n", input.data == nullptr, input.count,
|
|
input.direction, input.atlas != nullptr);
|
|
gfx->setBackgroundColor(background);
|
|
gfx->begin3DFrame();
|
|
REQUIRE(gfx->had3DThisFrame());
|
|
gfx->setMesh3DViewProj(vp);
|
|
gfx->drawVoxelFaceInstances(input.data, input.count, 0.f, 0.f, 0.f, input.direction, input.atlas, 1);
|
|
RenderSystem::render(*gfx);
|
|
const Color empty = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
REQUIRE(std::fabs(empty.r - cleared.r) < 0.01f);
|
|
REQUIRE(std::fabs(empty.g - cleared.g) < 0.01f);
|
|
REQUIRE(std::fabs(empty.b - cleared.b) < 0.01f);
|
|
|
|
// A no-op must not prevent a subsequent valid draw in the same frame.
|
|
gfx->begin3DFrame();
|
|
REQUIRE(gfx->had3DThisFrame());
|
|
gfx->setMesh3DViewProj(vp);
|
|
gfx->drawVoxelFaceInstances(input.data, input.count, 0.f, 0.f, 0.f, input.direction, input.atlas, 1);
|
|
gfx->drawVoxelFaceInstances(&packed, 1, 0.f, 0.f, 0.f, "posZ", nullptr, 1);
|
|
RenderSystem::render(*gfx);
|
|
const Color drawn = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
REQUIRE(drawn.r > 0.2f);
|
|
REQUIRE(drawn.g > 0.2f);
|
|
REQUIRE(drawn.b > 0.2f);
|
|
}
|
|
win->close();
|
|
}
|
|
|
|
TEST_CASE("voxel.render.multiBatchSameFrame") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 320, 240);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
std::unique_ptr<VoxelWorld> world(new VoxelWorld());
|
|
// Two separated pillars → multiple face batches.
|
|
for (int y = 0; y < 6; ++y) {
|
|
world->setVoxel(2, y, 2, 1);
|
|
world->setVoxel(10, y, 10, 1);
|
|
}
|
|
world->remeshDirty();
|
|
Texture *atlas = makeSolid(gfx, 180, 170, 90);
|
|
|
|
const glm::vec3 eye(6.f, 8.f, 22.f);
|
|
const glm::vec3 target(6.f, 3.f, 6.f);
|
|
renderVoxelFrame(gfx, world.get(), atlas, 1, eye, target, 200.f, true);
|
|
CHECK(world->getVisibleBatchCount() >= 2);
|
|
CHECK(world->getVisibleRectCount() >= 2);
|
|
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
CHECK(luma(mid) > 0.05f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.drawVisibleMatchesManualBatches") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 240, 180);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
std::unique_ptr<VoxelWorld> world(new VoxelWorld());
|
|
for (int z = 0; z < 3; ++z)
|
|
for (int y = 0; y < 3; ++y)
|
|
for (int x = 0; x < 3; ++x) world->setVoxel(x, y, z, 1);
|
|
world->remeshDirty();
|
|
Texture *atlas = makeSolid(gfx, 90, 140, 220);
|
|
|
|
const float aspect = float(std::max(1, gfx->getPixelWidth())) / float(std::max(1, gfx->getPixelHeight()));
|
|
const glm::vec3 eye(1.5f, 1.5f, 10.f);
|
|
const glm::vec3 target(1.5f, 1.5f, 1.5f);
|
|
const glm::mat4 view = glm::lookAtRH(eye, target, glm::vec3(0, 1, 0));
|
|
const glm::mat4 proj = perspectiveVulkanRH_ZO(glm::radians(50.f), aspect, 0.1f, 200.f);
|
|
const glm::mat4 vp = proj * view;
|
|
|
|
world->selectVisible(&vp[0][0], eye.x, eye.y, eye.z, 200.f, true);
|
|
const int batches = world->getVisibleBatchCount();
|
|
REQUIRE(batches > 0);
|
|
|
|
gfx->setBackgroundColor(Color(0.05f, 0.06f, 0.08f, 1.f));
|
|
gfx->begin3DFrame();
|
|
if (gfx->had3DThisFrame()) {
|
|
gfx->setMesh3DViewProj(vp);
|
|
gfx->setMesh3DCameraPos(eye);
|
|
for (int i = 0; i < batches; ++i) {
|
|
const DrawBatch &b = world->getVisibleBatch(i);
|
|
gfx->drawVoxelFaceInstances(b.packed, b.count, b.chunk->originX(), b.chunk->originY(), b.chunk->originZ(),
|
|
faceDirName(b.dir), atlas, 1);
|
|
}
|
|
}
|
|
RenderSystem::render(*gfx);
|
|
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
CHECK(luma(mid) > 0.06f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.requiresBegin3DFrame") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 160, 120);
|
|
|
|
uint32_t dummy = PackedRect::pack(0, 0, 0, 1, 1, 1).bits;
|
|
bool threw = false;
|
|
try {
|
|
gfx->drawVoxelFaceInstances(&dummy, 1, 0.f, 0.f, 0.f, "posZ", nullptr, 1);
|
|
} catch (...) {
|
|
threw = true;
|
|
}
|
|
CHECK(threw);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.largeInstanceCount") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 320, 240);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
// Many non-merged top faces: sparse pillars.
|
|
std::unique_ptr<VoxelWorld> world(new VoxelWorld());
|
|
for (int z = 0; z < 16; ++z)
|
|
for (int x = 0; x < 16; ++x)
|
|
if (((x * 3 + z * 5) % 7) == 0) world->setVoxel(x, 0, z, 1);
|
|
world->remeshDirty();
|
|
CHECK(world->getOrCreateChunk(0, 0, 0)->totalRectCount() > 20);
|
|
|
|
Texture *atlas = makeSolid(gfx, 200, 180, 60);
|
|
const glm::vec3 eye(8.f, 10.f, 28.f);
|
|
const glm::vec3 target(8.f, 0.f, 8.f);
|
|
renderVoxelFrame(gfx, world.get(), atlas, 1, eye, target, 200.f, true);
|
|
CHECK(world->getVisibleRectCount() > 10);
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
CHECK(luma(mid) > 0.04f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.multiFrameSlotReuse") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 240, 180);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
std::unique_ptr<VoxelWorld> world(new VoxelWorld());
|
|
world->setVoxel(0, 0, 0, 1);
|
|
world->remeshDirty();
|
|
Texture *atlas = makeSolid(gfx, 160, 160, 200);
|
|
const glm::vec3 eye(0.5f, 0.5f, 5.f);
|
|
const glm::vec3 target(0.5f, 0.5f, 0.5f);
|
|
|
|
for (int frame = 0; frame < 6; ++frame) {
|
|
renderVoxelFrame(gfx, world.get(), atlas, 1, eye, target, 100.f, true);
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
CHECK(luma(mid) > 0.04f);
|
|
}
|
|
}
|
|
|
|
TEST_CASE("voxel.render.editRemeshChangesPixels") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 320, 240);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
std::unique_ptr<VoxelWorld> world(new VoxelWorld());
|
|
Texture *atlas = makeSolid(gfx, 230, 230, 240);
|
|
const glm::vec3 eye(4.f, 4.f, 18.f);
|
|
const glm::vec3 target(4.f, 4.f, 4.f);
|
|
|
|
// Empty world → dark
|
|
world->remeshDirty();
|
|
renderVoxelFrame(gfx, world.get(), atlas, 1, eye, target, 200.f, true);
|
|
REQUIRE_EQ(world->getVisibleRectCount(), 0);
|
|
Color empty = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
REQUIRE(luma(testSceneLinearColor(empty)) < 0.2f);
|
|
|
|
for (int z = 0; z < 8; ++z)
|
|
for (int y = 0; y < 8; ++y)
|
|
for (int x = 0; x < 8; ++x) world->setVoxel(x, y, z, 1);
|
|
world->remeshDirty();
|
|
renderVoxelFrame(gfx, world.get(), atlas, 1, eye, target, 200.f, true);
|
|
Color filled = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
REQUIRE(luma(filled) > luma(empty) + 0.03f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.emptyWorldDrawVisible") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 200, 150);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
std::unique_ptr<VoxelWorld> world(new VoxelWorld());
|
|
Texture *atlas = makeSolid(gfx, 255, 255, 255);
|
|
const glm::vec3 eye(0.f, 0.f, 5.f);
|
|
const glm::vec3 target(0.f, 0.f, 0.f);
|
|
renderVoxelFrame(gfx, world.get(), atlas, 1, eye, target, 100.f, true);
|
|
REQUIRE_EQ(world->getVisibleBatchCount(), 0);
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
REQUIRE(luma(testSceneLinearColor(mid)) < 0.25f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.manyChunksBatched") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 320, 240);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
std::unique_ptr<VoxelWorld> world(new VoxelWorld());
|
|
for (int cx = 0; cx < 3; ++cx)
|
|
for (int cz = 0; cz < 3; ++cz) {
|
|
for (int y = 0; y < 2; ++y)
|
|
for (int x = 0; x < 2; ++x)
|
|
for (int z = 0; z < 2; ++z) world->setVoxel(cx * 32 + x + 8, y, cz * 32 + z + 8, 1);
|
|
}
|
|
world->remeshDirty();
|
|
CHECK_EQ(world->getChunkCount(), 9);
|
|
|
|
Texture *atlas = makeSolid(gfx, 120, 160, 200);
|
|
const glm::vec3 eye(48.f, 20.f, 120.f);
|
|
const glm::vec3 target(48.f, 1.f, 48.f);
|
|
renderVoxelFrame(gfx, world.get(), atlas, 1, eye, target, 300.f, true);
|
|
CHECK(world->getVisibleChunkCount() >= 3);
|
|
CHECK(world->getVisibleBatchCount() >= 3);
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
CHECK(luma(mid) > 0.04f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.instanceCountGrowth") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 240, 180);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
Texture *atlas = makeSolid(gfx, 200, 200, 210);
|
|
const float aspect = float(std::max(1, gfx->getPixelWidth())) / float(std::max(1, gfx->getPixelHeight()));
|
|
const glm::vec3 eye(8.f, 8.f, 40.f);
|
|
const glm::mat4 view = glm::lookAtRH(eye, glm::vec3(8.f, 0.f, 8.f), glm::vec3(0, 1, 0));
|
|
const glm::mat4 proj = perspectiveVulkanRH_ZO(glm::radians(50.f), aspect, 0.1f, 200.f);
|
|
const glm::mat4 vp = proj * view;
|
|
|
|
// Grow instance buffer across draws in one frame: 1, then many.
|
|
std::vector<uint32_t> many;
|
|
many.reserve(64);
|
|
for (int z = 0; z < 8; ++z)
|
|
for (int x = 0; x < 8; ++x) many.push_back(PackedRect::pack(x, 0, z, 1, 1, 1).bits);
|
|
|
|
gfx->setBackgroundColor(Color(0.05f, 0.06f, 0.08f, 1.f));
|
|
gfx->begin3DFrame();
|
|
if (gfx->had3DThisFrame()) {
|
|
gfx->setMesh3DViewProj(vp);
|
|
uint32_t one = many[0];
|
|
gfx->drawVoxelFaceInstances(&one, 1, 0.f, 0.f, 0.f, "posY", atlas, 1);
|
|
gfx->drawVoxelFaceInstances(many.data(), int(many.size()), 0.f, 0.f, 0.f, "posY", atlas, 1);
|
|
}
|
|
RenderSystem::render(*gfx);
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
CHECK(luma(mid) > 0.04f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.twoOriginsSameFrame") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 320, 240);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
uint32_t a = PackedRect::pack(0, 0, 0, 2, 2, 1).bits;
|
|
uint32_t b = PackedRect::pack(0, 0, 0, 2, 2, 1).bits;
|
|
Texture *atlas = makeSolid(gfx, 90, 200, 120);
|
|
|
|
const float aspect = float(std::max(1, gfx->getPixelWidth())) / float(std::max(1, gfx->getPixelHeight()));
|
|
const glm::vec3 eye(4.f, 4.f, 20.f);
|
|
const glm::mat4 view = glm::lookAtRH(eye, glm::vec3(4.f, 1.f, 4.f), glm::vec3(0, 1, 0));
|
|
const glm::mat4 proj = perspectiveVulkanRH_ZO(glm::radians(50.f), aspect, 0.1f, 100.f);
|
|
const glm::mat4 vp = proj * view;
|
|
|
|
gfx->setBackgroundColor(Color(0.05f, 0.06f, 0.08f, 1.f));
|
|
gfx->begin3DFrame();
|
|
if (gfx->had3DThisFrame()) {
|
|
gfx->setMesh3DViewProj(vp);
|
|
gfx->drawVoxelFaceInstances(&a, 1, 0.f, 0.f, 0.f, "posY", atlas, 1);
|
|
gfx->drawVoxelFaceInstances(&b, 1, 6.f, 0.f, 6.f, "posY", atlas, 1);
|
|
}
|
|
RenderSystem::render(*gfx);
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
CHECK(luma(mid) > 0.04f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.removeVoxelsDarkens") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 320, 240);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
std::unique_ptr<VoxelWorld> world(new VoxelWorld());
|
|
for (int z = 0; z < 6; ++z)
|
|
for (int y = 0; y < 6; ++y)
|
|
for (int x = 0; x < 6; ++x) world->setVoxel(x, y, z, 1);
|
|
world->remeshDirty();
|
|
Texture *atlas = makeSolid(gfx, 240, 240, 250);
|
|
const glm::vec3 eye(3.f, 3.f, 16.f);
|
|
const glm::vec3 target(3.f, 3.f, 3.f);
|
|
|
|
renderVoxelFrame(gfx, world.get(), atlas, 1, eye, target, 100.f, true);
|
|
Color filled = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
REQUIRE(luma(filled) > 0.08f);
|
|
|
|
world->clear();
|
|
world->remeshDirty();
|
|
renderVoxelFrame(gfx, world.get(), atlas, 1, eye, target, 100.f, true);
|
|
Color empty = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
REQUIRE(luma(empty) < luma(filled));
|
|
REQUIRE(luma(testSceneLinearColor(empty)) < 0.22f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.stressHundredsOfInstances") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 320, 240);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
std::vector<uint32_t> many;
|
|
many.reserve(256);
|
|
for (int z = 0; z < 16; ++z)
|
|
for (int x = 0; x < 16; ++x) many.push_back(PackedRect::pack(x, 0, z, 1, 1, 1).bits);
|
|
CHECK_EQ(int(many.size()), 256);
|
|
|
|
Texture *atlas = makeSolid(gfx, 180, 190, 200);
|
|
const float aspect = float(std::max(1, gfx->getPixelWidth())) / float(std::max(1, gfx->getPixelHeight()));
|
|
const glm::vec3 eye(8.f, 12.f, 30.f);
|
|
const glm::mat4 view = glm::lookAtRH(eye, glm::vec3(8.f, 0.f, 8.f), glm::vec3(0, 1, 0));
|
|
const glm::mat4 proj = perspectiveVulkanRH_ZO(glm::radians(50.f), aspect, 0.1f, 200.f);
|
|
const glm::mat4 vp = proj * view;
|
|
|
|
gfx->setBackgroundColor(Color(0.05f, 0.06f, 0.08f, 1.f));
|
|
gfx->begin3DFrame();
|
|
if (gfx->had3DThisFrame()) {
|
|
gfx->setMesh3DViewProj(vp);
|
|
gfx->drawVoxelFaceInstances(many.data(), int(many.size()), 0.f, 0.f, 0.f, "posY", atlas, 1);
|
|
}
|
|
RenderSystem::render(*gfx);
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
CHECK(luma(mid) > 0.04f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.manualAllSixDirsOneFrame") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 320, 240);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
uint32_t packed = PackedRect::pack(0, 0, 0, 2, 2, 1).bits;
|
|
Texture *atlas = makeSolid(gfx, 220, 220, 40);
|
|
const float aspect = float(std::max(1, gfx->getPixelWidth())) / float(std::max(1, gfx->getPixelHeight()));
|
|
// Orbit-ish view so several faces of a unit cube-ish placement are on screen.
|
|
const glm::vec3 eye(8.f, 8.f, 8.f);
|
|
const glm::mat4 view = glm::lookAtRH(eye, glm::vec3(1.f, 1.f, 1.f), glm::vec3(0, 1, 0));
|
|
const glm::mat4 proj = perspectiveVulkanRH_ZO(glm::radians(55.f), aspect, 0.1f, 100.f);
|
|
const glm::mat4 vp = proj * view;
|
|
|
|
const char *dirs[6] = {"posX", "negX", "posY", "negY", "posZ", "negZ"};
|
|
gfx->setBackgroundColor(Color(0.05f, 0.06f, 0.08f, 1.f));
|
|
gfx->begin3DFrame();
|
|
if (gfx->had3DThisFrame()) {
|
|
gfx->setMesh3DViewProj(vp);
|
|
for (const char *d : dirs) gfx->drawVoxelFaceInstances(&packed, 1, 0.f, 0.f, 0.f, d, atlas, 1);
|
|
}
|
|
RenderSystem::render(*gfx);
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
CHECK(luma(mid) > 0.03f);
|
|
}
|
|
|
|
TEST_CASE("voxel.render.remeshIncreasesThenDecreasesRects") {
|
|
hideLeftover3D();
|
|
eve::window::Window *win = nullptr;
|
|
Graphics *gfx = nullptr;
|
|
openGfxWindow(win, gfx, 300, 220);
|
|
tinyHud(gfx);
|
|
gfx->setScreenReadbackEnabled(true);
|
|
|
|
std::unique_ptr<VoxelWorld> world(new VoxelWorld());
|
|
world->setVoxel(2, 2, 2, 1);
|
|
world->remeshDirty();
|
|
const int one = world->getChunk(0, 0, 0)->totalRectCount();
|
|
CHECK_EQ(one, 6);
|
|
|
|
fillCube(world.get(), 0, 0, 0, 5, 1);
|
|
world->remeshDirty();
|
|
const int many = world->getChunk(0, 0, 0)->totalRectCount();
|
|
CHECK(many < one * 5); // greedy merges
|
|
CHECK(many >= 6);
|
|
|
|
Texture *atlas = makeSolid(gfx, 200, 200, 210);
|
|
renderVoxelFrame(gfx, world.get(), atlas, 1, glm::vec3(2.5f, 2.5f, 14.f), glm::vec3(2.5f, 2.5f, 2.5f), 100.f, true);
|
|
Color mid = gfx->getPixel(gfx->getWidth() / 2, gfx->getHeight() / 2);
|
|
CHECK(luma(mid) > 0.05f);
|
|
|
|
world->clear();
|
|
world->setVoxel(2, 2, 2, 1);
|
|
world->remeshDirty();
|
|
CHECK_EQ(world->getChunk(0, 0, 0)->totalRectCount(), 6);
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Large visual scenes (PNG under test/out/voxel_scenes/)
|
|
// ---------------------------------------------------------------------------
|