Particle Vertex Array
Hi,
how i can render particles, with Vertex arrays. I have this simple structur
init
and i like to render the particles like this:
but, that seems to be wrong. Someone an idea?
how i can render particles, with Vertex arrays. I have this simple structur
Code:
typedef struct _particle
{
float finalColor[4];
float vertices[12];
.
.
.
}Particle;init
Code:
_particles[i].vertices[0] =_particles[i].position[0]-(_particles[i].size/2);
_particles[i].vertices[1] =_particles[i].position[1]-(_particles[i].size/2);
_particles[i].vertices[2] =_particles[i].position[2];
_particles[i].vertices[3] =_particles[i].position[0]+(_particles[i].size/2);
_particles[i].vertices[4] =_particles[i].position[1]-(_particles[i].size/2);
_particles[i].vertices[5] =_particles[i].position[2];
_particles[i].vertices[6] =_particles[i].position[0]+(_particles[i].size/2);
_particles[i].vertices[7] =_particles[i].position[1]+(_particles[i].size/2);
_particles[i].vertices[8] =_particles[i].position[2];
_particles[i].vertices[9] =_particles[i].position[0]-(_particles[i].size/2);
_particles[i].vertices[10] =_particles[i].position[1]+(_particles[i].size/2);
_particles[i].vertices[11] =_particles[i].position[2];and i like to render the particles like this:
Code:
glVertexPointer(3, GL_FLOAT, sizeof(Particle), &_particles[0].vertices);
glDrawArrays(GL_QUADS, 0, NUM_PARTICLES);but, that seems to be wrong. Someone an idea?
Looks like there are two problems here:
- The stride parameter to glVertexPointer is the number of bytes from the end of one vertex to the beginning of the next, as opposed to the number of bytes from the beginning of one vertex to the beginning of the next. This tripped me up, too. You'll want something like sizeof(struct _particle) - sizeof(_particles[0].vertices).
- ...However, this won't actually work, because the stride specifies the bytes between vertices, as opposed to the space between primitives. You may need to reorganize your data so that the space between each set of vertex coordinates is consistent. As it's currently set up, you have a 16-byte chunk between each quad, but the vertices in the quad itself are tightly packed.
You'll need to model the data in your application in some way that allows lists of vertices to either be contiguous across the entire array you're drawing, or to have uniform byte spacing between each vertex across the entire array. How you accomplish this is really up to you; do whatever makes the most sense to fit into your current data model given the above constraints.
Here's how I arranged my data, for a foliage system ( a specialized particle system ).
And to submit it to GL:
Works for me!
Note: I'm billboarding in a vertex shader, so in principle I could use a VBO instead of a vertex array. BUT: I'm periodically depth-sorting the vertices, so I need to stream them. I could probably switch to a streaming or write-only vbo-format, but my foliage system allocation strategy is a little rough, and I don't want to blow out my vram.
Code:
struct foliage_vertex
{
static const int INTERLEAVED_FORMAT = GL_T2F_C3F_V3F;
inline foliage_vertex( void ) {}
inline foliage_vertex( const foliage_vertex &c ):
texcoord( c.texcoord ),
color( c.color ),
position( c.position )
{}
inline foliage_vertex( const vec2 &tc, const vec3 &c, const vec3 &p ):
texcoord( tc ),
color( c ),
position( p )
{}
inline foliage_vertex &operator = ( const foliage_vertex &c )
{
texcoord = c.texcoord;
color = c.color;
position = c.position;
return *this;
}
vec2 texcoord;
vec3 color, position;
};
struct foliage_quad {
foliage_vertex a,b,c,d;
inline foliage_quad( void ) {}
inline foliage_quad( const foliage_quad &f ):
a( f.a ),
b( f.b ),
c( f.c ),
d( f.d )
{}
inline foliage_quad &operator = ( const foliage_quad &f )
{
a = f.a;
b = f.b;
c = f.c;
d = f.d;
return *this;
}
};
... later
std::vector< foliage_quad > _foliage;And to submit it to GL:
Code:
glInterleavedArrays( foliage_vertex::INTERLEAVED_FORMAT, 0, &(_foliage.front()) );
glDrawArrays( GL_QUADS, 0, _numQuads * 4 );
glDisableClientState( GL_VERTEX_ARRAY );
glDisableClientState( GL_COLOR_ARRAY );
glDisableClientState( GL_TEXTURE_COORD_ARRAY );Works for me!
Note: I'm billboarding in a vertex shader, so in principle I could use a VBO instead of a vertex array. BUT: I'm periodically depth-sorting the vertices, so I need to stream them. I could probably switch to a streaming or write-only vbo-format, but my foliage system allocation strategy is a little rough, and I don't want to blow out my vram.
ThemsAllTook Wrote:Looks like there are two problems here:
- The stride parameter to glVertexPointer is the number of bytes from the end of one vertex to the beginning of the next, as opposed to the number of bytes from the beginning of one vertex to the beginning of the next. This tripped me up, too. You'll want something like sizeof(struct _particle) - sizeof(_particles[0].vertices).
Err, are you sure about that? I just wrote some testing code to render a VBO and the stride is the number of byte from the start of a vertice to the next.
For example, if you have
Code:
// FIXME: dirty testing code
size_t float_count = vertex_count * (3 + 3 + 2 + 2 + 1);
buf_len = sizeof(GLfloat) * float_count;
buf = malloc(buf_len);
uint32_t i;
for(i = 0; !feof(fd) && i < float_count;) {
// FIXME: fscanf is dirty, only for testing, move to binary when working.
vec3 v;
// pos
fscanf(fd, "%f %f %f\n", &v.f[0], &v.f[1], &v.f[2]);
v = v_div3f(v, 100000);
buf[i++] = v.f[0];
buf[i++] = v.f[1];
buf[i++] = v.f[2];
// norm
fscanf(fd, "%f %f %f\n", &v.f[0], &v.f[1], &v.f[2]);
v = v_div3f(v, 100000);
buf[i++] = v.f[0];
buf[i++] = v.f[1];
buf[i++] = v.f[2];
// uv0
fscanf(fd, "%f %f\n", &v.f[0], &v.f[1]);
v = v_div3f(v, 100000);
buf[i++] = v.f[0];
buf[i++] = v.f[1];
// uv1
fscanf(fd, "%f %f\n", &v.f[0], &v.f[1]);
v = v_div3f(v, 100000);
buf[i++] = v.f[0];
buf[i++] = v.f[1];
// flags
fscanf(fd, "%f\n", &v.f[0]);
buf[i++] = v.f[0];
}You will do something like:
Code:
#define glOffsetf(_x) ((const GLvoid *)(_x * sizeof(GLfloat)))
#define glStridef(_x) (_x * sizeof(GLfloat))
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glVertexPointer(3, GL_FLOAT, glStridef(11), glOffsetf(0));
glNormalPointer(GL_FLOAT, glStridef(11), glOffsetf(3));
glClientActiveTexture(GL_TEXTURE0);
glTexCoordPointer(2, GL_FLOAT, glStridef(11), glOffsetf(6));
glClientActiveTexture(GL_TEXTURE1);
glTexCoordPointer(2, GL_FLOAT, glStridef(11), glOffsetf(8));
glEnableVertexAttribArray(attrib_loc);
glVertexAttribPointer(attrib_loc, 1, GL_FLOAT, GL_FALSE, glStridef(11), glOffsetf(10));
glDrawArrays(GL_TRIANGLES, 0, vertex_count);Note that the stride is always 11 * sizeof(GLfloat).
This code is working properly (even if it's dirty).
kuon is correct; stride is either 0 ("tightly packed") or number of bytes from the beginning of one vertex to the beginning of the next.
Hmm, my mistake. The man page isn't worded as clearly as it could be...
ThemsAllTook Wrote:The man page isn't worded as clearly as it could be...
... Nice save!
Possibly Related Threads...
| Thread: | Author | Replies: | Views: | Last Post | |
| Vertex shader particle billboarding question | TomorrowPlusX | 3 | 4,772 |
Sep 15, 2008 06:46 AM Last Post: TomorrowPlusX |
|
| Vertex Array & Interleaved Array troubles | TomorrowPlusX | 5 | 4,920 |
Nov 17, 2007 09:59 AM Last Post: TomorrowPlusX |
|
| Vertex Array Range | bonanza | 3 | 3,345 |
Jun 19, 2007 12:42 PM Last Post: OneSadCookie |
|
| Compiled vertex array problem | Frank C. | 1 | 2,176 |
Feb 7, 2006 10:06 PM Last Post: Frogblast |
|
| Quad Vertex Array Woes | WakingJohn | 1 | 2,058 |
Apr 9, 2005 07:55 PM Last Post: WakingJohn |
|

