diff options
Diffstat (limited to 'src/RendererSection.cpp')
-rw-r--r-- | src/RendererSection.cpp | 328 |
1 files changed, 204 insertions, 124 deletions
diff --git a/src/RendererSection.cpp b/src/RendererSection.cpp index 59e3558..c813071 100644 --- a/src/RendererSection.cpp +++ b/src/RendererSection.cpp @@ -24,14 +24,7 @@ const GLfloat uv_coords[] = { const GLuint magicUniqueConstant = 88375; GLuint RendererSection::VboVertices = magicUniqueConstant; -GLuint RendererSection::VboUvs; -GLuint RendererSection::Vao; -GLuint RendererSection::Vbo[VBOCOUNT]; - -std::vector<glm::mat4> contentModels; -std::vector<glm::vec4> contentTextures; -std::vector<glm::vec3> contentColors; -std::vector<glm::vec2> contentLights; +GLuint RendererSection::VboUvs = magicUniqueConstant; RendererSection::RendererSection(RendererSectionData data) { if (VboVertices == magicUniqueConstant) { @@ -48,90 +41,87 @@ RendererSection::RendererSection(RendererSectionData data) { LOG(INFO) << "Created VBOs with vertices (" << VboVertices << ") and UVs (" << VboUvs << ") for faces"; + } - glGenVertexArrays(1, &Vao); - glGenBuffers(VBOCOUNT, Vbo); - - glBindVertexArray(Vao); - { - //Cube vertices - GLuint VertAttribPos = 0; - glBindBuffer(GL_ARRAY_BUFFER, VboVertices); - glVertexAttribPointer(VertAttribPos, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(VertAttribPos); - - //Cube UVs - GLuint UvAttribPos = 2; - glBindBuffer(GL_ARRAY_BUFFER, VboUvs); - glVertexAttribPointer(UvAttribPos, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(UvAttribPos); - - //Textures - GLuint textureAttribPos = 7; - glBindBuffer(GL_ARRAY_BUFFER, Vbo[TEXTURES]); - glVertexAttribPointer(textureAttribPos, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(textureAttribPos); - glVertexAttribDivisor(textureAttribPos, 1); - glCheckError(); - - //Blocks models - GLuint matAttribPos = 8; - size_t sizeOfMat4 = 4 * 4 * sizeof(GLfloat); - glBindBuffer(GL_ARRAY_BUFFER, Vbo[MODELS]); - glVertexAttribPointer(matAttribPos + 0, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, nullptr); - glVertexAttribPointer(matAttribPos + 1, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *)(1 * 4 * sizeof(GLfloat))); - glVertexAttribPointer(matAttribPos + 2, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *)(2 * 4 * sizeof(GLfloat))); - glVertexAttribPointer(matAttribPos + 3, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *)(3 * 4 * sizeof(GLfloat))); - glEnableVertexAttribArray(matAttribPos + 0); - glEnableVertexAttribArray(matAttribPos + 1); - glEnableVertexAttribArray(matAttribPos + 2); - glEnableVertexAttribArray(matAttribPos + 3); - glVertexAttribDivisor(matAttribPos + 0, 1); - glVertexAttribDivisor(matAttribPos + 1, 1); - glVertexAttribDivisor(matAttribPos + 2, 1); - glVertexAttribDivisor(matAttribPos + 3, 1); - - //Color - GLuint colorAttribPos = 12; - glBindBuffer(GL_ARRAY_BUFFER, Vbo[COLORS]); - glVertexAttribPointer(colorAttribPos, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(colorAttribPos); - glVertexAttribDivisor(colorAttribPos, 1); - - //Light - GLuint lightAttribPos = 13; - glBindBuffer(GL_ARRAY_BUFFER, Vbo[LIGHTS]); - glVertexAttribPointer(lightAttribPos, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); - glEnableVertexAttribArray(lightAttribPos); - glVertexAttribDivisor(lightAttribPos, 1); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - } - glBindVertexArray(0); + glGenVertexArrays(1, &Vao); + + glGenBuffers(VBOCOUNT, Vbo); + + glBindVertexArray(Vao); + { + //Cube vertices + GLuint VertAttribPos = 0; + glBindBuffer(GL_ARRAY_BUFFER, VboVertices); + glVertexAttribPointer(VertAttribPos, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(VertAttribPos); + + //Cube UVs + GLuint UvAttribPos = 2; + glBindBuffer(GL_ARRAY_BUFFER, VboUvs); + glVertexAttribPointer(UvAttribPos, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(UvAttribPos); + + //Textures + GLuint textureAttribPos = 7; + glBindBuffer(GL_ARRAY_BUFFER, Vbo[TEXTURES]); + glVertexAttribPointer(textureAttribPos, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(textureAttribPos); + glVertexAttribDivisor(textureAttribPos, 1); glCheckError(); + + //Blocks models + GLuint matAttribPos = 8; + size_t sizeOfMat4 = 4 * 4 * sizeof(GLfloat); + glBindBuffer(GL_ARRAY_BUFFER, Vbo[MODELS]); + glVertexAttribPointer(matAttribPos + 0, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, nullptr); + glVertexAttribPointer(matAttribPos + 1, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *)(1 * 4 * sizeof(GLfloat))); + glVertexAttribPointer(matAttribPos + 2, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *)(2 * 4 * sizeof(GLfloat))); + glVertexAttribPointer(matAttribPos + 3, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *)(3 * 4 * sizeof(GLfloat))); + glEnableVertexAttribArray(matAttribPos + 0); + glEnableVertexAttribArray(matAttribPos + 1); + glEnableVertexAttribArray(matAttribPos + 2); + glEnableVertexAttribArray(matAttribPos + 3); + glVertexAttribDivisor(matAttribPos + 0, 1); + glVertexAttribDivisor(matAttribPos + 1, 1); + glVertexAttribDivisor(matAttribPos + 2, 1); + glVertexAttribDivisor(matAttribPos + 3, 1); + + //Color + GLuint colorAttribPos = 12; + glBindBuffer(GL_ARRAY_BUFFER, Vbo[COLORS]); + glVertexAttribPointer(colorAttribPos, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(colorAttribPos); + glVertexAttribDivisor(colorAttribPos, 1); + + //Light + GLuint lightAttribPos = 13; + glBindBuffer(GL_ARRAY_BUFFER, Vbo[LIGHTS]); + glVertexAttribPointer(lightAttribPos, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(lightAttribPos); + glVertexAttribDivisor(lightAttribPos, 1); + + glBindBuffer(GL_ARRAY_BUFFER, 0); } + glBindVertexArray(0); + glCheckError(); + //Upload data to VRAM - contentModels.insert(contentModels.end(), data.models.begin(), data.models.end()); - glBindBuffer(GL_ARRAY_BUFFER, Vbo[MODELS]); - glBufferData(GL_ARRAY_BUFFER, contentModels.size() * sizeof(glm::mat4), contentModels.data(), GL_DYNAMIC_DRAW); - - contentTextures.insert(contentTextures.end(), data.textures.begin(), data.textures.end()); glBindBuffer(GL_ARRAY_BUFFER, Vbo[TEXTURES]); - glBufferData(GL_ARRAY_BUFFER, contentTextures.size() * sizeof(glm::vec4), contentTextures.data(), GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, data.textures.size() * sizeof(glm::vec4), data.textures.data(), GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, Vbo[MODELS]); + glBufferData(GL_ARRAY_BUFFER, data.models.size() * sizeof(glm::mat4), data.models.data(), GL_DYNAMIC_DRAW); - contentColors.insert(contentColors.end(), data.colors.begin(), data.colors.end()); glBindBuffer(GL_ARRAY_BUFFER, Vbo[COLORS]); - glBufferData(GL_ARRAY_BUFFER, contentColors.size() * sizeof(glm::vec3), contentColors.data(), GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, data.colors.size() * sizeof(glm::vec3), data.colors.data(), GL_DYNAMIC_DRAW); - contentLights.insert(contentLights.end(), data.lights.begin(), data.lights.end()); glBindBuffer(GL_ARRAY_BUFFER, Vbo[LIGHTS]); - glBufferData(GL_ARRAY_BUFFER, contentLights.size() * sizeof(glm::vec2), contentLights.data(), GL_DYNAMIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, data.lights.size() * sizeof(glm::vec2), data.lights.data(), GL_DYNAMIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); numOfFaces = data.textures.size(); - offset = contentModels.size() - numOfFaces; sectionPos = data.sectionPos; hash = data.hash; } @@ -142,13 +132,30 @@ RendererSection::RendererSection(RendererSection && other) { } RendererSection::~RendererSection() { + if (Vao != 0) + glDeleteVertexArrays(1, &Vao); + + for (int i = 0; i < VBOCOUNT; i++) + if (Vbo[i] != 0) { + glBindBuffer(GL_ARRAY_BUFFER, Vbo[i]); + glBufferData(GL_ARRAY_BUFFER, 0, 0, GL_STATIC_DRAW); + } + + glDeleteBuffers(VBOCOUNT, Vbo); } void swap(RendererSection & lhs, RendererSection & rhs) { + std::swap(lhs.Vbo, rhs.Vbo); + std::swap(lhs.Vao, rhs.Vao); std::swap(lhs.hash, rhs.hash); std::swap(lhs.numOfFaces, rhs.numOfFaces); std::swap(lhs.sectionPos, rhs.sectionPos); - std::swap(lhs.offset, rhs.offset); +} + +void RendererSection::Render(RenderState &renderState) { + renderState.SetActiveVao(Vao); + glDrawArraysInstanced(GL_TRIANGLES, 0, 6, numOfFaces); + glCheckError(); } Vector RendererSection::GetPosition() @@ -161,16 +168,16 @@ size_t RendererSection::GetHash() return hash; } -GLuint RendererSection::GetVao() { - return Vao; -} - RendererSectionData::RendererSectionData(World * world, Vector sectionPosition) { const std::map<BlockTextureId, glm::vec4> &textureAtlas = AssetManager::Instance().GetTextureAtlasIndexes(); const Section §ion = world->GetSection(sectionPosition); hash = section.GetHash(); sectionPos = sectionPosition; + SetBlockIdData(world); + + auto blockVisibility = GetBlockVisibilityData(world); + glm::mat4 baseOffset = glm::translate(glm::mat4(), (section.GetPosition() * 16).glm()),transform; auto sectionsList = world->GetSectionsList(); @@ -178,7 +185,7 @@ RendererSectionData::RendererSectionData(World * world, Vector sectionPosition) for (int y = 0; y < 16; y++) { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { - BlockId block = section.GetBlockId(Vector(x, y, z)); + BlockId block = GetBlockId(x,y,z); if (block.id == 0) continue; @@ -187,9 +194,9 @@ RendererSectionData::RendererSectionData(World * world, Vector sectionPosition) transform = glm::translate(baseOffset, Vector(x, y, z).glm()); - const BlockModel* model = AssetManager::Instance().GetBlockModelByBlockId(block); + const BlockModel* model = this->GetInternalBlockModel(block); if (model) { - this->AddFacesByBlockModel(sectionsList, world, Vector(x, y, z), *model, transform, section.GetBlockLight(Vector(x, y, z)), section.GetBlockSkyLight(Vector(x, y, z))); + this->AddFacesByBlockModel(sectionsList, world, Vector(x, y, z), *model, transform, section.GetBlockLight(Vector(x, y, z)), section.GetBlockSkyLight(Vector(x, y, z)), blockVisibility); } else { transform = glm::translate(transform, glm::vec3(0, 1, 0)); @@ -214,7 +221,7 @@ RendererSectionData::RendererSectionData(World * world, Vector sectionPosition) colors.shrink_to_fit(); } -void RendererSectionData::AddFacesByBlockModel(const std::vector<Vector> §ionsList, World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight) { +void RendererSectionData::AddFacesByBlockModel(const std::vector<Vector> §ionsList, World *world, Vector blockPos, const BlockModel &model, glm::mat4 transform, unsigned char light, unsigned char skyLight, const std::array<unsigned char, 16 * 16 * 16>& visibility) { glm::mat4 elementTransform, faceTransform; for (const auto& element : model.Elements) { Vector t = element.to - element.from; @@ -225,29 +232,31 @@ void RendererSectionData::AddFacesByBlockModel(const std::vector<Vector> §io for (const auto& face : element.faces) { if (face.second.cullface != BlockModel::ElementData::FaceDirection::none) { + unsigned char visible = visibility[blockPos.y * 256 + blockPos.z * 16 + blockPos.x]; + switch (face.second.cullface) { case BlockModel::ElementData::FaceDirection::down: - if (TestBlockExists(sectionsList, world, blockPos - Vector(0, +1, 0))) + if (visible >> 0 & 0x1) continue; break; case BlockModel::ElementData::FaceDirection::up: - if (TestBlockExists(sectionsList, world, blockPos - Vector(0, -1, 0))) + if (visible >> 1 & 0x1) continue; break; case BlockModel::ElementData::FaceDirection::north: - if (TestBlockExists(sectionsList, world, blockPos - Vector(0, 0, -1))) + if (visible >> 2 & 0x1) continue; break; case BlockModel::ElementData::FaceDirection::south: - if (TestBlockExists(sectionsList, world, blockPos - Vector(0, 0, +1))) + if (visible >> 3 & 0x1) continue; break; case BlockModel::ElementData::FaceDirection::west: - if (TestBlockExists(sectionsList, world, blockPos - Vector(-1, 0, 0))) + if (visible >> 4 & 0x1) continue; break; case BlockModel::ElementData::FaceDirection::east: - if (TestBlockExists(sectionsList, world, blockPos - Vector(+1, 0, 0))) + if (visible >> 5 & 0x1) continue; break; } @@ -302,39 +311,110 @@ void RendererSectionData::AddFacesByBlockModel(const std::vector<Vector> §io } } -bool RendererSectionData::TestBlockExists(const std::vector<Vector> §ionsList, World *world, Vector blockPos) { - Vector section = sectionPos; - if (blockPos.x == -1) { - section = section + Vector(-1, 0, 0); - blockPos.x = 15; - } - else if (blockPos.x == 16) { - section = section + Vector(+1, 0, 0); - blockPos.x = 0; - } - else if (blockPos.y == -1) { - section = section + Vector(0, -1, 0); - blockPos.y = 15; - } - else if (blockPos.y == 16) { - section = section + Vector(0, +1, 0); - blockPos.y = 0; - } - else if (blockPos.z == -1) { - section = section + Vector(0, 0, -1); - blockPos.z = 15; - } - else if (blockPos.z == 16) { - section = section + Vector(0, 0, +1); - blockPos.z = 0; +std::array<unsigned char, 4096> RendererSectionData::GetBlockVisibilityData(World *world) { + //const auto& section = world->GetSection(sectionPos); + const auto& sectionDown = world->GetSection(sectionPos + Vector(0, -1, 0)); + const auto& sectionUp = world->GetSection(sectionPos + Vector(0, +1, 0)); + const auto& sectionNorth = world->GetSection(sectionPos + Vector(0, 0, +1)); + const auto& sectionSouth = world->GetSection(sectionPos + Vector(0, 0, -1)); + const auto& sectionWest = world->GetSection(sectionPos + Vector(+1, 0, 0)); + const auto& sectionEast = world->GetSection(sectionPos + Vector(-1, 0, 0)); + + std::array<unsigned char, 4096> arr; + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + unsigned char value = 0; + BlockId blockIdDown; + BlockId blockIdUp; + BlockId blockIdNorth; + BlockId blockIdSouth; + BlockId blockIdWest; + BlockId blockIdEast; + + switch (y) { + case 0: + blockIdDown = sectionDown.GetBlockId(Vector(x, 15, z)); + blockIdUp = GetBlockId(x,1,z); + break; + case 15: + blockIdDown = GetBlockId(x,14,z); + blockIdUp = sectionUp.GetBlockId(Vector(x, 0, z)); + break; + default: + blockIdDown = GetBlockId(x, y -1, z); + blockIdUp = GetBlockId(x, y + 1, z); + break; + } + + switch (z) { + case 0: + blockIdNorth = GetBlockId(x, y, 1); + blockIdSouth = sectionSouth.GetBlockId(Vector(x, y, 15)); + break; + case 15: + blockIdNorth = sectionNorth.GetBlockId(Vector(x, y, 0)); + blockIdSouth = GetBlockId(x, y, 14); + break; + default: + blockIdNorth = GetBlockId(x, y, z + 1); + blockIdSouth = GetBlockId(x, y, z - 1); + break; + } + + switch (x) { + case 0: + blockIdWest = GetBlockId(1, y, z); + blockIdEast = sectionEast.GetBlockId(Vector(15, y, z)); + break; + case 15: + blockIdWest = sectionWest.GetBlockId(Vector(0, y, z)); + blockIdEast = GetBlockId(14, y, z); + break; + default: + blockIdWest = GetBlockId(x + 1, y, z); + blockIdEast = GetBlockId(x - 1, y, z); + break; + } + + auto blockModelDown = GetInternalBlockModel(blockIdDown); + auto blockModelUp = GetInternalBlockModel(blockIdUp); + auto blockModelNorth = GetInternalBlockModel(blockIdNorth); + auto blockModelSouth = GetInternalBlockModel(blockIdSouth); + auto blockModelWest = GetInternalBlockModel(blockIdWest); + auto blockModelEast = GetInternalBlockModel(blockIdEast); + + value |= (blockIdDown.id != 0 && blockModelDown && blockModelDown->IsBlock) << 0; + value |= (blockIdUp.id != 0 && blockModelUp && blockModelUp->IsBlock) << 1; + value |= (blockIdNorth.id != 0 && blockModelNorth && blockModelNorth->IsBlock) << 2; + value |= (blockIdSouth.id != 0 && blockModelSouth && blockModelSouth->IsBlock) << 3; + value |= (blockIdWest.id != 0 && blockModelWest && blockModelWest->IsBlock) << 4; + value |= (blockIdEast.id != 0 && blockModelEast && blockModelEast->IsBlock) << 5; + + arr[y * 256 + z * 16 + x] = value; + } + } } - - if (std::find(sectionsList.begin(), sectionsList.end(),section) == sectionsList.end()) - return true; + return arr; +} - BlockId blockId = world->GetSection(section).GetBlockId(blockPos); +const BlockModel* RendererSectionData::GetInternalBlockModel(const BlockId& id) { + for (const auto& it : idModels) { + if (it.first == id) + return it.second; + } + idModels.push_back(std::make_pair(id, am.GetBlockModelByBlockId(id))); + return idModels.back().second; +} - auto blockModel = AssetManager::Instance().GetBlockModelByBlockId(world->GetSection(section).GetBlockId(blockPos)); +void RendererSectionData::SetBlockIdData(World* world) { + const Section& section = world->GetSection(sectionPos); - return blockId.id != 0 && blockModel && blockModel->IsBlock; + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + blockIdData[y * 256 + z * 16 + x] = section.GetBlockId(Vector(x,y,z)); + } + } + } }
\ No newline at end of file |