X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=blobdiff_plain;f=meshqueue.c;h=af8c3ea5faa3607cbd846c3dcbc94b8f1ada021a;hp=a5510be722631f7b7d196e555dff081c8027ad1f;hb=HEAD;hpb=79d25017219944e264aadc7ab556c86d3955e4b2 diff --git a/meshqueue.c b/meshqueue.c index a5510be7..af8c3ea5 100644 --- a/meshqueue.c +++ b/meshqueue.c @@ -1,4 +1,3 @@ - #include "quakedef.h" #include "meshqueue.h" @@ -10,9 +9,14 @@ typedef struct meshqueue_s int surfacenumber; const rtlight_t *rtlight; float dist; + dptransparentsortcategory_t category; } meshqueue_t; +int trans_sortarraysize; +meshqueue_t **trans_hash = NULL; +meshqueue_t ***trans_hashpointer = NULL; + float mqt_viewplanedist; float mqt_viewmaxdist; meshqueue_t *mqt_array; @@ -26,7 +30,7 @@ void R_MeshQueue_BeginScene(void) mqt_viewmaxdist = 0; } -void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) +void R_MeshQueue_AddTransparent(dptransparentsortcategory_t category, const vec3_t center, void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist), const entity_render_t *ent, int surfacenumber, const rtlight_t *rtlight) { meshqueue_t *mq; if (mqt_count >= mqt_total || !mqt_array) @@ -46,50 +50,88 @@ void R_MeshQueue_AddTransparent(const vec3_t center, void (*callback)(const enti mq->ent = ent; mq->surfacenumber = surfacenumber; mq->rtlight = rtlight; - mq->dist = DotProduct(center, r_refdef.view.forward) - mqt_viewplanedist; + mq->category = category; + if (r_transparent_useplanardistance.integer) + mq->dist = DotProduct(center, r_refdef.view.forward) - mqt_viewplanedist; + else + mq->dist = VectorDistance(center, r_refdef.view.origin); mq->next = NULL; mqt_viewmaxdist = max(mqt_viewmaxdist, mq->dist); } void R_MeshQueue_RenderTransparent(void) { - int i; - int hashdist; - int batchnumsurfaces; + int i, hashindex, maxhashindex, batchnumsurfaces; float distscale; const entity_render_t *ent; const rtlight_t *rtlight; void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices); + int batchsurfaceindex[MESHQUEUE_TRANSPARENT_BATCHSIZE]; meshqueue_t *mqt; - static meshqueue_t *hash[4096], **hashpointer[4096]; - int batchsurfaceindex[256]; + if (!mqt_count) return; - memset(hash, 0, sizeof(hash)); - for (i = 0;i < 4096;i++) - hashpointer[i] = &hash[i]; - distscale = 4095.0f / max(mqt_viewmaxdist, 4095); - for (i = 0, mqt = mqt_array;i < mqt_count;i++, mqt++) + + // check for bad cvars + if (r_transparent_sortarraysize.integer < 1 || r_transparent_sortarraysize.integer > 32768) + Cvar_SetValueQuick(&r_transparent_sortarraysize, bound(1, r_transparent_sortarraysize.integer, 32768)); + if (r_transparent_sortmindist.integer < 0 || r_transparent_sortmindist.integer >= r_transparent_sortmaxdist.integer) + Cvar_SetValueQuick(&r_transparent_sortmindist, 0); + if (r_transparent_sortmaxdist.integer < r_transparent_sortmindist.integer || r_transparent_sortmaxdist.integer > 32768) + Cvar_SetValueQuick(&r_transparent_sortmaxdist, bound(r_transparent_sortmindist.integer, r_transparent_sortmaxdist.integer, 32768)); + + // update hash array + if (trans_sortarraysize != r_transparent_sortarraysize.integer) { - // generate index - hashdist = (int) (mqt->dist * distscale); - hashdist = bound(0, hashdist, 4095); + trans_sortarraysize = r_transparent_sortarraysize.integer; + if (trans_hash) + Mem_Free(trans_hash); + trans_hash = (meshqueue_t **)Mem_Alloc(cls.permanentmempool, sizeof(meshqueue_t *) * trans_sortarraysize); + if (trans_hashpointer) + Mem_Free(trans_hashpointer); + trans_hashpointer = (meshqueue_t ***)Mem_Alloc(cls.permanentmempool, sizeof(meshqueue_t **) * trans_sortarraysize); + } + + // build index + memset(trans_hash, 0, sizeof(meshqueue_t *) * trans_sortarraysize); + for (i = 0; i < trans_sortarraysize; i++) + trans_hashpointer[i] = &trans_hash[i]; + distscale = (trans_sortarraysize - 1) / min(mqt_viewmaxdist, r_transparent_sortmaxdist.integer); + maxhashindex = trans_sortarraysize - 1; + for (i = 0, mqt = mqt_array; i < mqt_count; i++, mqt++) + { + switch(mqt->category) + { + default: + case TRANSPARENTSORT_HUD: + hashindex = 0; + break; + case TRANSPARENTSORT_DISTANCE: + // this could use a reduced range if we need more categories + hashindex = bound(0, (int)(bound(0, mqt->dist - r_transparent_sortmindist.integer, r_transparent_sortmaxdist.integer) * distscale), maxhashindex); + break; + case TRANSPARENTSORT_SKY: + hashindex = maxhashindex; + break; + } // link to tail of hash chain (to preserve render order) mqt->next = NULL; - *hashpointer[hashdist] = mqt; - hashpointer[hashdist] = &mqt->next; + *trans_hashpointer[hashindex] = mqt; + trans_hashpointer[hashindex] = &mqt->next; } callback = NULL; ent = NULL; rtlight = NULL; batchnumsurfaces = 0; - for (i = 4095;i >= 0;i--) + + // draw + for (i = maxhashindex; i >= 0; i--) { - if (hash[i]) + if (trans_hash[i]) { - for (mqt = hash[i];mqt;mqt = mqt->next) + for (mqt = trans_hash[i]; mqt; mqt = mqt->next) { - if (ent != mqt->ent || rtlight != mqt->rtlight || callback != mqt->callback || batchnumsurfaces >= 256) + if (ent != mqt->ent || rtlight != mqt->rtlight || callback != mqt->callback || batchnumsurfaces >= MESHQUEUE_TRANSPARENT_BATCHSIZE) { if (batchnumsurfaces) callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);