fix spark
This commit is contained in:
parent
b855cff0e6
commit
115cbbb7fa
66
Game.cpp
66
Game.cpp
@ -200,21 +200,6 @@ void Game::setup() {
|
||||
|
||||
sparkTexture = std::make_unique<Texture>(CreateTextureDataFromPng("./resources/spark.png", CONST_ZIP_FILE));
|
||||
|
||||
/*singleSpark.data.PositionData.push_back({-1, -1, 0});
|
||||
singleSpark.data.PositionData.push_back({ -1, 1, 0 });
|
||||
singleSpark.data.PositionData.push_back({ 1, 1, 0 });
|
||||
singleSpark.data.PositionData.push_back({ -1, -1, 0 });
|
||||
singleSpark.data.PositionData.push_back({ 1, 1, 0 });
|
||||
singleSpark.data.PositionData.push_back({ 1, -1, 0 });
|
||||
|
||||
singleSpark.data.TexCoordData.push_back({0,0});
|
||||
singleSpark.data.TexCoordData.push_back({ 0,1 });
|
||||
singleSpark.data.TexCoordData.push_back({1,1});
|
||||
singleSpark.data.TexCoordData.push_back({0,0});
|
||||
singleSpark.data.TexCoordData.push_back({ 1,1 });
|
||||
singleSpark.data.TexCoordData.push_back({ 1,0 });
|
||||
|
||||
singleSpark.RefreshVBO();*/
|
||||
sparkQuad.data = CreateRect2D({ 0, 0 }, { 0.08f, 0.08f }, 0);
|
||||
sparkQuad.RefreshVBO();
|
||||
|
||||
@ -258,15 +243,48 @@ void Game::drawCubemap()
|
||||
|
||||
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";
|
||||
|
||||
if (sparkEmitter.getActiveParticleCount() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
renderer.shaderManager.PushShader(defaultShaderName);
|
||||
renderer.RenderUniform1i(textureUniformName, 0);
|
||||
renderer.EnableVertexAttribArray(vPositionName);
|
||||
@ -278,19 +296,13 @@ void Game::drawEffects()
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, sparkTexture->getTexID());
|
||||
|
||||
const auto& particles = sparkEmitter.getParticles();
|
||||
for (const auto& particle : particles) {
|
||||
if (!particle.active) continue;
|
||||
|
||||
renderer.PushMatrix();
|
||||
renderer.LoadIdentity();
|
||||
renderer.TranslateMatrix({ 0, 0, -1.0f * Environment::zoom });
|
||||
renderer.TranslateMatrix(particle.position);
|
||||
renderer.ScaleMatrix(particle.scale);
|
||||
renderer.RotateMatrix(Environment::inverseShipMatrix);
|
||||
|
||||
renderer.DrawVertexRenderStruct(sparkQuad);
|
||||
|
||||
renderer.PopMatrix();
|
||||
}
|
||||
renderer.PopProjectionMatrix();
|
||||
renderer.DisableVertexAttribArray(vPositionName);
|
||||
renderer.DisableVertexAttribArray(vTexCoordName);
|
||||
|
||||
@ -6,28 +6,59 @@
|
||||
namespace ZL {
|
||||
|
||||
SparkEmitter::SparkEmitter()
|
||||
: emissionRate(100.0f), isActive(true) {
|
||||
particles.resize(200);
|
||||
: emissionRate(100.0f), isActive(true), buffersDirty(true), maxParticles(200) {
|
||||
particles.resize(maxParticles);
|
||||
positionBuffer.resize(maxParticles * 4, 0.0f);
|
||||
texCoordBuffer.resize(maxParticles * 2, 0.0f);
|
||||
lastEmissionTime = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
SparkEmitter::SparkEmitter(const std::vector<Vector3f>& positions, float rate)
|
||||
: emissionPoints(positions), emissionRate(rate), isActive(true) {
|
||||
particles.resize(positions.size() * 100);
|
||||
: emissionPoints(positions), emissionRate(rate), isActive(true),
|
||||
buffersDirty(true), maxParticles(positions.size() * 100) {
|
||||
particles.resize(maxParticles);
|
||||
positionBuffer.resize(maxParticles * 4, 0.0f);
|
||||
texCoordBuffer.resize(maxParticles * 2, 0.0f);
|
||||
lastEmissionTime = std::chrono::steady_clock::now();
|
||||
}
|
||||
|
||||
void SparkEmitter::setEmissionPoints(const std::vector<Vector3f>& positions) {
|
||||
emissionPoints = positions;
|
||||
particles.resize(positions.size() * 100);
|
||||
maxParticles = positions.size() * 100;
|
||||
particles.resize(maxParticles);
|
||||
positionBuffer.resize(maxParticles * 4, 0.0f);
|
||||
texCoordBuffer.resize(maxParticles * 2, 0.0f);
|
||||
buffersDirty = true;
|
||||
}
|
||||
|
||||
void SparkEmitter::setEmissionRate(float rateMs) {
|
||||
emissionRate = rateMs;
|
||||
void SparkEmitter::updateBuffers() {
|
||||
if (!buffersDirty) 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;
|
||||
|
||||
texCoordBuffer[bufferIndex * 2] = 0.0f;
|
||||
texCoordBuffer[bufferIndex * 2 + 1] = 0.0f;
|
||||
|
||||
bufferIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
void SparkEmitter::setActive(bool active) {
|
||||
isActive = active;
|
||||
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;
|
||||
}
|
||||
|
||||
buffersDirty = false;
|
||||
}
|
||||
|
||||
void SparkEmitter::update(float deltaTimeMs) {
|
||||
@ -40,8 +71,11 @@ namespace ZL {
|
||||
lastEmissionTime = currentTime;
|
||||
}
|
||||
|
||||
bool anyChanged = false;
|
||||
for (auto& particle : particles) {
|
||||
if (particle.active) {
|
||||
Vector3f oldPosition = particle.position;
|
||||
|
||||
particle.position.v[0] += particle.velocity.v[0] * deltaTimeMs / 1000.0f;
|
||||
particle.position.v[1] += particle.velocity.v[1] * deltaTimeMs / 1000.0f;
|
||||
particle.position.v[2] += particle.velocity.v[2] * deltaTimeMs / 1000.0f;
|
||||
@ -50,16 +84,29 @@ namespace ZL {
|
||||
|
||||
if (particle.lifeTime >= particle.maxLifeTime) {
|
||||
particle.active = false;
|
||||
anyChanged = true;
|
||||
}
|
||||
|
||||
else {
|
||||
float lifeRatio = particle.lifeTime / particle.maxLifeTime;
|
||||
particle.scale = 1.0f - lifeRatio * 0.8f;
|
||||
|
||||
if (oldPosition.v[0] != particle.position.v[0] ||
|
||||
oldPosition.v[1] != particle.position.v[1] ||
|
||||
oldPosition.v[2] != particle.position.v[2]) {
|
||||
anyChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (anyChanged) {
|
||||
buffersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SparkEmitter::emit() {
|
||||
if (emissionPoints.empty()) return;
|
||||
bool emitted = false;
|
||||
|
||||
for (int i = 0; i < emissionPoints.size(); ++i) {
|
||||
bool particleFound = false;
|
||||
@ -72,6 +119,7 @@ namespace ZL {
|
||||
particle.position = emissionPoints[i];
|
||||
particle.emitterIndex = i;
|
||||
particleFound = true;
|
||||
emitted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -92,14 +140,19 @@ namespace ZL {
|
||||
particles[oldestIndex].lifeTime = 0;
|
||||
particles[oldestIndex].position = emissionPoints[i];
|
||||
particles[oldestIndex].emitterIndex = i;
|
||||
emitted = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (emitted) {
|
||||
buffersDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void SparkEmitter::initParticle(SparkParticle& particle, int emitterIndex) {
|
||||
particle.velocity = getRandomVelocity(emitterIndex);
|
||||
particle.scale = 1.0f;
|
||||
particle.maxLifeTime = 800.0f + (rand() % 400); // От 800 до 1200 мс
|
||||
particle.maxLifeTime = 800.0f + (rand() % 400);
|
||||
particle.emitterIndex = emitterIndex;
|
||||
}
|
||||
|
||||
@ -144,4 +197,15 @@ 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
|
||||
@ -14,6 +14,7 @@ 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) {
|
||||
@ -28,13 +29,16 @@ namespace ZL {
|
||||
float emissionRate;
|
||||
bool isActive;
|
||||
|
||||
std::vector<float> positionBuffer;
|
||||
std::vector<float> texCoordBuffer;
|
||||
bool buffersDirty;
|
||||
int maxParticles;
|
||||
|
||||
public:
|
||||
SparkEmitter();
|
||||
SparkEmitter(const std::vector<Vector3f>& positions, float rate = 100.0f);
|
||||
|
||||
void setEmissionPoints(const std::vector<Vector3f>& positions);
|
||||
void setEmissionRate(float rateMs);
|
||||
void setActive(bool active);
|
||||
|
||||
void update(float deltaTimeMs);
|
||||
void emit();
|
||||
@ -42,6 +46,13 @@ namespace ZL {
|
||||
const std::vector<SparkParticle>& 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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user