From 1fdb85e19b37eb797e3b1118b844c7071e9cdefb Mon Sep 17 00:00:00 2001 From: havoc Date: Tue, 27 Aug 2002 11:59:28 +0000 Subject: [PATCH] liquid now goes through meshqueue sorting 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 | 10 ++- gl_rsurf.c | 168 ++++++++++++++++++++++---------------------------- meshqueue.c | 65 +++++++++++-------- meshqueue.h | 2 + model_brush.c | 20 ++++-- model_brush.h | 2 + 6 files changed, 137 insertions(+), 130 deletions(-) diff --git a/gl_rmain.c b/gl_rmain.c index 0fc2dafc..fbb0c1dc 100644 --- a/gl_rmain.c +++ b/gl_rmain.c @@ -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"); } diff --git a/gl_rsurf.c b/gl_rsurf.c index 10002fff..3ce3800e 100644 --- a/gl_rsurf.c +++ b/gl_rsurf.c @@ -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) diff --git a/meshqueue.c b/meshqueue.c index e75bddd1..467b4c55 100644 --- a/meshqueue.c +++ b/meshqueue.c @@ -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(); + } } diff --git a/meshqueue.h b/meshqueue.h index 60b7aa46..f3f9e3fc 100644 --- a/meshqueue.h +++ b/meshqueue.h @@ -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 diff --git a/model_brush.c b/model_brush.c index 167f19d4..79be4373 100644 --- a/model_brush.c +++ b/model_brush.c @@ -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) diff --git a/model_brush.h b/model_brush.h index 9d6ffc68..eebdc525 100644 --- a/model_brush.h +++ b/model_brush.h @@ -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 -- 2.39.2