Esempio n. 1
0
void triMeshApp::setup(){
	// cam, lights material
	mCam = new CameraPersp(getWindowWidth(), getWindowHeight(), 45.0f);
	mCam->lookAt( Vec3f(300, 700, -600), Vec3f(0,0,0) );
	mCam->setPerspective( 60.0f, getWindowAspectRatio(), 0.1f, 5000.0f );
	yrot = 0;
	
	glEnable(GL_DEPTH_TEST);
	glShadeModel(GL_SMOOTH);
	glEnable(GL_LIGHTING);
	glEnable(GL_NORMALIZE);

	mLight = new gl::Light(gl::Light::DIRECTIONAL, 0);
	mLight->setDirection( Vec3f(0,0.1,0.3).normalized());
	mLight->setAmbient( Color( 0.2f, 0.2f, 0.2f ) );
	mLight->setDiffuse( Color( 1.0f, 1.0f, 1.0f ) );
	mLight->update( *mCam );
	mLight->enable();
	
	mMaterial1.setSpecular( Color(0.5,0.5,0.5) );
	mMaterial1.setDiffuse( Color( 0.0f, 1.0f, 0.0f ) );
	mMaterial1.setAmbient( Color( 0.1f, 0.1f, 0.1f ) );
	mMaterial1.setShininess( 20.0f );
	mMaterial1.apply();
	
	mMaterial2.setSpecular( Color(0,0,0) );
	mMaterial2.setDiffuse( Color(1,0,0) );
	mMaterial2.setAmbient( Color( 0.4f, 0.0f, 0.0f ) );
	mMaterial2.setEmission(Color(1,0,0));
	
	initPhysics();
	
	
	ObjLoader loader( loadResource( RES_LOSPHERE )->createStream() );
	loader.load( &mConvex );
	mVBO = gl::VboMesh( mConvex );
	
	ObjLoader loader2( loadResource( RES_TORUS )->createStream() );
	loader2.load( &mConcave );
	mVBOTerrain = gl::VboMesh( mConcave );

	btConvexHullShape* shape = bullet::createConvexHullShape(mConvex, Vec3f(CONVEX_SCALE, CONVEX_SCALE, CONVEX_SCALE));
	m_convexRigidBody = bullet::createConvexHullBody(m_dynamicsWorld, shape, Vec3f(0,500,0), 10000);
	
	btBvhTriangleMeshShape* concaveShape = bullet::createStaticConcaveMeshShape(mConcave, Vec3f(CONCAVE_SCALE, CONCAVE_SCALE, CONCAVE_SCALE), 5.0f);
	m_concaveRigidBody = bullet::createStaticRigidBody(m_dynamicsWorld, concaveShape, Vec3f(0,255,0));
	
	m_hfImage = loadImage(loadResource(RES_HEIGHTMAP));
	m_hfChannel = new Channel32f(m_hfImage);
	// note that HF_HEIGHTSCALE is ignored since we are using float data. we adjust the y-scale with the local scaling parameter only!
	btHeightfieldTerrainShape* hfShape = bullet::createHeightfieldTerrainShape(m_hfChannel, 64, 64, HF_HEIGHTSCALE, -500, 500, 1, Vec3f(HF_SCALE,HF_SCALEY,HF_SCALE));
	m_hfRigidBody = bullet::createStaticRigidBody(m_dynamicsWorld, hfShape, Vec3f(0,0,0));
	
	gl::VboMesh::Layout layout;
	layout.setDynamicColorsRGB();
	layout.setDynamicPositions();
	mVBOHeightfield = gl::VboMesh( m_hfImage.getWidth() * m_hfImage.getHeight(), 0, layout, GL_POINTS );
	
	updateData( );		
}
void DelaunayMeshMaker::fileDrop( FileDropEvent event ){
	try {
		mSurface = loadImage( event.getFile( 0 ) );

		int width = mSurface.getWidth();
		int height = mSurface.getHeight();
		app::setWindowSize( width, height );

		mFbo = gl::Fbo( width, height, false );

		mBorderPoints.clear();
		mBorderPoints.push_back( Vec2f::zero() );
		mBorderPoints.push_back( Vec2f( (float)width, 0 ) );
		mBorderPoints.push_back( Vec2f( (float)width ,(float)height ) );
		mBorderPoints.push_back( Vec2f( 0 ,(float)height ) );

		mSteinerPoints.clear();
		mMesh.clear();

		tesselate();
	}
	catch( ... ) {
		console() << "unable to load the texture file!" << std::endl;
	};
	
}
Esempio n. 3
0
void gpuPSApp::setupTextures(){
	// Position 2D texture array
	mInitPos = Surface32f( SIDE, SIDE, true);
	Surface32f::Iter pixelIter = mInitPos.getIter();
	while( pixelIter.line() ) {
		while( pixelIter.pixel() ) {
			/* Initial particle positions are passed in as R,G,B 
			 float values. Alpha is used as particle mass. */
			mInitPos.setPixel( pixelIter.getPos(), ColorAf( Rand::randFloat()-0.5f, Rand::randFloat()-0.5f, Rand::randFloat()-0.5f, Rand::randFloat(0.2f, 1.0f) ) );
		}
	}
	gl::Texture::Format tFormat;
	tFormat.setInternalFormat(GL_RGBA32F_ARB);
	mPositions = gl::Texture( mInitPos, tFormat);
	mPositions.setWrap( GL_REPEAT, GL_REPEAT );
	mPositions.setMinFilter( GL_NEAREST );
	mPositions.setMagFilter( GL_NEAREST );
	
	//Velocity 2D texture array
	mInitVel = Surface32f( SIDE, SIDE, true);
	pixelIter = mInitVel.getIter();
	while( pixelIter.line() ) {
		while( pixelIter.pixel() ) {
			/* Initial particle velocities are
			 passed in as R,G,B float values. */
			mInitVel.setPixel( pixelIter.getPos(), ColorAf( 0.0f, 0.0f, 0.0f, 1.0f ) );
		}
	}
	mVelocities = gl::Texture( mInitVel, tFormat);
	mVelocities.setWrap( GL_REPEAT, GL_REPEAT );
	mVelocities.setMinFilter( GL_NEAREST );
	mVelocities.setMagFilter( GL_NEAREST );
}
Esempio n. 4
0
Colorf ChessPiece::getColor(Surface32f surface, Vec2i pixel)
{
	float r = *surface.getDataRed(pixel);
	float g = *surface.getDataGreen(pixel);
	float b = *surface.getDataBlue(pixel);
	return Colorf(r, g, b);
}
void DelaunayMeshMaker::setup()
{
	mSurface = loadImage( app::loadAsset( "texture0.jpg" ) );
	
	int width = mSurface.getWidth();
	int height = mSurface.getHeight();
	app::setWindowSize( width, height );

	mFbo = gl::Fbo( width, height, false );

	mBorderPoints.push_back( Vec2f::zero() );
	mBorderPoints.push_back( Vec2f( (float)width, 0 ) );
	mBorderPoints.push_back( Vec2f( (float)width ,(float)height ) );
	mBorderPoints.push_back( Vec2f( 0 ,(float)height ) );

	mMesh.clear();

	mParams = params::InterfaceGl( "Parameters", Vec2i( 300, 250 ) );
	mParams.addParam( "Alpha", &mAlpha, "max=1.0 min=0.0 step=0.005" );
	mParams.addParam( "Blend", &mBlend );
	mParams.addParam( "Phong Shading", &mApplyPhongShading );
	mParams.addParam( "Depth Offset", &mDepthOffset, "step=0.1" );
	mParams.addParam( "Draw wireframe", &mDrawWireframe );
	
	mParams.addSeparator();
	mParams.addText("Edge detection");
	mParams.addParam( "Edge detection scale down", &mScaleDown, "min=1" );
	mParams.addParam( "Minimum threshold", &mCannyMinThreshold, "min=0.0f" );
	mParams.addParam( "Maximum threshold", &mCannyMaxThreshold, "min=0.0f" );

	mParams.addSeparator();
	mParams.addButton( "Tesselate", std::bind( &DelaunayMeshMaker::tesselate, this ) );

	mScaleDown			= 8;
	mScaleDownPrev		= mScaleDown;
	mCannyMinThreshold	= 60.0;
	mCannyMaxThreshold	= 70.0;
	mAlpha				= 0.0f;
	mBlend				= false;
	mApplyPhongShading	= false;
	mDrawWireframe		= false;
	mDepthOffset		= 0.0f;
	mPrevDepthOffset	= mDepthOffset;
	mPrevBlend			= mBlend;

	mPhongShader = gl::GlslProg( loadAsset("phong_vert.glsl"), loadAsset("phong_frag.glsl") );

	mEdgeDetectSurface = edgeDetect( Surface8u( mSurface ), mCannyMinThreshold, mCannyMaxThreshold, mScaleDownPrev );

	mTesselator = Tesselator::makeTesselator();
	mTesselator->sDone.connect( boost::bind( &DelaunayMeshMaker::onTesselationDone, this ) );
}
Esempio n. 6
0
void BasicApp::openFile()
{
	mImage = loadImage( loadAsset( "mona.jpg" ) );

	mWidth = mImage.getWidth();
	mHeight = mImage.getHeight();

	dx::VboMesh::Layout layout;
	layout.setDynamicColorsRGB();
	layout.setDynamicPositions();
	mVboMesh = dx::VboMesh( mWidth * mHeight, 0, layout, D3D_PRIMITIVE_TOPOLOGY_POINTLIST );

	updateData( kColor );		
}
void ImageHFApp::openFile()
{
	fs::path path = getOpenFilePath( "", ImageIo::getLoadExtensions() );
	if( ! path.empty() ) {
		mImage = loadImage( path );
	 
		mWidth = mImage.getWidth();
		mHeight = mImage.getHeight();

		mVboMesh = gl::VboMesh::create( mWidth * mHeight, GL_POINTS, { gl::VboMesh::Layout().usage(GL_STATIC_DRAW).attrib(geom::POSITION, 3).attrib(geom::COLOR, 3) } );
		mPointsBatch = gl::Batch::create( mVboMesh, gl::getStockShader( gl::ShaderDef().color() ) );

		updateData( kColor );		
	}
}
Esempio n. 8
0
void triMeshApp::updateData()
{
	Surface32f::Iter pixelIter = m_hfImage.getIter();
	gl::VboMesh::VertexIter vertexIter( mVBOHeightfield );
	
	while( pixelIter.line() ) {
		while( pixelIter.pixel() ) {
			Color color( pixelIter.r(), pixelIter.g(), pixelIter.b() );
			float height;

			height = color.dot( Color( 0.3333f, 0.3333f, 0.3333f ) );
         

			// the x and the z coordinates correspond to the pixel's x & y
			float x = (pixelIter.x() - m_hfImage.getWidth() / 2.0f);
			float z = (pixelIter.y() - m_hfImage.getHeight() / 2.0f);
			
            vertexIter.setPosition( x * HF_SCALE, height * HF_SCALEY, z * HF_SCALE);
			vertexIter.setColorRGB( color );
			++vertexIter;
		}
	}
}
Esempio n. 9
0
void AudioObjApp::update()
{
	if ( mFeature )
	{
		mFeature->setDamping( mFeatureDamping );
		mFeature->setGain( mFeatureGain );
		mFeature->setOffset( mFeatureOffset );
	}

    mXtract->update();

	if ( mFeature )
	{
		// update Surface
		int x, y;
		for( int k=0; k < mFeature->getSize(); k++ )
		{
			x = k % mFeatureSurf.getWidth();
			y = k / mFeatureSurf.getWidth();
			mFeatureSurf.setPixel( Vec2i(x, y), Color::gray( mFeature->getDataValue(k) ) );
		}
		mFeatureTex = gl::Texture( mFeatureSurf );
	}
}
void ImageHFApp::updateData( ImageHFApp::ColorSwitch whichColor )
{
	Surface32f::Iter pixelIter = mImage.getIter();
	auto vertPosIter = mVboMesh->mapAttrib3f( geom::POSITION );
	auto vertColorIter = mVboMesh->mapAttrib3f( geom::COLOR );

	while( pixelIter.line() ) {
		while( pixelIter.pixel() ) {
			Color color( pixelIter.r(), pixelIter.g(), pixelIter.b() );
			float height;
			const float muteColor = 0.2f;

			// calculate the height based on a weighted average of the RGB, and emphasize either the red green or blue color in each of those modes
			switch( whichColor ) {
				case kColor:
					height = color.dot( Color( 0.3333f, 0.3333f, 0.3333f ) );
				break;
				case kRed:
					height = color.dot( Color( 1, 0, 0 ) );
					color *= Color( 1, muteColor, muteColor );
				break;
				case kGreen:
					height = color.dot( Color( 0, 1, 0 ) );
					color *= Color( muteColor, 1, muteColor );
				break;
				case kBlue:
					height = color.dot( Color( 0, 0, 1 ) );
					color *= Color( muteColor, muteColor, 1 );					
				break;            
			}

			// the x and the z coordinates correspond to the pixel's x & y
			float x = pixelIter.x() - mWidth / 2.0f;
			float z = pixelIter.y() - mHeight / 2.0f;

			*vertPosIter++ = vec3( x, height * 30.0f, z );
			*vertColorIter++ = vec3( color.r, color.g, color.b );
		}
	}

	vertPosIter.unmap();
	vertColorIter.unmap();
}
Esempio n. 11
0
Texture::Texture( const Surface32f &surface, Format format )
	: mObj( shared_ptr<Obj>( new Obj( surface.getWidth(), surface.getHeight() ) ) )
{
	if( format.mInternalFormat < 0 ) {
#if ! defined( CINDER_GLES )
		if( GLEE_ARB_texture_float )
			format.mInternalFormat = surface.hasAlpha() ? GL_RGBA32F_ARB : GL_RGB32F_ARB;
		else
			format.mInternalFormat = surface.hasAlpha() ? GL_RGBA : GL_RGB;
#else
		format.mInternalFormat = surface.hasAlpha() ? GL_RGBA : GL_RGB;
#endif	
	}
	mObj->mInternalFormat = format.mInternalFormat;
	mObj->mTarget = format.mTarget;

	init( surface.getData(), surface.hasAlpha()?GL_RGBA:GL_RGB, format );	
}
Esempio n. 12
0
void BasicApp::updateData( BasicApp::ColorSwitch whichColor )
{
	Surface32f::Iter pixelIter = mImage.getIter();
	dx::VboMesh::VertexIter vertexIter( mVboMesh );

	while( pixelIter.line() ) {
		while( pixelIter.pixel() ) {
			Color color( pixelIter.r(), pixelIter.g(), pixelIter.b() );
			float height;
			const float muteColor = 0.2f;

			// calculate the height based on a weighted average of the RGB, and emphasize either the red green or blue color in each of those modes
			switch( whichColor ) {
				case kColor:
					height = color.dot( Color( 0.3333f, 0.3333f, 0.3333f ) );
				break;
				case kRed:
					height = color.dot( Color( 1, 0, 0 ) );
					color *= Color( 1, muteColor, muteColor );
				break;
				case kGreen:
					height = color.dot( Color( 0, 1, 0 ) );
					color *= Color( muteColor, 1, muteColor );
				break;
				case kBlue:
					height = color.dot( Color( 0, 0, 1 ) );
					color *= Color( muteColor, muteColor, 1 );					
				break;            
			}

			// the x and the z coordinates correspond to the pixel's x & y
			float x = pixelIter.x() - mWidth / 2.0f;
			float z = pixelIter.y() - mHeight / 2.0f;

            vertexIter.setPosition( x, height * 60.0f, z );
			vertexIter.setColorRGB( color );
			++vertexIter;
		}
	}
}
Esempio n. 13
0
Texture::Texture( const Surface32f &surface, Format format )
	: mObj( shared_ptr<Obj>( new Obj( surface.getWidth(), surface.getHeight() ) ) )
{
#if defined( CINDER_MAC )
	bool supportsTextureFloat = gl::isExtensionAvailable( "GL_ARB_texture_float" );
#elif defined( CINDER_MSW )
	bool supportsTextureFloat = GLEE_ARB_texture_float != 0;
#endif

	if( format.mInternalFormat < 0 ) {
#if ! defined( CINDER_GLES )
		if( supportsTextureFloat )
			format.mInternalFormat = surface.hasAlpha() ? GL_RGBA32F_ARB : GL_RGB32F_ARB;
		else
			format.mInternalFormat = surface.hasAlpha() ? GL_RGBA : GL_RGB;
#else
		format.mInternalFormat = surface.hasAlpha() ? GL_RGBA : GL_RGB;
#endif	
	}
	mObj->mInternalFormat = format.mInternalFormat;
	mObj->mTarget = format.mTarget;

	init( surface.getData(), surface.hasAlpha()?GL_RGBA:GL_RGB, format );	
}
Esempio n. 14
0
void fsExperiments::setupVbo()
{
	GlobalData& data = GlobalData::get();
	TriMesh neutralMesh = data.mFaceShift.getNeutralMesh();
	size_t numVertices = neutralMesh.getNumVertices();
	size_t numBlendShapes = data.mFaceShift.getNumBlendshapes();

	gl::VboMesh::Layout layout;

	layout.setStaticPositions();
	layout.setStaticIndices();
	layout.setStaticNormals();
	layout.setStaticTexCoords2d();

	// TODO: int attribute
	layout.mCustomStatic.push_back( std::make_pair( gl::VboMesh::Layout::CUSTOM_ATTR_FLOAT, 0 ) );

	data.mVboMesh = gl::VboMesh( neutralMesh.getNumVertices(),
							neutralMesh.getNumIndices(), layout, GL_TRIANGLES );

	data.mVboMesh.bufferPositions( neutralMesh.getVertices() );
	data.mVboMesh.bufferIndices( neutralMesh.getIndices() );
	if ( !neutralMesh.hasNormals() )
		neutralMesh.recalculateNormals();
	data.mVboMesh.bufferNormals( neutralMesh.getNormals() );
	data.mVboMesh.bufferTexCoords2d( 0, neutralMesh.getTexCoords() );
	data.mVboMesh.unbindBuffers();

	vector< float > vertexIndices( numVertices, 0.f );
	for ( uint32_t i = 0; i < numVertices; ++i )
		vertexIndices[ i ] = static_cast< float >( i );

	data.mVboMesh.getStaticVbo().bind();
	size_t offset = sizeof( GLfloat ) * ( 3 + 3 + 2 ) * neutralMesh.getNumVertices();
	data.mVboMesh.getStaticVbo().bufferSubData( offset,
			numVertices * sizeof( float ),
			&vertexIndices[ 0 ] );
	data.mVboMesh.getStaticVbo().unbind();

	// blendshapes texture
	gl::Texture::Format format;
	format.setTargetRect();
	format.setWrap( GL_CLAMP, GL_CLAMP );
	format.setMinFilter( GL_NEAREST );
	format.setMagFilter( GL_NEAREST );
	format.setInternalFormat( GL_RGB32F_ARB );

	int verticesPerRow = 32;
	int txtWidth = verticesPerRow * numBlendShapes;
	int txtHeight = math< float >::ceil( numVertices / (float)verticesPerRow );

	Surface32f blendshapeSurface = Surface32f( txtWidth, txtHeight, false );
	float *ptr = blendshapeSurface.getData();

	size_t idx = 0;
	for ( int j = 0; j < txtHeight; j++ )
	{
		for ( int s = 0; s < verticesPerRow; s++ )
		{
			for ( size_t i = 0; i < numBlendShapes; i++ )
			{
				*( reinterpret_cast< Vec3f * >( ptr ) ) = data.mFaceShift.getBlendshapeMesh( i ).getVertices()[ idx ] - neutralMesh.getVertices()[ idx ];
				ptr += 3;
			}
			idx++;
		}
	}

	data.mBlendshapeTexture = gl::Texture( blendshapeSurface, format );
}
void millionParticlesApp::setup()
{
    gl::clear();

    try {
        mPosShader = gl::GlslProg(ci::app::loadResource(POS_VS),ci::app::loadResource(POS_FS));
        mVelShader = gl::GlslProg(ci::app::loadResource(VEL_VS),ci::app::loadResource(VEL_FS));
    }
    catch( gl::GlslProgCompileExc &exc ) {
        std::cout << "Shader compile error: " << std::endl;
        std::cout << exc.what();
    }
    catch( ... ) {
        std::cout << "Unable to load shader" << std::endl;
    }

    //controls
    mDrawTextures = false;
    mIsFullScreen = false;

    mFrameCounter = 0;

    mPerlin = Perlin(32,clock() * .1f);

    //initialize buffer
    Surface32f mPosSurface = Surface32f(PARTICLES,PARTICLES,true);
    Surface32f mVelSurface = Surface32f(PARTICLES,PARTICLES,true);
    Surface32f mInfoSurface = Surface32f(PARTICLES,PARTICLES,true);
    Surface32f mNoiseSurface = Surface32f(PARTICLES,PARTICLES,true);

    Surface32f::Iter iterator = mPosSurface.getIter();


    while(iterator.line())
    {
        while(iterator.pixel())
        {

            mVertPos = Vec3f(Rand::randFloat(getWindowWidth()) / (float)getWindowWidth(),
                             Rand::randFloat(getWindowHeight()) / (float)getWindowHeight(),0.0f);

            //velocity
            Vec2f vel = Vec2f(Rand::randFloat(-.005f,.005f),Rand::randFloat(-.005f,.005f));

            float nX = iterator.x() * 0.005f;
            float nY = iterator.y() * 0.005f;
            float nZ = app::getElapsedSeconds() * 0.1f;
            Vec3f v( nX, nY, nZ );
            float noise = mPerlin.fBm( v );

            float angle = noise * 15.0f ;

            //vel = Vec3f( cos( angle ) * 6.28f, cos( angle ) * 6.28f, 0.0f );

            //noise
            mNoiseSurface.setPixel(iterator.getPos(),
                                   Color( cos( angle ) * Rand::randFloat(.00005f,.0002f), sin( angle ) * Rand::randFloat(.00005f,.0002f), 0.0f ));

            //position + mass
            mPosSurface.setPixel(iterator.getPos(),
                                 ColorA(mVertPos.x,mVertPos.y,mVertPos.z,
                                        Rand::randFloat(.00005f,.0002f)));
            //forces + decay
            mVelSurface.setPixel(iterator.getPos(), Color(vel.x,vel.y, Rand::randFloat(.01f,1.00f)));

            //particle age
            mInfoSurface.setPixel(iterator.getPos(),
                                  ColorA(Rand::randFloat(.007f,1.0f), 1.0f,0.00f,1.00f));

        }
    }

    //gl texture settings
    gl::Texture::Format tFormat;
    tFormat.setInternalFormat(GL_RGBA16F_ARB);

    gl::Texture::Format tFormatSmall;
    tFormat.setInternalFormat(GL_RGBA8);

    mSpriteTex = gl::Texture( loadImage( loadResource( "point.png" ) ), tFormatSmall);


    mNoiseTex = gl::Texture(mNoiseSurface, tFormatSmall);
    mNoiseTex.setWrap( GL_REPEAT, GL_REPEAT );
    mNoiseTex.setMinFilter( GL_NEAREST );
    mNoiseTex.setMagFilter( GL_NEAREST );

    mPosTex = gl::Texture(mPosSurface, tFormat);
    mPosTex.setWrap( GL_REPEAT, GL_REPEAT );
    mPosTex.setMinFilter( GL_NEAREST );
    mPosTex.setMagFilter( GL_NEAREST );

    mVelTex = gl::Texture(mVelSurface, tFormat);
    mVelTex.setWrap( GL_REPEAT, GL_REPEAT );
    mVelTex.setMinFilter( GL_NEAREST );
    mVelTex.setMagFilter( GL_NEAREST );

    mInfoTex = gl::Texture(mInfoSurface, tFormatSmall);
    mInfoTex.setWrap( GL_REPEAT, GL_REPEAT );
    mInfoTex.setMinFilter( GL_NEAREST );
    mInfoTex.setMagFilter( GL_NEAREST );

    //initialize fbo
    gl::Fbo::Format format;
    format.enableDepthBuffer(false);
    format.enableColorBuffer(true, 3);
    format.setMinFilter( GL_NEAREST );
    format.setMagFilter( GL_NEAREST );
    format.setWrap(GL_CLAMP,GL_CLAMP);
    format.setColorInternalFormat( GL_RGBA16F_ARB );

    mFbo[0] = gl::Fbo(PARTICLES,PARTICLES, format);
    mFbo[1] = gl::Fbo(PARTICLES,PARTICLES, format);

    initFBO();

    //fill dummy fbo
    vector<Vec2f> texCoords;
    vector<Vec3f> vertCoords, normCoords;
    vector<uint32_t> indices;

    gl::VboMesh::Layout layout;
    layout.setStaticIndices();
    layout.setStaticPositions();
    layout.setStaticTexCoords2d();
    layout.setStaticNormals();

    mVbo = gl::VboMesh(PARTICLES*PARTICLES,PARTICLES*PARTICLES,layout,GL_POINTS);

    for (int x = 0; x < PARTICLES; ++x) {
        for (int y = 0; y < PARTICLES; ++y) {
            indices.push_back( x * PARTICLES + y);
            texCoords.push_back( Vec2f( x/(float)PARTICLES, y/(float)PARTICLES));
        }
    }

    mVbo.bufferIndices(indices);
    mVbo.bufferTexCoords2d(0, texCoords);

}