mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-12 22:41:49 +00:00
feat: different textures/atlases support
This commit is contained in:
parent
27dd8f6375
commit
b0ecfd5add
3 changed files with 110 additions and 44 deletions
|
|
@ -1,7 +1,6 @@
|
||||||
#include "BlockWrapsRenderer.hpp"
|
#include "BlockWrapsRenderer.hpp"
|
||||||
|
|
||||||
#include "assets/Assets.hpp"
|
#include "assets/Assets.hpp"
|
||||||
#include "assets/assets_util.hpp"
|
|
||||||
#include "constants.hpp"
|
#include "constants.hpp"
|
||||||
#include "content/Content.hpp"
|
#include "content/Content.hpp"
|
||||||
#include "graphics/core/Atlas.hpp"
|
#include "graphics/core/Atlas.hpp"
|
||||||
|
|
@ -13,6 +12,8 @@
|
||||||
#include "voxels/Chunks.hpp"
|
#include "voxels/Chunks.hpp"
|
||||||
#include "world/Level.hpp"
|
#include "world/Level.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
BlockWrapsRenderer::BlockWrapsRenderer(
|
BlockWrapsRenderer::BlockWrapsRenderer(
|
||||||
const Assets& assets, const Level& level, const Chunks& chunks
|
const Assets& assets, const Level& level, const Chunks& chunks
|
||||||
)
|
)
|
||||||
|
|
@ -24,62 +25,46 @@ BlockWrapsRenderer::BlockWrapsRenderer(
|
||||||
|
|
||||||
BlockWrapsRenderer::~BlockWrapsRenderer() = default;
|
BlockWrapsRenderer::~BlockWrapsRenderer() = default;
|
||||||
|
|
||||||
void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) {
|
void BlockWrapsRenderer::draw(const BlockWrapper& wrapper, const Texture* texture) {
|
||||||
auto& shader = assets.require<Shader>("entity");
|
if (wrapper.cullingBits == 0x0) {
|
||||||
shader.use();
|
|
||||||
shader.uniform1i("u_alphaClip", false);
|
|
||||||
|
|
||||||
util::TextureRegion texRegions[6] {};
|
|
||||||
const Texture* texture = nullptr;
|
|
||||||
UVRegion uvRegions[6] {};
|
|
||||||
for (int i = 0; i < 6; i++) {
|
|
||||||
if (wrapper.cullingBits & (1 << i) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
auto texRegion = util::get_texture_region(assets, wrapper.textureFaces[i], "");
|
|
||||||
texRegions[i] = texRegion;
|
|
||||||
uvRegions[i] = texRegion.region;
|
|
||||||
|
|
||||||
if (texture == nullptr) {
|
|
||||||
texture = texRegion.texture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
batch->setTexture(texture);
|
|
||||||
|
|
||||||
const voxel* vox = chunks.get(wrapper.position);
|
|
||||||
if (vox == nullptr || vox->id == BLOCK_VOID) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto& def = level.content.getIndices()->blocks.require(vox->id);
|
|
||||||
switch (def.getModel(vox->state.userbits).type) {
|
uint8_t cullingBits = wrapper.cullingBits;
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
if ((cullingBits & (1 << i)) == 0x0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
cullingBits &= ~((wrapper.texRegions[i].texture != texture) << i);
|
||||||
|
}
|
||||||
|
if (cullingBits == 0x0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& def = level.content.getIndices()->blocks.require(wrapper.vox->id);
|
||||||
|
switch (def.getModel(wrapper.vox->state.userbits).type) {
|
||||||
case BlockModelType::BLOCK:
|
case BlockModelType::BLOCK:
|
||||||
batch->cube(
|
batch->cube(
|
||||||
glm::vec3(wrapper.position) + glm::vec3(0.5f),
|
glm::vec3(wrapper.position) + glm::vec3(0.5f),
|
||||||
glm::vec3(1.01f),
|
glm::vec3(1.01f),
|
||||||
uvRegions,
|
wrapper.uvRegions,
|
||||||
glm::vec4(1, 1, 1, 0),
|
glm::vec4(1, 1, 1, 0),
|
||||||
false,
|
false,
|
||||||
wrapper.cullingBits
|
cullingBits
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case BlockModelType::AABB: {
|
case BlockModelType::AABB: {
|
||||||
const auto& aabb =
|
const auto& aabb =
|
||||||
(def.rotatable ? def.rt.hitboxes[vox->state.rotation]
|
(def.rotatable ? def.rt.hitboxes[wrapper.vox->state.rotation]
|
||||||
: def.hitboxes).at(0);
|
: def.hitboxes).at(0);
|
||||||
const auto& size = aabb.size();
|
const auto& size = aabb.size();
|
||||||
uvRegions[0].scale(size.z, size.y);
|
|
||||||
uvRegions[1].scale(size.z, size.y);
|
|
||||||
uvRegions[2].scale(size.x, size.z);
|
|
||||||
uvRegions[3].scale(size.x, size.z);
|
|
||||||
uvRegions[4].scale(size.x, size.y);
|
|
||||||
uvRegions[5].scale(size.x, size.y);
|
|
||||||
batch->cube(
|
batch->cube(
|
||||||
glm::vec3(wrapper.position) + aabb.center(),
|
glm::vec3(wrapper.position) + aabb.center(),
|
||||||
size * glm::vec3(1.01f),
|
size * glm::vec3(1.01f),
|
||||||
uvRegions,
|
wrapper.uvRegions,
|
||||||
glm::vec4(1, 1, 1, 0),
|
glm::vec4(1, 1, 1, 0),
|
||||||
false,
|
false,
|
||||||
wrapper.cullingBits
|
cullingBits
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -88,10 +73,60 @@ void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlockWrapsRenderer::refreshWrapper(BlockWrapper& wrapper) {
|
||||||
|
for (int i = 0; i < 6; i++) {
|
||||||
|
if ((wrapper.cullingBits & (1 << i)) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto texRegion = util::get_texture_region(assets, wrapper.textureFaces[i], "");
|
||||||
|
wrapper.texRegions[i] = texRegion;
|
||||||
|
wrapper.uvRegions[i] = texRegion.region;
|
||||||
|
|
||||||
|
renderOrder.insert({texRegion.texture, &wrapper});
|
||||||
|
}
|
||||||
|
wrapper.dirtySides = 0x0;
|
||||||
|
|
||||||
|
const voxel* vox = chunks.get(wrapper.position);
|
||||||
|
if (vox == nullptr || vox->id == BLOCK_VOID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const auto& def = level.content.getIndices()->blocks.require(vox->id);
|
||||||
|
switch (def.getModel(vox->state.userbits).type) {
|
||||||
|
case BlockModelType::AABB: {
|
||||||
|
const auto& aabb =
|
||||||
|
(def.rotatable ? def.rt.hitboxes[vox->state.rotation]
|
||||||
|
: def.hitboxes).at(0);
|
||||||
|
const auto& size = aabb.size();
|
||||||
|
wrapper.uvRegions[0].scale(size.z, size.y);
|
||||||
|
wrapper.uvRegions[1].scale(size.z, size.y);
|
||||||
|
wrapper.uvRegions[2].scale(size.x, size.z);
|
||||||
|
wrapper.uvRegions[3].scale(size.x, size.z);
|
||||||
|
wrapper.uvRegions[4].scale(size.x, size.y);
|
||||||
|
wrapper.uvRegions[5].scale(size.x, size.y);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wrapper.vox = vox;
|
||||||
|
}
|
||||||
|
|
||||||
void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) {
|
void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) {
|
||||||
auto ctx = pctx.sub();
|
auto ctx = pctx.sub();
|
||||||
|
|
||||||
|
auto& shader = assets.require<Shader>("entity");
|
||||||
|
shader.use();
|
||||||
|
shader.uniform1i("u_alphaClip", false);
|
||||||
|
|
||||||
for (const auto& [_, wrapper] : wrappers) {
|
for (const auto& [_, wrapper] : wrappers) {
|
||||||
draw(*wrapper);
|
if (wrapper->dirtySides) {
|
||||||
|
refreshWrapper(*wrapper);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& [texture, wrapper] : renderOrder) {
|
||||||
|
batch->setTexture(texture);
|
||||||
|
draw(*wrapper, texture);
|
||||||
}
|
}
|
||||||
batch->flush();
|
batch->flush();
|
||||||
}
|
}
|
||||||
|
|
@ -114,5 +149,19 @@ BlockWrapper* BlockWrapsRenderer::get(u64id_t id) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockWrapsRenderer::remove(u64id_t id) {
|
void BlockWrapsRenderer::remove(u64id_t id) {
|
||||||
|
auto found = wrappers.find(id);
|
||||||
|
if (found == wrappers.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto wrapper = std::move(found->second);
|
||||||
wrappers.erase(id);
|
wrappers.erase(id);
|
||||||
|
|
||||||
|
auto it = renderOrder.begin();
|
||||||
|
while (it != renderOrder.end()) {
|
||||||
|
if (it->second == wrapper.get()) {
|
||||||
|
it = renderOrder.erase(it);
|
||||||
|
} else {
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,28 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include "assets/assets_util.hpp"
|
||||||
#include "MainBatch.hpp"
|
#include "MainBatch.hpp"
|
||||||
#include "typedefs.hpp"
|
#include "typedefs.hpp"
|
||||||
|
|
||||||
class Assets;
|
class Assets;
|
||||||
class Player;
|
class Player;
|
||||||
class Level;
|
class Level;
|
||||||
|
struct voxel;
|
||||||
class Chunks;
|
class Chunks;
|
||||||
|
class Texture;
|
||||||
class DrawContext;
|
class DrawContext;
|
||||||
|
|
||||||
struct BlockWrapper {
|
struct BlockWrapper {
|
||||||
glm::ivec3 position;
|
glm::ivec3 position;
|
||||||
std::array<std::string, 6> textureFaces {};
|
std::array<std::string, 6> textureFaces {};
|
||||||
|
util::TextureRegion texRegions[6] {};
|
||||||
|
UVRegion uvRegions[6] {};
|
||||||
|
const voxel* vox = nullptr;
|
||||||
uint8_t cullingBits = 0xFF;
|
uint8_t cullingBits = 0xFF;
|
||||||
|
uint8_t dirtySides = 0xFF;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BlockWrapsRenderer {
|
class BlockWrapsRenderer {
|
||||||
|
|
@ -26,10 +34,13 @@ class BlockWrapsRenderer {
|
||||||
const Chunks& chunks;
|
const Chunks& chunks;
|
||||||
std::unique_ptr<MainBatch> batch;
|
std::unique_ptr<MainBatch> batch;
|
||||||
|
|
||||||
|
std::multimap<const Texture*, BlockWrapper*> renderOrder;
|
||||||
std::unordered_map<u64id_t, std::unique_ptr<BlockWrapper>> wrappers;
|
std::unordered_map<u64id_t, std::unique_ptr<BlockWrapper>> wrappers;
|
||||||
u64id_t nextWrapper = 1;
|
u64id_t nextWrapper = 1;
|
||||||
|
|
||||||
void draw(const BlockWrapper& wrapper);
|
void draw(const BlockWrapper& wrapper, const Texture* texture);
|
||||||
|
|
||||||
|
void refreshWrapper(BlockWrapper& wrapper);
|
||||||
public:
|
public:
|
||||||
BlockWrapsRenderer(
|
BlockWrapsRenderer(
|
||||||
const Assets& assets, const Level& level, const Chunks& chunks
|
const Assets& assets, const Level& level, const Chunks& chunks
|
||||||
|
|
|
||||||
|
|
@ -40,11 +40,17 @@ static int l_set_faces(lua::State* L) {
|
||||||
if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) {
|
if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) {
|
||||||
for (int i = 0; i < wrapper->textureFaces.size(); i++) {
|
for (int i = 0; i < wrapper->textureFaces.size(); i++) {
|
||||||
if (lua::isnil(L, 2 + i)) {
|
if (lua::isnil(L, 2 + i)) {
|
||||||
wrapper->cullingBits &= ~(1 << i);
|
if (wrapper->cullingBits & (1 << i)) {
|
||||||
wrapper->textureFaces[i] = "";
|
wrapper->cullingBits &= ~(1 << i);
|
||||||
|
wrapper->textureFaces[i] = "";
|
||||||
|
wrapper->dirtySides |= (1 << i);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
wrapper->cullingBits |= (1 << i);
|
auto texture = lua::require_string(L, 2 + i);;
|
||||||
wrapper->textureFaces[i] = lua::require_string(L, 2 + i);
|
if ((wrapper->cullingBits & (1 << i)) == 0x0 || wrapper->textureFaces[i] != texture) {
|
||||||
|
wrapper->cullingBits |= (1 << i);
|
||||||
|
wrapper->textureFaces[i] = texture;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue