Author Message

<  advanced  ~  large point cloud w/ depth of field

PostPosted: Fri Nov 27, 2009 4:34 am
Joined: Fri Jun 27, 2008 4:49 amPosts: 453Location: Brooklyn
Hi everyone!

I've been testing an alternative way of rendering point clouds, using DOF to help give a more photographic feel and actually use the 3D information in 2D renders. They look like this:

Image
http://www.flickr.com/photos/kylemcdonald/4136191836/in/photostream/
Image
http://www.flickr.com/photos/kylemcdonald/4135432059/in/photostream/

Unfortunately, the only way I've found to get them looking nice is by rendering into a floating point FBO without depth testing, so that I can draw each point as part of a GL_POINTS call with their point size and opacity based on distance from the camera's focal plane (opacity is 1/(distance^2), point size is just distance).

This means that there are a lot of points that are very large being drawn to the screen. So every pixel has to be passed over multiple times. Right now with about 315k points I only get 3 frames per second if I turn off point smoothing (i.e., use a square aperture).

Does anyone have any ideas for how you might get a similar effect with a single (or just fewer) passes? Something that looks about the same, but could be rendered in realtime? I'm familiar with some approaches like this http://developer.amd.com/media/gpu_assets/Scheuermann_DepthOfField.pdf but skeptical that they would approximate the effect I have here with point clouds.

Any help is hugely appreciated!


Offline Profile
PostPosted: Fri Nov 27, 2009 8:02 am
Site AdminJoined: Thu Mar 01, 2007 10:03 pmPosts: 916Location: Amsterdam
hey this looks really amazing - nice work!

One thing I had pretty good luck with is having 3 to 5 FBOs. Each one is blurred (with a shader) by a different amount. Then you draw each point into each FBO with the opacity being a percentage of the blur you want.

This could end up being more calculations however because you are drawing each point more than once per frame.

Something that could help your performance is VBOs - I think memo has used them quite a bit when working with large numbers of particles.

Good luck!
T



_________________
http://www.theowatson.com
Offline Profile
PostPosted: Fri Nov 27, 2009 8:09 am
Joined: Fri Jun 27, 2008 4:49 amPosts: 453Location: Brooklyn
Thanks!

Multiple FBOs could help, but then you have the issue of drawing multiple transparent FBOs on top of each other, too. And there seem to be some unresolved issues with drawing FBOs with transparency on backgrounds. The whole "layer" based idea is really good though -- I can imagine doing it in N passes, where you divide all the points into one of N bins based on their distance from the focal plane (drawing only 1x1 px points) and then blur the entire layer using a frag shader to account for the "point size" and opacity. I feel like the artifacts might be really obvious using that technique, though -- you'd need to have a high N value.

I was considering VBOs (that's what Memo recommended too), but I'm positive they're not the bottleneck. If I just replace glPointSize(distance) with glPointSize(1), everything speeds up to realtime. So it's definitely the fill rate of the points that's killing the fps.


Offline Profile
PostPosted: Fri Nov 27, 2009 11:55 am
User avatarJoined: Tue May 27, 2008 10:03 amPosts: 691Location: London, UK
Quote:
If I just replace glPointSize(distance) with glPointSize(1), everything speeds up to realtime.


that pretty much says it all! maybe you can roughly calculate how pixels you are drawing to the screen (sum of pi * r^2) and compare it to you graphics card's fillrate (usually givin in Million pixels per second) and see if you are indeed near it.

The only way to avoid fillrate bandwidth issues, is to draw less pixels! This can be done through depth testing, alpha testing (i.e. do not draw to screen if alpha is say, less than 0.5) or other tests, but it seems you need to draw each pixel and blend them.... not looking good :P


Offline Profile
PostPosted: Fri Nov 27, 2009 2:14 pm
Joined: Mon Jun 02, 2008 8:24 pmPosts: 409Location: Kiel - Germany
hmm maybe you could use opaque particles instead? Then you could make use of openGLs occlusion culling and most likely discard alot of them before they get sent to the GPU. some sort of spatial hashing / octree based on their position could help alot aswell because you could discard a whole bunch of particles with just one occlusion query. (also consider frustum culling)

Another benefit of opaque particles is that you could of course use depth test and maybe even an early z-pass!

This leaves the question open on how to get the DOF effect. Actually when well done, the technique described in the paper could work pretty well, i myself implemeted it a while back:
http://vimeo.com/1746286

Another easy trick could be using point sprites and one big texture with different blur stages of a circle (or whatever you prefer). Then you could adjust the texCoords depending on the distance to the cam focal plane in the shader.

The look might not be exactly as smooth as the blended ones but you might get a big performance improvement. Also mipmapping the particle texture will help alot.

To get something more similar to your current aesthetics, you could simply add a bloom postprocessing effect or something similar i guess!

Hope that helps.


Offline Profile
PostPosted: Sat Nov 28, 2009 5:26 am
Joined: Fri Jun 27, 2008 4:49 amPosts: 453Location: Brooklyn
Thanks for all the replies!

moka, I can't use opaque particles with depth testing enabled, unfortunately, as the effect relies on the ability to see through points. Here's a video that might help explain how essential that is:



But I'm still thinking about this layering approach you and Theo have described... it seems the most promising. Some bloom probably wouldn't be bad either :) I am definitely interested in a photographic feel.

Memo, I did the calculation and I need anywhere from 1-100 billion pixels filled per frame. I calculated this by summing the area of all the points in different circumstances. My graphics card is a mediocre laptop model http://www.m3fe.com/fillratetestweb/ViewResult.php?id=608 apparently on the order of 1 billion texels/sec...


Offline Profile
PostPosted: Sat Nov 28, 2009 4:37 pm
Joined: Mon Jun 02, 2008 8:24 pmPosts: 409Location: Kiel - Germany
hmm well I dont really get why the trasparency is essential. can you maybe show a screenshot without blending?


Offline Profile
PostPosted: Sat Nov 28, 2009 5:06 pm
User avatarJoined: Mon May 14, 2007 10:57 amPosts: 720Location: Melbourne, Australia
Wooah Kyle that video looks amazing!

This is using your structured light stuff, non?
Do you have any code available for this stuff? I remember some related posts but my memory fails me...

Personally I think you're in a tight spot - any different techniques are going to look, well, _different_ as the combination of point size and opacity gives it its particular look. If you want to speed it up you will probably have to compromise and use a different technique, but it may not look the same....

It's definitely worth trying Moka's suggestion, rendering opaque particles and then blurring in a shader, but you probably will lose the ghostly, transparent effect.



_________________
Pierre Proske - www.digitalstar.net
Offline Profile
PostPosted: Sat Nov 28, 2009 5:50 pm
Joined: Fri Jun 27, 2008 4:49 amPosts: 453Location: Brooklyn
moka -- certainly, I suppose that might have been more helpful than the video :)

Image
http://www.flickr.com/photos/kylemcdonald/4141401350/sizes/o/

You can see that the large opaque points end up occluding each other and creating sort of modernist forms rather than a photographic feel.

Pierre -- thanks! Yes, this is the structured light stuff. All these scans were done in about 2 seconds using a digital camera and projector, capturing 3 frames. There is an addon I'm working on called "ofxStructuredLight" hosted here http://code.google.com/p/structured-light/. Chris Sugrue has helped a ton guiding me towards making a sort of binary app that people can run. I'll be finishing an initial version and releasing that in a couple of weeks (before December 10th).

I had an idea last night that is an extension of the layering idea... moka mentioned octtrees, but he was thinking for throwing away occluded points. I could try instead using octtrees the way they're used for Barnes-Hut -- if a bunch of points are sufficiently blurred and close together, I can approximate them as one large blurred point.


Offline Profile
PostPosted: Sat Nov 28, 2009 9:40 pm
Joined: Mon Jun 02, 2008 8:24 pmPosts: 409Location: Kiel - Germany
ah i see, good idea with the layering, definately worth a try!


Offline Profile
PostPosted: Mon Nov 30, 2009 11:13 am
User avatarJoined: Fri Jul 04, 2008 9:31 amPosts: 414Location: Vienna, Austria
hi kyle,

i built a DOF system recently for textured quads using imposters. with imageMagick i created 8 textures for the same image, each with an exp/^2 increasing gaussian blur effect applied. then i worked out the focal length/image plane difference and rendered the appropriate image. this worked quite well, even with only 8 bands. from memory i may have also blended between two adjacent images to make it look nicer - ie rather than an integer index i used a real index and then rendered twice using the two images on the integer indices on either side of the real, blended appropriately, eg 3.2 -> image 3 with 0.8 alpha and image 4 with 0.2 alpha.

so, what springs to my mind for your case is that you could make use of the depth-banded nature of DOF to help you reduce the horizontal aspect of the rewriting issue (not necessarily the vertical though). essentially this is about re-stating the problem in terms of the distance from the image plane to the point, rather than in terms of the image plane (x/y).

1. the effect you end up with at the moment clearly has a kind of a banding effect. this could be exploited in an LoD kind of way.

2. at the centre of a given band, the opacity is the same across the entire band. therefore it should be possible to precalculate the final colour of the pixels within that band easily without multiple writes in the image-plane-distance x axis.

3. once you have precalculated the final colour of a given band, then you should be able to render that band in one go. rendering a line of pixels with precalculated alpha (even if the line deviates from straight) should be more efficient than writing multiple times to each pixels.

4. also, notice that as the blur amount increases, the bands get wider and wider. essentially, when the individual points are very out-of-focus the resultant pixel data reduces to smooth colour fields, which could be rebuilt/precomputed somehow since they visually do not benefit from multiple writes. just thinking now - perhaps you could even do this by clumping the image points together when the blur value is high: collapse 9 or 25 adjacent image points into one larger one by averaging colour values..?

5. as with any LoD based method the transition between detail levels will be crucial. a smooth transition is better than a binary switch.

i hope this is helpful. essentially you're dealing with a compression problem i suppose, and that means that you just have to figure out where you can throw source data away by reducing it to a more abstract form that still looks as good. throw away individual blurred points and reduce to smooth colour fields. JPEG compression in 3d innit.



_________________
damian stewart | skype: damiansnz | damian [at] frey [dot] co [dot] nz
frey | live art with machines | http://www.frey.co.nz
Offline Profile
PostPosted: Mon Nov 30, 2009 4:15 pm
Joined: Fri Jun 27, 2008 4:49 amPosts: 453Location: Brooklyn
Damian, that's super helpful! It's essentially what I was imagining when I wrote above about Barnes-Hutstyle octtrees for approximating regions where there are solid color fields, but you've described it to a point where I'm more confident it will work.

I'm surprised you can get a good effect with only 8 bands. I wonder if you even need an octtree-type structure to store things, then? Maybe you can just go through and do a single O(n) pass, classifying each point and writing it to a buffer for that layer/band.


Offline Profile
PostPosted: Tue Dec 01, 2009 1:18 pm
Joined: Tue Jun 09, 2009 7:40 pmPosts: 17
kylemcdonald wrote:
I was considering VBOs (that's what Memo recommended too), but I'm positive they're not the bottleneck. If I just replace glPointSize(distance) with glPointSize(1), everything speeds up to realtime. So it's definitely the fill rate of the points that's killing the fps.


Are you calling glPointSize for each point? Would be a lot quicker to pass in a vertex attribute array containing the point sizes. Here's a bit of code I was using for something similar. All my particles were the same colour but you could easily pass in a colour attribute as well.

Code:
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   
   glEnable(GL_BLEND);
   glActiveTexture(GL_TEXTURE0);
        particleImage.getTextureReference().bind();
            
   glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);   
   
   drawShader.setShaderActive(true);
   drawShader.setUniformVariable1i("tex", 0);
   
   GLint sizeLoc = glGetAttribLocationARB (drawShader.shader,"particleSize");
   GLint alphaLoc = glGetAttribLocationARB (drawShader.shader,"alpha");
   
   glDisable(GL_DEPTH_TEST);
   glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
   glEnable(GL_POINT_SPRITE);
   
   glEnableVertexAttribArrayARB(sizeLoc);
   glEnableVertexAttribArrayARB(alphaLoc);
   glEnableClientState(GL_VERTEX_ARRAY);
   
   // send data
   glVertexPointer(2, GL_FLOAT, 4 * sizeof(float), pos);
   glVertexAttribPointerARB(sizeLoc, 1, GL_FLOAT, 0, 0, size);
   glVertexAttribPointerARB(alphaLoc, 1, GL_FLOAT, 0, 4 * sizeof(float), &pos[0][2]);
   glDrawArrays(GL_POINTS, 0, NUM_PARTICLES);
   
   glDisableVertexAttribArrayARB(sizeLoc);
   glDisableVertexAttribArrayARB(alphaLoc);
   
   glDisableClientState(GL_VERTEX_ARRAY);
   
   glDisable(GL_VERTEX_PROGRAM_POINT_SIZE);
   glDisable(GL_POINT_SPRITE);
   glEnable(GL_DEPTH_TEST);
   glDisable(GL_TEXTURE_2D);
   glDisable(GL_BLEND);
   
   drawShader.setShaderActive(false);



vertex shader:
Code:
attribute float particleSize;
attribute float alpha;

varying float fragAlpha;

void main()
{
   gl_TexCoord[0] = gl_MultiTexCoord0;
    gl_PointSize = particleSize;
    gl_Position = ftransform();
   fragAlpha = alpha;



fragment shader:
Code:
uniform sampler2D tex;

varying float fragAlpha;

void main( void )

   vec4 texture = texture2D(tex, gl_TexCoord[0].st);
   gl_FragColor = clamp(vec4(1.0, 0.0, 0.0, texture.a * fragAlpha), 0.0, 1.0);
}



_________________
http://16b.it/portfolio
Offline Profile
PostPosted: Tue Dec 01, 2009 4:27 pm
User avatarJoined: Sat Jun 02, 2007 6:39 pmPosts: 231
Yes - I did this for the VBO particle system here:
viewtopic.php?f=9&t=2639&hilit=vbo&start=15


Offline Profile
PostPosted: Tue Dec 01, 2009 4:29 pm
User avatarJoined: Fri Jul 04, 2008 9:31 amPosts: 414Location: Vienna, Austria
re good effect with 8 bands - yeah, i was surprised too, but in retrospect it makes sense. the key is to make sure that the transitions are smooth. i mean, with photographs taken with a real camera, you'd be hard-pressed to group them into 8 categories of out-of-focus-ness, which means our brains aren't so clever at identifying. it's just when it suddenly switches that we notice..

i think i could've even gotten away with a situation where there's a transition region (10% of the band width, for eg) when two images are drawn and blended, just to make it look nicer when animating, leaving the other 90% of the region rendered with just one (static) texture.



_________________
damian stewart | skype: damiansnz | damian [at] frey [dot] co [dot] nz
frey | live art with machines | http://www.frey.co.nz
Offline Profile

Display posts from previous:  Sort by:

All times are UTC
Page 1 of 2
25 posts
Go to page 1, 2  Next
Users browsing this forum: No registered users and 0 guests
Search for:
Post new topic  Reply to topic
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum
cron