summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjjesswan <jessica_wan@brown.edu>2024-05-10 01:49:32 -0400
committerjjesswan <jessica_wan@brown.edu>2024-05-10 01:49:32 -0400
commitd2f792c6fee2a6e78dcf2fff77f43ef036c58877 (patch)
tree8085f9428fc26d20df1ad44b0d714f61436b1cd1
parent4150f19230962abaf68a8be209c7fa10bc7691e3 (diff)
saving parts
-rw-r--r--.DS_Storebin12292 -> 10244 bytes
-rw-r--r--CMakeLists.txt5
-rw-r--r--resources/shaders/particles.frag15
-rw-r--r--resources/shaders/particles.vert19
-rw-r--r--src/arap.h4
-rwxr-xr-xsrc/glwidget.cpp11
-rwxr-xr-xsrc/glwidget.h4
-rw-r--r--src/ocean/ocean_alt.cpp18
-rw-r--r--src/ocean/ocean_alt.h12
-rw-r--r--src/particlesystem.cpp176
-rw-r--r--src/particlesystem.h83
11 files changed, 334 insertions, 13 deletions
diff --git a/.DS_Store b/.DS_Store
index 7295d0d..6e43419 100644
--- a/.DS_Store
+++ b/.DS_Store
Binary files differ
diff --git a/CMakeLists.txt b/CMakeLists.txt
index b72cde6..b7bd5ff 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -61,6 +61,8 @@ add_executable(${PROJECT_NAME}
src/ocean/halftone.h src/ocean/halftone.cpp
src/skybox.h src/skybox.cpp
+
+ src/particlesystem.h src/particlesystem.cpp
)
# GLEW: this creates its library and allows you to `#include "GL/glew.h"`
@@ -131,6 +133,9 @@ qt6_add_resources(${PROJECT_NAME} "Resources"
resources/shaders/caustics.vert
resources/shaders/caustics.frag
+
+ resources/shaders/particles.vert
+ resources/shaders/particles.frag
)
# GLEW: this provides support for Windows (including 64-bit)
diff --git a/resources/shaders/particles.frag b/resources/shaders/particles.frag
new file mode 100644
index 0000000..73a4eb4
--- /dev/null
+++ b/resources/shaders/particles.frag
@@ -0,0 +1,15 @@
+#version 330 core
+in vec2 TexCoords;
+in vec4 ParticleColor;
+
+out vec4 fragColor;
+
+uniform sampler2D sprite;
+uniform float alpha;
+
+
+void main()
+{
+ // color = (texture(sprite, TexCoords) * ParticleColor);
+ fragColor = vec4(0,1,0,alpha);
+}
diff --git a/resources/shaders/particles.vert b/resources/shaders/particles.vert
new file mode 100644
index 0000000..0905514
--- /dev/null
+++ b/resources/shaders/particles.vert
@@ -0,0 +1,19 @@
+#version 330 core
+layout (location = 0) in vec2 pos; // <vec2 position, vec2 texCoords>
+
+out vec2 TexCoords;
+out vec4 ParticleColor;
+
+uniform mat4 view, projection, model;
+uniform vec3 offset;
+uniform vec4 color;
+
+void main()
+{
+ float scale = 1.f;//2000.0f;
+ //TexCoords = vertex.zw;
+ ParticleColor = color;
+ // gl_Position = projection *view* vec4((pos * scale) + vec2(offset), 0.0, 1.0);
+ gl_Position = (vec4(pos.x, pos.y, 0, 1) + projection*view*vec4(vec3(offset), 1))*scale;
+
+}
diff --git a/src/arap.h b/src/arap.h
index 39b2076..f9dd81e 100644
--- a/src/arap.h
+++ b/src/arap.h
@@ -32,6 +32,9 @@ public:
void move(int vertex, Eigen::Vector3f pos);
void update(double seconds);
+ ocean_alt m_ocean;
+
+
// ================== Students, If You Choose To Modify The Code Below, It's On You
@@ -96,7 +99,6 @@ public:
int m_num_iterations;
const char * m_mesh_path;
- ocean_alt m_ocean;
double m_time = 0.00;
double m_timestep = 0.3;
diff --git a/src/glwidget.cpp b/src/glwidget.cpp
index 57b4468..8f3c0c1 100755
--- a/src/glwidget.cpp
+++ b/src/glwidget.cpp
@@ -97,6 +97,8 @@ void GLWidget::initializeGL()
m_colorShader = new Shader(":resources/shaders/color.vert", ":resources/shaders/color.frag");
m_foamShader = new Shader(":resources/shaders/foam.vert", ":resources/shaders/foam.frag");
m_skyboxShader = new Shader(":resources/shaders/skybox.vert", ":resources/shaders/skybox.frag");
+ m_particleShader = new Shader(":resources/shaders/particles.vert", ":resources/shaders/particles.frag");
+
m_halftone_tex = loadTextureFromFile(":resources/images/halftone.png").textureID;
@@ -198,6 +200,10 @@ void GLWidget::initializeGL()
m_deltaTimeProvider.start();
m_intervalTimer.start(1000 / 60);
+ // OCEAN SPRAY
+ m_arap.update(0); // important to get initial heights
+ m_particles.init(m_arap.m_ocean.m_heights);
+
}
void GLWidget::paintCaustics() {
@@ -458,6 +464,8 @@ void GLWidget::paintGL()
m_skybox.draw(m_skyboxShader, m_camera);
+ m_particles.draw(m_particleShader, m_camera);
+
@@ -684,7 +692,10 @@ void GLWidget::tick()
float deltaSeconds = m_deltaTimeProvider.restart() / 1000.f;
m_arap.update(deltaSeconds);
// rotate skybox
+ m_particles.setVerts(m_arap.m_ocean.m_heights);
m_skybox.update(deltaSeconds);
+ m_particles.update(deltaSeconds);
+
// Move camera
auto look = m_camera.getLook();
diff --git a/src/glwidget.h b/src/glwidget.h
index 60cca66..50d6347 100755
--- a/src/glwidget.h
+++ b/src/glwidget.h
@@ -1,6 +1,8 @@
#pragma once
#include "skybox.h"
+#include "particlesystem.h"
+
#include <GL/glew.h>
@@ -70,6 +72,7 @@ private:
Shader *m_colorShader;
Shader *m_foamShader;
Shader *m_skyboxShader;
+ Shader *m_particleShader;
@@ -122,4 +125,5 @@ private:
int m_lastSelectedVertex = -1;
skybox m_skybox;
+ particlesystem m_particles;
};
diff --git a/src/ocean/ocean_alt.cpp b/src/ocean/ocean_alt.cpp
index dcc3e42..58e76f8 100644
--- a/src/ocean/ocean_alt.cpp
+++ b/src/ocean/ocean_alt.cpp
@@ -330,6 +330,7 @@ void ocean_alt::update_ocean()
// reset normals & vertices arrays for the single tile
m_vertices = std::vector<Eigen::Vector3f>(N);
m_normals = std::vector<Eigen::Vector3f>(N);
+ m_heights.clear();
for (int i = 0; i < N; i++){
Eigen::Vector2d horiz_pos = spacing*m_waveIndexConstants[i].base_horiz_pos;
Eigen::Vector2d amplitude = m_current_h[i];
@@ -357,9 +358,10 @@ void ocean_alt::update_ocean()
Eigen::Vector2d disp = lambda*Eigen::Vector2d(m_displacements_x[i][0], m_displacements_z[i][0])
+ Eigen::Vector2d(vertex_displacement, vertex_displacement); // set corner at 0,0 for retiling
+ Eigen::Vector3f v = Eigen::Vector3f(horiz_pos[0] + disp[0], height, horiz_pos[1] + disp[1]);
// for final vertex position, use the real number component of amplitude vector
- m_vertices[i] = {horiz_pos[0] + disp[0], height, horiz_pos[1] + disp[1]};
+ m_vertices[i] = v;
m_normals[i] = norm.normalized();//Eigen::Vector3f(-slope[0], 1.0, -slope[1]).normalized();
//std::cout << "normal: " << m_normals[i] << std::endl
Eigen::Vector2i m_n = index_1d_to_2d(i);
@@ -367,14 +369,14 @@ void ocean_alt::update_ocean()
// m_foam_constants.wavelengths[i] = 2.f* M_PI * m_slopes[i].dot(m_slopes[i]) / Lx;
float h_0 = m_waveIndexConstants[i].h0_prime[0]; // min*.2f;
- float h_max = max*.01f; // the smaller the constant, the more foam there is
- m_foam_constants.wavelengths[i] = (height - h_0 ) / (h_max - h_0);
-
-// if (i < 5){
-// std::cout << h_0 << ", " << h_max << std::endl;
-// std::cout << m_foam_constants.wavelengths[i] << std::endl;
-// }
+ float h_max = max*.001f; // the smaller the constant, the more foam there is
+ float waveheight = (height - h_0 ) / (h_max - h_0);
+ m_foam_constants.wavelengths[i] = waveheight;
+ if (waveheight >= height_threshold){
+ //std::cout << "push" << std::endl;
+ m_heights.push_back(v);
+ }
}
diff --git a/src/ocean/ocean_alt.h b/src/ocean/ocean_alt.h
index 9c5e4e2..a5bcd12 100644
--- a/src/ocean/ocean_alt.h
+++ b/src/ocean/ocean_alt.h
@@ -43,6 +43,8 @@ public:
}
std::vector<Eigen::Vector3f> m_vertices; // current displacement vector for each K
+ std::vector<Eigen::Vector3f> m_heights; // stores height above threshold
+
@@ -71,8 +73,8 @@ private:
const double Lx = 512.0;
const double Lz = 512.0;
- const int num_rows = 256;
- const int num_cols = 256;
+ const int num_rows = 128;
+ const int num_cols = 128;
const int num_tiles_x = 1;
const int num_tiles_z = 1;
@@ -83,8 +85,8 @@ private:
const double lambda = .5; // how much displacement matters
const double spacing = 1.0; // spacing between grid points
- const double A = 10000; // numeric constant for the Phillips spectrum
- const double V = 500; // wind speed
+ const double A = 100; // numeric constant for the Phillips spectrum
+ const double V = 50; // wind speed
const double gravity = 9.81;
const double L = V*V/gravity;
const Eigen::Vector2d omega_wind = Eigen::Vector2d(1.0, 0.0); // wind direction, used in Phillips equation
@@ -102,6 +104,8 @@ private:
// FOR FOAM:
FoamConstants m_foam_constants;
+ float height_threshold = 2.f;
+
float max = 0;
diff --git a/src/particlesystem.cpp b/src/particlesystem.cpp
new file mode 100644
index 0000000..104b449
--- /dev/null
+++ b/src/particlesystem.cpp
@@ -0,0 +1,176 @@
+#include "particlesystem.h"
+#include <iostream>
+
+particlesystem::particlesystem()
+{
+
+}
+
+std::pair<double,double> sample_complex_gaussian(){
+ double uniform_1 = (double)rand() / (RAND_MAX);
+ double uniform_2 = (double)rand() / (RAND_MAX);
+
+ // set a lower bound on zero to avoid undefined log(0)
+ if (uniform_1 == 0)
+ {
+ uniform_1 = 1e-10;
+ }
+ if (uniform_2 == 0)
+ {
+ uniform_2 = 1e-10;
+ }
+
+ // real and imaginary parts of the complex number
+ double real = sqrt(-2*log(uniform_1)) * cos(2*M_PI*uniform_2);
+ double imag = sqrt(-2*log(uniform_1)) * sin(2*M_PI*uniform_2);
+
+ return std::make_pair(real, imag);
+}
+
+float getRandomInRange(float max, float min){
+ return min + static_cast <float> (rand()) /( static_cast <float> (RAND_MAX/(max-min)));
+
+}
+
+Eigen::Vector3f particlesystem::getRandomInitialVel(){
+
+
+ std::pair<float, float> r = sample_complex_gaussian();
+ return factor*Eigen::Vector3f(r.first, getRandomInRange(1.f, 10.f), r.second);
+}
+
+void particlesystem::init(std::vector<Eigen::Vector3f> verts){
+ // make sure to set m_verts
+ setVerts(verts);
+
+ m_particles.reserve(4000);
+
+ for (Eigen::Vector3f v : m_verts){
+ Particle p;
+ p.pos = Eigen::Vector3f(v);
+ p.vel = getRandomInitialVel();
+
+
+ m_particles.push_back(p);
+ }
+
+
+ glGenVertexArrays(1, &VAO);
+ glGenBuffers(1, &VBO);
+ glBindVertexArray(VAO);
+
+ glBindBuffer(GL_ARRAY_BUFFER, VBO);
+ glBufferData(GL_ARRAY_BUFFER, m_vertices.size()*sizeof(float), m_vertices.data(), GL_STATIC_DRAW);
+
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2*sizeof(float), (void*)0);
+
+ // unbind
+ glEnableVertexAttribArray(0);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+}
+
+
+void particlesystem::update(double deltaTime){
+
+ // add new particles
+ for (int i=0; i<m_particles.size(); i++){
+ int particle_index = getUnusedParticleIndex();
+ if (particle_index == -1) continue;
+ if (particle_index >= m_particles.size() - 1 || particle_index >= m_verts.size() - 1) continue;
+ respawn_particle(m_particles[particle_index], m_verts[particle_index]);
+
+ }
+
+
+ float dt = deltaTime;
+ // update all particles values
+ for (Particle &p : m_particles){
+ p.life -= deltaTime * getRandomInRange(.01f, .5f);
+
+ // if particle is still alive, update pos
+ if (p.life >= 0.f){
+ p.vel += gravity*dt;
+ p.pos += p.vel * dt * 10.f;
+
+ }
+
+ }
+}
+
+
+
+// finds the first instance of a particle that is dead, and returns its index so it can be replaced
+int particlesystem::getUnusedParticleIndex(){
+
+ // search from last used index
+ for (int i=lastUsedIndex; i<m_verts.size(); ++i){
+ if (m_particles[i].life <= 0.f){
+ lastUsedIndex = i;
+ return i;
+ }
+ }
+
+ // otherwise do linear search up to last used
+ for (int i=0; i<lastUsedIndex; ++i){
+ if (m_particles[i].life <= 0.f){
+ lastUsedIndex = i;
+ return i;
+ }
+ }
+
+ // if no dead ones found, don't respawn
+ lastUsedIndex = 0;
+ //std::cout << "first particle override!" << std::endl;
+ return -1;
+}
+
+void particlesystem::respawn_particle(Particle &p, Eigen::Vector3f new_pos){
+
+ p.pos = new_pos;
+ p.vel = getRandomInitialVel(); // TODO: change to more accurate vel
+
+ // reset life
+ p.life = 1.f;
+
+}
+
+void particlesystem::draw(Shader *shader, Camera m_camera){
+
+ shader->bind();
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+
+
+ // activate texture
+// glActiveTexture(GL_TEXTURE10);
+// glBindTexture(GL_TEXTURE_CUBE_MAP, skybox_tex);
+// glUniform1i(glGetUniformLocation(shader->id(), "cubeMap"), 9); // bind texture at slot 9
+
+
+ // manually set view and projection, for non-translating view
+ Eigen::Matrix4f projection = m_camera.getProjection();
+ Eigen::Matrix4f view = m_camera.getView();
+ // view.col(3) = Eigen::Vector4f(0, 0, 0, 0);
+
+ glUniformMatrix4fv(glGetUniformLocation(shader->id(), "view"), 1, GL_FALSE, view.data());
+ glUniformMatrix4fv(glGetUniformLocation(shader->id(), "projection"), 1, GL_FALSE, projection.data());
+ // shader->setUniform("model", model);
+
+ int i = 0;
+ for (Particle p : m_particles){
+ if (p.life >= 0.f){
+ shader->setUniform("offset", p.pos);
+ shader->setUniform("alpha", p.life);
+
+ glBindVertexArray(VAO);
+ glDrawArrays(GL_TRIANGLES, 0, m_vertices.size());
+ glBindVertexArray(0);
+ i++;
+ }
+ }
+ shader->unbind();
+
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+
+}
diff --git a/src/particlesystem.h b/src/particlesystem.h
new file mode 100644
index 0000000..9744153
--- /dev/null
+++ b/src/particlesystem.h
@@ -0,0 +1,83 @@
+
+#ifndef PARTICLESYSTEM_H
+#define PARTICLESYSTEM_H
+
+#include <iostream>
+#define EIGEN_DISABLE_UNALIGNED_ARRAY_ASSERT
+#define EIGEN_DONT_VECTORIZE
+#include "graphics/shader.h"
+#include "graphics/camera.h"
+
+#include <Eigen/Core>
+#include <Eigen/Dense>
+#include <Eigen/Sparse>
+#include <Eigen/Geometry>
+
+struct Particle{
+ Eigen::Vector3f pos = Eigen::Vector3f(0,0,0);
+ Eigen::Vector3f vel = Eigen::Vector3f(0,2000,0);
+
+ Eigen::Vector4f color = Eigen::Vector4f(1,1,1,1);
+ float life = 1.f;
+
+};
+
+class particlesystem
+{
+public:
+ particlesystem();
+
+ void update(double deltaTime);
+ void draw(Shader *skybox_shader, Camera m_camera);
+ void draw(Shader *shader, Camera m_camera, std::vector<Eigen::Vector3f> verts, Eigen::Matrix4f model);
+
+ void init(std::vector<Eigen::Vector3f> verts);
+
+ void setVerts(std::vector<Eigen::Vector3f> verts){
+ std::cout << "VERTS SIZE:" << verts.size() << std::endl;
+ m_verts = verts;
+
+ }
+
+
+
+private:
+ int m_amount = 500;
+ int m_new_amount = 100; // new particles per frame
+ int lastUsedIndex = 0;
+ Eigen::Vector3f gravity = Eigen::Vector3f(0,-9.81f,0);
+ float factor = 10.f; // velocity multiplier
+
+
+
+ void respawn_particle(Particle &p, Eigen::Vector3f new_pos);
+ int getUnusedParticleIndex();
+ Eigen::Vector3f getRandomInitialVel();
+
+
+
+
+ float d = 5.f;
+ std::vector<float> m_vertices = {
+ -d, d,
+ d,d,
+ -d, -d,
+ d, d,
+ d, -d,
+ -d, -d
+ };
+
+ GLuint VAO, VBO; // holds quad shape
+
+
+
+
+
+
+ std::vector<Particle> m_particles;
+
+ std::vector<Eigen::Vector3f> m_verts;
+
+};
+
+#endif // PARTICLESYSTEM_H