Skip to content

Instantly share code, notes, and snippets.

@axjxwright
Last active May 21, 2022 15:30
Show Gist options
  • Save axjxwright/da59d96fae91943059857c4b2d3b7250 to your computer and use it in GitHub Desktop.
Save axjxwright/da59d96fae91943059857c4b2d3b7250 to your computer and use it in GitHub Desktop.
#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"
#include "cinder/Rand.h"
#include "cinder/CameraUi.h"
#include "cinder/Perlin.h"
using namespace ci;
using namespace ci::app;
using namespace std;
class PointSpriteApp : public App
{
public:
void setup ( ) override;
void update ( ) override;
void draw ( ) override;
gl::BatchRef _geometry;
CameraPersp _camera;
CameraUi _cameraUi;
gl::Texture2dRef _sprite;
std::vector<vec3> _positions;
int _numPoints{10000};
};
void PointSpriteApp::setup()
{
_camera = CameraPersp ( getWindowWidth(), getWindowHeight(), 60.0f, 0.1f, 1000.0f );
_camera.lookAt ( vec3 ( 0, 0, 5 ), vec3 ( 0 ) );
_cameraUi = CameraUi ( &_camera, getWindow() );
{
Surface8u circle ( 128, 128, true );
for ( int i = 0; i < circle.getWidth(); i++ )
{
for ( int j = 0; j < circle.getHeight(); j++ )
{
ivec2 pixel{i, j};
ColorAf color = glm::distance ( vec2(pixel), circle.getBounds().getCenter() ) <= circle.getWidth() / 2 ? ColorAf::white() : ColorAf ( 1, 1, 1, 0 );
circle.setPixel(pixel, color);
}
}
_sprite = gl::Texture2d::create ( circle, gl::Texture2d::Format().mipmap().minFilter(GL_LINEAR_MIPMAP_LINEAR).magFilter(GL_LINEAR) );
}
auto vs = CI_GLSL(150,
uniform mat4 ciModelViewProjection;
in vec4 ciPosition;
in vec3 ciColor;
in float vSize;
out vec3 Color;
void main ( )
{
gl_PointSize = vSize;
gl_Position = ciModelViewProjection * ciPosition;
Color = ciColor;
}
);
auto fs = CI_GLSL(150,
uniform sampler2D uTexture;
in vec3 Color;
out vec4 FinalColor;
void main ( )
{
vec4 color = vec4(Color, 1);
color *= texture(uTexture, gl_PointCoord);
if ( color.a < 0.01f ) discard;
FinalColor = color;
}
);
auto shader = gl::GlslProg::create ( vs, fs );
shader->uniform ( "uTexture", 0 );
std::vector<Colorf> colors;
std::vector<float> sizes;
for ( int i = 0; i < _numPoints; i++ )
{
vec3 position { randFloat(-1, 1), randFloat(-1, 1), randFloat(-1, 1) };
_positions.push_back( position * 50.0f );
sizes.push_back( randFloat ( 0.1f, 30.0f ));
colors.push_back( Colorf { randFloat(0.2, 0.7), randFloat(0.2, 0.7), randFloat(0.2, 0.7) } );
}
auto posLayout = gl::VboMesh::Layout().attrib( geom::POSITION, 3 ).usage(GL_DYNAMIC_DRAW); // Because these update every frame
auto colorAndSizeLayout = gl::VboMesh::Layout().attrib( geom::COLOR, 3 ).attrib(geom::CUSTOM_0, 1).usage(GL_STATIC_DRAW); // Because these dont
auto mesh = gl::VboMesh::create(_numPoints, GL_POINTS, { posLayout, colorAndSizeLayout } );
mesh->bufferAttrib( geom::POSITION, _positions );
mesh->bufferAttrib( geom::COLOR, colors );
mesh->bufferAttrib( geom::CUSTOM_0, sizes );
_geometry = gl::Batch::create ( mesh, shader, { { geom::Attrib::CUSTOM_0, "vSize" } } );
gl::enableAlphaBlending();
gl::enableDepth();
gl::enable ( GL_VERTEX_PROGRAM_POINT_SIZE );
}
void PointSpriteApp::update()
{
static Perlin kNoise;
for ( int i = 0; i < _geometry->getNumVertices(); i++ )
{
_positions[i].z += std::sin ( getElapsedSeconds() ) * 0.2f * ( _positions[i].z * 0.05 );
}
_geometry->getVboMesh()->bufferAttrib( geom::POSITION, _positions );
}
void PointSpriteApp::draw()
{
gl::clear ( Colorf::gray(0.2f) );
gl::setMatrices( _camera );
{
gl::ScopedTextureBind tex0 ( _sprite, 0 );
_geometry->draw ( );
}
}
CINDER_APP( PointSpriteApp, RendererGl, [] ( App::Settings * settings ) { settings->setWindowSize(1280, 720); } )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment