diff --git a/particle.frag b/particle.frag index 820ae6e..e7a56ef 100755 --- a/particle.frag +++ b/particle.frag @@ -4,19 +4,22 @@ in vec2 texCoords; flat in int id; +const int numParticles = 500; + layout (location = 0) out vec4 FragColor; layout (location = 1) out vec4 BrightColor; uniform sampler2D tex; -uniform float lifePercentage[500]; +uniform float lifePercentage[numParticles]; uniform vec4 startColor, endColor; void main(){ float alpha = texture(tex, texCoords).r; - vec4 c = startColor + (endColor - startColor) * lifePercentage[id]; - c = vec4(c.x, c.y, c.z, alpha); + vec4 c = mix(startColor, endColor, lifePercentage[id]); + c = vec4(c.xyz, alpha); + FragColor = c; + float brightness = dot(c.rgb, vec3(0.2126, 0.7152, 0.0722)); if(brightness > 1) BrightColor = vec4(c.rgb, 1); - FragColor = c; } diff --git a/particle.vert b/particle.vert index 8258c5c..3a006d9 100755 --- a/particle.vert +++ b/particle.vert @@ -8,12 +8,12 @@ out vec2 texCoords; flat out int id; -uniform mat4 proj; -uniform mat4 view; -uniform float lifePercentage[500]; -uniform vec3 trans[500]; -uniform vec2 startSize; -uniform vec2 endSize; +const int numParticles = 500; + +uniform mat4 proj, view; +uniform float lifePercentage[numParticles]; +uniform vec3 trans[numParticles]; +uniform vec2 startSize, endSize; void main(){ vec3 camLeft = vec3(view[0][0], view[1][0], view[2][0]); @@ -23,9 +23,9 @@ void main(){ vec2 s = startSize + (endSize - startSize) * lifePercentage[id]; vec3 v = camLeft * s.x * aPos.x+camUp * s.y * aPos.y; mat4 model = aInstancedModel; - model[3][0] = trans[gl_InstanceID].x; - model[3][1] = trans[gl_InstanceID].y; - model[3][2] = trans[gl_InstanceID].z; + model[3][0] = trans[id].x; + model[3][1] = trans[id].y; + model[3][2] = trans[id].z; gl_Position = proj * view * model * vec4(v, 1); texCoords = aTexCoords; diff --git a/particleEmitter.cpp b/particleEmitter.cpp index a423d2f..c786086 100755 --- a/particleEmitter.cpp +++ b/particleEmitter.cpp @@ -1,14 +1,15 @@ -#include"particleEmitter.h" -#include"shader.h" -#include -#include -#include -#include -#include -#include"material.h" -#include"node.h" -#include"root.h" -#include"camera.h" +#include +#include +#include +#include +#include + +#include "particleEmitter.h" +#include "shader.h" +#include "material.h" +#include "node.h" +#include "root.h" +#include "camera.h" using namespace glm; using namespace std; @@ -51,7 +52,6 @@ namespace vb01{ for(int i = 0; i < numParticles; i++){ Particle *p = new Particle; - p->dir = direction; particles[i] = p; matrices[i] = mat4(1.f); } @@ -139,66 +139,61 @@ namespace vb01{ mat4 view = lookAt(vec3(camPos.x, camPos.y, camPos.z), vec3(camPos.x + camDir.x, camPos.y + camDir.y, camPos.z + camDir.z), vec3(up.x, up.y, up.z)); mat4 proj = perspective(radians(fov), width / height, nearPlane, farPlane); + material->update(); + + Shader *shader = material->getShader(); + const string line = "const int numParticles = " + to_string(numParticles) + ";"; + shader->editShader(Shader::VERTEX_SHADER, 10, line); + shader->editShader(Shader::FRAGMENT_SHADER, 6, line); + updateParticles(camDir, camPos); - material->update(); - Shader *shader=material->getShader(); shader->setMat4(view, "view"); shader->setMat4(proj, "proj"); shader->setVec4(startColor, "startColor"); shader->setVec4(endColor, "endColor"); shader->setVec2(startSize, "startSize"); shader->setVec2(endSize, "endSize"); - for(int i = 0; i < numParticles; i++) - shader->setVec3(particles[i]->trans, "trans[" + to_string(i) + "]"); heapSort(); render(); } void ParticleEmitter::updateParticles(Vector3 camDir, Vector3 camPos){ - Shader *shader=material->getShader(); + Shader *shader = material->getShader(); Vector3 nodePos = node->localToGlobalPosition(Vector3::VEC_ZERO); Vector3 nodeDir = node->getGlobalAxis(2); Vector3 nodeUp = node->getGlobalAxis(1); Vector3 nodeLeft = node->getGlobalAxis(0); for(int i = 0; i < numParticles; i++){ - Vector3 dir = particles[i]->dir; + Vector3 dir = nodeDir; if(getTime() - particles[i]->time >= particles[i]->timeToLive){ - particles[i]->time = getTime(); float factor = (float)(rand() % 100) / 100; - float s1 = float(rand() % (int)spread) / 180 * PI, s2 = float(rand() % 360) / 180 * PI; - Vector3 ra1 = (Vector3(0, 1, 0).cross(dir)).norm(), ra2 = dir.norm(); + particles[i]->time = getTime(); + particles[i]->timeToLive = s64(1000 * ((highLife - lowLife) * factor + lowLife)); + + float spr1 = float(rand() % (int)spread) / 180 * PI, spr2 = float(rand() % 360) / 180 * PI; + Vector3 ra1 = (nodeUp.cross(dir)).norm(), ra2 = dir.norm(); if(ra1 == Vector3::VEC_ZERO) ra1 = Vector3::VEC_I; - dir = Quaternion(s1, ra1) * dir; - dir = Quaternion(s2, ra2) * dir; - - particles[i]->timeToLive = s64(1000 * ((highLife - lowLife) * factor + lowLife)); + dir = Quaternion(spr1, ra1) * dir; + dir = Quaternion(spr2, ra2) * dir; particles[i]->trans = nodePos; } - particles[i]->dir = dir.norm() * direction.getLengthSq() + gravity; - float lifePercentage = (float)(getTime() - particles[i]->time) / particles[i]->timeToLive; - particles[i]->color = startColor + (endColor - startColor) * lifePercentage; - particles[i]->size = startSize + (endSize - startSize) * lifePercentage; + dir = dir.norm() * speed + gravity; particles[i]->trans = particles[i]->trans + dir; + particles[i]->d = cos(camDir.getAngleBetween((particles[i]->trans - camPos).norm())) * camPos.getDistanceFrom(particles[i]->trans); - Vector3 trans = particles[i]->trans; - particles[i]->d = cos(camDir.getAngleBetween((trans - camPos).norm())) * camPos.getDistanceFrom(trans); + float lifePercentage = (float)(getTime() - particles[i]->time) / particles[i]->timeToLive; shader->setFloat(lifePercentage, "lifePercentage[" + to_string(i) + "]"); + shader->setVec3(particles[i]->trans, "trans[" + to_string(i) + "]"); } } - void ParticleEmitter::setDirection(Vector3 dir){ - this->direction = dir; - for(int i = 0; i < numParticles; i++) - particles[i]->dir = dir; - } - void ParticleEmitter::render(){ glBindVertexArray(VAO); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); diff --git a/particleEmitter.h b/particleEmitter.h index 4d40575..3246aeb 100755 --- a/particleEmitter.h +++ b/particleEmitter.h @@ -1,9 +1,9 @@ #ifndef PARTICLE_EMITTER_H #define PARTICLE_EMITTER_H -#include"vector.h" -#include"util.h" -#include +#include "vector.h" +#include "util.h" +#include namespace vb01{ class Shader; @@ -26,9 +26,8 @@ namespace vb01{ inline void setLowLife(float l){this->lowLife = l;} inline void setHighLife(float h){this->highLife = h;} inline void setGravity(Vector3 g){this->gravity = g;} + inline void setSpeed(float s){this->speed = s;} inline Node* getNode(){return node;} - inline Vector3 getDirection(){return direction;} - void setDirection(Vector3 dir); private: struct Vertex{ Vector3 pos; @@ -37,9 +36,7 @@ namespace vb01{ struct Particle{ int VAO; s64 time = 0, timeToLive = 0; - Vector4 color; - Vector3 dir, trans; - Vector2 size; + Vector3 trans; float d; }; @@ -50,16 +47,16 @@ namespace vb01{ void setupDisplay(Vertex[], u32[]); void render(); - unsigned int VAO, VBO, EBO, MBO; + u32 VAO, VBO, EBO, MBO; glm::mat4 *matrices; int numParticles; Particle **particles; Material *material = nullptr; Node *node = nullptr; Vector2 startSize = Vector2::VEC_IJ, endSize = Vector2::VEC_IJ; - Vector3 direction = Vector3(0, .1, 0), gravity = Vector3::VEC_ZERO; + Vector3 gravity = Vector3::VEC_ZERO; Vector4 startColor, endColor; - float spread = 1, lowLife = 1, highLife = 2; + float speed = .2, spread = 1, lowLife = 1, highLife = 2; friend class ParticleEmitterTest; };