add particles lighting

This commit is contained in:
MihailRis 2024-11-03 02:23:37 +03:00
parent b944f257f7
commit 7abb1a88c7
10 changed files with 66 additions and 26 deletions

View File

@ -39,11 +39,14 @@ void Emitter::update(float delta, std::vector<Particle>& particles) {
// spawn particle
Particle particle = prototype;
particle.emitter = this;
particle.random = rand();
particle.position = position;
particle.velocity += glm::ballRand(1.0f) * explosion;
particles.push_back(std::move(particle));
timer -= spawnInterval;
count--;
if (count > 0) {
count--;
}
}
}

View File

@ -14,6 +14,7 @@ struct Particle {
/// @brief Pointer used to access common behaviour.
/// Emitter must be utilized after all related particles despawn.
Emitter* emitter;
int random;
/// @brief Global position
glm::vec3 position;
/// @brief Linear velocity
@ -28,6 +29,7 @@ class Texture;
struct ParticleBehaviour {
bool collision = true;
bool lighting = true;
glm::vec3 gravity {0.0f, -16.0f, 0.0f};
};

View File

@ -3,6 +3,8 @@
#include "graphics/core/Texture.hpp"
#include "graphics/core/Mesh.hpp"
#include "graphics/core/ImageData.hpp"
#include "voxels/Chunks.hpp"
#include "voxels/Chunk.hpp"
static const vattr attrs[] = {
{3}, {2}, {3}, {1}, {0}
@ -62,3 +64,19 @@ void MainBatch::prepare(int vertices) {
flush();
}
}
glm::vec4 MainBatch::sampleLight(
const glm::vec3& pos, const Chunks& chunks, bool backlight
) {
light_t light = chunks.getLight(
std::floor(pos.x),
std::floor(std::min(CHUNK_H-1.0f, pos.y)),
std::floor(pos.z));
light_t minIntensity = backlight ? 1 : 0;
return glm::vec4(
glm::max(Lightmap::extract(light, 0), minIntensity) / 15.0f,
glm::max(Lightmap::extract(light, 1), minIntensity) / 15.0f,
glm::max(Lightmap::extract(light, 2), minIntensity) / 15.0f,
glm::max(Lightmap::extract(light, 3), minIntensity) / 15.0f
);
}

View File

@ -9,6 +9,7 @@
class Mesh;
class Texture;
class Chunks;
class MainBatch {
std::unique_ptr<float[]> const buffer;
@ -36,6 +37,10 @@ public:
void setTexture(const Texture* texture, const UVRegion& region);
void flush();
static glm::vec4 sampleLight(
const glm::vec3& pos, const Chunks& chunks, bool backlight
);
inline void vertex(
const glm::vec3& pos,
const glm::vec2& uv,

View File

@ -65,17 +65,7 @@ void ModelBatch::draw(const model::Mesh& mesh, const glm::mat4& matrix,
bool backlight) {
glm::vec3 gpos = matrix * glm::vec4(0.0f, 0.0f, 0.0f, 1.0f);
gpos += lightsOffset;
light_t light = chunks->getLight(
std::floor(gpos.x),
std::floor(std::min(CHUNK_H-1.0f, gpos.y)),
std::floor(gpos.z));
light_t minIntensity = backlight ? 1 : 0;
glm::vec4 lights(
glm::max(Lightmap::extract(light, 0), minIntensity) / 15.0f,
glm::max(Lightmap::extract(light, 1), minIntensity) / 15.0f,
glm::max(Lightmap::extract(light, 2), minIntensity) / 15.0f,
glm::max(Lightmap::extract(light, 3), minIntensity) / 15.0f
);
glm::vec4 lights = MainBatch::sampleLight(gpos, *chunks, backlight);
setTexture(mesh.texture, varTextures);
size_t vcount = mesh.vertices.size();
const auto& vertexData = mesh.vertices.data();

View File

@ -8,16 +8,20 @@
#include "window/Camera.hpp"
#include "world/Level.hpp"
#include "voxels/Chunks.hpp"
#include "settings.hpp"
size_t ParticlesRenderer::visibleParticles = 0;
size_t ParticlesRenderer::aliveEmitters = 0;
ParticlesRenderer::ParticlesRenderer(const Assets& assets, const Level& level)
: batch(std::make_unique<MainBatch>(1024)), level(level) {
auto region = util::get_texture_region(assets, "blocks:bazalt", "");
emitters.push_back(std::make_unique<Emitter>(glm::vec3(0, 100, 0), Particle {
nullptr, glm::vec3(), glm::vec3(), 5.0f, region.region
ParticlesRenderer::ParticlesRenderer(
const Assets& assets, const Level& level, const GraphicsSettings* settings
)
: batch(std::make_unique<MainBatch>(1024)),
level(level),
settings(settings) {
auto region = util::get_texture_region(assets, "blocks:grass_top", "");
emitters.push_back(std::make_unique<Emitter>(glm::vec3(0, 80, 0), Particle {
nullptr, 0, glm::vec3(), glm::vec3(), 5.0f, region.region
},region.texture, 0.002f, -1));
}
@ -42,6 +46,9 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
const auto& right = camera.right;
const auto& up = camera.up;
const auto& chunks = *level.chunks;
bool backlight = settings->backlight.get();
std::vector<const Texture*> unusedTextures;
for (auto& [texture, vec] : particles) {
@ -57,14 +64,21 @@ void ParticlesRenderer::renderParticles(const Camera& camera, float delta) {
while (iter != vec.end()) {
auto& particle = *iter;
update_particle(particle, delta, *level.chunks);
update_particle(particle, delta, chunks);
glm::vec4 light(1, 1, 1, 0);
if (particle.emitter->behaviour.lighting) {
light = MainBatch::sampleLight(
particle.position, chunks, backlight
);
light *= 0.7f + (particle.random % 300) * 0.001f;
}
batch->quad(
particle.position,
right,
up,
glm::vec2(0.3f),
glm::vec4(1),
light,
glm::vec3(1.0f),
particle.region
);

View File

@ -11,16 +11,22 @@ class Assets;
class Camera;
class MainBatch;
class Level;
struct GraphicsSettings;
class ParticlesRenderer {
const Level& level;
const GraphicsSettings* settings;
std::unordered_map<const Texture*, std::vector<Particle>> particles;
std::vector<std::unique_ptr<Emitter>> emitters;
std::unique_ptr<MainBatch> batch;
void renderParticles(const Camera& camera, float delta);
public:
ParticlesRenderer(const Assets& assets, const Level& level);
ParticlesRenderer(
const Assets& assets,
const Level& level,
const GraphicsSettings* settings
);
~ParticlesRenderer();
void render(const Camera& camera, float delta);

View File

@ -63,7 +63,9 @@ WorldRenderer::WorldRenderer(
&engine->getSettings()
)),
particles(std::make_unique<ParticlesRenderer>(
*engine->getAssets(), *frontend->getLevel()
*engine->getAssets(),
*frontend->getLevel(),
&engine->getSettings().graphics
)) {
renderer = std::make_unique<ChunksRenderer>(
level, frontend->getContentGfxCache(), &engine->getSettings()

View File

@ -112,7 +112,7 @@ bool Chunks::isObstacleBlock(int32_t x, int32_t y, int32_t z) {
return indices->blocks.get(v->id)->obstacle; //-V522
}
ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) {
ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) const {
if (y < 0 || y >= CHUNK_H) {
return 0;
}
@ -132,7 +132,7 @@ ubyte Chunks::getLight(int32_t x, int32_t y, int32_t z, int channel) {
return chunk->lightmap.get(lx, y, lz, channel);
}
light_t Chunks::getLight(int32_t x, int32_t y, int32_t z) {
light_t Chunks::getLight(int32_t x, int32_t y, int32_t z) const {
if (y < 0 || y >= CHUNK_H) {
return 0;
}

View File

@ -60,8 +60,8 @@ public:
return get(pos.x, pos.y, pos.z);
}
light_t getLight(int32_t x, int32_t y, int32_t z);
ubyte getLight(int32_t x, int32_t y, int32_t z, int channel);
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;
void set(int32_t x, int32_t y, int32_t z, uint32_t id, blockstate state);
/// @brief Seek for the extended block origin position