Jump to content
  • Advertisement
Sign in to follow this  
spek

OpenGL Render point array into a 3D texture

This topic is 2758 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hey, I'd like to render a bunch of points into a 32x32x32 volume texture. Eventually I'd like to apply vertex displacement in the vertex shader; the vertex shader converts the point world position to a 3D cell coordinate.

The nVidia OpenGL 10 SDK has an example of how to do that;

for i:=1 to sliceCount
switch FBO target slice
render quad(s), points, whatever

Since each point could be on a different slice, I either have to sort the whole thing per slice, or render the same point array 32 times. Isn't there a simpler way?

Maybe I understood it wrong, but someone once told it is possible to "unfold" a 3D texture as 1 big 2D texture (thus 32 slices next to each other in this case, a 1024 x 32 texture). Then render onto the flat surface. Not sure how to do this though. I could render it to a real flat 2D texture, but then I would miss the lineair sampling functionality between 9 cells...

Tips? Thank you!
Rick

Share this post


Link to post
Share on other sites
Advertisement
my first guess,

render everything into one big texture and then copy every slice back into a texture array(with glBlitFramebuffer)

Don't know how fast this will be, but I think this would be the simples and fastest method, it all depends how often you will do this I guess

Share this post


Link to post
Share on other sites
Hmmm, that is an option. How many times... multiple times per cycle. It is used to insert Virtual Point Lights into a 3D grid. Little bit similar to what Crytek does with their Light Propagation Volume technique. Forgot to mention there are actually two different passes that need to insert data into the grid:
1.- Reflective Shadowmaps;
Shader reads a (small) shadowMap and convert the positional data stored in each shadowMap pixel into the grid.
2.- CPU renders about 10.000 points. Again the vertex shader has to displace the world coordinates into that same grid.

Copying each slice would mean copying 32 screenfilling quads from 1 2D source texture. Shouldn't be too slow, yet I'm curious if Crytek isn't doing all of this in a smarter way...

Thanks for the advice!

Share this post


Link to post
Share on other sites
the EXT_framebuffer_blit extension is written against OpenGL 1.1, but only core under 3.0.

This method of copying data should be much faster then full screen quads. Also you wouldn'T waste any fillrate.

Share this post


Link to post
Share on other sites
So I read a bit of the crytek paper and I think the faced the same problem as you.
They rendered to a 2D texture and they either emulated trillinear filtering in the shader between the slices,on dx9 hardware, or used copying of the data on dx10 hardware.

[Edited by - Danny02 on December 27, 2010 11:25:25 AM]

Share this post


Link to post
Share on other sites
Unless there is another magical trick, your suggestions work best I think. Now it's chosing between trillinear texture picking, or blitting to 32 slices. Probably it will be 128 copies (1x Reflective shadowMap input, 3x point array) in total. That would be a matter of trying both out I guess.

Share this post


Link to post
Share on other sites
Sorry to bounce this thread back alive, but a new question arose while trying blitting.

Is it possible to blit 3 textures at the same time? MRT is used to render onto a set of 3 2D textures at the same time. So it would be nice if all 3 could be copied with a single call as well. I tried binding 3 textures to the target FBO + enabling MRT, but all 3 target textures are filled the same. Maybe I need an extra instruction to tell to read/draw 3 buffers instead of 1?

glBindFramebufferEXT( GL_READ_FRAMEBUFFER_EXT, currentFBO.handke );
glBindFramebufferEXT( GL_DRAW_FRAMEBUFFER_EXT, targetFBO.handle );
glReadBuffers(3, @READ_BUFFERS3); // Readbuffers is a set of attachment0..2
glBlitFramebufferEXT( 0, 0, w,h, 0,0, w,h ,
GL_COLOR_BUFFER_BIT , GL_NEAREST );

The amount of copies is going to be bigger than expected. Crytek LPV for example has:
- 3 3D textures (3 are needed to store all SH coefficients)
- 3 cascaded grids
- 32 x 32 x 32
- Another pass to inject geometry. Same stuff.
Thus that means
2(pass)x (3(tex) x 3(grids) x 32(slices) = 576 copies


My technique isn't exactly the same, but since I'm aiming for multiple bounce GI, the count could get even higher. Trilinear sampling of simple 2D textures is another option, but in the worst case a fragment would need to take 18 samples. No really nice either. If Crytek really copies that much, how the heck can they do it that fast? Does DX10 have better features to solve this problem?

I tested a 2D blit operation by simply looping it 600 times. Framerate dropped from ~58 to ~30 on a brand new video-card. I guess I'm doing something wrong.

[Edited by - spek on December 31, 2010 6:54:53 AM]

Share this post


Link to post
Share on other sites
in the specs it says:
"blit operations only read from the color buffer specified by glReadBuffer and will only write to the color buffers specified by glDrawBuffers."

so you can only read from one buffer, but can write to multiple.

Share this post


Link to post
Share on other sites
yes I finally found out how to do this :-)
I was curious how others had done this(crytek) cause obviously copying 500 textures isn't quite efficient.

it seams as crytek stated it is only possible with DX10 capable hardware, because a geometry shader is needed.

so here it comes ^^:

"Geometry shaders can be used to render to one of several different layers
of cube map textures, three-dimensional textures, plus one- dimensional
and two-dimensional texture arrays. This functionality allows an
application to bind an entire "complex" texture to a framebuffer object,
and render primitives to arbitrary layers computed at run time. For
example, this mechanism can be used to project and render a scene onto all
six faces of a cubemap texture in one pass. The layer to render to is
specified by writing to the built-in output variable gl_Layer."


So you would need something like that

layout(points) in;
layout(points, max_vertices = 1) out;

in int layer[1];

void main()
{
gl_Position = gl_in[0].gl_Position;
gl_Layer = layer[0];
EmitVertex();
}


Share this post


Link to post
Share on other sites
Once again, thank you Danny!!

Haven't used geomshaders yet, but it was on the planning for cubeMaps. If I understand it right, you can toggle the layer inside the GS after the vertex-shader output, before drawing pixels. Well, I know what to do then!

Let's hope I can still remember it after tonight. Probably 2011 will be started with another hangover :)

Happy 2011 all!

Rick

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!