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);
T Get(int x, int y) const;
T Remove(int x, int y);
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>
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>
void Array2d<T>::Reset(T type) {
for (int i = 0; i < m_x * m_y; ++i)

View File

@ -47,7 +47,7 @@ private:
TextureAtlas m_textureAtlas = TextureAtlas(BTYPE_LAST);
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_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; }
void Player::Transpose(int& x, int& z) {
void Player::Teleport(int& x, int& z) {
m_position.x -= x * CHUNK_SIZE_X;
m_position.z -= z * CHUNK_SIZE_Z;
}

View File

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

View File

@ -1,102 +1,105 @@
#include "world.h"
World::World(){}
World::World() {}
World::~World(){}
World::~World() {}
Array2d<Chunk*>& World::GetChunks() { return m_chunks; }
Chunk* World::ChunkAt(float x, float y, float z) const {
int cx = (int)x / CHUNK_SIZE_X;
int cz = (int)z / CHUNK_SIZE_Z;
int cx = (int)x / CHUNK_SIZE_X;
int cz = (int)z / CHUNK_SIZE_Z;
if (x < 0 || y < 0 || z < 0 ||
x >= WORLD_SIZE_X * CHUNK_SIZE_X ||
z >= CHUNK_SIZE_Z * WORLD_SIZE_Y ||
y > CHUNK_SIZE_Y)
return 0;
if (x < 0 || y < 0 || z < 0 ||
x >= WORLD_SIZE_X * CHUNK_SIZE_X ||
z >= CHUNK_SIZE_Z * WORLD_SIZE_Y ||
y > CHUNK_SIZE_Y)
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); }
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)
return defaultBlockType;
if (!c)
return defaultBlockType;
int bx = (int)x % CHUNK_SIZE_X;
int by = (int)y % CHUNK_SIZE_Y;
int bz = (int)z % CHUNK_SIZE_Z;
int bx = (int)x % CHUNK_SIZE_X;
int by = (int)y % CHUNK_SIZE_Y;
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 {
return BlockAt(pos.x, pos.y, pos.z, defaultBlockType);
return BlockAt(pos.x, pos.y, pos.z, defaultBlockType);
}
void World::TransposeWorld(Player& player) {
int x = 0;
int y = 0;
int x = 0;
int y = 0;
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;
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;
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;
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;
if (!x && !y) return;
if (!x && !y) return;
if (x != 0)
for (int ay = 0; ay < WORLD_SIZE_Y; ++ay)
for (int ax = 0; ax < abs(x); ++ay)
if (ChunkAt(x < 0 ? (WORLD_SIZE_X - 1 - ax) * WORLD_SIZE_X : ax, 1, ay * WORLD_SIZE_Y))
m_tbDeleted.push_back(std::move(m_chunks.Get(x < 0? WORLD_SIZE_X - 1 - ax: ax, ay)));
if (y != 0)
for (int ax = 0; ax < WORLD_SIZE_X; ++ax)
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))
m_tbDeleted.push_back(std::move(m_chunks.Get(ax, y < 0 ? WORLD_SIZE_Y - 1 - ay: ay)));
for (int ax = 0; ax < WORLD_SIZE_X; ++ax)
for (int ay = 0; ay < WORLD_SIZE_Y; ++ay)
if (ax + x < WORLD_SIZE_X && ax + x > 0 &&
ay + y < WORLD_SIZE_Y && ay + y > 0)
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)
for (int ay = 0; ay < WORLD_SIZE_Y; ++ay)
for (int ax = 0; ax < abs(x); ++ay)
m_chunks.Set(x > 0 ? WORLD_SIZE_X - 1 - ax : ax, ay, nullptr);
if (y != 0)
for (int ax = 0; ax < WORLD_SIZE_X; ++ax)
for (int ay = 0; ay < abs(y); ++ay)
m_chunks.Set(ax, y > 0 ? WORLD_SIZE_Y - 1 - ay : ay, nullptr);
m_center[0] += x; m_center[1] += y;
player.Transpose(x, y);
if (x > 0) {
for (int ax = 0; ax < WORLD_SIZE_X; ++ax)
for (int ay = 0; ay < WORLD_SIZE_Y; ++ay)
if (ax - x >= 0)
m_chunks.Set(ax - x, ay,
m_chunks.Remove(ax, ay));
else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay));
}
else if (x < 0) {
for (int ax = WORLD_SIZE_X - 1; ax >= 0; --ax)
for (int ay = WORLD_SIZE_Y - 1; ay >= 0; --ay)
if (ax - x < WORLD_SIZE_X)
m_chunks.Set(ax - x, ay,
m_chunks.Remove(ax, ay));
else if (m_chunks.Get(ax, ay)) m_tbDeleted.emplace_back(m_chunks.Remove(ax, ay));
}
if (y > 0) {
for (int ax = 0; ax < WORLD_SIZE_X; ++ax)
for (int ay = 0; ay < WORLD_SIZE_Y; ++ay)
if (ay - y >= 0)
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));
}
else if (y < 0) {
for (int ax = WORLD_SIZE_X - 1; ax >= 0; --ax)
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) {
if (clear) m_tbDeleted.clear();
if (!m_tbDeleted.empty() && !deleteframes) {
m_tbDeleted.pop_back();
deleteframes = FRAMES_DELETE_CHUNKS;
}
}
Chunk* World::RetrieveChunk(int x, int y) {
for (int index = 0; index < m_tbDeleted.size(); ++index) {
int cx, cy;
m_tbDeleted.at(index)->GetPosition(cx, cy);
if (cx == x && cy == y)
return std::move(m_tbDeleted.at(index));
}
return nullptr;
if (clear) {
while (m_tbDeleted.size() > 0) {
delete m_tbDeleted.back();
m_tbDeleted.pop_back();
}
}
if (!m_tbDeleted.empty() && !deleteframes) {
delete m_tbDeleted.back();
m_tbDeleted.pop_back();
deleteframes = FRAMES_DELETE_CHUNKS;
}
std::cout << "Chunk Write Buffer: " << m_tbDeleted.size() << std::endl;
}
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]) {
atlas.Bind();
TransposeWorld(player);
RenderWorld(rendercount, badhitcount, player, world, shader);
TransposeWorld(player);
UpdateWorld(player, perlin, blockinfo);
shader.Disable();
}
bool World::GenerateChunk(int chx, int chy, Perlin& perlin) {
if (chx < WORLD_SIZE_X * CHUNK_SIZE_X && chy < WORLD_SIZE_Y * CHUNK_SIZE_Z &&
chx >= 0 && chy >= 0)
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.
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) {
GetChunks().Set(chx / CHUNK_SIZE_X, chy / CHUNK_SIZE_Z, std::move(m_tbDeleted.at(index)));
return true;
}
}
}
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 z = 0; z < CHUNK_SIZE_Z; ++z) {
Vector3f noise;
noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]);
noise.y = 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.z) * 3 - 32;
for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y)
float xnoiz, ynoiz;
xnoiz = (double)(x + (chx / CHUNK_SIZE_X + m_center[0]) * CHUNK_SIZE_X) / (double)INT16_MAX;
ynoiz = (double)(z + (chy / CHUNK_SIZE_Z + m_center[1]) * CHUNK_SIZE_Z) / (double)INT16_MAX;
float height = (perlin.Get(xnoiz, ynoiz)) * 10.f;
for (int y = 0; y <= (int)height; ++y)
chunk->SetBlock(x, y, z, BTYPE_METAL, this);
}
for (int x = 0; x < CHUNK_SIZE_X; ++x)
for (int z = 0; z < CHUNK_SIZE_Z; ++z) {
Vector3f noise;
noise.x = x * (CHUNK_SIZE_X + 1) + (CHUNK_SIZE_X - 1) * (chx + m_center[0]);
noise.y = 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.z) + 16;
float xnoiz, ynoiz;
xnoiz = (double)(x + (chx / CHUNK_SIZE_X + m_center[0]) * CHUNK_SIZE_X) / (double)INT16_MAX;
ynoiz = (double)(z + (chy / CHUNK_SIZE_Z + m_center[1]) * CHUNK_SIZE_Z) / (double)INT16_MAX;
float height = (perlin.Get(xnoiz, ynoiz) + 16.f);
for (int y = 0; y <= (int)height % CHUNK_SIZE_Y; ++y) {
if (chunk->GetBlock(x, y, z) == BTYPE_AIR)
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 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)
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 {
input.seekg(0, std::ios_base::end);
@ -197,7 +187,6 @@ bool World::GenerateChunk(int chx, int chy, Perlin& perlin) {
delete[] data;
}
std::cout << "Chunk generated: " << chx / CHUNK_SIZE_X + m_center[0] << ", " << chy / CHUNK_SIZE_Z + m_center[1] << std::endl;
return true;
}
@ -274,7 +263,7 @@ void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Tran
shader.Use();
rendercount = 0;
badhitcount = 0;
static std::vector<Vector3i> renderManifest;
//static std::vector<Vector3i> renderManifest;
Vector3f angle;
Vector3f cursor;
Vector3f direct = player.GetDirection();
@ -283,18 +272,61 @@ void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Tran
direct.y = 0;
direct.Normalize();
pos.y = 1;
renderManifest.clear();
//renderManifest.clear();
static Vector3i renderManifest[VIEW_DISTANCE * 4];
for (int dist = VIEW_DISTANCE; dist >= 0; dist -= CHUNK_SIZE_X) {
// Configuration du radar.
angle.x = direct.z + direct.x;
angle.y = 0;
angle.z = direct.z - direct.x;
angle.Normalize();
float sinus, cosinus;
int echantillons;
float sinus = .01745240643; // sin(1 degré)
float cosinus = .99984769515; // cos(1 degré)
int echantillons = 90;
if (dist > VIEW_DISTANCE * .375f) {
angle.x = direct.z + direct.x;
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) {
float x = angle.x;
@ -312,7 +344,7 @@ void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Tran
if (ChunkAt(cursor)) {
int 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)) {
valide = false;
++badhitcount;
@ -326,8 +358,8 @@ void World::RenderWorld(int& rendercount, int& badhitcount, Player& player, Tran
glBlendColor(0.f, 0.f, 0.f, blend);
ChunkAt(cursor)->Render();
world.ApplyTranslation(-(chx - m_center[0]) * CHUNK_SIZE_X, 0, -(chy - m_center[1]) * CHUNK_SIZE_Z);
renderManifest.push_back(Vector3i(chx, 0, chy));
++rendercount;
renderManifest[++rendercount] = Vector3i(chx, 0, chy);
//++rendercount;
}
}
}

View File

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