diff options
Diffstat (limited to 'src/graphics/RenderSection.cpp')
-rw-r--r-- | src/graphics/RenderSection.cpp | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/src/graphics/RenderSection.cpp b/src/graphics/RenderSection.cpp new file mode 100644 index 0000000..fec67b5 --- /dev/null +++ b/src/graphics/RenderSection.cpp @@ -0,0 +1,281 @@ +#include <graphics/RenderSection.hpp> + +const GLfloat vertices[] = { + //Z+ edge + -0.5f, 0.5f, 0.5f, + -0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + + //Z- edge + -0.5f, -0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, + + //X+ edge + -0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + -0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, + -0.5f, 0.5f, 0.5f, + + //X- edge + 0.5f, -0.5f, 0.5f, + 0.5f, 0.5f, -0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, -0.5f, + 0.5f, 0.5f, -0.5f, + + //Y+ edge + 0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, 0.5f, + 0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, -0.5f, + -0.5f, 0.5f, 0.5f, + + //Y- edge + -0.5f, -0.5f, 0.5f, + 0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, 0.5f, + -0.5f, -0.5f, -0.5f, + 0.5f, -0.5f, -0.5f, + -0.5f, -0.5f, 0.5f, +}; + +const GLfloat uv_coords[] = { + //Z+ + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 0.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + + //Z- + 1.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 0.0f, + 0.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + + //X+ + 0.0f, 0.0f, + 1.0f, 0.0f, + 0.0f, 1.0f, + 0.0f, 1.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + + //X- + 0.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + + //Y+ + 0.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 0.0f, + 1.0f, 1.0f, + + //Y- + 1.0f, 0.0f, + 0.0f, 1.0f, + 0.0f, 0.0f, + 1.0f, 1.0f, + 0.0f, 1.0f, + 1.0f, 0.0f, +}; + +void RenderState::SetActiveVao(GLuint Vao) { + if (Vao != ActiveVao) { + glBindVertexArray(Vao); + ActiveVao = Vao; + } +} + +void RenderState::SetActiveShader(GLuint Shader) { + if (Shader != ActiveShader) { + glUseProgram(Shader); + ActiveShader = Shader; + } +} + +const GLuint magicUniqueConstant = 88375; +GLuint RenderSection::VboVertices = magicUniqueConstant; +GLuint RenderSection::VboUvs = magicUniqueConstant; +std::map<GLuint, int> RenderSection::refCounterVbo; +std::map<GLuint, int> RenderSection::refCounterVao; + + +RenderSection::RenderSection(World *world, Vector position) : sectionPosition(position), world(world) { + + if (VboVertices == magicUniqueConstant) { + glGenBuffers(1, &VboVertices); + glGenBuffers(1, &VboUvs); + + //Cube vertices + glBindBuffer(GL_ARRAY_BUFFER, VboVertices); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); + + //Cube UVs + glBindBuffer(GL_ARRAY_BUFFER, VboUvs); + glBufferData(GL_ARRAY_BUFFER, sizeof(uv_coords), uv_coords, GL_STATIC_DRAW); + + LOG(INFO) << "Created VBOs with vertices (" << VboVertices << ") and UVs (" << VboUvs + << ") for ordinary blocks"; + } + + glGenBuffers(1, &VboBlocks); + if (refCounterVbo.find(VboBlocks) == refCounterVbo.end()) + refCounterVbo[VboBlocks] = 0; + refCounterVbo[VboBlocks]++; + + glGenBuffers(1, &VboModels); + if (refCounterVbo.find(VboModels) == refCounterVbo.end()) + refCounterVbo[VboModels] = 0; + refCounterVbo[VboModels]++; + + glGenVertexArrays(1, &Vao); + if (refCounterVao.find(Vao) == refCounterVao.end()) + refCounterVao[Vao] = 0; + refCounterVao[Vao]++; + + glBindVertexArray(Vao); + { + //Cube vertices + glBindBuffer(GL_ARRAY_BUFFER, VboVertices); + glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(0); + + //Cube UVs + glBindBuffer(GL_ARRAY_BUFFER, VboUvs); + glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(2); + + //Blocks ids + glBindBuffer(GL_ARRAY_BUFFER, VboBlocks); + glVertexAttribPointer(7, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), nullptr); + glEnableVertexAttribArray(7); + glVertexAttribDivisor(7, 1); + glCheckError(); + + //Blocks models + size_t sizeOfMat4 = 4 * 4 * sizeof(GLfloat); + glBindBuffer(GL_ARRAY_BUFFER, VboModels); + glVertexAttribPointer(8 + 0, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, nullptr); + glVertexAttribPointer(8 + 1, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (1 * 4 * sizeof(GLfloat))); + glVertexAttribPointer(8 + 2, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (2 * 4 * sizeof(GLfloat))); + glVertexAttribPointer(8 + 3, 4, GL_FLOAT, GL_FALSE, sizeOfMat4, (void *) (3 * 4 * sizeof(GLfloat))); + glEnableVertexAttribArray(8 + 0); + glEnableVertexAttribArray(8 + 1); + glEnableVertexAttribArray(8 + 2); + glEnableVertexAttribArray(8 + 3); + glVertexAttribDivisor(8 + 0, 1); + glVertexAttribDivisor(8 + 1, 1); + glVertexAttribDivisor(8 + 2, 1); + glVertexAttribDivisor(8 + 3, 1); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + glBindVertexArray(0); + UpdateState(); + glCheckError(); +} + +RenderSection::~RenderSection() { + refCounterVbo[VboBlocks]--; + refCounterVbo[VboModels]--; + refCounterVao[Vao]--; + if (refCounterVbo[VboBlocks] <= 0) + glDeleteBuffers(1, &VboBlocks); + if (refCounterVbo[VboModels] <= 0) + glDeleteBuffers(1, &VboBlocks); + if (refCounterVao[Vao] <= 0) + glDeleteVertexArrays(1, &Vao); +} + +void RenderSection::UpdateState() { + Section *section = &world->sections.find(sectionPosition)->second; + std::vector<glm::mat4> models; + std::vector<glm::vec2> blocks; + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + Block block = section->GetBlock(Vector(x, y, z)); + if (block.id == 0) + continue; + + unsigned char isVisible = 0; + if (x == 0 || x == 15 || y == 0 || y == 15 || z == 0 || z == 15) { + isVisible = 0; + } else { + isVisible |= (section->GetBlock(Vector(x + 1, y, z)).id != 0) << 0; + isVisible |= (section->GetBlock(Vector(x - 1, y, z)).id != 0) << 1; + isVisible |= (section->GetBlock(Vector(x, y + 1, z)).id != 0) << 2; + isVisible |= (section->GetBlock(Vector(x, y - 1, z)).id != 0) << 3; + isVisible |= (section->GetBlock(Vector(x, y, z + 1)).id != 0) << 4; + isVisible |= (section->GetBlock(Vector(x, y, z - 1)).id != 0) << 5; + } + if (isVisible == 0x3F) + continue; + + glm::vec2 data(block.id, block.state); + blocks.push_back(data); + glm::mat4 model; + model = glm::translate(model, glm::vec3(section->GetPosition().GetX() * 16, + section->GetPosition().GetY() * 16, + section->GetPosition().GetZ() * 16)); + model = glm::translate(model, glm::vec3(x, y, z)); + double size = 0.999; + model = glm::scale(model, glm::vec3(size, size, size)); + models.push_back(model); + } + } + } + glBindBuffer(GL_ARRAY_BUFFER, VboBlocks); + glBufferData(GL_ARRAY_BUFFER, blocks.size() * sizeof(glm::vec2), blocks.data(), GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, VboModels); + glBufferData(GL_ARRAY_BUFFER, models.size() * sizeof(glm::mat4), models.data(), GL_DYNAMIC_DRAW); + + glBindBuffer(GL_ARRAY_BUFFER, 0); + + numOfBlocks = blocks.size(); +} + +void RenderSection::Render(RenderState &state) { + state.SetActiveVao(Vao); + glDrawArraysInstanced(GL_TRIANGLES, 0, 36, numOfBlocks); + glCheckError(); +} + +Section *RenderSection::GetSection() { + return &world->sections.find(sectionPosition)->second; +} + +RenderSection::RenderSection(const RenderSection &other) { + this->world = other.world; + this->VboModels = other.VboModels; + this->VboBlocks = other.VboBlocks; + this->sectionPosition = other.sectionPosition; + this->Vao = other.Vao; + this->numOfBlocks = other.numOfBlocks; + + refCounterVbo[VboBlocks]++; + refCounterVbo[VboModels]++; + refCounterVao[Vao]++; +} |