Browse Source

chunk rendering

feature/replace-renderer
Martin Dørum 3 years ago
parent
commit
7b477216e7
5 changed files with 30 additions and 33 deletions
  1. 2
    6
      libcygnet/src/Renderer.cc
  2. 10
    7
      libswan/include/swan/Chunk.h
  3. 10
    12
      libswan/src/Chunk.cc
  4. 4
    4
      libswan/src/Game.cc
  5. 4
    4
      libswan/src/WorldPlane.cc

+ 2
- 6
libcygnet/src/Renderer.cc View File



RenderChunk Renderer::createChunk( RenderChunk Renderer::createChunk(
TileID tiles[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT]) { TileID tiles[SwanCommon::CHUNK_WIDTH * SwanCommon::CHUNK_HEIGHT]) {
// TODO: Maybe don't do this here? Maybe instead store the buffer and
// upload the texture in the draw method?
// The current approach needs createChunk to be called on the graphics thread.

RenderChunk chunk; RenderChunk chunk;
glGenTextures(1, &chunk.tex); glGenTextures(1, &chunk.tex);
glCheck(); glCheck();
glBindTexture(GL_TEXTURE_2D, chunk.tex); glBindTexture(GL_TEXTURE_2D, chunk.tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glCheck(); glCheck();


static_assert( static_assert(

+ 10
- 7
libswan/include/swan/Chunk.h View File

#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <memory> #include <memory>
#include <cygnet/Renderer.h>


#include "util.h" #include "util.h"
#include "common.h" #include "common.h"


void setTileID(RelPos pos, Tile::ID id) { void setTileID(RelPos pos, Tile::ID id) {
getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id; getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id;
drawList_.push_back({pos, id});
changeList_.emplace_back(pos, id);
isModified_ = true;
} }


void setTileData(RelPos pos, Tile::ID id) { void setTileData(RelPos pos, Tile::ID id) {
getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id; getTileData()[pos.y * CHUNK_WIDTH + pos.x] = id;
needRender_ = true;
} }


uint8_t getLightLevel(RelPos pos) { uint8_t getLightLevel(RelPos pos) {
needLightRender_ = true; needLightRender_ = true;
} }


void compress();
void generateDone();
void keepActive();
void decompress(); void decompress();
void compress(Cygnet::Renderer &rnd);
void destroy(Cygnet::Renderer &rnd) { rnd.destroyChunk(renderChunk_); }
void draw(const Context &ctx, Cygnet::Renderer &rnd); void draw(const Context &ctx, Cygnet::Renderer &rnd);
TickAction tick(float dt); TickAction tick(float dt);


bool isActive() { return deactivateTimer_ > 0; } bool isActive() { return deactivateTimer_ > 0; }
void keepActive();
void markModified() { isModified_ = true; }


ChunkPos pos_; ChunkPos pos_;


bool isCompressed() { return compressedSize_ != -1; } bool isCompressed() { return compressedSize_ != -1; }


std::unique_ptr<uint8_t[]> data_; std::unique_ptr<uint8_t[]> data_;
std::vector<std::pair<RelPos, Tile::ID>> drawList_;
std::vector<std::pair<RelPos, Tile::ID>> changeList_;


ssize_t compressedSize_ = -1; // -1 if not compressed, a positive number if compressed ssize_t compressedSize_ = -1; // -1 if not compressed, a positive number if compressed
bool needRender_ = false;
Cygnet::RenderChunk renderChunk_;
bool needChunkRender_ = true;
bool needLightRender_ = false; bool needLightRender_ = false;
float deactivateTimer_ = DEACTIVATE_INTERVAL; float deactivateTimer_ = DEACTIVATE_INTERVAL;
bool isModified_ = false; bool isModified_ = false;

+ 10
- 12
libswan/src/Chunk.cc View File



namespace Swan { namespace Swan {


void Chunk::compress() {
void Chunk::compress(Cygnet::Renderer &rnd) {
if (isCompressed()) if (isCompressed())
return; return;


warn << "Chunk compression error: " << ret << " (Out of memory?)"; warn << "Chunk compression error: " << ret << " (Out of memory?)";
} }


// TODO: Delete renderChunk_
rnd.destroyChunk(renderChunk_);
} }


void Chunk::decompress() { void Chunk::decompress() {
} }


data_ = std::move(dest); data_ = std::move(dest);
needRender_ = true;


info info
<< "Decompressed chunk " << pos_ << " from " << "Decompressed chunk " << pos_ << " from "
<< DATA_SIZE << " bytes."; << DATA_SIZE << " bytes.";
compressedSize_ = -1; compressedSize_ = -1;


// TODO: Create renderChunk_
needChunkRender_ = true;
} }


void Chunk::draw(const Context &ctx, Cygnet::Renderer &rnd) { void Chunk::draw(const Context &ctx, Cygnet::Renderer &rnd) {
if (isCompressed()) if (isCompressed())
return; return;


// The world plane is responsible for managing initial renders
if (needRender_)
return;

if (drawList_.size() > 0) {
//renderList(win.renderer_); TODO
drawList_.clear();
if (needChunkRender_) {
renderChunk_ = rnd.createChunk((Tile::ID *)data_.get());
} else {
for (auto &change: changeList_) {
rnd.modifyChunk(renderChunk_, change.first, change.second);
}
} }


// rnd.drawChunk(renderChunk_, (Vec2)pos_ * Vec2{CHUNK_WIDTH, CHUNK_HEIGHT}); TODO
rnd.drawChunk(renderChunk_, (Vec2)pos_ * Vec2{CHUNK_WIDTH, CHUNK_HEIGHT});
} }


Chunk::TickAction Chunk::tick(float dt) { Chunk::TickAction Chunk::tick(float dt) {

+ 4
- 4
libswan/src/Game.cc View File

void Game::update(float dt) { void Game::update(float dt) {
// Zoom the window using the scroll wheel // Zoom the window using the scroll wheel
cam_.zoom += (float)wasWheelScrolled() * 0.1f * cam_.zoom; cam_.zoom += (float)wasWheelScrolled() * 0.1f * cam_.zoom;
if (cam_.zoom > 3)
cam_.zoom = 3;
else if (cam_.zoom < 0.3)
cam_.zoom = 0.3;
if (cam_.zoom > 1)
cam_.zoom = 1;
else if (cam_.zoom < 0.05)
cam_.zoom = 0.05;


world_->update(dt); world_->update(dt);



+ 4
- 4
libswan/src/WorldPlane.cc View File

} }


Chunk &chunk = slowGetChunk(pos); Chunk &chunk = slowGetChunk(pos);
tickChunks_.push_back({ pos, &chunk });
tickChunks_.push_back({pos, &chunk});
return chunk; return chunk;
} }


lc.blocks[y * CHUNK_HEIGHT + x] = true; lc.blocks[y * CHUNK_HEIGHT + x] = true;
} }
if (tile.lightLevel > 0) { if (tile.lightLevel > 0) {
lc.lightSources[{ x, y }] = tile.lightLevel;
lc.lightSources[{x, y}] = tile.lightLevel;
} }
} }
} }
Tile &newTile = world_->getTileByID(id); Tile &newTile = world_->getTileByID(id);
Tile &oldTile = world_->getTileByID(old); Tile &oldTile = world_->getTileByID(old);
chunk.setTileID(rp, id); chunk.setTileID(rp, id);
chunk.markModified();


if (!oldTile.isSolid && newTile.isSolid) { if (!oldTile.isSolid && newTile.isSolid) {
lighting_->onSolidBlockAdded(pos); lighting_->onSolidBlockAdded(pos);
switch (action) { switch (action) {
case Chunk::TickAction::DEACTIVATE: case Chunk::TickAction::DEACTIVATE:
info << "Compressing inactive modified chunk " << chunk->pos_; info << "Compressing inactive modified chunk " << chunk->pos_;
chunk->compress();
chunk->compress(world_->game_->renderer_);
iter = activeChunks_.erase(iter); iter = activeChunks_.erase(iter);
last = activeChunks_.end(); last = activeChunks_.end();
break; break;
case Chunk::TickAction::DELETE: case Chunk::TickAction::DELETE:
info << "Deleting inactive unmodified chunk " << chunk->pos_; info << "Deleting inactive unmodified chunk " << chunk->pos_;
chunk->destroy(world_->game_->renderer_);
chunks_.erase(chunk->pos_); chunks_.erase(chunk->pos_);
iter = activeChunks_.erase(iter); iter = activeChunks_.erase(iter);
last = activeChunks_.end(); last = activeChunks_.end();

Loading…
Cancel
Save