Skip to content

Instantly share code, notes, and snippets.

@TatsuyaOGth
Last active August 29, 2015 14:20
Show Gist options
  • Save TatsuyaOGth/891f59e2d490a268e707 to your computer and use it in GitHub Desktop.
Save TatsuyaOGth/891f59e2d490a268e707 to your computer and use it in GitHub Desktop.
An openFrameworks example of particle generation with point sprite.
#include "ofMain.h"
#include "ofxAnimationPrimitives.h"
static const string SHADER_FILEPATH_VERT = "shaders/pointSprite.vert";
static const string SHADER_FILEPATH_FRAG = "shaders/pointSprite.frag";
static const string TEXTURE_FILE_DIR = "textures";
class Particle : public ofxAnimationPrimitives::Instance
{
const int mNum;
const ofVec2f mPos;
const float mWide;
ofVbo mVbo;
ofVec3f* mVerts;
ofFloatColor* mColors;
ofVec3f* mNormals;
public:
static vector<ofImage> smTextures;
static ofShader smPointSprite;
public:
Particle(int x, int y, const int wide, const int num):
mPos(ofVec2f(x, y)), mWide(wide), mNum(num)
{
mVerts = new ofVec3f[mNum];
mColors = new ofFloatColor[mNum];
mNormals = new ofVec3f[mNum];
const float halfW = mWide * 0.5;
const int numTex = smTextures.size();
for (int i = 0; i < mNum; ++i)
{
mVerts[i].set(x + ofRandom(-halfW, halfW), y + ofRandom(-halfW, halfW));
mColors[i].set(255, 255, 255);
mNormals[i].set(ofRandom(1,10), (int)ofRandom(0,numTex));
}
mVbo.setVertexData(mVerts, mNum, GL_DYNAMIC_DRAW);
mVbo.setColorData(mColors, mNum, GL_DYNAMIC_DRAW);
mVbo.setNormalData(mNormals, mNum, GL_DYNAMIC_DRAW);
}
void update()
{
const int numTex = smTextures.size();
for(int i = 0; i < mNum; i++)
{
mVerts[i].y += 0.8;
const float a = ofxAnimationPrimitives::Easing::Quint::easeOut(getLife());
mColors[i].a = a;
mNormals[i].set(ofRandom(1,10), (int)ofRandom(0,numTex));
}
mVbo.updateVertexData(mVerts, mNum);
mVbo.updateColorData(mColors, mNum);
mVbo.updateNormalData(mNormals, mNum);
}
void draw()
{
ofEnableBlendMode(OF_BLENDMODE_ADD);
ofEnablePointSprites();
smPointSprite.begin();
for (int i = 0; i < smTextures.size(); ++i)
{
smPointSprite.setUniformTexture("tex"+ofToString(i), smTextures[i], i);
}
mVbo.draw(GL_POINTS, 0, mNum);
smPointSprite.end();
}
void willDelete()
{
delete [] mVerts;
delete [] mColors;
delete [] mNormals;
}
};
vector<ofImage> Particle::smTextures;
ofShader Particle::smPointSprite;
class ofApp : public ofBaseApp
{
ofxAnimationPrimitives::InstanceManager mParticles;
public:
ofApp()
{
ofDirectory dir;
int n = dir.listDir(TEXTURE_FILE_DIR);
ofDisableArbTex();
for (int i = 0; i < n; ++i)
{
Particle::smTextures.push_back(ofImage());
Particle::smTextures.back().loadImage(dir.getPath(i));
}
ofEnableArbTex();
Particle::smPointSprite.load(SHADER_FILEPATH_VERT, SHADER_FILEPATH_FRAG);
}
void update()
{
mParticles.update();
}
void draw()
{
ofBackground(0, 0, 0);
ofSetColor(255, 255, 255);
mParticles.draw();
ofDrawBitmapString(ofToString(ofGetFrameRate()), 20, 20);
}
void keyPressed(int key)
{
const float x = ofGetMouseX();
const float y = ofGetMouseY();
// The instance need 4 arguments.
// x and y are particle center position, wide is expand size from center position and num is number of particles.
mParticles.createInstance<Particle>(x, y, 200, 200)->play(2);
}
};
int main()
{
ofSetupOpenGL(1024,768, OF_WINDOW);
ofRunApp( new ofApp());
}
#version 120
uniform sampler2D tex1;
uniform sampler2D tex2;
varying float textureNumber;
void main()
{
vec2 st = gl_TexCoord[0].st;
vec4 color = vec4(0);
if(textureNumber == 0)
{
color = texture2D(tex1,st);
}
else {
color = texture2D(tex2,st);
}
gl_FragColor = color * gl_Color;
}
#version 120
varying float textureNumber;
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = gl_Color;
gl_PointSize = gl_Normal.x;
textureNumber = gl_Normal.y;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment