Optimization du renderer.

This commit is contained in:
MarcEricMartel 2021-12-03 11:49:59 -05:00
parent 033f69465c
commit ecddc82e7b
13 changed files with 158 additions and 117 deletions

View File

@ -12,6 +12,7 @@ class Array2d {
void Set(int x, int y, T type); void Set(int x, int y, T type);
T Get(int x, int y) const; T Get(int x, int y) const;
T Remove(int x, int y);
void Reset(T type); void Reset(T type);
@ -41,6 +42,13 @@ void Array2d<T>::Set(int x, int y, T type) { m_array[To1dIndex(x, y)] = type; }
template <class T> template <class T>
T Array2d<T>::Get(int x, int y) const { return m_array[To1dIndex(x, y)]; } T Array2d<T>::Get(int x, int y) const { return m_array[To1dIndex(x, y)]; }
template <class T>
T Array2d<T>::Remove(int x, int y) {
T thing = std::move(m_array[To1dIndex(x, y)]);
m_array[To1dIndex(x, y)] = nullptr;
return thing;
}
template <class T> template <class T>
void Array2d<T>::Reset(T type) { void Array2d<T>::Reset(T type) {
for (int i = 0; i < m_x * m_y; ++i) for (int i = 0; i < m_x * m_y; ++i)

View File

@ -47,7 +47,7 @@ private:
TextureAtlas m_textureAtlas = TextureAtlas(BTYPE_LAST); TextureAtlas m_textureAtlas = TextureAtlas(BTYPE_LAST);
World m_world = World(); World m_world = World();
Perlin m_perlin = Perlin(3,7.f,127.f,12345); Perlin m_perlin = Perlin(4,32.f,7.f,12345);
Texture m_textureSkybox; Texture m_textureSkybox;
Texture m_textureFont; Texture m_textureFont;

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -158,7 +158,7 @@ Vector3f Player::GetPOV() const { return Vector3f(GetPosition().x, m_POV, GetPos
Vector3f Player::GetDirection() const { return m_direction; } Vector3f Player::GetDirection() const { return m_direction; }
void Player::Transpose(int& x, int& z) { void Player::Teleport(int& x, int& z) {
m_position.x -= x * CHUNK_SIZE_X; m_position.x -= x * CHUNK_SIZE_X;
m_position.z -= z * CHUNK_SIZE_Z; m_position.z -= z * CHUNK_SIZE_Z;
} }

View File

@ -19,7 +19,7 @@ public:
Vector3f GetDirection() const; Vector3f GetDirection() const;
Vector3f GetVelocity() const; Vector3f GetVelocity() const;
Vector3f GetPOV() const; Vector3f GetPOV() const;
void Transpose(int& x, int& z); void Teleport(int& x, int& z);
private: private:
Vector3f m_position; Vector3f m_position;

View File

@ -1,102 +1,105 @@
#include "world.h" #include "world.h"
World::World(){} World::World() {}
World::~World(){} World::~World() {}
Array2d<Chunk*>& World::GetChunks() { return m_chunks; } Array2d<Chunk*>& World::GetChunks() { return m_chunks; }
Chunk* World::ChunkAt(float x, float y, float z) const { Chunk* World::ChunkAt(float x, float y, float z) const {
int cx = (int)x / CHUNK_SIZE_X; int cx = (int)x / CHUNK_SIZE_X;
int cz = (int)z / CHUNK_SIZE_Z; int cz = (int)z / CHUNK_SIZE_Z;
if (x < 0 || y < 0 || z < 0 || if (x < 0 || y < 0 || z < 0 ||
x >= WORLD_SIZE_X * CHUNK_SIZE_X || x >= WORLD_SIZE_X * CHUNK_SIZE_X ||
z >= CHUNK_SIZE_Z * WORLD_SIZE_Y || z >= CHUNK_SIZE_Z * WORLD_SIZE_Y ||
y > CHUNK_SIZE_Y) y > CHUNK_SIZE_Y)
return 0; return 0;
return m_chunks.Get(cx, cz); return m_chunks.Get(cx, cz);
} }
Chunk* World::ChunkAt(const Vector3f& pos) const { return ChunkAt(pos.x, pos.y, pos.z); } Chunk* World::ChunkAt(const Vector3f& pos) const { return ChunkAt(pos.x, pos.y, pos.z); }
BlockType World::BlockAt(float x, float y, float z, BlockType defaultBlockType) const { BlockType World::BlockAt(float x, float y, float z, BlockType defaultBlockType) const {
Chunk* c = ChunkAt(x, y, z); Chunk* c = ChunkAt(x, y, z);
if (!c) if (!c)
return defaultBlockType; return defaultBlockType;
int bx = (int)x % CHUNK_SIZE_X; int bx = (int)x % CHUNK_SIZE_X;
int by = (int)y % CHUNK_SIZE_Y; int by = (int)y % CHUNK_SIZE_Y;
int bz = (int)z % CHUNK_SIZE_Z; int bz = (int)z % CHUNK_SIZE_Z;
return c->GetBlock(bx, by, bz); return c->GetBlock(bx, by, bz);
} }
BlockType World::BlockAt(const Vector3f& pos, BlockType defaultBlockType) const { BlockType World::BlockAt(const Vector3f& pos, BlockType defaultBlockType) const {
return BlockAt(pos.x, pos.y, pos.z, defaultBlockType); return BlockAt(pos.x, pos.y, pos.z, defaultBlockType);
} }
void World::TransposeWorld(Player& player) { void World::TransposeWorld(Player& player) {
int x = 0; int x = 0;
int y = 0; int y = 0;
if (player.GetPosition().x > (WORLD_SIZE_X * CHUNK_SIZE_X) * .66f) ++x; if (player.GetPosition().x > (WORLD_SIZE_X * CHUNK_SIZE_X) * .66f) ++x;
else if (player.GetPosition().x < (WORLD_SIZE_X * CHUNK_SIZE_X) * .33f) --x; else if (player.GetPosition().x < (WORLD_SIZE_X * CHUNK_SIZE_X) * .33f) --x;
if (player.GetPosition().z > (WORLD_SIZE_Y * CHUNK_SIZE_Z) * .66f) ++y; if (player.GetPosition().z > (WORLD_SIZE_Y * CHUNK_SIZE_Z) * .66f) ++y;
else if (player.GetPosition().z < (WORLD_SIZE_Y * CHUNK_SIZE_Z) * .33f) --y; else if (player.GetPosition().z < (WORLD_SIZE_Y * CHUNK_SIZE_Z) * .33f) --y;
if (!x && !y) return; if (!x && !y) return;
if (x != 0) if (x > 0) {
for (int ay = 0; ay < WORLD_SIZE_Y; ++ay) for (int ax = 0; ax < WORLD_SIZE_X; ++ax)
for (int ax = 0; ax < abs(x); ++ay) for (int ay = 0; ay < WORLD_SIZE_Y; ++ay)
if (ChunkAt(x < 0 ? (WORLD_SIZE_X - 1 - ax) * WORLD_SIZE_X : ax, 1, ay * WORLD_SIZE_Y)) if (ax - x >= 0)
m_tbDeleted.push_back(std::move(m_chunks.Get(x < 0? WORLD_SIZE_X - 1 - ax: ax, ay))); m_chunks.Set(ax - x, ay,
if (y != 0) m_chunks.Remove(ax, ay));
for (int ax = 0; ax < WORLD_SIZE_X; ++ax) else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay));
for (int ay = 0; ay < abs(y); ++ay) }
if (ChunkAt(ax * WORLD_SIZE_X , 1, y < 0 ? (WORLD_SIZE_Y - 1 - ay) * WORLD_SIZE_Y : ay)) else if (x < 0) {
m_tbDeleted.push_back(std::move(m_chunks.Get(ax, y < 0 ? WORLD_SIZE_Y - 1 - ay: ay))); for (int ax = WORLD_SIZE_X - 1; ax >= 0; --ax)
for (int ay = WORLD_SIZE_Y - 1; ay >= 0; --ay)
for (int ax = 0; ax < WORLD_SIZE_X; ++ax) if (ax - x < WORLD_SIZE_X)
for (int ay = 0; ay < WORLD_SIZE_Y; ++ay) m_chunks.Set(ax - x, ay,
if (ax + x < WORLD_SIZE_X && ax + x > 0 && m_chunks.Remove(ax, ay));
ay + y < WORLD_SIZE_Y && ay + y > 0) else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay));
m_chunks.Set(x > 0? ax: ax + x, y > 0? ay: ay + y, }
m_chunks.Get(x < 0 ? ax : ax + x, y < 0 ? ay : ay + y));
if (x != 0) if (y > 0) {
for (int ay = 0; ay < WORLD_SIZE_Y; ++ay) for (int ax = 0; ax < WORLD_SIZE_X; ++ax)
for (int ax = 0; ax < abs(x); ++ay) for (int ay = 0; ay < WORLD_SIZE_Y; ++ay)
m_chunks.Set(x > 0 ? WORLD_SIZE_X - 1 - ax : ax, ay, nullptr); if (ay - y >= 0)
if (y != 0) m_chunks.Set(ax, ay - y,
for (int ax = 0; ax < WORLD_SIZE_X; ++ax) m_chunks.Remove(ax, ay));
for (int ay = 0; ay < abs(y); ++ay) else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay));
m_chunks.Set(ax, y > 0 ? WORLD_SIZE_Y - 1 - ay : ay, nullptr); }
else if (y < 0) {
m_center[0] += x; m_center[1] += y; for (int ax = WORLD_SIZE_X - 1; ax >= 0; --ax)
player.Transpose(x, y); for (int ay = WORLD_SIZE_Y - 1; ay >= 0; --ay)
if (ay - y < WORLD_SIZE_Y)
m_chunks.Set(ax, ay - y,
m_chunks.Remove(ax, ay));
else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay));
}
m_center[0] += x; m_center[1] += y;
player.Teleport(x, y);
} }
void World::CleanUpWorld(int& deleteframes, bool clear = false) { void World::CleanUpWorld(int& deleteframes, bool clear = false) {
if (clear) m_tbDeleted.clear(); if (clear) {
if (!m_tbDeleted.empty() && !deleteframes) { while (m_tbDeleted.size() > 0) {
m_tbDeleted.pop_back(); delete m_tbDeleted.back();
deleteframes = FRAMES_DELETE_CHUNKS; m_tbDeleted.pop_back();
} }
} }
if (!m_tbDeleted.empty() && !deleteframes) {
Chunk* World::RetrieveChunk(int x, int y) { delete m_tbDeleted.back();
for (int index = 0; index < m_tbDeleted.size(); ++index) { m_tbDeleted.pop_back();
int cx, cy; deleteframes = FRAMES_DELETE_CHUNKS;
m_tbDeleted.at(index)->GetPosition(cx, cy); }
std::cout << "Chunk Write Buffer: " << m_tbDeleted.size() << std::endl;
if (cx == x && cy == y)
return std::move(m_tbDeleted.at(index));
}
return nullptr;
} }
void World::GetScope(int& x, int& y) { void World::GetScope(int& x, int& y) {
@ -106,25 +109,29 @@ void World::GetScope(int& x, int& y) {
void World::Update(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) { void World::Update(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader, TextureAtlas& atlas, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]) {
atlas.Bind(); atlas.Bind();
TransposeWorld(player);
RenderWorld(rendercount, badhitcount, player, world, shader); RenderWorld(rendercount, badhitcount, player, world, shader);
TransposeWorld(player);
UpdateWorld(player, perlin, blockinfo); UpdateWorld(player, perlin, blockinfo);
shader.Disable(); shader.Disable();
} }
bool World::GenerateChunk(int chx, int chy, Perlin& perlin) { bool World::GenerateChunk(int chx, int chy, Perlin& perlin) {
if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z && if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z &&
chx >= 0 && chy >= 0) chx >= 0 && chy >= 0)
if (!ChunkAt(chx, 1, chy)) { if (!ChunkAt(chx, 1, chy)) {
for (int index = 0; index < m_tbDeleted.size(); ++index) { // Vérifie l'existence d'un chunk dans le buffer de suppression avec sa position. for (int index = 0; index < m_tbDeleted.size(); ++index) { // Vérifie l'existence d'un chunk dans le buffer de suppression avec sa position.
int x, y; int x, y;
m_tbDeleted.at(index)->GetPosition(x, y);
if (chx / CHUNK_SIZE_X + m_center[0] == x && if (&m_tbDeleted.at(index)) {
m_tbDeleted.at(index)->GetPosition(x, y);
if (chx / CHUNK_SIZE_X + m_center[0] == x &&
chy / CHUNK_SIZE_Z + m_center[1] == y) { chy / CHUNK_SIZE_Z + m_center[1] == y) {
GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, std::move(m_tbDeleted.at(index))); GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, std::move(m_tbDeleted.at(index)));
return true; return true;
} }
}
} }
std::ostringstream pos; // Vérifie l'existence d'un fichier .chunk avec sa position. std::ostringstream pos; // Vérifie l'existence d'un fichier .chunk avec sa position.
@ -138,24 +145,20 @@ bool World::GenerateChunk(int chx, int chy, Perlin& perlin) {
for (int x = 0; x < CHUNK_SIZE_X; ++x) for (int x = 0; x < CHUNK_SIZE_X; ++x)
for (int z = 0; z < CHUNK_SIZE_Z; ++z) { for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
Vector3f noise; float xnoiz, ynoiz;
noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]); xnoiz = (double)(x + (chx / CHUNK_SIZE_X + m_center[0]) * CHUNK_SIZE_X) / (double)INT16_MAX;
noise.y = 0; ynoiz = (double)(z + (chy / CHUNK_SIZE_Z + m_center[1]) * CHUNK_SIZE_Z) / (double)INT16_MAX;
noise.z = z * (CHUNK_SIZE_Z + 1) + (CHUNK_SIZE_Z - 1) * (chy + m_center[1]); float height = (perlin.Get(xnoiz, ynoiz)) * 10.f;
noise.Normalize(); for (int y = 0; y <= (int)height; ++y)
float height = perlin.Get(noise.x, noise.z) * 3 - 32;
for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y)
chunk->SetBlock(x, y, z, BTYPE_METAL, this); chunk->SetBlock(x, y, z, BTYPE_METAL, this);
} }
for (int x = 0; x < CHUNK_SIZE_X; ++x) for (int x = 0; x < CHUNK_SIZE_X; ++x)
for (int z = 0; z < CHUNK_SIZE_Z; ++z) { for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
Vector3f noise; float xnoiz, ynoiz;
noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]); xnoiz = (double)(x + (chx / CHUNK_SIZE_X + m_center[0]) * CHUNK_SIZE_X) / (double)INT16_MAX;
noise.y = 0; ynoiz = (double)(z + (chy / CHUNK_SIZE_Z + m_center[1]) * CHUNK_SIZE_Z) / (double)INT16_MAX;
noise.z = z * (CHUNK_SIZE_Z + 1) + (CHUNK_SIZE_Z - 1) * (chy + m_center[1]); float height = (perlin.Get(xnoiz, ynoiz) + 16.f);
noise.Normalize();
float height = perlin.Get(noise.x, noise.z) + 16;
for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y) { for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y) {
if (chunk->GetBlock(x, y, z) == BTYPE_AIR) if (chunk->GetBlock(x, y, z) == BTYPE_AIR)
chunk->SetBlock(x, y, z, BTYPE_GRASS, this); chunk->SetBlock(x, y, z, BTYPE_GRASS, this);
@ -164,25 +167,12 @@ bool World::GenerateChunk(int chx, int chy, Perlin& perlin) {
for (int x = 0; x < CHUNK_SIZE_X; ++x) for (int x = 0; x < CHUNK_SIZE_X; ++x)
for (int z = 0; z < CHUNK_SIZE_Z; ++z) { for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
for (int y = 0; y <= 10; ++y) { for (int y = 0; y < 15; ++y) {
if (chunk->GetBlock(x, y, z) == BTYPE_AIR) if (chunk->GetBlock(x, y, z) == BTYPE_AIR)
chunk->SetBlock(x, y, z, BTYPE_ICE, this); chunk->SetBlock(x, y, z, BTYPE_ICE, this);
} }
} }
for (int x = 0; x < CHUNK_SIZE_X; ++x)
for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
for (int y = 0; y < CHUNK_SIZE_Y; ++y) {
Vector3f noise;
noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]);
noise.y = (x + z) * CHUNK_SIZE_Y + m_center[0];
noise.z = z * (CHUNK_SIZE_Z + 1) + (CHUNK_SIZE_Z - 1) * (chy + m_center[1]);
noise.Normalize();
float height = perlin.Get(noise.x, noise.y, noise.z);
if (chunk->GetBlock(x, y, z) != BTYPE_AIR && height > 18)
chunk->SetBlock(x, y, z, BTYPE_DIRT, this);
}
}
} }
else { else {
input.seekg(0, std::ios_base::end); input.seekg(0, std::ios_base::end);
@ -197,7 +187,6 @@ bool World::GenerateChunk(int chx, int chy, Perlin& perlin) {
delete[] data; delete[] data;
} }
std::cout << "Chunk generated: " << chx / CHUNK_SIZE_X + m_center[0] << ", " << chy / CHUNK_SIZE_Z + m_center[1] << std::endl;
return true; return true;
} }
@ -274,7 +263,7 @@ void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Tran
shader.Use(); shader.Use();
rendercount = 0; rendercount = 0;
badhitcount = 0; badhitcount = 0;
static std::vector<Vector3i> renderManifest; //static std::vector<Vector3i> renderManifest;
Vector3f angle; Vector3f angle;
Vector3f cursor; Vector3f cursor;
Vector3f direct = player.GetDirection(); Vector3f direct = player.GetDirection();
@ -283,18 +272,61 @@ void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Tran
direct.y = 0; direct.y = 0;
direct.Normalize(); direct.Normalize();
pos.y = 1; pos.y = 1;
renderManifest.clear(); //renderManifest.clear();
static Vector3i renderManifest[VIEW_DISTANCE * 4];
for (int dist = VIEW_DISTANCE; dist >= 0; dist -= CHUNK_SIZE_X) { for (int dist = VIEW_DISTANCE; dist >= 0; dist -= CHUNK_SIZE_X) {
// Configuration du radar. // Configuration du radar.
angle.x = direct.z + direct.x; float sinus, cosinus;
angle.y = 0; int echantillons;
angle.z = direct.z - direct.x;
angle.Normalize();
float sinus = .01745240643; // sin(1 degré) if (dist > VIEW_DISTANCE * .375f) {
float cosinus = .99984769515; // cos(1 degré) angle.x = direct.z + direct.x;
int echantillons = 90; angle.z = direct.z - direct.x;
sinus = .01745240643; // sin(1 degré)
cosinus = .99984769515; // cos(1 degré)
echantillons = 90;
}
else if (dist > VIEW_DISTANCE * .5f) {
angle.x = direct.z + direct.x;
angle.z = direct.z - direct.x;
sinus = .0261769483;
cosinus = .99965732497;
echantillons = 60;
}
else if (dist > VIEW_DISTANCE * .625f) {
angle.x = direct.z + direct.x;
angle.z = direct.z - direct.x;
sinus = .0348994967;
cosinus = .99939082701;
echantillons = 45;
}
else /*if (dist > VIEW_DISTANCE * .75f)*/ {
angle.x = direct.z + direct.x;
angle.z = direct.z - direct.x;
sinus = .05233595624;
cosinus = .99862953475;
echantillons = 30;
}
//else if (dist > VIEW_DISTANCE * .875f) { // - CHUNK_SIZE_X * 28) {
// angle.x = direct.z;
// angle.z = -direct.x;
// sinus = .08715574274;
// cosinus = .996194698091;
// echantillons = 36;
// //echantillons = 0;
//}
//else {
// angle.x = direct.z;
// angle.z = -direct.x;
// sinus = .13052619222;
// cosinus = .99144486137;
// echantillons = 24;
//}
angle.y = 0;
angle.Normalize();
for (int radar = 0; radar < echantillons; ++radar) { for (int radar = 0; radar < echantillons; ++radar) {
float x = angle.x; float x = angle.x;
@ -312,7 +344,7 @@ void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Tran
if (ChunkAt(cursor)) { if (ChunkAt(cursor)) {
int chx, chy; int chx, chy;
ChunkAt(cursor)->GetPosition(chx, chy); ChunkAt(cursor)->GetPosition(chx, chy);
for (int index = 0; index < renderManifest.size(); ++index) for (int index = 0; index < rendercount; ++index)
if (renderManifest[index] == Vector3i(chx, 0, chy)) { if (renderManifest[index] == Vector3i(chx, 0, chy)) {
valide = false; valide = false;
++badhitcount; ++badhitcount;
@ -326,8 +358,8 @@ void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Tran
glBlendColor(0.f, 0.f, 0.f, blend); glBlendColor(0.f, 0.f, 0.f, blend);
ChunkAt(cursor)->Render(); ChunkAt(cursor)->Render();
world.ApplyTranslation(-(chx - m_center[0]) * CHUNK_SIZE_X, 0, -(chy - m_center[1]) * CHUNK_SIZE_Z); world.ApplyTranslation(-(chx - m_center[0]) * CHUNK_SIZE_X, 0, -(chy - m_center[1]) * CHUNK_SIZE_Z);
renderManifest.push_back(Vector3i(chx, 0, chy)); renderManifest[++rendercount] = Vector3i(chx, 0, chy);
++rendercount; //++rendercount;
} }
} }
} }

View File

@ -46,7 +46,7 @@ private:
void RenderWorld(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader); void RenderWorld(int& rendercount, int& badhitcount, Player& player, Transformation& world, Shader& shader);
void UpdateWorld(Player& player, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]); void UpdateWorld(Player& player, Perlin& perlin, BlockInfo* blockinfo[BTYPE_LAST]);
void TransposeWorld(Player& player); void TransposeWorld(Player& player);
Chunk* RetrieveChunk(int x, int y); /*Chunk* RetrieveChunk(int x, int y);*/
}; };