4 typedef struct meshqueue_s
6 struct meshqueue_s *next;
7 void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices);
8 const entity_render_t *ent;
10 const rtlight_t *rtlight;
12 dptransparentsortcategory_t category;
16 int trans_sortarraysize;
17 meshqueue_t **trans_hash = NULL;
18 meshqueue_t ***trans_hashpointer = NULL;
20 float mqt_viewplanedist;
21 float mqt_viewmaxdist;
22 meshqueue_t *mqt_array;
26 void R_MeshQueue_BeginScene(void)
29 mqt_viewplanedist = DotProduct(r_refdef.view.origin, r_refdef.view.forward);
33 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)
36 if (mqt_count >= mqt_total || !mqt_array)
38 int newtotal = max(1024, mqt_total * 2);
39 meshqueue_t *newarray = (meshqueue_t *)Mem_Alloc(cls.permanentmempool, newtotal * sizeof(meshqueue_t));
42 memcpy(newarray, mqt_array, mqt_total * sizeof(meshqueue_t));
48 mq = &mqt_array[mqt_count++];
49 mq->callback = callback;
51 mq->surfacenumber = surfacenumber;
52 mq->rtlight = rtlight;
53 mq->category = category;
54 if (r_transparent_useplanardistance.integer)
55 mq->dist = DotProduct(center, r_refdef.view.forward) - mqt_viewplanedist;
57 mq->dist = VectorDistance(center, r_refdef.view.origin);
59 mqt_viewmaxdist = max(mqt_viewmaxdist, mq->dist);
62 void R_MeshQueue_RenderTransparent(void)
64 int i, hashindex, maxhashindex, batchnumsurfaces;
66 const entity_render_t *ent;
67 const rtlight_t *rtlight;
68 void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices);
69 int batchsurfaceindex[MESHQUEUE_TRANSPARENT_BATCHSIZE];
75 // check for bad cvars
76 if (r_transparent_sortarraysize.integer < 1 || r_transparent_sortarraysize.integer > 32768)
77 Cvar_SetValueQuick(&r_transparent_sortarraysize, bound(1, r_transparent_sortarraysize.integer, 32768));
78 if (r_transparent_sortmindist.integer < 0 || r_transparent_sortmindist.integer >= r_transparent_sortmaxdist.integer)
79 Cvar_SetValueQuick(&r_transparent_sortmindist, 0);
80 if (r_transparent_sortmaxdist.integer < r_transparent_sortmindist.integer || r_transparent_sortmaxdist.integer > 32768)
81 Cvar_SetValueQuick(&r_transparent_sortmaxdist, bound(r_transparent_sortmindist.integer, r_transparent_sortmaxdist.integer, 32768));
84 if (trans_sortarraysize != r_transparent_sortarraysize.integer)
86 trans_sortarraysize = r_transparent_sortarraysize.integer;
89 trans_hash = (meshqueue_t **)Mem_Alloc(cls.permanentmempool, sizeof(meshqueue_t *) * trans_sortarraysize);
90 if (trans_hashpointer)
91 Mem_Free(trans_hashpointer);
92 trans_hashpointer = (meshqueue_t ***)Mem_Alloc(cls.permanentmempool, sizeof(meshqueue_t **) * trans_sortarraysize);
96 memset(trans_hash, 0, sizeof(meshqueue_t *) * trans_sortarraysize);
97 for (i = 0; i < trans_sortarraysize; i++)
98 trans_hashpointer[i] = &trans_hash[i];
99 distscale = (trans_sortarraysize - 1) / min(mqt_viewmaxdist, r_transparent_sortmaxdist.integer);
100 maxhashindex = trans_sortarraysize - 1;
101 for (i = 0, mqt = mqt_array; i < mqt_count; i++, mqt++)
103 switch(mqt->category)
106 case TRANSPARENTSORT_HUD:
109 case TRANSPARENTSORT_DISTANCE:
110 // this could use a reduced range if we need more categories
111 hashindex = bound(0, (int)(bound(0, mqt->dist - r_transparent_sortmindist.integer, r_transparent_sortmaxdist.integer) * distscale), maxhashindex);
113 case TRANSPARENTSORT_SKY:
114 hashindex = maxhashindex;
117 // link to tail of hash chain (to preserve render order)
119 *trans_hashpointer[hashindex] = mqt;
120 trans_hashpointer[hashindex] = &mqt->next;
125 batchnumsurfaces = 0;
128 for (i = maxhashindex; i >= 0; i--)
132 for (mqt = trans_hash[i]; mqt; mqt = mqt->next)
134 if (ent != mqt->ent || rtlight != mqt->rtlight || callback != mqt->callback || batchnumsurfaces >= MESHQUEUE_TRANSPARENT_BATCHSIZE)
136 if (batchnumsurfaces)
137 callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);
138 batchnumsurfaces = 0;
140 rtlight = mqt->rtlight;
141 callback = mqt->callback;
143 batchsurfaceindex[batchnumsurfaces++] = mqt->surfacenumber;
147 if (batchnumsurfaces)
148 callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);