liquid now goes through meshqueue sorting
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 27 Aug 2002 11:59:28 +0000 (11:59 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 27 Aug 2002 11:59:28 +0000 (11:59 +0000)
fixed a bunch of minor sorting consistency bugs in the meshqueue code
changed behavior of R_MeshQueue_EndScene and exposed R_MeshQueue_Render and R_MeshQueue_RenderTransparent
cleaned up liquid rendering code a bit

git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@2293 d7cf8633-e32d-0410-b094-e92efae38249

gl_rmain.c
gl_rsurf.c
meshqueue.c
meshqueue.h
model_brush.c
model_brush.h

index 0fc2daf..fbb0c1d 100644 (file)
@@ -613,8 +613,6 @@ void R_RenderView (void)
        R_SkyStartFrame();
        R_BuildLightList();
 
-       R_MeshQueue_BeginScene();
-
        R_FarClip_Start(r_origin, vpn, 768.0f);
 
        R_TimeReport("setup");
@@ -632,6 +630,8 @@ void R_RenderView (void)
 
        R_Mesh_Start(r_farclip);
 
+       R_MeshQueue_BeginScene();
+
 
        if (skyrendermasked)
        {
@@ -677,7 +677,7 @@ void R_RenderView (void)
        R_DrawExplosions();
        R_TimeReport("explosions");
 
-       R_MeshQueue_EndScene();
+       R_MeshQueue_RenderTransparent();
 
        R_Mesh_AddTransparent();
        R_TimeReport("addtrans");
@@ -691,6 +691,10 @@ void R_RenderView (void)
        R_BlendView();
        R_TimeReport("blendview");
 
+       R_MeshQueue_Render();
+
+       R_MeshQueue_EndScene();
+
        R_Mesh_Finish();
        R_TimeReport("meshfinish");
 }
index 10002ff..3ce3800 100644 (file)
@@ -730,8 +730,10 @@ static int RSurf_LightCheck(int *dlightbits, surfmesh_t *mesh)
        return false;
 }
 
-static void RSurfShader_Water_Pass_Base(entity_render_t *ent, msurface_t *surf)
+static void RSurfShader_Water_Callback(void *calldata1, int calldata2)
 {
+       entity_render_t *ent = calldata1;
+       msurface_t *surf = ent->model->surfaces + calldata2;
        int i, size3;
        surfvertex_t *v;
        float *outv, *outc, *outst, cl, diff[3];
@@ -740,16 +742,16 @@ static void RSurfShader_Water_Pass_Base(entity_render_t *ent, msurface_t *surf)
        surfmesh_t *mesh;
        rmeshbufferinfo_t m;
        float alpha = ent->alpha * (surf->flags & SURF_DRAWNOALPHA ? 1 : r_wateralpha.value);
+
+       softwaretransformforentity(ent);
        memset(&m, 0, sizeof(m));
        if (ent->effects & EF_ADDITIVE)
        {
-               m.transparent = true;
                m.blendfunc1 = GL_SRC_ALPHA;
                m.blendfunc2 = GL_ONE;
        }
        else if (surf->currenttexture->fogtexture != NULL || alpha < 1)
        {
-               m.transparent = true;
                m.blendfunc1 = GL_SRC_ALPHA;
                m.blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
        }
@@ -759,56 +761,30 @@ static void RSurfShader_Water_Pass_Base(entity_render_t *ent, msurface_t *surf)
                m.blendfunc2 = GL_ZERO;
        }
        m.tex[0] = R_GetTexture(surf->currenttexture->texture);
-       if (surf->flags & SURF_DRAWFULLBRIGHT || ent->effects & EF_FULLBRIGHT)
+       size3 = ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3;
+       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
        {
-               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+               m.numtriangles = mesh->numtriangles;
+               m.numverts = mesh->numverts;
+               if (R_Mesh_Draw_GetBuffer(&m, true))
                {
-                       m.numtriangles = mesh->numtriangles;
-                       m.numverts = mesh->numverts;
-                       if (R_Mesh_Draw_GetBuffer(&m, true))
+                       cl = m.colorscale;
+                       memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
+                       for (i = 0, v = mesh->vertex, outv = m.vertex, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outst += 2)
                        {
-                               base[0] = base[1] = base[2] = 1.0f * m.colorscale;
-                               memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
-                               for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
-                               {
-                                       softwaretransform(v->v, outv);
-                                       outv[3] = 1;
-                                       VectorCopy(base, outc);
-                                       outc[3] = alpha;
-                                       outst[0] = v->st[0];
-                                       outst[1] = v->st[1];
-                                       if (fogenabled)
-                                       {
-                                               VectorSubtract(outv, r_origin, diff);
-                                               f = 1 - exp(fogdensity/DotProduct(diff, diff));
-                                               VectorScale(outc, f, outc);
-                                       }
-                               }
-                               R_Mesh_Render();
+                               softwaretransform(v->v, outv);
+                               outv[3] = 1;
+                               outst[0] = v->st[0];
+                               outst[1] = v->st[1];
                        }
-               }
-       }
-       else
-       {
-               size3 = ((surf->extents[0]>>4)+1)*((surf->extents[1]>>4)+1)*3;
-               base[0] = base[1] = base[2] = (r_ambient.value * (1.0f / 64.0f) + ((surf->flags & SURF_LIGHTMAP) ? 0 : 0.5f));
-               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
-               {
-                       m.numtriangles = mesh->numtriangles;
-                       m.numverts = mesh->numverts;
-                       if (R_Mesh_Draw_GetBuffer(&m, true))
+                       base[0] = base[1] = base[2] = surf->flags & SURF_DRAWFULLBRIGHT ? 1.0f : ((surf->flags & SURF_LIGHTMAP) ? 0 : 0.5f);
+                       for (i = 0, outc = m.color;i < m.numverts;i++, outc += 4)
+                       {
+                               VectorCopy(base, outc);
+                               outc[3] = alpha;
+                       }
+                       if (!(surf->flags & SURF_DRAWFULLBRIGHT || ent->effects & EF_FULLBRIGHT))
                        {
-                               cl = m.colorscale;
-                               memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
-                               for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outc += 4, outst += 2)
-                               {
-                                       softwaretransform(v->v, outv);
-                                       outv[3] = 1;
-                                       VectorCopy(base, outc);
-                                       outc[3] = alpha;
-                                       outst[0] = v->st[0];
-                                       outst[1] = v->st[1];
-                               }
                                if (surf->dlightframe == r_framecount)
                                        RSurf_LightSeparate(surf->dlightbits, m.numverts, m.vertex, m.color);
                                for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color;i < m.numverts;i++, v++, outv += 4, outc += 4)
@@ -838,61 +814,59 @@ static void RSurfShader_Water_Pass_Base(entity_render_t *ent, msurface_t *surf)
                                                        }
                                                }
                                        }
-                                       if (fogenabled)
-                                       {
-                                               VectorSubtract(outv, r_origin, diff);
-                                               f = cl * (1 - exp(fogdensity/DotProduct(diff, diff)));
-                                               VectorScale(outc, f, outc);
-                                       }
-                                       else
-                                               VectorScale(outc, cl, outc);
                                }
-                               R_Mesh_Render();
                        }
+                       if (fogenabled)
+                       {
+                               for (i = 0, outv = m.vertex, outc = m.color;i < m.numverts;i++, outv += 4, outc += 4)
+                               {
+                                       VectorSubtract(outv, r_origin, diff);
+                                       f = m.colorscale * (1 - exp(fogdensity/DotProduct(diff, diff)));
+                                       VectorScale(outc, f, outc);
+                               }
+                       }
+                       else if (m.colorscale != 1)
+                       {
+                               for (i = 0, outv = m.vertex, outc = m.color;i < m.numverts;i++, outv += 4, outc += 4)
+                                       VectorScale(outc, m.colorscale, outc);
+                       }
+                       R_Mesh_Render();
                }
        }
-}
 
-static void RSurfShader_Water_Pass_Fog(entity_render_t *ent, msurface_t *surf)
-{
-       int i;
-       surfvertex_t *v;
-       float *outv, *outc, *outst, diff[3];
-       float base[3], f;
-       surfmesh_t *mesh;
-       rmeshbufferinfo_t m;
-       float alpha = ent->alpha * (surf->flags & SURF_DRAWNOALPHA ? 1 : r_wateralpha.value);
-       memset(&m, 0, sizeof(m));
-       m.transparent = ent->effects & EF_ADDITIVE || surf->currenttexture->fogtexture != NULL || alpha < 1;
-       m.blendfunc1 = GL_SRC_ALPHA;
-       m.blendfunc2 = GL_ONE;
-       m.tex[0] = R_GetTexture(surf->currenttexture->fogtexture);
-       for (mesh = surf->mesh;mesh;mesh = mesh->chain)
+       if (fogenabled)
        {
-               m.numtriangles = mesh->numtriangles;
-               m.numverts = mesh->numverts;
-               if (R_Mesh_Draw_GetBuffer(&m, false))
+               memset(&m, 0, sizeof(m));
+               m.blendfunc1 = GL_SRC_ALPHA;
+               m.blendfunc2 = GL_ONE;
+               m.tex[0] = R_GetTexture(surf->currenttexture->fogtexture);
+               for (mesh = surf->mesh;mesh;mesh = mesh->chain)
                {
-                       VectorScale(fogcolor, m.colorscale, base);
-                       memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
-                       for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color;i < m.numverts;i++, v++, outv += 4, outc += 4)
-                       {
-                               softwaretransform(v->v, outv);
-                               outv[3] = 1;
-                               VectorSubtract(outv, r_origin, diff);
-                               f = exp(fogdensity/DotProduct(diff, diff));
-                               VectorScale(base, f, outc);
-                               outc[3] = alpha;
-                       }
-                       if (m.tex[0])
+                       m.numtriangles = mesh->numtriangles;
+                       m.numverts = mesh->numverts;
+                       if (R_Mesh_Draw_GetBuffer(&m, false))
                        {
-                               for (i = 0, v = mesh->vertex, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outst += 2)
+                               VectorScale(fogcolor, m.colorscale, base);
+                               memcpy(m.index, mesh->index, m.numtriangles * sizeof(int[3]));
+                               for (i = 0, v = mesh->vertex, outv = m.vertex, outc = m.color;i < m.numverts;i++, v++, outv += 4, outc += 4)
                                {
-                                       outst[0] = v->st[0];
-                                       outst[1] = v->st[1];
+                                       softwaretransform(v->v, outv);
+                                       outv[3] = 1;
+                                       VectorSubtract(outv, r_origin, diff);
+                                       f = exp(fogdensity/DotProduct(diff, diff));
+                                       VectorScale(base, f, outc);
+                                       outc[3] = alpha;
+                               }
+                               if (m.tex[0])
+                               {
+                                       for (i = 0, v = mesh->vertex, outst = m.texcoords[0];i < m.numverts;i++, v++, outv += 4, outst += 2)
+                                       {
+                                               outst[0] = v->st[0];
+                                               outst[1] = v->st[1];
+                                       }
                                }
+                               R_Mesh_Render();
                        }
-                       R_Mesh_Render();
                }
        }
 }
@@ -901,10 +875,12 @@ static void RSurfShader_Water(entity_render_t *ent, msurface_t *firstsurf)
 {
        msurface_t *surf;
        for (surf = firstsurf;surf;surf = surf->chain)
-               RSurfShader_Water_Pass_Base(ent, surf);
-       if (fogenabled)
-               for (surf = firstsurf;surf;surf = surf->chain)
-                       RSurfShader_Water_Pass_Fog(ent, surf);
+       {
+               if ((r_wateralpha.value < 1 && !(surf->flags & SURF_DRAWNOALPHA)) || ent->effects & EF_ADDITIVE || surf->currenttexture->fogtexture)
+                       R_MeshQueue_AddTransparent(surf->poly_center, RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
+               else
+                       R_MeshQueue_Add(RSurfShader_Water_Callback, ent, surf - ent->model->surfaces);
+       }
 }
 
 static void RSurfShader_Wall_Pass_BaseVertex(entity_render_t *ent, msurface_t *surf)
index e75bddd..467b4c5 100644 (file)
@@ -36,9 +36,11 @@ void R_MeshQueue_Init(void)
        mqt_array = NULL;
 }
 
-static void R_MeshQueue_Render(void)
+void R_MeshQueue_Render(void)
 {
        meshqueue_t *mq;
+       if (!mq_count)
+               return;
        for (mq = mq_listhead;mq;mq = mq->next)
                mq->callback(mq->data1, mq->data2);
        mq_count = 0;
@@ -73,32 +75,30 @@ void R_MeshQueue_Add(void (*callback)(void *data1, int data2), void *data1, int
        mq->data1 = data1;
        mq->data2 = data2;
 
-       // bubble-insert sort into meshqueue
-       mqnext = &mq_listhead;
        if (r_meshqueue_sort.integer)
        {
-               for(;;)
+               // bubble-insert sort into meshqueue
+               for(mqnext = &mq_listhead;*mqnext;mqnext = &(*mqnext)->next)
                {
-                       if (*mqnext)
+                       if (mq->callback == (*mqnext)->callback)
                        {
-                               if (mq->callback == (*mqnext)->callback)
+                               if (mq->data1 == (*mqnext)->data1)
                                {
-                                       if (mq->data1 == (*mqnext)->data1)
-                                       {
-                                               if (mq->data2 <= (*mqnext)->data2)
-                                                       break;
-                                       }
-                                       else if (mq->data1 < (*mqnext)->data1)
+                                       if (mq->data2 <= (*mqnext)->data2)
                                                break;
                                }
-                               else if (mq->callback < (*mqnext)->callback)
+                               else if (mq->data1 < (*mqnext)->data1)
                                        break;
                        }
-                       else
+                       else if (mq->callback < (*mqnext)->callback)
                                break;
-                       mqnext = &(*mqnext)->next;
                }
        }
+       else
+       {
+               // maintain the order
+               for(mqnext = &mq_listhead;*mqnext;mqnext = &(*mqnext)->next);
+       }
        mq->next = *mqnext;
        *mqnext = mq;
 }
@@ -116,28 +116,33 @@ void R_MeshQueue_AddTransparent(vec3_t center, void (*callback)(void *data1, int
        mq->next = NULL;
 }
 
-static void R_MeshQueue_RenderTransparent(void)
+void R_MeshQueue_RenderTransparent(void)
 {
        int i;
        int hashdist;
        meshqueue_t *mqt;
-       meshqueue_t *hash[4096];
-       memset(hash, 0, 4096 * sizeof(meshqueue_t *));
+       meshqueue_t *hash[4096], **hashpointer[4096];
+       if (mq_count)
+               R_MeshQueue_Render();
+       if (!mqt_count)
+               return;
+       memset(hash, 0, sizeof(hash));
+       for (i = 0;i < 4096;i++)
+               hashpointer[i] = &hash[i];
        for (i = 0, mqt = mqt_array;i < mqt_count;i++, mqt++)
        {
                // generate index
                hashdist = (int) (mqt->dist);
                hashdist = bound(0, hashdist, 4095);
-               // reversed to simplify render loop
-               hashdist = 4095 - hashdist;
-               // link into hash chain
-               mqt->next = hash[hashdist];
-               hash[hashdist] = mqt;
+               // link to tail of hash chain (to preserve render order)
+               mqt->next = NULL;
+               *hashpointer[hashdist] = mqt;
+               hashpointer[hashdist] = &mqt->next;
        }
-       for (i = 0;i < 4096;i++)
+       for (i = 4095;i >= 0;i--)
                if (hash[i])
                        for (mqt = hash[i];mqt;mqt = mqt->next)
-                               R_MeshQueue_Add(mqt->callback, mqt->data1, mqt->data2);
+                               mqt->callback(mqt->data1, mqt->data2);
        mqt_count = 0;
 }
 
@@ -167,9 +172,15 @@ void R_MeshQueue_BeginScene(void)
 
 void R_MeshQueue_EndScene(void)
 {
-       if (mqt_count)
-               R_MeshQueue_RenderTransparent();
        if (mq_count)
+       {
+               Con_Printf("R_MeshQueue_EndScene: main mesh queue still has %i items left, flushing\n", mq_count);
                R_MeshQueue_Render();
+       }
+       if (mqt_count)
+       {
+               Con_Printf("R_MeshQueue_EndScene: transparent mesh queue still has %i items left, flushing\n", mqt_count);
+               R_MeshQueue_RenderTransparent();
+       }
 }
 
index 60b7aa4..f3f9e3f 100644 (file)
@@ -6,6 +6,8 @@ void R_MeshQueue_Init(void);
 void R_MeshQueue_Add(void (*callback)(void *data1, int data2), void *data1, int data2);
 void R_MeshQueue_AddTransparent(vec3_t center, void (*callback)(void *data1, int data2), void *data1, int data2);
 void R_MeshQueue_BeginScene(void);
+void R_MeshQueue_Render(void);
+void R_MeshQueue_RenderTransparent(void);
 void R_MeshQueue_EndScene(void);
 
 #endif
index 167f19d..79be437 100644 (file)
@@ -1248,10 +1248,8 @@ void Mod_GenerateVertexMesh (msurface_t *surf)
 
 void Mod_GenerateSurfacePolygon (msurface_t *surf)
 {
-       float           *vert;
-       int                     i;
-       int                     lindex;
-       float           *vec;
+       int i, lindex;
+       float *vec, *vert, mins[3], maxs[3];
 
        // convert edges back to a normal polygon
        surf->poly_numverts = surf->numedges;
@@ -1266,6 +1264,20 @@ void Mod_GenerateSurfacePolygon (msurface_t *surf)
                VectorCopy (vec, vert);
                vert += 3;
        }
+       vert = surf->poly_verts;
+       VectorCopy(vert, mins);
+       VectorCopy(vert, maxs);
+       vert += 3;
+       for (i = 1;i < surf->poly_numverts;i++)
+       {
+               if (mins[0] > vert[0]) mins[0] = vert[0];if (maxs[0] < vert[0]) maxs[0] = vert[0];
+               if (mins[1] > vert[1]) mins[1] = vert[1];if (maxs[1] < vert[1]) maxs[1] = vert[1];
+               if (mins[2] > vert[2]) mins[2] = vert[2];if (maxs[2] < vert[2]) maxs[2] = vert[2];
+               vert += 3;
+       }
+       surf->poly_center[0] = (mins[0] + maxs[0]) * 0.5f;
+       surf->poly_center[1] = (mins[1] + maxs[1]) * 0.5f;
+       surf->poly_center[2] = (mins[2] + maxs[2]) * 0.5f;
 }
 
 static void Mod_SplitSurfMeshIfTooBig(msurface_t *s)
index 9d6ffc6..eebdc52 100644 (file)
@@ -176,6 +176,8 @@ typedef struct msurface_s
        // no texcoord info (that can be generated from these)
        int                     poly_numverts;
        float           *poly_verts;
+       // the center is useful for sorting
+       float           poly_center[3];
 
        // these are regenerated every frame
        // lighting info