Skip to content

Instantly share code, notes, and snippets.

@fenbf
Last active February 4, 2018 00:02
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fenbf/31e4762a8ebad6aa3beb to your computer and use it in GitHub Desktop.
Save fenbf/31e4762a8ebad6aa3beb to your computer and use it in GitHub Desktop.
particle rendering 'system'.
#include "glParticleRenderer.h"
#include "particles.h"
#include <assert.h>
#include "gl_includes.h"
namespace particles
{
void GLParticleRenderer::generate(ParticleSystem *sys, bool)
{
assert(sys != nullptr);
m_system = sys;
const size_t count = sys->numAllParticles();
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
glGenBuffers(1, &m_bufPos);
glBindBuffer(GL_ARRAY_BUFFER, m_bufPos);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)* 4 * count, nullptr, GL_STREAM_DRAW);
glEnableVertexAttribArray(0);
if (ogl_ext_ARB_vertex_attrib_binding)
{
glBindVertexBuffer(0, m_bufPos, 0, sizeof(float)* 4);
glVertexAttribFormat(0, 4, GL_FLOAT, GL_FALSE, 0);
glVertexAttribBinding(0, 0);
}
else
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, (4)*sizeof(float), (void *)((0)*sizeof(float)));
glGenBuffers(1, &m_bufCol);
glBindBuffer(GL_ARRAY_BUFFER, m_bufCol);
glBufferData(GL_ARRAY_BUFFER, sizeof(float)* 4 * count, nullptr, GL_STREAM_DRAW);
glEnableVertexAttribArray(1);
if (ogl_ext_ARB_vertex_attrib_binding)
{
glBindVertexBuffer(1, m_bufCol, 0, sizeof(float)* 4);
glVertexAttribFormat(1, 4, GL_FLOAT, GL_FALSE, 0);
glVertexAttribBinding(1, 1);
}
else
glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, (4)*sizeof(float), (void *)((0)*sizeof(float)));
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
void GLParticleRenderer::destroy()
{
if (m_bufPos != 0)
{
glDeleteBuffers(1, &m_bufPos);
m_bufPos = 0;
}
if (m_bufCol != 0)
{
glDeleteBuffers(1, &m_bufCol);
m_bufCol = 0;
}
}
void GLParticleRenderer::update()
{
assert(m_system != nullptr);
assert(m_bufPos > 0 && m_bufCol > 0);
const size_t count = m_system->numAliveParticles();
if (count > 0)
{
glBindBuffer(GL_ARRAY_BUFFER, m_bufPos);
float *ptr = (float *)(m_system->finalData()->m_pos.get());
glBufferSubData(GL_ARRAY_BUFFER, 0, count*sizeof(float)* 4, ptr);
glBindBuffer(GL_ARRAY_BUFFER, m_bufCol);
ptr = (float*)(m_system->finalData()->m_col.get());
glBufferSubData(GL_ARRAY_BUFFER, 0, count*sizeof(float)* 4, ptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
}
void GLParticleRenderer::render()
{
glBindVertexArray(m_vao);
const size_t count = m_system->numAliveParticles();
if (count > 0)
glDrawArrays(GL_POINTS, 0, count);
glBindVertexArray(0);
}
}
#pragma once
#include "particleRenderer.h"
namespace particles
{
class GLParticleRenderer : public IParticleRenderer
{
protected:
ParticleSystem *m_system{ nullptr };
unsigned int m_bufPos{ 0 };
unsigned int m_bufCol{ 0 };
unsigned int m_vao{ 0 };
public:
GLParticleRenderer() { }
~GLParticleRenderer() { destroy(); }
void generate(ParticleSystem *sys, bool useQuads) override;
void destroy() override;
void update() override;
void render() override;
};
}
#include "particleRenderer.h"
#include "glParticleRenderer.h"
#include <string>
namespace particles
{
std::shared_ptr<IParticleRenderer> RendererFactory::create(const char *name)
{
std::string renderer{ name };
if (renderer == "gl")
return std::make_shared<GLParticleRenderer>();
return nullptr;
}
}
#pragma once
#include <memory>
namespace particles
{
class ParticleSystem;
class IParticleRenderer
{
public:
IParticleRenderer() { }
virtual ~IParticleRenderer() { }
virtual void generate(ParticleSystem *sys, bool useQuads) = 0;
virtual void destroy() = 0;
virtual void update() = 0;
virtual void render() = 0;
};
class RendererFactory
{
public:
static std::shared_ptr<IParticleRenderer> create(const char *name);
};
}
// vertex shader
#version 330
uniform mat4x4 matModelview;
uniform mat4x4 matProjection;
layout(location = 0) in vec4 vVertex;
layout(location = 1) in vec4 vColor;
out vec4 outColor;
void main()
{
vec4 eyePos = matModelview * gl_Vertex;
gl_Position = matProjection * eyePos;
outColor = vColor;
float dist = length(eyePos.xyz);
float att = inversesqrt(0.1f*dist);
gl_PointSize = 2.0f * att;
}
// fragment shader
#version 330
uniform sampler2D tex;
in vec4 outColor;
out vec4 vFragColor;
void main()
{
vFragColor = texture(tex, gl_PointCoord) * outColor;
}
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, gParticleTexture);
glEnable(GL_PROGRAM_POINT_SIZE);
mProgram.use();
mProgram.uniformMatrix4f("matProjection", glm::value_ptr(camera.projectionMatrix));
mProgram.uniformMatrix4f("matModelview", glm::value_ptr(camera.modelviewMatrix));
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
gpuRender.begin();
gCurrentEffect->render();
gpuRender.end();
glDisable(GL_BLEND);
mProgram.disable();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment