From d2605d91084a7087d2dfc2b48569db39392908fd Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 12 Dec 2025 16:58:23 +0600 Subject: [PATCH] moved drawEffect() to SparkEmitter --- Game.cpp | 74 +--------------------- Game.h | 3 - SparkEmitter.cpp | 159 +++++++++++++++++++++++++++++++++-------------- SparkEmitter.h | 27 ++++---- 4 files changed, 131 insertions(+), 132 deletions(-) diff --git a/Game.cpp b/Game.cpp index fe5f577..5714bc2 100755 --- a/Game.cpp +++ b/Game.cpp @@ -200,8 +200,7 @@ namespace ZL sparkTexture = std::make_unique(CreateTextureDataFromPng("./resources/spark.png", CONST_ZIP_FILE)); - sparkQuad.data = CreateRect2D({ 0, 0 }, { 0.08f, 0.08f }, 0); - sparkQuad.RefreshVBO(); + sparkEmitter.setTexture(sparkTexture); renderer.InitOpenGL(); @@ -241,75 +240,6 @@ namespace ZL CheckGlError(); } - void Game::drawEffects() - { - if (sparkEmitter.getActiveParticleCount() == 0) { - return; - } - - sparkQuad.data.PositionData.clear(); - sparkQuad.data.TexCoordData.clear(); - - const auto& particles = sparkEmitter.getParticles(); - for (const auto& particle : particles) { - if (!particle.active) continue; - - Vector3f pos = particle.position; - float size = 0.04f * particle.scale; - - sparkQuad.data.PositionData.push_back({ pos.v[0] - size, pos.v[1] - size, pos.v[2] }); - sparkQuad.data.TexCoordData.push_back({ 0.0f, 0.0f }); - - sparkQuad.data.PositionData.push_back({ pos.v[0] - size, pos.v[1] + size, pos.v[2] }); - sparkQuad.data.TexCoordData.push_back({ 0.0f, 1.0f }); - - sparkQuad.data.PositionData.push_back({ pos.v[0] + size, pos.v[1] + size, pos.v[2] }); - sparkQuad.data.TexCoordData.push_back({ 1.0f, 1.0f }); - - sparkQuad.data.PositionData.push_back({ pos.v[0] - size, pos.v[1] - size, pos.v[2] }); - sparkQuad.data.TexCoordData.push_back({ 0.0f, 0.0f }); - - sparkQuad.data.PositionData.push_back({ pos.v[0] + size, pos.v[1] + size, pos.v[2] }); - sparkQuad.data.TexCoordData.push_back({ 1.0f, 1.0f }); - - sparkQuad.data.PositionData.push_back({ pos.v[0] + size, pos.v[1] - size, pos.v[2] }); - sparkQuad.data.TexCoordData.push_back({ 1.0f, 0.0f }); - } - - if (sparkQuad.data.PositionData.empty()) return; - - sparkQuad.RefreshVBO(); - - static const std::string defaultShaderName = "default"; - static const std::string vPositionName = "vPosition"; - static const std::string vTexCoordName = "vTexCoord"; - static const std::string textureUniformName = "Texture"; - - renderer.shaderManager.PushShader(defaultShaderName); - renderer.RenderUniform1i(textureUniformName, 0); - renderer.EnableVertexAttribArray(vPositionName); - renderer.EnableVertexAttribArray(vTexCoordName); - - renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, - static_cast(Environment::width) / static_cast(Environment::height), - 1, 1000); - - glBindTexture(GL_TEXTURE_2D, sparkTexture->getTexID()); - - renderer.PushMatrix(); - renderer.LoadIdentity(); - renderer.TranslateMatrix({ 0, 0, -1.0f * Environment::zoom }); - - renderer.DrawVertexRenderStruct(sparkQuad); - - renderer.PopMatrix(); - renderer.PopProjectionMatrix(); - renderer.DisableVertexAttribArray(vPositionName); - renderer.DisableVertexAttribArray(vTexCoordName); - renderer.shaderManager.PopShader(); - CheckGlError(); - } - void Game::drawShip() { static const std::string defaultShaderName = "default"; @@ -335,7 +265,7 @@ namespace ZL glBindTexture(GL_TEXTURE_2D, spaceshipTexture->getTexID()); renderer.DrawVertexRenderStruct(spaceship); - drawEffects(); + sparkEmitter.draw(renderer, Environment::zoom, Environment::width, Environment::height); renderer.PopMatrix(); renderer.PopProjectionMatrix(); diff --git a/Game.h b/Game.h index 5f65f98..236e8ce 100755 --- a/Game.h +++ b/Game.h @@ -31,7 +31,6 @@ namespace ZL { void processTickCount(); void drawScene(); void drawCubemap(); - void drawEffects(); void drawShip(); void drawBoxes(); @@ -59,9 +58,7 @@ namespace ZL { std::vector boxCoordsArr; std::vector boxRenderArr; - //VertexRenderStruct singleSpark; SparkEmitter sparkEmitter; - VertexRenderStruct sparkQuad; }; } // namespace ZL \ No newline at end of file diff --git a/SparkEmitter.cpp b/SparkEmitter.cpp index 2ca1392..59eb352 100644 --- a/SparkEmitter.cpp +++ b/SparkEmitter.cpp @@ -6,59 +6,127 @@ namespace ZL { SparkEmitter::SparkEmitter() - : emissionRate(100.0f), isActive(true), buffersDirty(true), maxParticles(200) { + : emissionRate(100.0f), isActive(true), drawDataDirty(true), maxParticles(200) { particles.resize(maxParticles); - positionBuffer.resize(maxParticles * 4, 0.0f); - texCoordBuffer.resize(maxParticles * 2, 0.0f); + drawPositions.reserve(maxParticles * 6); + drawTexCoords.reserve(maxParticles * 6); lastEmissionTime = std::chrono::steady_clock::now(); + + sparkQuad.data = VertexDataStruct(); } SparkEmitter::SparkEmitter(const std::vector& positions, float rate) : emissionPoints(positions), emissionRate(rate), isActive(true), - buffersDirty(true), maxParticles(positions.size() * 100) { + drawDataDirty(true), maxParticles(positions.size() * 100) { particles.resize(maxParticles); - positionBuffer.resize(maxParticles * 4, 0.0f); - texCoordBuffer.resize(maxParticles * 2, 0.0f); + drawPositions.reserve(maxParticles * 6); + drawTexCoords.reserve(maxParticles * 6); lastEmissionTime = std::chrono::steady_clock::now(); + + sparkQuad.data = VertexDataStruct(); } - void SparkEmitter::setEmissionPoints(const std::vector& positions) { - emissionPoints = positions; - maxParticles = positions.size() * 100; + SparkEmitter::SparkEmitter(const std::vector& positions, + std::shared_ptr tex, + float rate) + : emissionPoints(positions), texture(tex), emissionRate(rate), + isActive(true), drawDataDirty(true), maxParticles(positions.size() * 100) { particles.resize(maxParticles); - positionBuffer.resize(maxParticles * 4, 0.0f); - texCoordBuffer.resize(maxParticles * 2, 0.0f); - buffersDirty = true; + drawPositions.reserve(maxParticles * 6); + drawTexCoords.reserve(maxParticles * 6); + lastEmissionTime = std::chrono::steady_clock::now(); + + sparkQuad.data = VertexDataStruct(); } - void SparkEmitter::updateBuffers() { - if (!buffersDirty) return; + void SparkEmitter::setTexture(std::shared_ptr tex) { + texture = tex; + } + + void SparkEmitter::prepareDrawData() { + if (!drawDataDirty) return; + + drawPositions.clear(); + drawTexCoords.clear(); + + if (getActiveParticleCount() == 0) { + drawDataDirty = false; + return; + } - size_t bufferIndex = 0; for (const auto& particle : particles) { - if (particle.active) { - positionBuffer[bufferIndex * 4] = particle.position.v[0]; - positionBuffer[bufferIndex * 4 + 1] = particle.position.v[1]; - positionBuffer[bufferIndex * 4 + 2] = particle.position.v[2]; - positionBuffer[bufferIndex * 4 + 3] = particle.scale; + if (!particle.active) continue; - texCoordBuffer[bufferIndex * 2] = 0.0f; - texCoordBuffer[bufferIndex * 2 + 1] = 0.0f; + Vector3f pos = particle.position; + float size = 0.04f * particle.scale; - bufferIndex++; - } + drawPositions.push_back({ pos.v[0] - size, pos.v[1] - size, pos.v[2] }); + drawTexCoords.push_back({ 0.0f, 0.0f }); + + drawPositions.push_back({ pos.v[0] - size, pos.v[1] + size, pos.v[2] }); + drawTexCoords.push_back({ 0.0f, 1.0f }); + + drawPositions.push_back({ pos.v[0] + size, pos.v[1] + size, pos.v[2] }); + drawTexCoords.push_back({ 1.0f, 1.0f }); + + drawPositions.push_back({ pos.v[0] - size, pos.v[1] - size, pos.v[2] }); + drawTexCoords.push_back({ 0.0f, 0.0f }); + + drawPositions.push_back({ pos.v[0] + size, pos.v[1] + size, pos.v[2] }); + drawTexCoords.push_back({ 1.0f, 1.0f }); + + drawPositions.push_back({ pos.v[0] + size, pos.v[1] - size, pos.v[2] }); + drawTexCoords.push_back({ 1.0f, 0.0f }); } - for (size_t i = bufferIndex; i < maxParticles; i++) { - positionBuffer[i * 4] = 0.0f; - positionBuffer[i * 4 + 1] = 0.0f; - positionBuffer[i * 4 + 2] = 0.0f; - positionBuffer[i * 4 + 3] = 0.0f; - texCoordBuffer[i * 2] = 0.0f; - texCoordBuffer[i * 2 + 1] = 0.0f; + drawDataDirty = false; + } + + void SparkEmitter::draw(Renderer& renderer, float zoom, int screenWidth, int screenHeight) { + if (getActiveParticleCount() == 0) { + return; } - buffersDirty = false; + if (!texture) { + return; + } + + prepareDrawData(); + + if (drawPositions.empty()) { + return; + } + + sparkQuad.data.PositionData = drawPositions; + sparkQuad.data.TexCoordData = drawTexCoords; + sparkQuad.RefreshVBO(); + + static const std::string defaultShaderName = "default"; + static const std::string vPositionName = "vPosition"; + static const std::string vTexCoordName = "vTexCoord"; + static const std::string textureUniformName = "Texture"; + + renderer.shaderManager.PushShader(defaultShaderName); + renderer.RenderUniform1i(textureUniformName, 0); + renderer.EnableVertexAttribArray(vPositionName); + renderer.EnableVertexAttribArray(vTexCoordName); + + float aspectRatio = static_cast(screenWidth) / static_cast(screenHeight); + renderer.PushPerspectiveProjectionMatrix(1.0 / 1.5, aspectRatio, 1, 1000); + + glBindTexture(GL_TEXTURE_2D, texture->getTexID()); + + renderer.PushMatrix(); + renderer.LoadIdentity(); + renderer.TranslateMatrix({ 0, 0, -1.0f * zoom }); + + renderer.DrawVertexRenderStruct(sparkQuad); + + renderer.PopMatrix(); + renderer.PopProjectionMatrix(); + renderer.DisableVertexAttribArray(vPositionName); + renderer.DisableVertexAttribArray(vTexCoordName); + renderer.shaderManager.PopShader(); } void SparkEmitter::update(float deltaTimeMs) { @@ -69,12 +137,14 @@ namespace ZL { if (isActive && elapsed >= emissionRate) { emit(); lastEmissionTime = currentTime; + drawDataDirty = true; } bool anyChanged = false; for (auto& particle : particles) { if (particle.active) { Vector3f oldPosition = particle.position; + float oldScale = particle.scale; particle.position.v[0] += particle.velocity.v[0] * deltaTimeMs / 1000.0f; particle.position.v[1] += particle.velocity.v[1] * deltaTimeMs / 1000.0f; @@ -92,7 +162,8 @@ namespace ZL { if (oldPosition.v[0] != particle.position.v[0] || oldPosition.v[1] != particle.position.v[1] || - oldPosition.v[2] != particle.position.v[2]) { + oldPosition.v[2] != particle.position.v[2] || + oldScale != particle.scale) { anyChanged = true; } } @@ -100,7 +171,7 @@ namespace ZL { } if (anyChanged) { - buffersDirty = true; + drawDataDirty = true; } } @@ -145,10 +216,17 @@ namespace ZL { } if (emitted) { - buffersDirty = true; + drawDataDirty = true; } } + void SparkEmitter::setEmissionPoints(const std::vector& positions) { + emissionPoints = positions; + maxParticles = positions.size() * 100; + particles.resize(maxParticles); + drawDataDirty = true; + } + void SparkEmitter::initParticle(SparkParticle& particle, int emitterIndex) { particle.velocity = getRandomVelocity(emitterIndex); particle.scale = 1.0f; @@ -197,15 +275,4 @@ namespace ZL { return count; } - size_t SparkEmitter::getActiveParticleBufferIndex(size_t particleIndex) const { - size_t activeIndex = 0; - for (size_t i = 0; i <= particleIndex; i++) { - if (particles[i].active) { - if (i == particleIndex) return activeIndex; - activeIndex++; - } - } - return 0; - } - } // namespace ZL \ No newline at end of file diff --git a/SparkEmitter.h b/SparkEmitter.h index d5356b3..4f1027a 100644 --- a/SparkEmitter.h +++ b/SparkEmitter.h @@ -1,6 +1,8 @@ #pragma once #include "ZLMath.h" +#include "Renderer.h" +#include "TextureManager.h" #include #include @@ -14,7 +16,6 @@ namespace ZL { float maxLifeTime; bool active; int emitterIndex; - Vector2f texCoord; SparkParticle() : position({ 0,0,0 }), velocity({ 0,0,0 }), scale(1.0f), lifeTime(0), maxLifeTime(1000.0f), active(false), emitterIndex(0) { @@ -29,30 +30,34 @@ namespace ZL { float emissionRate; bool isActive; - std::vector positionBuffer; - std::vector texCoordBuffer; - bool buffersDirty; + std::vector drawPositions; + std::vector drawTexCoords; + bool drawDataDirty; + VertexRenderStruct sparkQuad; + std::shared_ptr texture; + int maxParticles; + void prepareDrawData(); + public: SparkEmitter(); SparkEmitter(const std::vector& positions, float rate = 100.0f); + SparkEmitter(const std::vector& positions, + std::shared_ptr tex, + float rate = 100.0f); void setEmissionPoints(const std::vector& positions); + void setTexture(std::shared_ptr tex); void update(float deltaTimeMs); void emit(); + void draw(Renderer& renderer, float zoom, int screenWidth, int screenHeight); + const std::vector& getParticles() const; size_t getActiveParticleCount() const; - const float* getPositionBuffer() const { return positionBuffer.data(); } - const float* getTexCoordBuffer() const { return texCoordBuffer.data(); } - size_t getBufferSize() const { return positionBuffer.size() / 4; } - void updateBuffers(); - - size_t getActiveParticleBufferIndex(size_t particleIndex) const; - private: void initParticle(SparkParticle& particle, int emitterIndex); Vector3f getRandomVelocity(int emitterIndex);