[GLQuake] Improved Water Warp
Posted: Tue Jun 29, 2010 11:24 pm
Water warps in GLQuake suck. Here we're going to improve them quite dramatically, in a manner that doesn't require any functionality beyond the basic OpenGL 1.1 that GLQuake uses.
The trick here is to use a low subdivision but draw them faster. This will be almost, but not quite, as rock-solid as software Quake.
To keep code to a minimum here I'm not going to use vertex arrays. I'd suggest a migration to an indexed vertex array as an exercise for the individual. This would be the recommended approach and will get you substantial performance increases.
So here we go. All changes are in gl_warp.c
Go to the SubdividePolygon function and add this among the other variables at the start:
Just before the call to BoundPoly add this:
Now find this line:
And change it to:
Now for the renderer. Find your EmitWaterPolys function and change it to this:
What's going on here is that we're batching up our vertex submissions better. It's a simple fact of life that bigger batches of vertexes draw much much faster than smaller ones, meaning that we're able to subdivide water at a very low level and still retain all of our speed - I haven't done a direct head-to-head but I suspect that it may even be faster than GLQuake with a gl_subdivide_size of 128 or even 256.
Like I said, moving this to indexed vertex arrays would raise performance to another level again. That's for you to do. If you don't fancy doing that you can restructure things so that you're able to move your glBegin/glEnd to outside of the texture chain loop; then you'll really see some fireworks with it. Bonus marks for anyone who does something similar on world surfaces and lightmaps.
Credit to the mighty metlslime for the corrected warp define.
The trick here is to use a low subdivision but draw them faster. This will be almost, but not quite, as rock-solid as software Quake.
To keep code to a minimum here I'm not going to use vertex arrays. I'd suggest a migration to an indexed vertex array as an exercise for the individual. This would be the recommended approach and will get you substantial performance increases.
So here we go. All changes are in gl_warp.c
Go to the SubdividePolygon function and add this among the other variables at the start:
Code: Select all
float sdsize;Code: Select all
if (warpface->flags & SURF_DRAWTURB)
sdsize = 24;
else sdsize = gl_subdivide_size.value;Code: Select all
m = gl_subdivide_size.value * floor (m / gl_subdivide_size.value + 0.5);Code: Select all
m = sdsize * floor (m / sdsize + 0.5);Code: Select all
#define WARPCALC(s,t) ((s + turbsin[(int)((t*2)+(cl.time*(128.0/M_PI))) & 255]) * (1.0/64)) // correct warp from fitzquake
void EmitWarpVert (float *v)
{
glTexCoord2f (WARPCALC (v[3], v[4]), WARPCALC (v[4], v[3]));
glVertex3fv (v);
}
void EmitWaterPolys (msurface_t *fa)
{
glpoly_t *p;
int i;
glBegin (GL_TRIANGLES);
for (p = fa->polys; p; p = p->next)
{
for (i = 2; i < p->numverts; i++)
{
EmitWarpVert (p->verts[0]);
EmitWarpVert (p->verts[i - 1]);
EmitWarpVert (p->verts[i]);
}
}
glEnd ();
}Like I said, moving this to indexed vertex arrays would raise performance to another level again. That's for you to do. If you don't fancy doing that you can restructure things so that you're able to move your glBegin/glEnd to outside of the texture chain loop; then you'll really see some fireworks with it. Bonus marks for anyone who does something similar on world surfaces and lightmaps.
Credit to the mighty metlslime for the corrected warp define.