51 glBufferData(GL_UNIFORM_BUFFER,
sizeof(glm::mat4), NULL, GL_STATIC_DRAW);
52 glBindBuffer(GL_UNIFORM_BUFFER, 0);
61 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
62 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
63 float borderColor[] = { 1.0f, 1.0f, 1.0f, 1.0f };
64 glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
65 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
66 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
70 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, atlas->
GetWidth(), atlas->
GetHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, atlas->
Get());
71 glGenerateMipmap(GL_TEXTURE_2D);
73 glBindTexture(GL_TEXTURE_2D, 0);
78 if (
camera->GetHasChangedOrientation() ||
camera->GetHasChangedPosition())
81 glm::mat4 view_matrix =
camera->GetViewMatrix();
82 if (
camera->GetHasChangedPosition())
91 camera->ResetHasChangedPosition();
92 camera->ResetHasChangedOrientation();
95 glBufferSubData(GL_UNIFORM_BUFFER, 0,
sizeof(glm::mat4), glm::value_ptr(view_matrix));
96 glBindBuffer(GL_UNIFORM_BUFFER, 0);
167 for (
auto it =
chunks.begin(); it !=
chunks.end(); ++it)
169 if (it->first.x == x_ && it->first.z == z_)
171 it->second->ClearFaces();
180 if (it->first.x == x_ && it->first.z == z_)
182 it->second->ClearFaces();
187 if (!chunk.has_value())
195 const std::vector<Position> neighbour_positions({
Position(0, -1, 0),
Position(0, 0, -1),
196 Position(-1, 0, 0),
Position(1, 0, 0),
Position(0, 0, 1),
Position(0, 1, 0) });
198 std::vector<const Blockstate*> neighbour_blockstates(6);
201 for (
int y = chunk->GetMinY(); y < chunk->GetHeight() + chunk->GetMinY(); ++y)
212 const Blockstate* this_block = chunk->GetBlock(pos);
213 if (this_block ==
nullptr || this_block->
IsAir())
219 for (
int i = 0; i < 6; ++i)
221 neighbour_blockstates[i] = chunk->GetBlock(pos + neighbour_positions[i]);
224 bool is_surrounded_by_opaque =
false;
226 for (
int i = 0; i < neighbour_positions.size(); ++i)
228 if (neighbour_blockstates[i] ==
nullptr ||
229 neighbour_blockstates[i]->IsTransparent())
236 if (i == neighbour_positions.size() - 1)
238 is_surrounded_by_opaque =
true;
242 if (is_surrounded_by_opaque)
255#if PROTOCOL_VERSION < 552
256 const Biome* current_biome = chunk->GetBiome(x, z);
258 const Biome* current_biome = chunk->GetBiome(x, y, z);
261 for (
int i = 0; i < current_faces.size(); ++i)
267 !neighbour_blockstates[
static_cast<int>(current_faces[i].cullface_direction)] ||
268 (neighbour_blockstates[
static_cast<int>(current_faces[i].cullface_direction)]->IsTransparent() &&
269 neighbour_blockstates[
static_cast<int>(current_faces[i].cullface_direction)]->GetName() != this_block->
GetName())
273 current_faces[i].face, current_faces[i].texture_names,
274 GetColorModifier(pos.
y, current_biome, this_block, current_faces[i].use_tintindexes));
355 int* num_entities_,
int* num_rendered_entities_,
356 int* num_faces_,
int* num_rendered_faces_)
358 const std::array<glm::vec4, 6>& frustum_planes =
camera->GetFrustumPlanes();
361 std::unordered_set<Position> all_loaded_chunks;
366 for (
auto it =
chunks.begin(); it !=
chunks.end(); ++it)
368 all_loaded_chunks.insert(it->first);
369 num_faces += it->second->GetNumFace();
375 all_loaded_chunks.insert(it->first);
376 num_faces += it->second->GetNumFace();
379 const int num_chunks =
static_cast<int>(all_loaded_chunks.size());
382 std::vector<Position> chunks_to_render;
383 chunks_to_render.reserve(all_loaded_chunks.size());
384 std::unordered_map<Position, bool> inside_frustum;
386 for (
auto it = all_loaded_chunks.begin(); it != all_loaded_chunks.end(); ++it)
390 const float min_x =
static_cast<float>(
CHUNK_WIDTH * (*it).x);
391 const float max_x =
static_cast<float>(
CHUNK_WIDTH * ((*it).x + 1));
392 const float min_y =
static_cast<float>(
static_cast<int>(
section_height) * (*it).y);
393 const float max_y =
static_cast<float>(
static_cast<int>(
section_height) * ((*it).y + 1));
394 const float min_z =
static_cast<float>(
CHUNK_WIDTH * (*it).z);
395 const float max_z =
static_cast<float>(
CHUNK_WIDTH * ((*it).z + 1));
397 for (
int i = 0; i < 6; ++i)
399 const bool sign_x = frustum_planes[i].x > 0.0f;
400 const bool sign_y = frustum_planes[i].y > 0.0f;
401 const bool sign_z = frustum_planes[i].z > 0.0f;
403 const glm::vec4 p_vertex = glm::vec4(sign_x ? max_x : min_x, sign_y ? max_y : min_y, sign_z ? max_z : min_z, 1.0f);
405 if (glm::dot(frustum_planes[i], p_vertex) < 0.0f)
411 const glm::vec4 n_vertex = glm::vec4(sign_x ? min_x : max_x, sign_y ? min_y : max_y, sign_z ? min_z : max_z, 1.0f);
413 if (glm::dot(frustum_planes[i], n_vertex) < 0.0f)
422 chunks_to_render.push_back(*it);
428 std::sort(chunks_to_render.begin(), chunks_to_render.end(), [
this](
const Position& p1,
const Position& p2) {return this->DistanceToCamera(p1) > this->DistanceToCamera(p2); });
432 const int num_rendered_chunks =
static_cast<int>(chunks_to_render.size());
433 int num_rendered_faces = 0;
435 for (
int i = 0; i < num_rendered_chunks; ++i)
437 auto found_it =
chunks.find(chunks_to_render[i]);
438 if (found_it !=
chunks.end())
440 found_it->second->Render();
441 num_rendered_faces += found_it->second->GetNumFace();
448 Position(-1, 0, 0),
Position(1, 0, 0),
Position(0, 0, 1),
Position(0, 1, 0) });
450 const int num_entities =
static_cast<int>(
entities.size());
451 int num_rendered_entities = 0;
454 num_faces += e.second->GetNumFace();
458 static_cast<int>(floor(approx_pos.
x /
static_cast<double>(
CHUNK_WIDTH))),
459 static_cast<int>(floor(approx_pos.
y /
static_cast<double>(
section_height))),
460 static_cast<int>(floor(approx_pos.
z /
static_cast<double>(
CHUNK_WIDTH)))
463 for (
int i = 0; i < neighbouring_positions.size(); ++i)
465 if (inside_frustum[chunk_position + neighbouring_positions[i]])
468 num_rendered_entities += 1;
469 num_rendered_faces += e.second->GetNumFace();
477 const glm::vec3 cam_pos =
camera->GetPosition();
482 for (
int i = 0; i < num_rendered_chunks; ++i)
487 found_it->second->Sort(cam_pos);
488 found_it->second->Render();
489 num_rendered_faces += found_it->second->GetNumFace();
496 *num_chunks_ = num_chunks;
498 if (num_rendered_chunks_)
500 *num_rendered_chunks_ = num_rendered_chunks;
504 *num_faces_ = num_faces;
506 if (num_rendered_faces_)
508 *num_rendered_faces_ = num_rendered_faces;
512 *num_entities_ = num_entities;
514 if (num_rendered_entities_)
516 *num_rendered_entities_ = num_rendered_entities;
522 std::array<unsigned int, 2> texture_multipliers = { 0xFFFFFFFF, 0xFFFFFFFF };
523 for (
int i = 0; i < std::min(2, static_cast<int>(texture_multipliers_.size())); ++i)
525 texture_multipliers[i] = texture_multipliers_[i];
529 static_cast<int>(floor(block_pos.
x /
static_cast<double>(
CHUNK_WIDTH))),
530 static_cast<int>(floor(block_pos.
y /
static_cast<double>(
section_height))),
531 static_cast<int>(floor(block_pos.
z /
static_cast<double>(
CHUNK_WIDTH)))
544 transparent_chunks[chunk_position]->AddFace(face_, texture_multipliers, offset.
x + 0.5f, offset.
y + 0.5f, offset.
z + 0.5f);
549 auto chunk_it =
chunks.find(chunk_position);
550 if (chunk_it ==
chunks.end())
552 chunks[chunk_position] = std::make_shared<Chunk>();
554 chunks[chunk_position]->AddFace(face_, texture_multipliers, offset.
x + 0.5f, offset.
y + 0.5f, offset.
z + 0.5f);
560 std::vector<unsigned int> texture_modifier(use_tintindex.size(), 0xFFFFFFFF);
561 for (
int i = 0; i < use_tintindex.size(); ++i)
568 if (use_tintindex[i])
577 if (use_tintindex[i])
587#if PROTOCOL_VERSION == 340
588 texture_modifier[i] = 0xFF000000 | (25 + 15 * blockstate->
GetId().second);
590 texture_modifier[i] = 0xFF000000 | (25 + 15 * std::stoi(blockstate->
GetVariableValue(
"power")));
603 return texture_modifier;