Repository navigation
Expand file tree
/
Copy pathParticleSystem.hpp
More file actions
145 lines (119 loc) · 4.63 KB
/
Copy pathParticleSystem.hpp
File metadata and controls
145 lines (119 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#pragma once
#include <vector>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <GLFW/glfw3.h>
#include "Shader.hpp"
#include "Block.hpp"
#include "TextureManager.hpp"
#include "DayTime.hpp"
class ParticleSystem {
private:
struct Particle {
glm::vec3 position;
glm::vec3 velocity;
float life;
float size;
int textureLayer; // 新增:用于存储纹理数组层索引
};
std::vector<Particle> particles;
GLuint VAO, VBO;
Shader particleShader;
TextureManager& textureManager; // 引用纹理管理器
public:
ParticleSystem(TextureManager& tm,int maxParticles = 1000) : textureManager(tm) {
particles.reserve(maxParticles);
setupParticleBuffers();
particleShader.createProgram("shaders/particle.vert", "shaders/particle.frag");
}
void emit(const glm::vec3& position, BlockType blockType);
void update(float deltaTime);
void render(const glm::mat4& view, const glm::mat4& projection);
void setupParticleBuffers();
};
// Add helper function to map BlockType to texture layer
void ParticleSystem::emit(const glm::vec3& position, BlockType blockType) {
for(int i = 0; i < 10; i++) { // 每次产生10个粒子
Particle p;
p.position = position;
// 随机速度
float randomAngle = static_cast<float>(rand()) / RAND_MAX * 2.0f * 3.14159f;
float randomSpeed = static_cast<float>(rand()) / RAND_MAX * 2.0f + 1.0f;
p.velocity = glm::vec3(
cos(randomAngle) * randomSpeed,
static_cast<float>(rand()) / RAND_MAX * 2.0f + 2.0f, // 向上的速度
sin(randomAngle) * randomSpeed
);
p.life = 1.0f;
p.size = 80.0f;
p.textureLayer = getTextureLayer(blockType);
particles.push_back(p);
}
}
void ParticleSystem::update(float deltaTime) {
for(auto it = particles.begin(); it != particles.end();) {
it->position += it->velocity * deltaTime;
it->velocity.y -= 9.81f * deltaTime; // 重力
it->life -= deltaTime;
it->size -= deltaTime * 2.0f;
if(it->life <= 0.0f) {
it = particles.erase(it);
} else {
++it;
}
}
}
void ParticleSystem::setupParticleBuffers() {
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// Position (3) + Size (1) + TextureLayer (1) = 5 floats per vertex
glBufferData(GL_ARRAY_BUFFER, 1000 * 5 * sizeof(float), nullptr, GL_DYNAMIC_DRAW);
// Position attribute
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
// Size attribute
glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// Texture layer attribute
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(4 * sizeof(float)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void ParticleSystem::render(const glm::mat4& view, const glm::mat4& projection) {
if (particles.empty()) return;
glEnable(GL_PROGRAM_POINT_SIZE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
particleShader.use();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D_ARRAY, textureManager.getTextureArrayID());
particleShader.setUniform1i("textureArray", 0);
particleShader.setUniformMatrix4fv("view", glm::value_ptr(view));
particleShader.setUniformMatrix4fv("projection", glm::value_ptr(projection));
particleShader.setUniform1f("dayNightBlendFactor", DayTime::getDayNightBlendFactor());
std::vector<float> particleData;
for (const auto& particle : particles) {
if(particle.life > 0.0f) {
// Position
particleData.push_back(particle.position.x);
particleData.push_back(particle.position.y);
particleData.push_back(particle.position.z);
// Size
particleData.push_back(particle.size);
// Texture layer
particleData.push_back(static_cast<float>(particle.textureLayer));
}
}
if(!particleData.empty()) {
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferSubData(GL_ARRAY_BUFFER, 0, particleData.size() * sizeof(float), particleData.data());
glDrawArrays(GL_POINTS, 0, particleData.size() / 5);
glBindVertexArray(0);
}
glDisable(GL_BLEND);
glDisable(GL_PROGRAM_POINT_SIZE);
}