Skip to content

Instantly share code, notes, and snippets.

@amulware amulware/00-particle-vertex.cs Secret
Last active Aug 29, 2015

Embed
What would you like to do?
Snippets for GameDev<T> post on GPU simulated parametric particles
struct ParticleVertex : IVertexData
{
private readonly Vector3 position0;
private readonly Vector3 velocity0;
private readonly float lifetime;
public ParticleVertex(Vector3 position0, Vector3 velocity0, float lifetime)
{
this.position0 = position0;
this.velocity0 = velocity0;
this.lifetime = lifetime;
}
public VertexAttribute[] VertexAttributes()
{
return attributes;
}
public int Size()
{
return size;
}
private static readonly VertexAttribute[] attributes =
VertexData.MakeAttributeArray(
VertexData.MakeAttributeTemplate<Vector3>("position0"),
VertexData.MakeAttributeTemplate<Vector3>("velocity0"),
VertexData.MakeAttributeTemplate<float>("lifetime")
);
private static readonly int size = VertexData.SizeOf<ParticleVertex>();
}
#version 150
// the time since the creation of the particular particle system
uniform float time;
// constant acceleration (gravity) to apply to the particles' movement
uniform vec3 acceleration;
in vec3 position0;
in vec3 velocity0;
in float lifetime;
out Particle
{
vec3 position;
float alpha;
} particle;
void main()
{
// calculate the corrent position of the particle
particle.position = position0
+ velocity0 * time
+ acceleration * (time * time * 0.5);
// calculate the opacity of the particle
// (does not have to be clamped to 0 since we are discarding
// non-positive alpha particles in the geometry shader)
particle.alpha = min(1, (time - lifetime) * -2);
}
#version 150
// we take single points as input
layout (points) in;
// we emit a triangle strip with up to 4 vertices per shader instance
layout (triangle_strip, max_vertices = 4) out;
uniform mat4 modelviewMatrix;
uniform mat4 projectionMatrix;
in Particle
{
vec3 position;
float alpha;
} particle[];
out Fragment
{
vec2 uv;
float alpha;
} fragment;
void main()
{
// we discard particles that have already faded out
if (particle[0].alpha <= 0)
return;
// assign alpha to output
fragment.alpha = particle[0].alpha;
// transform the center of the particle into camera space
vec4 center = modelviewMatrix * vec4(particle[0].position, 1);
// emit the four vertices
vec2 uv = vec2(-1, -1);
vec4 p = center;
p.xy += uv;
fragment.uv = uv;
gl_Position = projectionMatrix * p;
EmitVertex();
uv = vec2(1, -1);
p = center;
p.xy += uv;
fragment.uv = uv;
gl_Position = projectionMatrix * p;
EmitVertex();
uv = vec2(-1, 1);
p = center;
p.xy += uv;
fragment.uv = uv;
gl_Position = projectionMatrix * p;
EmitVertex();
uv = vec2(1, 1);
p = center;
p.xy += uv;
fragment.uv = uv;
gl_Position = projectionMatrix * p;
EmitVertex();
// emitting the primitive excplicitely is optional,
// but I like to include it to make it clear when
// geometry is created
EndPrimitive();
}
#version 150
in Fragment
{
vec2 uv;
float alpha;
} fragment;
out vec4 fragColor;
void main()
{
// colour the vertex with a simple procedural circular texture
float d = dot(fragment.uv, fragment.uv);
if(d > 1)
discard;
float a = 1 - d;
fragColor = vec4(0, 0, 0, a * fragment.alpha * 0.1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.