This commit is contained in:
Wojciech Łukasik 2021-02-25 21:46:41 +01:00
parent aa70421d68
commit f07b6fdd62
5 changed files with 241 additions and 9 deletions

View File

@ -0,0 +1,10 @@
#version 330 core
in float lifeTime;
out vec4 fragColor;
void main()
{
float normalizedLifeTime = lifeTime / 2;
fragColor = vec4( 5.f, normalizedLifeTime, 0.f, normalizedLifeTime);
};

View File

@ -0,0 +1,18 @@
#version 330 core
layout ( location = 0 ) in vec3 vertex_position;
layout ( location = 4 ) in vec4 position;
uniform mat4 M_v;
uniform mat4 M_p;
uniform mat4 transformation;
uniform float particleSize;
out float lifeTime;
void main()
{
vec4 position_viewspace = M_v * transformation * vec4( position.xyz , 1 );
position_viewspace.xy += particleSize * (vertex_position.xy - vec2(0.5f));
gl_Position = M_p * position_viewspace;
lifeTime = position.w;
};

128
src/ParticleEmiter.cpp Normal file
View File

@ -0,0 +1,128 @@
#include "ParticleEmiter.h"
#include <cstdlib>
//ParticleEmitter::ParticleEmitter(GLuint* program)
//{
// this->program = program;
//
// this->positionsArr = new float[PARTICLES_COUNT * 4];
//
// particles.resize(PARTICLES_COUNT);
// for (int i = 0; i < PARTICLES_COUNT; ++i)
// {
// particles[i].position = glm::vec3(0);
// particles[i].lifetime = randomFloat(1.0f, 2.0f);
// particles[i].radius = 0.01f;
// }
//
// generateBuffers();
//}
ParticleEmitter::ParticleEmitter(GLuint* program, int particleCount, float particleSize)
{
this->program = program;
this->positionsArr = new float[particleCount * 4];
this->particleSize = particleSize;
particles.resize(particleCount);
for (int i = 0; i < particleCount; ++i)
{
particles[i].position = glm::vec3(0, 100, 0);
particles[i].lifetime = randomFloat(1.0f, 2.0f);
particles[i].radius = 0.003f;
}
generateBuffers();
}
void ParticleEmitter::generateBuffers()
{
glGenBuffers(1, &particleVertexBuffer);
std::vector< float > vertices;
vertices.push_back(0.0f); vertices.push_back(0.0f); vertices.push_back(0.0f);
vertices.push_back(1.0f); vertices.push_back(0.0f); vertices.push_back(0.0f);
vertices.push_back(0.0f); vertices.push_back(1.0f); vertices.push_back(0.0f);
vertices.push_back(1.0f); vertices.push_back(1.0f); vertices.push_back(0.0f);
glBindBuffer(GL_ARRAY_BUFFER, particleVertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float), vertices.data(), GL_STATIC_DRAW);
glGenBuffers(1, &particlePositionBuffer);
glBindBuffer(GL_ARRAY_BUFFER, particlePositionBuffer);
glBufferData(GL_ARRAY_BUFFER, particles.size() * 4 * sizeof(float), positionsArr, GL_DYNAMIC_DRAW);
}
void ParticleEmitter::setupUniforms(const glm::mat4 transformation, glm::mat4 cameraMatrix, glm::mat4 perspectiveMatrix)
{
glUniformMatrix4fv(glGetUniformLocation(*program, "transformation"), 1, GL_FALSE, (float*)&transformation);
glUniformMatrix4fv(glGetUniformLocation(*program, "M_v"), 1, GL_FALSE, (float*)&cameraMatrix);
glUniformMatrix4fv(glGetUniformLocation(*program, "M_p"), 1, GL_FALSE, (float*)&perspectiveMatrix);
glUniform1f(glGetUniformLocation(*program, "particleSize"), this->particleSize);
}
void ParticleEmitter::update(const float dt, const glm::mat4 transformation, glm::mat4 cameraMatrix, glm::mat4 perspectiveMatrix)
{
glUseProgram(*program);
setupUniforms(transformation, cameraMatrix, perspectiveMatrix);
for (int i = 0; i < particles.size(); ++i)
{
particles[i].lifetime -= dt;
particles[i].radius += 0.0002;
if (particles[i].lifetime <= 0.0f)
{
particles[i].position = glm::vec3(0);
particles[i].lifetime = randomFloat(1.0f, 2.0f);
particles[i].radius = 0.003f;
}
float radius = particles[i].radius;
particles[i].position -= glm::vec3(randomFloat(-radius, radius), dt / 2, randomFloat(-radius, radius));
positionsArr[i * 4 + 0] = particles[i].position[0];
positionsArr[i * 4 + 1] = particles[i].position[1];
positionsArr[i * 4 + 2] = particles[i].position[2];
positionsArr[i * 4 + 3] = particles[i].lifetime;
}
}
void ParticleEmitter::draw()
{
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(4);
glBindBuffer(GL_ARRAY_BUFFER, particlePositionBuffer);
glBufferSubData(GL_ARRAY_BUFFER, 0, particles.size() * 4 * sizeof(float), positionsArr);
glBindBuffer(GL_ARRAY_BUFFER, particleVertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, particlePositionBuffer);
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, 0, nullptr);
glVertexAttribDivisor(4, 1);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, particles.size());
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(4);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glUseProgram(0);
}
float ParticleEmitter::randomFloat(float min, float max) {
return (max - min) * ((((float)rand()) / (float)RAND_MAX)) + min;
}
ParticleEmitter::~ParticleEmitter()
{
glDeleteBuffers(1, &particleVertexBuffer);
glDeleteBuffers(1, &particlePositionBuffer);
}

37
src/ParticleEmiter.h Normal file
View File

@ -0,0 +1,37 @@
#include "glew.h"
#include "freeglut.h"
#include "glm.hpp"
#include <vector>
#define PARTICLES_COUNT 0
class ParticleEmitter
{
public:
ParticleEmitter(GLuint* program);
ParticleEmitter(GLuint* program, int particleCount, float particleSize);
~ParticleEmitter();
void update(const float dt, const glm::mat4 transformation, glm::mat4 cameraMatrix, glm::mat4 perspectiveMatrix);
void draw();
private:
struct Particle
{
glm::vec3 position;
float lifetime = 0.0f;
float radius = 0.0f;
};
float* positionsArr;
float particleSize = 0.015f;
GLuint* program;
GLuint particleVertexBuffer;
GLuint particlePositionBuffer;
std::vector< Particle > particles;
float randomFloat(float min, float max);
void generateBuffers();
void setupUniforms(const glm::mat4 transformation, glm::mat4 cameraMatrix, glm::mat4 perspectiveMatrix);
};

View File

@ -12,6 +12,7 @@
#include "Texture.h"
#include "Physics.h"
#include "Skybox.h"
#include "ParticleEmiter.h"
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
@ -20,14 +21,18 @@ GLuint programColor;
GLuint programTexture;
GLuint programSkybox;
GLuint programSun;
GLuint programParticle;
GLuint cubemapTexture;
GLuint cubemapTexture2;
GLuint cubemapTexture3;
GLuint cubemapTexture4;
GLuint cubemapTexture5;
GLuint skyboxVAO, skyboxVBO;
ParticleEmitter* particleEmitterOrbit;
ParticleEmitter* particleEmitterStartShip;
ParticleEmitter* particleEmitterStartBooster;
Core::Shader_Loader shaderLoader;
obj::Model planeModel;
@ -65,11 +70,18 @@ GLuint textureMoon;
Core::RenderContext shipContextOrbit, sphereContextOrbit, stationContextOrbit;
float acceleration = 0.f;
float frustumScale = 1.f;
bool loading = false;
bool reload = false;
bool end = false;
float orbitSpeed = 0.003f;
const glm::mat4 particleStartShipTranslation = glm::translate(glm::vec3(-2.f, 3.1f, 0.f));
const glm::mat4 particleStartBoosterTranslation = glm::translate(glm::vec3(-2.f, -4.5f, 0.f));
const glm::vec3 particleOrbitOffset = glm::vec3(2.75f, 0.f, -0.f);
const glm::mat4 particleOrbitRotation = glm::rotate(glm::radians(90.0f), glm::vec3(0, 0, 1));
const glm::mat4 particleOrbitTranslation = glm::translate(glm::vec3(2.75f, 0.f, -0.f)) * glm::rotate(glm::radians(90.0f), glm::vec3(0, 0, 1));
float particleLife = 0.f;
// skybox
std::vector<std::string> faces
@ -298,12 +310,20 @@ void keyboard(unsigned char key, int x, int y)
case 'w':
if (orbitSpeed < 0.02f) {
orbitSpeed += 0.0001f;
if (!loading) {
acceleration += 0.1f;
}
else if (!end) {
orbitSpeed += 0.0001f;
}
}
break;
case 's':
if (orbitSpeed > 0.001f) {
orbitSpeed -= 0.0001f;
particleLife -= 0.01f;
}
break;
@ -413,6 +433,8 @@ void drawObjectTexture(Core::RenderContext* context, glm::mat4 modelMatrix, GLui
}
void shutdown()
{
shaderLoader.DeleteProgram(programColor);
@ -450,6 +472,8 @@ void renderScene()
// Update of camera and perspective matrices
cameraMatrix = createCameraMatrix();
perspectiveMatrix = Core::createPerspectiveMatrix(0.1f, 1500.f);
glm::mat4 shipModelStartMatrix = glm::translate(cameraPos + cameraDir * 4.f + glm::vec3(0, -0.25f, 0)) * glm::rotate(glm::orientedAngle(glm::vec3(0, 0, 1), cameraDir, glm::vec3(0, 1, 0)), glm::vec3(0, 1, 0)) * glm::scale(glm::vec3(0.2)) * glm::translate(glm::vec3(2, 0, 0));
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glClearColor(0.0f, 0.1f, 0.3f, 1.0f);
@ -458,18 +482,24 @@ void renderScene()
// update transforms from physics simulation
updateTransforms();
std::cout << acceleration << std::endl;
if (time > 2 && time < 7) {
boxBodies[0]->setLinearVelocity(PxVec3(0, time * 0.8, 0));
boxBodies[1]->setLinearVelocity(PxVec3(0, time * 0.8, 0));
if (acceleration > 1 && acceleration < 20) {
boxBodies[0]->setLinearVelocity(PxVec3(0, acceleration, 0));
boxBodies[1]->setLinearVelocity(PxVec3(0, acceleration, 0));
particleEmitterStartBooster->update(0.01f, shipModelStartMatrix * particleStartBoosterTranslation, cameraMatrix, perspectiveMatrix);
particleEmitterStartBooster->draw();
}
if (time > 7 && time < 15) {
boxBodies[1]->setLinearVelocity(PxVec3(0, 15, 0));
if (acceleration > 20 && acceleration < 40) {
boxBodies[1]->setLinearVelocity(PxVec3(0, acceleration, 0));
particleEmitterStartShip->update(0.01f, shipModelStartMatrix * particleStartShipTranslation, cameraMatrix, perspectiveMatrix);
particleEmitterStartShip->draw();
}
if (time > 15) {
if (acceleration > 40) {
loading = true;
lightDir = glm::normalize(glm::vec3(1.0f, -1.0f, -1.0f));
lightPos = glm::vec3(0, 0, -800);
@ -484,6 +514,7 @@ void renderScene()
drawObjectTexture(renderable->context, renderable->modelMatrix, renderable->textureId);
}
glutSwapBuffers();
}
@ -580,6 +611,9 @@ void renderScene()
glUniform3f(glGetUniformLocation(programSun, "cameraPos"), cameraPos.x, cameraPos.y, cameraPos.z);
drawObject(programSun, sphereContextOrbit, glm::translate(lightPos) * glm::scale(glm::vec3(10.f)), glm::vec3(1.0f, 0.8f, 0.2f));
particleEmitterOrbit->update(0.01f, shipModelOrbitMatrix * particleOrbitTranslation, cameraMatrix, perspectiveMatrix);
particleEmitterOrbit->draw();
glUseProgram(0);
glutSwapBuffers();
@ -627,6 +661,7 @@ void init()
programColor = shaderLoader.CreateProgram("shaders/shader_color.vert", "shaders/shader_color.frag");
programTexture = shaderLoader.CreateProgram("shaders/shader_tex.vert", "shaders/shader_tex.frag");
programSkybox = shaderLoader.CreateProgram("shaders/shader_skybox.vert", "shaders/shader_skybox.frag");
programParticle = shaderLoader.CreateProgram("shaders/shader_particles.vert", "shaders/shader_particles.frag");
cubemapTexture = Skybox::loadCubemap(faces);
cubemapTexture2 = Skybox::loadCubemap(faces2);
@ -634,6 +669,10 @@ void init()
cubemapTexture4 = Skybox::loadCubemap(faces4);
cubemapTexture5 = Skybox::loadCubemap(faces5);
particleEmitterOrbit = new ParticleEmitter(&programParticle, 1000, 0.02f);
particleEmitterStartShip = new ParticleEmitter(&programParticle, 1000, 0.02f);
particleEmitterStartBooster = new ParticleEmitter(&programParticle, 2000, 0.1f);
glEnable(GL_DEPTH_TEST);
programSun = shaderLoader.CreateProgram("shaders/shader_4_2.vert", "shaders/shader_4_2.frag");