mirror of
https://github.com/MihailRis/voxelcore.git
synced 2026-10-04 18:41:51 +00:00
Merge pull request #742 from MihailRis/block-wraps-update
Block wraps update
This commit is contained in:
commit
1940fa7fa4
12 changed files with 341 additions and 95 deletions
|
|
@ -7,7 +7,14 @@ Block wrappers are introduced to implement block destruction animation and can b
|
||||||
```lua
|
```lua
|
||||||
-- Creates a wrapper at the specified position, with the specified texture.
|
-- Creates a wrapper at the specified position, with the specified texture.
|
||||||
-- Returns the wrapper id.
|
-- Returns the wrapper id.
|
||||||
gfx.blockwraps.wrap(position: vec3, texture: str) --> int
|
gfx.blockwraps.wrap(
|
||||||
|
-- block position
|
||||||
|
position: vec3,
|
||||||
|
-- wrap texture
|
||||||
|
texture: string,
|
||||||
|
-- emission [0.0; 1.0]
|
||||||
|
[optional] emission: number = 1.0
|
||||||
|
) -> int
|
||||||
|
|
||||||
-- Removes the wrapper, if it exists.
|
-- Removes the wrapper, if it exists.
|
||||||
gfx.blockwraps.unwrap(id: int)
|
gfx.blockwraps.unwrap(id: int)
|
||||||
|
|
@ -17,6 +24,35 @@ gfx.blockwraps.set_pos(id: int, position: vec3)
|
||||||
|
|
||||||
-- Changes the texture of the wrapper, if it exists.
|
-- Changes the texture of the wrapper, if it exists.
|
||||||
gfx.blockwraps.set_texture(id: int, texture: str)
|
gfx.blockwraps.set_texture(id: int, texture: str)
|
||||||
|
|
||||||
|
-- Sets the face textures (-X, +X, -Y, +Y, -Z, +Z).
|
||||||
|
-- - nil - disables face rendering.
|
||||||
|
-- - "" - monotone texture.
|
||||||
|
gfx.blockwraps.set_faces(
|
||||||
|
-- wrapper id
|
||||||
|
id: int,
|
||||||
|
-- face texture 1 (-X)
|
||||||
|
face1?: string,
|
||||||
|
-- face texture 2 (+X)
|
||||||
|
face2?: string,
|
||||||
|
...
|
||||||
|
-- face texture 6 (+Z)
|
||||||
|
face6?: string
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Sets the tint of the sides (-X, +X, -Y, +Y, -Z, +Z).
|
||||||
|
-- RGB [0.0; 1.0]
|
||||||
|
gfx.blockwraps.set_tints(
|
||||||
|
-- wrapper id
|
||||||
|
id: int,
|
||||||
|
-- side 1 color (-X)
|
||||||
|
face1?: vec3,
|
||||||
|
-- side 2 color (+X)
|
||||||
|
face2?: vec3,
|
||||||
|
...
|
||||||
|
-- side 6 color (+Z)
|
||||||
|
face6?: vec3
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Wrappers are not automatically removed without calling `unwrap`.
|
Wrappers will not be automatically removed without calling `unwrap`.
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,14 @@
|
||||||
```lua
|
```lua
|
||||||
-- Создаёт обертку на указанной позиции, с указанной текстурой.
|
-- Создаёт обертку на указанной позиции, с указанной текстурой.
|
||||||
-- Возвращает id обёртки.
|
-- Возвращает id обёртки.
|
||||||
gfx.blockwraps.wrap(position: vec3, texture: string) -> int
|
gfx.blockwraps.wrap(
|
||||||
|
-- Позиция блока
|
||||||
|
position: vec3,
|
||||||
|
-- Текстура обёртки
|
||||||
|
texture: string,
|
||||||
|
-- Излучение [0.0; 1.0]
|
||||||
|
[опционально] emission: number = 1.0
|
||||||
|
) -> int
|
||||||
|
|
||||||
-- Удаляет обертку, если она существует.
|
-- Удаляет обертку, если она существует.
|
||||||
gfx.blockwraps.unwrap(id: int)
|
gfx.blockwraps.unwrap(id: int)
|
||||||
|
|
@ -18,6 +25,35 @@ gfx.blockwraps.set_pos(id: int, position: vec3)
|
||||||
|
|
||||||
-- Меняет текстуру обёртки, если она существует.
|
-- Меняет текстуру обёртки, если она существует.
|
||||||
gfx.blockwraps.set_texture(id: int, texture: string)
|
gfx.blockwraps.set_texture(id: int, texture: string)
|
||||||
|
|
||||||
|
-- Устанавливает текстуры сторон (-X, +X, -Y, +Y, -Z, +Z).
|
||||||
|
-- - nil - отключает отображение стороны.
|
||||||
|
-- - "" - монотонная текстура.
|
||||||
|
gfx.blockwraps.set_faces(
|
||||||
|
-- id обёртки
|
||||||
|
id: int,
|
||||||
|
-- текстура стороны 1 (-X)
|
||||||
|
face1?: string,
|
||||||
|
-- текстура стороны 2 (+X)
|
||||||
|
face2?: string,
|
||||||
|
...
|
||||||
|
-- текстура стороны 6 (+Z)
|
||||||
|
face6?: string
|
||||||
|
)
|
||||||
|
|
||||||
|
-- Устанавливает окраску сторон (-X, +X, -Y, +Y, -Z, +Z).
|
||||||
|
-- RGB [0.0; 1.0]
|
||||||
|
gfx.blockwraps.set_tints(
|
||||||
|
-- id обёртки
|
||||||
|
id: int,
|
||||||
|
-- цвет стороны 1 (-X)
|
||||||
|
face1?: vec3,
|
||||||
|
-- цвет стороны 2 (+X)
|
||||||
|
face2?: vec3,
|
||||||
|
...
|
||||||
|
-- цвет стороны 6 (+Z)
|
||||||
|
face6?: vec3
|
||||||
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
Обертки не удаляются автоматически без вызова `unwrap`.
|
Обертки не удаляются автоматически без вызова `unwrap`.
|
||||||
|
|
@ -1,18 +1,20 @@
|
||||||
#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"
|
||||||
#include "graphics/core/Shader.hpp"
|
#include "graphics/core/Shader.hpp"
|
||||||
#include "graphics/core/DrawContext.hpp"
|
#include "graphics/core/DrawContext.hpp"
|
||||||
#include "graphics/render/MainBatch.hpp"
|
#include "graphics/render/MainBatch.hpp"
|
||||||
|
#include "lighting/Lightmap.hpp"
|
||||||
#include "objects/Player.hpp"
|
#include "objects/Player.hpp"
|
||||||
#include "voxels/Block.hpp"
|
#include "voxels/Block.hpp"
|
||||||
#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,78 +26,145 @@ BlockWrapsRenderer::BlockWrapsRenderer(
|
||||||
|
|
||||||
BlockWrapsRenderer::~BlockWrapsRenderer() = default;
|
BlockWrapsRenderer::~BlockWrapsRenderer() = default;
|
||||||
|
|
||||||
void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) {
|
void BlockWrapsRenderer::draw(BlockWrapper& wrapper, const Texture* texture) {
|
||||||
auto textureRegion = util::get_texture_region(assets, wrapper.texture, "");
|
if (wrapper.cullingBits == 0x0) {
|
||||||
|
|
||||||
auto& shader = assets.require<Shader>("entity");
|
|
||||||
shader.use();
|
|
||||||
shader.uniform1i("u_alphaClip", false);
|
|
||||||
|
|
||||||
const UVRegion& cracksRegion = textureRegion.region;
|
|
||||||
UVRegion regions[6] {
|
|
||||||
cracksRegion, cracksRegion, cracksRegion,
|
|
||||||
cracksRegion, cracksRegion, cracksRegion
|
|
||||||
};
|
|
||||||
batch->setTexture(textureRegion.texture);
|
|
||||||
|
|
||||||
const voxel* vox = chunks.get(wrapper.position);
|
|
||||||
if (vox == nullptr) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (vox->id != BLOCK_VOID) {
|
|
||||||
const auto& def = level.content.getIndices()->blocks.require(vox->id);
|
uint8_t cullingBits = wrapper.cullingBits;
|
||||||
switch (def.getModel(vox->state.userbits).type) {
|
for (int i = 0; i < 6; i++) {
|
||||||
case BlockModelType::BLOCK:
|
if ((cullingBits & (1 << i)) == 0x0) {
|
||||||
batch->cube(
|
continue;
|
||||||
glm::vec3(wrapper.position) + glm::vec3(0.5f),
|
|
||||||
glm::vec3(1.01f),
|
|
||||||
regions,
|
|
||||||
glm::vec4(1,1,1,0),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case BlockModelType::AABB: {
|
|
||||||
const auto& aabb =
|
|
||||||
(def.rotatable ? def.rt.hitboxes[vox->state.rotation]
|
|
||||||
: def.hitboxes)
|
|
||||||
.at(0);
|
|
||||||
const auto& size = aabb.size();
|
|
||||||
regions[0].scale(size.z, size.y);
|
|
||||||
regions[1].scale(size.z, size.y);
|
|
||||||
regions[2].scale(size.x, size.z);
|
|
||||||
regions[3].scale(size.x, size.z);
|
|
||||||
regions[4].scale(size.x, size.y);
|
|
||||||
regions[5].scale(size.x, size.y);
|
|
||||||
batch->cube(
|
|
||||||
glm::vec3(wrapper.position) + aabb.center(),
|
|
||||||
size * glm::vec3(1.01f),
|
|
||||||
regions,
|
|
||||||
glm::vec4(1,1,1,0),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
cullingBits &= ~((wrapper.texRegions[i].texture != texture) << i);
|
||||||
|
}
|
||||||
|
if (cullingBits == 0x0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const voxel* vox = chunks.get(wrapper.position);
|
||||||
|
if (vox == nullptr || vox->id == BLOCK_VOID) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// one frame can be invalid due to texture change but ok
|
||||||
|
const auto& def =
|
||||||
|
level.content.getIndices()->blocks.require(vox->id);
|
||||||
|
|
||||||
|
if (wrapper.modelType != def.getModel(vox->state.userbits).type) {
|
||||||
|
wrapper.dirtySides = 0xFF;
|
||||||
|
refreshWrapper(wrapper);
|
||||||
|
}
|
||||||
|
glm::vec4 light(1, 1, 1, 0);
|
||||||
|
if (wrapper.emission < 1.0f) {
|
||||||
|
light = Lightmap::extractNormalized(chunks.getLight(wrapper.position));
|
||||||
|
light.r += wrapper.emission;
|
||||||
|
light.g += wrapper.emission;
|
||||||
|
light.b += wrapper.emission;
|
||||||
|
}
|
||||||
|
switch (wrapper.modelType) {
|
||||||
|
case BlockModelType::BLOCK:
|
||||||
|
batch->cube(
|
||||||
|
glm::vec3(wrapper.position) + glm::vec3(0.5f),
|
||||||
|
glm::vec3(1.01f),
|
||||||
|
wrapper.uvRegions,
|
||||||
|
light,
|
||||||
|
wrapper.tints.data(),
|
||||||
|
wrapper.emission,
|
||||||
|
cullingBits
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
case BlockModelType::AABB: {
|
||||||
|
const auto& aabb =
|
||||||
|
(def.rotatable ? def.rt.hitboxes[vox->state.rotation]
|
||||||
|
: def.hitboxes).at(0);
|
||||||
|
const auto& size = aabb.size();
|
||||||
|
batch->cube(
|
||||||
|
glm::vec3(wrapper.position) + aabb.center(),
|
||||||
|
size * glm::vec3(1.01f),
|
||||||
|
wrapper.uvRegions,
|
||||||
|
light,
|
||||||
|
wrapper.tints.data(),
|
||||||
|
wrapper.emission,
|
||||||
|
cullingBits
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
wrapper.modelType = def.getModel(vox->state.userbits).type;
|
||||||
|
switch (wrapper.modelType) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
u64id_t BlockWrapsRenderer::add(
|
u64id_t BlockWrapsRenderer::add(
|
||||||
const glm::ivec3& position, const std::string& texture
|
const glm::ivec3& position,
|
||||||
|
const std::string& texture,
|
||||||
|
const glm::vec3& tint,
|
||||||
|
float emission
|
||||||
) {
|
) {
|
||||||
u64id_t id = nextWrapper++;
|
u64id_t id = nextWrapper++;
|
||||||
wrappers[id] = std::make_unique<BlockWrapper>(
|
wrappers[id] = std::make_unique<BlockWrapper>(BlockWrapper {
|
||||||
BlockWrapper {position, texture}
|
position,
|
||||||
);
|
{texture, texture, texture, texture, texture, texture},
|
||||||
|
{tint, tint, tint, tint, tint, tint},
|
||||||
|
emission});
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,5 +177,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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,37 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "assets/assets_util.hpp"
|
||||||
|
#include "voxels/Block.hpp"
|
||||||
|
#include "MainBatch.hpp"
|
||||||
|
#include "typedefs.hpp"
|
||||||
|
|
||||||
|
#include <array>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <map>
|
||||||
#include "MainBatch.hpp"
|
#include <glm/vec4.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::string texture;
|
std::array<std::string, 6> textureFaces {};
|
||||||
|
std::array<glm::vec3, 6> tints {};
|
||||||
|
float emission = 0.0f;
|
||||||
|
|
||||||
|
// --- render cache ---
|
||||||
|
util::TextureRegion texRegions[6] {};
|
||||||
|
UVRegion uvRegions[6] {};
|
||||||
|
BlockModelType modelType {};
|
||||||
|
uint8_t cullingBits = 0xFF;
|
||||||
|
uint8_t dirtySides = 0xFF;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BlockWrapsRenderer {
|
class BlockWrapsRenderer {
|
||||||
|
|
@ -24,10 +40,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(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
|
||||||
|
|
@ -36,7 +55,12 @@ public:
|
||||||
|
|
||||||
void draw(const DrawContext& ctx, const Player& player);
|
void draw(const DrawContext& ctx, const Player& player);
|
||||||
|
|
||||||
u64id_t add(const glm::ivec3& position, const std::string& texture);
|
u64id_t add(
|
||||||
|
const glm::ivec3& position,
|
||||||
|
const std::string& texture,
|
||||||
|
const glm::vec3& tint,
|
||||||
|
float emission
|
||||||
|
);
|
||||||
|
|
||||||
BlockWrapper* get(u64id_t id) const;
|
BlockWrapper* get(u64id_t id) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -452,10 +452,7 @@ glm::vec4 BlocksRenderer::pickLight(int x, int y, int z) const {
|
||||||
if (isOpenForLight(x, y, z)) {
|
if (isOpenForLight(x, y, z)) {
|
||||||
light_t light = voxelsBuffer->pickLight(chunk->x * CHUNK_W + x, y,
|
light_t light = voxelsBuffer->pickLight(chunk->x * CHUNK_W + x, y,
|
||||||
chunk->z * CHUNK_D + z);
|
chunk->z * CHUNK_D + z);
|
||||||
return glm::vec4(Lightmap::extract(light, 0),
|
return Lightmap::extractNormalized(light);
|
||||||
Lightmap::extract(light, 1),
|
|
||||||
Lightmap::extract(light, 2),
|
|
||||||
Lightmap::extract(light, 3)) / 15.0f;
|
|
||||||
} else {
|
} else {
|
||||||
return glm::vec4(0.0f);
|
return glm::vec4(0.0f);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -128,12 +128,11 @@ const Mesh<ChunkVertex>* ChunksRenderer::render(
|
||||||
chunk->flags.modified = false;
|
chunk->flags.modified = false;
|
||||||
if (important) {
|
if (important) {
|
||||||
auto voxelsBuffer = prepareVoxelsVolume(*chunk);
|
auto voxelsBuffer = prepareVoxelsVolume(*chunk);
|
||||||
inwork[key] = true;
|
|
||||||
|
|
||||||
auto mesh = renderer->render(chunk.get(), *voxelsBuffer);
|
auto mesh = renderer->render(chunk.get(), *voxelsBuffer);
|
||||||
meshes[glm::ivec2(chunk->x, chunk->z)] =
|
meshes[key] =
|
||||||
ChunkMesh {std::move(mesh.mesh), std::move(mesh.sortingMeshData)};
|
ChunkMesh {std::move(mesh.mesh), std::move(mesh.sortingMeshData)};
|
||||||
return meshes[glm::ivec2(chunk->x, chunk->z)].mesh.get();
|
return meshes[key].mesh.get();
|
||||||
}
|
}
|
||||||
if (inwork.find(key) != inwork.end()) {
|
if (inwork.find(key) != inwork.end()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
|
||||||
|
|
@ -83,50 +83,58 @@ inline glm::vec4 do_tint(float value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainBatch::cube(
|
void MainBatch::cube(
|
||||||
const glm::vec3 &coord,
|
const glm::vec3& coord,
|
||||||
const glm::vec3 &size,
|
const glm::vec3& size,
|
||||||
const UVRegion(&texfaces)[6],
|
const UVRegion(&texfaces)[6],
|
||||||
const glm::vec4 &tint,
|
const glm::vec4& lights,
|
||||||
bool shading
|
const glm::vec3 tints[],
|
||||||
|
float emission,
|
||||||
|
uint8_t cullingBits
|
||||||
) {
|
) {
|
||||||
const glm::vec3 X(1.0f, 0.0f, 0.0f);
|
const glm::vec3 X(1.0f, 0.0f, 0.0f);
|
||||||
const glm::vec3 Y(0.0f, 1.0f, 0.0f);
|
const glm::vec3 Y(0.0f, 1.0f, 0.0f);
|
||||||
const glm::vec3 Z(0.0f, 0.0f, 1.0f);
|
const glm::vec3 Z(0.0f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
if (cullingBits & 0x20)
|
||||||
quad(
|
quad(
|
||||||
coord + Z * size.z * 0.5f,
|
coord + Z * size.z * 0.5f,
|
||||||
X, Y, Z, glm::vec2(size.x, size.y),
|
X, Y, Z, glm::vec2(size.x, size.y),
|
||||||
(shading ? do_tint(0.8) * tint : tint),
|
do_tint((1.0f - emission) * 0.8 + emission) * lights,
|
||||||
glm::vec3(1.0f), texfaces[5]
|
tints[5], texfaces[5]
|
||||||
);
|
);
|
||||||
|
if (cullingBits & 0x10)
|
||||||
quad(
|
quad(
|
||||||
coord - Z * size.z * 0.5f,
|
coord - Z * size.z * 0.5f,
|
||||||
-X, Y, -Z, glm::vec2(size.x, size.y),
|
-X, Y, -Z, glm::vec2(size.x, size.y),
|
||||||
(shading ? do_tint(0.9f) * tint : tint),
|
do_tint((1.0f - emission) * 0.9 + emission) * lights,
|
||||||
glm::vec3(1.0f), texfaces[4]
|
tints[4], texfaces[4]
|
||||||
);
|
);
|
||||||
|
if (cullingBits & 0x8)
|
||||||
quad(
|
quad(
|
||||||
coord + Y * size.y * 0.5f,
|
coord + Y * size.y * 0.5f,
|
||||||
-X, Z, Y, glm::vec2(size.x, size.z),
|
-X, Z, Y, glm::vec2(size.x, size.z),
|
||||||
(shading ? do_tint(1.0f) * tint : tint),
|
do_tint((1.0f - emission) * 1.0 + emission) * lights,
|
||||||
glm::vec3(1.0f), texfaces[3]
|
tints[3], texfaces[3]
|
||||||
);
|
);
|
||||||
|
if (cullingBits & 0x4)
|
||||||
quad(
|
quad(
|
||||||
coord - Y * size.y * 0.5f,
|
coord - Y * size.y * 0.5f,
|
||||||
X, Z, -Y, glm::vec2(size.x, size.z),
|
X, Z, -Y, glm::vec2(size.x, size.z),
|
||||||
(shading ? do_tint(0.7f) * tint : tint),
|
do_tint((1.0f - emission) * 0.7 + emission) * lights,
|
||||||
glm::vec3(1.0f), texfaces[2]
|
tints[2], texfaces[2]
|
||||||
);
|
);
|
||||||
|
if (cullingBits & 0x2)
|
||||||
quad(
|
quad(
|
||||||
coord + X * size.x * 0.5f,
|
coord + X * size.x * 0.5f,
|
||||||
-Z, Y, X, glm::vec2(size.z, size.y),
|
-Z, Y, X, glm::vec2(size.z, size.y),
|
||||||
(shading ? do_tint(0.8f) * tint : tint),
|
do_tint((1.0f - emission) * 0.8 + emission) * lights,
|
||||||
glm::vec3(1.0f), texfaces[1]
|
tints[1], texfaces[1]
|
||||||
);
|
);
|
||||||
|
if (cullingBits & 0x1)
|
||||||
quad(
|
quad(
|
||||||
coord - X * size.x * 0.5f,
|
coord - X * size.x * 0.5f,
|
||||||
Z, Y, -X, glm::vec2(size.z, size.y),
|
Z, Y, -X, glm::vec2(size.z, size.y),
|
||||||
(shading ? do_tint(0.9f) * tint : tint),
|
do_tint((1.0f - emission) * 0.9 + emission) * lights,
|
||||||
glm::vec3(1.0f), texfaces[1]
|
tints[0], texfaces[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -151,7 +151,9 @@ public:
|
||||||
const glm::vec3& coord,
|
const glm::vec3& coord,
|
||||||
const glm::vec3& size,
|
const glm::vec3& size,
|
||||||
const UVRegion(&texfaces)[6],
|
const UVRegion(&texfaces)[6],
|
||||||
const glm::vec4& tint,
|
const glm::vec4& lights,
|
||||||
bool shading
|
const glm::vec3 tints[],
|
||||||
|
float emission,
|
||||||
|
uint8_t cullingBits = 0xFF
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <glm/vec4.hpp>
|
||||||
|
|
||||||
inline constexpr int LIGHTMAP_DATA_LEN = CHUNK_VOL/2;
|
inline constexpr int LIGHTMAP_DATA_LEN = CHUNK_VOL/2;
|
||||||
|
|
||||||
|
|
@ -87,6 +88,15 @@ public:
|
||||||
return (light >> (channel << 2)) & 0xF;
|
return (light >> (channel << 2)) & 0xF;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static glm::vec4 extractNormalized(light_t light) {
|
||||||
|
return glm::vec4(
|
||||||
|
extract(light, 0) / 15.0f,
|
||||||
|
extract(light, 1) / 15.0f,
|
||||||
|
extract(light, 2) / 15.0f,
|
||||||
|
extract(light, 3) / 15.0f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<ubyte[]> encode() const;
|
std::unique_ptr<ubyte[]> encode() const;
|
||||||
void decode(const ubyte* src);
|
void decode(const ubyte* src);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,14 @@ using namespace scripting;
|
||||||
static int l_wrap(lua::State* L) {
|
static int l_wrap(lua::State* L) {
|
||||||
auto position = lua::tovec3(L, 1);
|
auto position = lua::tovec3(L, 1);
|
||||||
std::string texture = lua::require_string(L, 2);
|
std::string texture = lua::require_string(L, 2);
|
||||||
|
float emission = lua::isnumber(L, 3) ? lua::tonumber(L, 3) : 1.0f;
|
||||||
|
glm::vec3 tint = lua::istable(L, 4) ? lua::tovec3(L, 4) : glm::vec3(1.0f);
|
||||||
|
|
||||||
return lua::pushinteger(
|
return lua::pushinteger(
|
||||||
L, renderer->blockWraps->add(position, std::move(texture))
|
L,
|
||||||
|
renderer->blockWraps->add(
|
||||||
|
position, std::move(texture), std::move(tint), emission
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -29,7 +34,46 @@ static int l_set_pos(lua::State* L) {
|
||||||
|
|
||||||
static int l_set_texture(lua::State* L) {
|
static int l_set_texture(lua::State* L) {
|
||||||
if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) {
|
if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) {
|
||||||
wrapper->texture = lua::require_string(L, 2);
|
for (int i = 0; i < wrapper->textureFaces.size(); i++) {
|
||||||
|
wrapper->textureFaces[i] = lua::require_string(L, 2);
|
||||||
|
}
|
||||||
|
wrapper->dirtySides = 0xFF;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_set_faces(lua::State* L) {
|
||||||
|
if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) {
|
||||||
|
for (int i = 0; i < wrapper->textureFaces.size(); i++) {
|
||||||
|
if (lua::isnil(L, 2 + i)) {
|
||||||
|
if (wrapper->cullingBits & (1 << i)) {
|
||||||
|
wrapper->cullingBits &= ~(1 << i);
|
||||||
|
wrapper->textureFaces[i] = "";
|
||||||
|
wrapper->dirtySides |= (1 << i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auto texture = lua::require_string(L, 2 + i);;
|
||||||
|
if ((wrapper->cullingBits & (1 << i)) == 0x0
|
||||||
|
|| wrapper->textureFaces[i] != texture) {
|
||||||
|
wrapper->cullingBits |= (1 << i);
|
||||||
|
wrapper->textureFaces[i] = texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int l_set_tints(lua::State* L) {
|
||||||
|
if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) {
|
||||||
|
for (int i = 0; i < wrapper->textureFaces.size(); i++) {
|
||||||
|
if (lua::isnil(L, 2 + i)) {
|
||||||
|
wrapper->tints[i] = glm::vec3(1.0f);
|
||||||
|
} else {
|
||||||
|
wrapper->tints[i] = lua::tovec3(L, 2 + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wrapper->dirtySides = 0xFF;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -39,5 +83,7 @@ const luaL_Reg blockwrapslib[] = {
|
||||||
{"unwrap", lua::wrap<l_unwrap>},
|
{"unwrap", lua::wrap<l_unwrap>},
|
||||||
{"set_pos", lua::wrap<l_set_pos>},
|
{"set_pos", lua::wrap<l_set_pos>},
|
||||||
{"set_texture", lua::wrap<l_set_texture>},
|
{"set_texture", lua::wrap<l_set_texture>},
|
||||||
|
{"set_faces", lua::wrap<l_set_faces>},
|
||||||
|
{"set_tints", lua::wrap<l_set_tints>},
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,10 @@ bool Chunks::isObstacleBlock(int32_t x, int32_t y, int32_t z) {
|
||||||
return indices.blocks.require(v->id).obstacle;
|
return indices.blocks.require(v->id).obstacle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
light_t Chunks::getLight(const glm::ivec3& pos) const {
|
||||||
|
return getLight(pos.x, pos.y, pos.z);
|
||||||
|
}
|
||||||
|
|
||||||
ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) const {
|
ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) const {
|
||||||
if (y < 0 || y >= CHUNK_H) {
|
if (y < 0 || y >= CHUNK_H) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,7 @@ public:
|
||||||
return get(pos.x, pos.y, pos.z);
|
return get(pos.x, pos.y, pos.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
light_t getLight(const glm::ivec3& pos) const;
|
||||||
light_t getLight(int32_t x, int32_t y, int32_t z) const;
|
light_t getLight(int32_t x, int32_t y, int32_t z) const;
|
||||||
ubyte getLight(int32_t x, int32_t y, int32_t z, int channel) const;
|
ubyte getLight(int32_t x, int32_t y, int32_t z, int channel) const;
|
||||||
void set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state);
|
void set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue