5 typedef struct meshqueue_s
7 struct meshqueue_s *next;
8 void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices);
9 const entity_render_t *ent;
11 const rtlight_t *rtlight;
16 int trans_sortarraysize;
17 meshqueue_t **trans_hash = NULL;
18 meshqueue_t ***trans_hashpointer = NULL;
19 extern cvar_t r_transparent_sortarraysize;
20 extern cvar_t r_transparent_sortmaxdist;
22 float mqt_viewplanedist;
23 float mqt_viewmindist;
24 float mqt_viewmaxdist;
25 meshqueue_t *mqt_array;
29 void R_MeshQueue_BeginScene(void)
32 mqt_viewplanedist = DotProduct(r_refdef.view.origin, r_refdef.view.forward);
34 mqt_viewmindist = 999999999;
37 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)
40 if (mqt_count >= mqt_total || !mqt_array)
42 int newtotal = max(1024, mqt_total * 2);
43 meshqueue_t *newarray = (meshqueue_t *)Mem_Alloc(cls.permanentmempool, newtotal * sizeof(meshqueue_t));
46 memcpy(newarray, mqt_array, mqt_total * sizeof(meshqueue_t));
52 mq = &mqt_array[mqt_count++];
53 mq->callback = callback;
55 mq->surfacenumber = surfacenumber;
56 mq->rtlight = rtlight;
57 mq->dist = DotProduct(center, r_refdef.view.forward) - mqt_viewplanedist;
59 mqt_viewmaxdist = max(mqt_viewmaxdist, mq->dist);
60 mqt_viewmindist = min(mqt_viewmindist, mq->dist);
63 void R_MeshQueue_RenderTransparent(void)
65 int i, hashindex, maxhashindex, batchnumsurfaces;
67 const entity_render_t *ent;
68 const rtlight_t *rtlight;
69 void (*callback)(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfaceindices);
70 int batchsurfaceindex[MESHQUEUE_TRANSPARENT_BATCHSIZE];
76 // check for bad cvars
77 if (r_transparent_sortarraysize.integer < 1 || r_transparent_sortarraysize.integer > 32768)
78 Cvar_SetValueQuick(&r_transparent_sortarraysize, bound(1, r_transparent_sortarraysize.integer, 32768));
79 if (r_transparent_sortmaxdist.integer < 1 || r_transparent_sortmaxdist.integer > 32768)
80 Cvar_SetValueQuick(&r_transparent_sortmaxdist, bound(1, r_transparent_sortmaxdist.integer, 32768));
83 if (trans_sortarraysize != r_transparent_sortarraysize.integer)
85 trans_sortarraysize = r_transparent_sortarraysize.integer;
88 trans_hash = (meshqueue_t **)Mem_Alloc(cls.permanentmempool, sizeof(trans_hash) * trans_sortarraysize);
89 if (trans_hashpointer)
90 Mem_Free(trans_hashpointer);
91 trans_hashpointer = (meshqueue_t ***)Mem_Alloc(cls.permanentmempool, sizeof(trans_hashpointer) * trans_sortarraysize);
95 memset(trans_hash, 0, sizeof(trans_hash) * trans_sortarraysize);
96 for (i = 0; i < trans_sortarraysize; i++)
97 trans_hashpointer[i] = &trans_hash[i];
98 distscale = (trans_sortarraysize - 1) / max( min(mqt_viewmaxdist, r_transparent_sortmaxdist.integer) - mqt_viewmindist, 64 );
99 maxhashindex = trans_sortarraysize - 1;
100 for (i = 0, mqt = mqt_array; i < mqt_count; i++, mqt++)
102 hashindex = bound(0, (int)(min(mqt->dist - mqt_viewmindist, r_transparent_sortmaxdist.integer) * distscale - 0.1), maxhashindex);
103 // link to tail of hash chain (to preserve render order)
105 *trans_hashpointer[hashindex] = mqt;
106 trans_hashpointer[hashindex] = &mqt->next;
111 batchnumsurfaces = 0;
114 for (i = maxhashindex; i >= 0; i--)
118 for (mqt = trans_hash[i]; mqt; mqt = mqt->next)
120 if (ent != mqt->ent || rtlight != mqt->rtlight || callback != mqt->callback || batchnumsurfaces >= MESHQUEUE_TRANSPARENT_BATCHSIZE)
122 if (batchnumsurfaces)
123 callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);
124 batchnumsurfaces = 0;
126 rtlight = mqt->rtlight;
127 callback = mqt->callback;
129 batchsurfaceindex[batchnumsurfaces++] = mqt->surfacenumber;
133 if (batchnumsurfaces)
134 callback(ent, rtlight, batchnumsurfaces, batchsurfaceindex);