3 #include "cl_collision.h"
5 // on GLES we have to use some proper #define's
7 #define GL_FRAMEBUFFER 0x8D40
8 #define GL_DEPTH_ATTACHMENT 0x8D00
9 #define GL_COLOR_ATTACHMENT0 0x8CE0
10 #define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506
12 #ifndef GL_COLOR_ATTACHMENT1
13 #define GL_COLOR_ATTACHMENT1 0x8CE1
14 #define GL_COLOR_ATTACHMENT2 0x8CE2
15 #define GL_COLOR_ATTACHMENT3 0x8CE3
16 #define GL_COLOR_ATTACHMENT4 0x8CE4
17 #define GL_COLOR_ATTACHMENT5 0x8CE5
18 #define GL_COLOR_ATTACHMENT6 0x8CE6
19 #define GL_COLOR_ATTACHMENT7 0x8CE7
20 #define GL_COLOR_ATTACHMENT8 0x8CE8
21 #define GL_COLOR_ATTACHMENT9 0x8CE9
22 #define GL_COLOR_ATTACHMENT10 0x8CEA
23 #define GL_COLOR_ATTACHMENT11 0x8CEB
24 #define GL_COLOR_ATTACHMENT12 0x8CEC
25 #define GL_COLOR_ATTACHMENT13 0x8CED
26 #define GL_COLOR_ATTACHMENT14 0x8CEE
27 #define GL_COLOR_ATTACHMENT15 0x8CEF
29 #ifndef GL_ARRAY_BUFFER
30 #define GL_ARRAY_BUFFER 0x8892
31 #define GL_ELEMENT_ARRAY_BUFFER 0x8893
34 #define GL_TEXTURE0 0x84C0
35 #define GL_TEXTURE1 0x84C1
36 #define GL_TEXTURE2 0x84C2
37 #define GL_TEXTURE3 0x84C3
38 #define GL_TEXTURE4 0x84C4
39 #define GL_TEXTURE5 0x84C5
40 #define GL_TEXTURE6 0x84C6
41 #define GL_TEXTURE7 0x84C7
42 #define GL_TEXTURE8 0x84C8
43 #define GL_TEXTURE9 0x84C9
44 #define GL_TEXTURE10 0x84CA
45 #define GL_TEXTURE11 0x84CB
46 #define GL_TEXTURE12 0x84CC
47 #define GL_TEXTURE13 0x84CD
48 #define GL_TEXTURE14 0x84CE
49 #define GL_TEXTURE15 0x84CF
50 #define GL_TEXTURE16 0x84D0
51 #define GL_TEXTURE17 0x84D1
52 #define GL_TEXTURE18 0x84D2
53 #define GL_TEXTURE19 0x84D3
54 #define GL_TEXTURE20 0x84D4
55 #define GL_TEXTURE21 0x84D5
56 #define GL_TEXTURE22 0x84D6
57 #define GL_TEXTURE23 0x84D7
58 #define GL_TEXTURE24 0x84D8
59 #define GL_TEXTURE25 0x84D9
60 #define GL_TEXTURE26 0x84DA
61 #define GL_TEXTURE27 0x84DB
62 #define GL_TEXTURE28 0x84DC
63 #define GL_TEXTURE29 0x84DD
64 #define GL_TEXTURE30 0x84DE
65 #define GL_TEXTURE31 0x84DF
69 #define GL_TEXTURE_3D 0x806F
71 #ifndef GL_TEXTURE_CUBE_MAP
72 #define GL_TEXTURE_CUBE_MAP 0x8513
76 #define MAX_RENDERTARGETS 4
78 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
79 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
80 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
82 cvar_t r_render = {0, "r_render", "1", "enables rendering 3D views (you want this on!)"};
83 cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
84 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
85 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
86 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
87 cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "3", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering, 0 disables VBO allocation or use, 1 enables VBOs for vertex and triangle data, 2 only for vertex data, 3 for vertex data and triangle data of simple meshes (ones with only one surface)"};
88 cvar_t gl_vbo_dynamicvertex = {CVAR_SAVE, "gl_vbo_dynamicvertex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
89 cvar_t gl_vbo_dynamicindex = {CVAR_SAVE, "gl_vbo_dynamicindex", "0", "make use of GL_ARB_vertex_buffer_object extension when rendering dynamic (animated/procedural) geometry such as text and particles"};
90 cvar_t gl_fbo = {CVAR_SAVE, "gl_fbo", "1", "make use of GL_ARB_framebuffer_object extension to enable shadowmaps and other features using pixel formats different from the framebuffer"};
92 cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
93 qboolean v_flipped_state = false;
95 r_viewport_t gl_viewport;
96 matrix4x4_t gl_modelmatrix;
97 matrix4x4_t gl_viewmatrix;
98 matrix4x4_t gl_modelviewmatrix;
99 matrix4x4_t gl_projectionmatrix;
100 matrix4x4_t gl_modelviewprojectionmatrix;
101 float gl_modelview16f[16];
102 float gl_modelviewprojection16f[16];
103 qboolean gl_modelmatrixchanged;
105 int gl_maxdrawrangeelementsvertices;
106 int gl_maxdrawrangeelementsindices;
109 int gl_errornumber = 0;
111 void GL_PrintError(int errornumber, const char *filename, int linenumber)
115 #ifdef GL_INVALID_ENUM
116 case GL_INVALID_ENUM:
117 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
120 #ifdef GL_INVALID_VALUE
121 case GL_INVALID_VALUE:
122 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
125 #ifdef GL_INVALID_OPERATION
126 case GL_INVALID_OPERATION:
127 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
130 #ifdef GL_STACK_OVERFLOW
131 case GL_STACK_OVERFLOW:
132 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
135 #ifdef GL_STACK_UNDERFLOW
136 case GL_STACK_UNDERFLOW:
137 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
140 #ifdef GL_OUT_OF_MEMORY
141 case GL_OUT_OF_MEMORY:
142 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
145 #ifdef GL_TABLE_TOO_LARGE
146 case GL_TABLE_TOO_LARGE:
147 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
150 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION
151 case GL_INVALID_FRAMEBUFFER_OPERATION:
152 Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
156 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
162 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
164 void SCR_ScreenShot_f (void);
166 typedef struct gltextureunit_s
168 int pointer_texcoord_components;
169 int pointer_texcoord_gltype;
170 size_t pointer_texcoord_stride;
171 const void *pointer_texcoord_pointer;
172 const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
173 size_t pointer_texcoord_offset;
176 int t2d, t3d, tcubemap;
178 int rgbscale, alphascale;
180 int combinergb, combinealpha;
181 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
182 int texmatrixenabled;
187 typedef struct gl_state_s
195 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
199 float polygonoffset[2];
202 float alphafuncvalue;
203 qboolean alphatocoverage;
206 unsigned int clientunit;
207 gltextureunit_t units[MAX_TEXTUREUNITS];
211 int vertexbufferobject;
212 int elementbufferobject;
213 int uniformbufferobject;
214 int framebufferobject;
215 int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
216 qboolean pointer_color_enabled;
218 int pointer_vertex_components;
219 int pointer_vertex_gltype;
220 size_t pointer_vertex_stride;
221 const void *pointer_vertex_pointer;
222 const r_meshbuffer_t *pointer_vertex_vertexbuffer;
223 size_t pointer_vertex_offset;
225 int pointer_color_components;
226 int pointer_color_gltype;
227 size_t pointer_color_stride;
228 const void *pointer_color_pointer;
229 const r_meshbuffer_t *pointer_color_vertexbuffer;
230 size_t pointer_color_offset;
232 void *preparevertices_tempdata;
233 size_t preparevertices_tempdatamaxsize;
234 r_vertexgeneric_t *preparevertices_vertexgeneric;
235 r_vertexmesh_t *preparevertices_vertexmesh;
236 int preparevertices_numvertices;
238 qboolean usevbo_staticvertex;
239 qboolean usevbo_staticindex;
240 qboolean usevbo_dynamicvertex;
241 qboolean usevbo_dynamicindex;
243 memexpandablearray_t meshbufferarray;
249 static gl_state_t gl_state;
253 note: here's strip order for a terrain row:
260 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
262 *elements++ = i + row;
264 *elements++ = i + row + 1;
267 *elements++ = i + row + 1;
270 for (y = 0;y < rows - 1;y++)
272 for (x = 0;x < columns - 1;x++)
275 *elements++ = i + columns;
277 *elements++ = i + columns + 1;
280 *elements++ = i + columns + 1;
291 for (y = 0;y < rows - 1;y++)
293 for (x = 0;x < columns - 1;x++)
297 *elements++ = i + columns;
298 *elements++ = i + columns + 1;
299 *elements++ = i + columns;
300 *elements++ = i + columns + 1;
306 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
307 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
308 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
309 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
311 static void GL_VBOStats_f(void)
313 GL_Mesh_ListVBOs(true);
316 static void GL_Backend_ResetState(void);
318 static void R_Mesh_SetUseVBO(void)
320 switch(vid.renderpath)
322 case RENDERPATH_GL20:
323 case RENDERPATH_GLES2:
324 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
325 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
326 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo.integer) || vid.forcevbo;
327 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer && gl_vbo.integer) || vid.forcevbo;
332 static void gl_backend_start(void)
334 memset(&gl_state, 0, sizeof(gl_state));
337 Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
339 Con_DPrintf("OpenGL backend started.\n");
343 GL_Backend_ResetState();
345 switch(vid.renderpath)
347 case RENDERPATH_GL20:
348 case RENDERPATH_GLES2:
349 // fetch current fbo here (default fbo is not 0 on some GLES devices)
350 if (vid.support.ext_framebuffer_object)
351 qglGetIntegerv(GL_FRAMEBUFFER_BINDING, &gl_state.defaultframebufferobject);
356 static void gl_backend_shutdown(void)
358 Con_DPrint("OpenGL Backend shutting down\n");
360 switch(vid.renderpath)
362 case RENDERPATH_GL20:
363 case RENDERPATH_GLES2:
367 if (gl_state.preparevertices_tempdata)
368 Mem_Free(gl_state.preparevertices_tempdata);
370 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
372 memset(&gl_state, 0, sizeof(gl_state));
375 static void gl_backend_newmap(void)
379 static void gl_backend_devicelost(void)
382 r_meshbuffer_t *buffer;
383 switch(vid.renderpath)
385 case RENDERPATH_GL20:
386 case RENDERPATH_GLES2:
389 endindex = (int)Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
390 for (i = 0;i < endindex;i++)
392 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
393 if (!buffer || !buffer->isdynamic)
395 switch(vid.renderpath)
397 case RENDERPATH_GL20:
398 case RENDERPATH_GLES2:
404 static void gl_backend_devicerestored(void)
406 switch(vid.renderpath)
408 case RENDERPATH_GL20:
409 case RENDERPATH_GLES2:
414 void gl_backend_init(void)
418 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
420 polygonelement3s[i * 3 + 0] = 0;
421 polygonelement3s[i * 3 + 1] = i + 1;
422 polygonelement3s[i * 3 + 2] = i + 2;
424 // elements for rendering a series of quads as triangles
425 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
427 quadelement3s[i * 6 + 0] = i * 4;
428 quadelement3s[i * 6 + 1] = i * 4 + 1;
429 quadelement3s[i * 6 + 2] = i * 4 + 2;
430 quadelement3s[i * 6 + 3] = i * 4;
431 quadelement3s[i * 6 + 4] = i * 4 + 2;
432 quadelement3s[i * 6 + 5] = i * 4 + 3;
435 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
436 polygonelement3i[i] = polygonelement3s[i];
437 for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
438 quadelement3i[i] = quadelement3s[i];
440 Cvar_RegisterVariable(&r_render);
441 Cvar_RegisterVariable(&r_renderview);
442 Cvar_RegisterVariable(&r_waterwarp);
443 Cvar_RegisterVariable(&gl_polyblend);
444 Cvar_RegisterVariable(&v_flipped);
445 Cvar_RegisterVariable(&gl_dither);
446 Cvar_RegisterVariable(&gl_vbo);
447 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
448 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
449 Cvar_RegisterVariable(&gl_paranoid);
450 Cvar_RegisterVariable(&gl_printcheckerror);
452 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
454 Cmd_AddCommand("gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them");
456 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
459 void GL_SetMirrorState(qboolean state);
461 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
465 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
466 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
468 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
470 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
471 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
472 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
474 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
479 switch(vid.renderpath)
481 case RENDERPATH_GL20:
482 case RENDERPATH_GLES2:
488 static int bboxedges[12][2] =
507 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
509 int i, ix1, iy1, ix2, iy2;
510 float x1, y1, x2, y2;
521 scissor[0] = r_refdef.view.viewport.x;
522 scissor[1] = r_refdef.view.viewport.y;
523 scissor[2] = r_refdef.view.viewport.width;
524 scissor[3] = r_refdef.view.viewport.height;
526 // if view is inside the box, just say yes it's visible
527 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
530 // transform all corners that are infront of the nearclip plane
531 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
532 plane4f[3] = r_refdef.view.frustum[4].dist;
534 for (i = 0;i < 8;i++)
536 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
537 dist[i] = DotProduct4(corner[i], plane4f);
538 sign[i] = dist[i] > 0;
541 VectorCopy(corner[i], vertex[numvertices]);
545 // if some points are behind the nearclip, add clipped edge points to make
546 // sure that the scissor boundary is complete
547 if (numvertices > 0 && numvertices < 8)
549 // add clipped edge points
550 for (i = 0;i < 12;i++)
554 if (sign[j] != sign[k])
556 f = dist[j] / (dist[j] - dist[k]);
557 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
563 // if we have no points to check, it is behind the view plane
567 // if we have some points to transform, check what screen area is covered
568 x1 = y1 = x2 = y2 = 0;
570 //Con_Printf("%i vertices to transform...\n", numvertices);
571 for (i = 0;i < numvertices;i++)
573 VectorCopy(vertex[i], v);
574 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
575 //Con_Printf("%.3f %.3f %.3f %.3f transformed to %.3f %.3f %.3f %.3f\n", v[0], v[1], v[2], v[3], v2[0], v2[1], v2[2], v2[3]);
578 if (x1 > v2[0]) x1 = v2[0];
579 if (x2 < v2[0]) x2 = v2[0];
580 if (y1 > v2[1]) y1 = v2[1];
581 if (y2 < v2[1]) y2 = v2[1];
590 // now convert the scissor rectangle to integer screen coordinates
591 ix1 = (int)(x1 - 1.0f);
592 //iy1 = vid.height - (int)(y2 - 1.0f);
593 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
594 iy1 = (int)(y1 - 1.0f);
595 ix2 = (int)(x2 + 1.0f);
596 //iy2 = vid.height - (int)(y1 + 1.0f);
597 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
598 iy2 = (int)(y2 + 1.0f);
599 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
601 // clamp it to the screen
602 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
603 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
604 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
605 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
607 // if it is inside out, it's not visible
608 if (ix2 <= ix1 || iy2 <= iy1)
611 // the light area is visible, set up the scissor rectangle
614 scissor[2] = ix2 - ix1;
615 scissor[3] = iy2 - iy1;
617 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
618 switch(vid.renderpath)
620 case RENDERPATH_GL20:
621 case RENDERPATH_GLES2:
629 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
633 float clipPlane[4], v3[3], v4[3];
636 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
638 VectorSet(normal, normalx, normaly, normalz);
639 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
640 VectorScale(normal, -dist, v3);
641 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
642 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
643 clipPlane[3] = -DotProduct(v4, clipPlane);
647 // testing code for comparing results
649 VectorCopy4(clipPlane, clipPlane2);
650 R_EntityMatrix(&identitymatrix);
651 VectorSet(q, normal[0], normal[1], normal[2], -dist);
652 qglClipPlane(GL_CLIP_PLANE0, q);
653 qglGetClipPlane(GL_CLIP_PLANE0, q);
654 VectorCopy4(q, clipPlane);
658 // Calculate the clip-space corner point opposite the clipping plane
659 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
660 // transform it into camera space by multiplying it
661 // by the inverse of the projection matrix
662 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
663 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
665 q[3] = (1.0f + m[10]) / m[14];
667 // Calculate the scaled plane vector
668 d = 2.0f / DotProduct4(clipPlane, q);
670 // Replace the third row of the projection matrix
671 m[2] = clipPlane[0] * d;
672 m[6] = clipPlane[1] * d;
673 m[10] = clipPlane[2] * d + 1.0f;
674 m[14] = clipPlane[3] * d;
677 void R_Viewport_InitOrtho(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float x1, float y1, float x2, float y2, float nearclip, float farclip, const float *nearplane)
679 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
681 memset(v, 0, sizeof(*v));
682 v->type = R_VIEWPORTTYPE_ORTHO;
683 v->cameramatrix = *cameramatrix;
690 memset(m, 0, sizeof(m));
691 m[0] = 2/(right - left);
692 m[5] = 2/(top - bottom);
693 m[10] = -2/(zFar - zNear);
694 m[12] = - (right + left)/(right - left);
695 m[13] = - (top + bottom)/(top - bottom);
696 m[14] = - (zFar + zNear)/(zFar - zNear);
698 switch(vid.renderpath)
700 case RENDERPATH_GL20:
701 case RENDERPATH_GLES2:
704 v->screentodepth[0] = -farclip / (farclip - nearclip);
705 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
707 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
710 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
712 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
718 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
719 R_Viewport_TransformToScreen(v, test1, test2);
720 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
725 void R_Viewport_InitOrtho3D(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, float farclip, const float *nearplane)
727 matrix4x4_t tempmatrix, basematrix;
729 memset(v, 0, sizeof(*v));
731 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
732 v->cameramatrix = *cameramatrix;
739 memset(m, 0, sizeof(m));
740 m[0] = 1.0 / frustumx;
741 m[5] = 1.0 / frustumy;
742 m[10] = -2 / (farclip - nearclip);
743 m[14] = -(farclip + nearclip) / (farclip - nearclip);
745 v->screentodepth[0] = -farclip / (farclip - nearclip);
746 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
748 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
749 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
750 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
751 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
754 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
756 if(v_flipped.integer)
764 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
767 void R_Viewport_InitPerspective(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, float farclip, const float *nearplane)
769 matrix4x4_t tempmatrix, basematrix;
771 memset(v, 0, sizeof(*v));
773 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
774 v->cameramatrix = *cameramatrix;
781 memset(m, 0, sizeof(m));
782 m[0] = 1.0 / frustumx;
783 m[5] = 1.0 / frustumy;
784 m[10] = -(farclip + nearclip) / (farclip - nearclip);
786 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
787 v->screentodepth[0] = -farclip / (farclip - nearclip);
788 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
790 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
791 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
792 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
793 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
796 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
798 if(v_flipped.integer)
806 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
809 void R_Viewport_InitPerspectiveInfinite(r_viewport_t *v, const matrix4x4_t *cameramatrix, int x, int y, int width, int height, float frustumx, float frustumy, float nearclip, const float *nearplane)
811 matrix4x4_t tempmatrix, basematrix;
812 const float nudge = 1.0 - 1.0 / (1<<23);
814 memset(v, 0, sizeof(*v));
816 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
817 v->cameramatrix = *cameramatrix;
824 memset(m, 0, sizeof(m));
825 m[ 0] = 1.0 / frustumx;
826 m[ 5] = 1.0 / frustumy;
829 m[14] = -2 * nearclip * nudge;
830 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
831 v->screentodepth[1] = m[14] * -0.5;
833 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
834 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
835 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
836 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
839 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
841 if(v_flipped.integer)
849 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
852 float cubeviewmatrix[6][16] =
854 // standard cubemap projections
892 float rectviewmatrix[6][16] =
894 // sign-preserving cubemap projections
933 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
935 matrix4x4_t tempmatrix, basematrix;
937 memset(v, 0, sizeof(*v));
938 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
939 v->cameramatrix = *cameramatrix;
943 memset(m, 0, sizeof(m));
945 m[10] = -(farclip + nearclip) / (farclip - nearclip);
947 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
949 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
950 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
951 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
954 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
956 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
959 void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, int border, float nearclip, float farclip, const float *nearplane, int offsetx, int offsety)
961 matrix4x4_t tempmatrix, basematrix;
963 memset(v, 0, sizeof(*v));
964 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
965 v->cameramatrix = *cameramatrix;
966 v->x = offsetx + (side & 1) * size;
967 v->y = offsety + (side >> 1) * size;
971 memset(m, 0, sizeof(m));
972 m[0] = m[5] = 1.0f * ((float)size - border) / size;
973 m[10] = -(farclip + nearclip) / (farclip - nearclip);
975 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
977 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
978 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
979 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
982 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
984 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
987 void R_SetViewport(const r_viewport_t *v)
991 // FIXME: v_flipped_state is evil, this probably breaks somewhere
992 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
994 // copy over the matrices to our state
995 gl_viewmatrix = v->viewmatrix;
996 gl_projectionmatrix = v->projectmatrix;
998 switch(vid.renderpath)
1000 case RENDERPATH_GL20:
1001 case RENDERPATH_GLES2:
1003 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1007 // force an update of the derived matrices
1008 gl_modelmatrixchanged = true;
1009 R_EntityMatrix(&gl_modelmatrix);
1012 void R_GetViewport(r_viewport_t *v)
1017 static void GL_BindVBO(int bufferobject)
1019 if (gl_state.vertexbufferobject != bufferobject)
1021 gl_state.vertexbufferobject = bufferobject;
1023 qglBindBufferARB(GL_ARRAY_BUFFER, bufferobject);CHECKGLERROR
1027 static void GL_BindEBO(int bufferobject)
1029 if (gl_state.elementbufferobject != bufferobject)
1031 gl_state.elementbufferobject = bufferobject;
1033 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, bufferobject);CHECKGLERROR
1037 static void GL_BindUBO(int bufferobject)
1039 if (gl_state.uniformbufferobject != bufferobject)
1041 gl_state.uniformbufferobject = bufferobject;
1042 #ifdef GL_UNIFORM_BUFFER
1044 qglBindBufferARB(GL_UNIFORM_BUFFER, bufferobject);CHECKGLERROR
1049 static const GLuint drawbuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
1050 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1052 switch(vid.renderpath)
1054 case RENDERPATH_GL20:
1055 case RENDERPATH_GLES2:
1056 if (vid.support.arb_framebuffer_object)
1060 qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
1061 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1062 // GL_ARB_framebuffer_object (GL3-class hardware) - depth stencil attachment
1064 // FIXME: separate stencil attachment on GLES
1065 if (depthtexture && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
1066 if (depthtexture && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
1068 if (depthtexture && depthtexture->texnum )
1070 qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
1071 if (depthtexture->glisdepthstencil) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
1073 if (depthtexture && depthtexture->renderbuffernum )
1075 qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
1076 if (depthtexture->glisdepthstencil) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
1079 if (colortexture && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR
1080 if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR
1081 if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR
1082 if (colortexture4 && colortexture4->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR
1083 if (colortexture && colortexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR
1084 if (colortexture2 && colortexture2->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR
1085 if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR
1086 if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR
1089 if (colortexture4 && qglDrawBuffersARB)
1091 qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR
1092 qglReadBuffer(GL_NONE);CHECKGLERROR
1094 else if (colortexture3 && qglDrawBuffersARB)
1096 qglDrawBuffersARB(3, drawbuffers);CHECKGLERROR
1097 qglReadBuffer(GL_NONE);CHECKGLERROR
1099 else if (colortexture2 && qglDrawBuffersARB)
1101 qglDrawBuffersARB(2, drawbuffers);CHECKGLERROR
1102 qglReadBuffer(GL_NONE);CHECKGLERROR
1104 else if (colortexture && qglDrawBuffer)
1106 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1107 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1109 else if (qglDrawBuffer)
1111 qglDrawBuffer(GL_NONE);CHECKGLERROR
1112 qglReadBuffer(GL_NONE);CHECKGLERROR
1115 status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR
1116 if (status != GL_FRAMEBUFFER_COMPLETE)
1118 Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status);
1119 gl_state.framebufferobject = 0; // GL unbinds it for us
1120 qglDeleteFramebuffers(1, (GLuint*)&temp);
1125 else if (vid.support.ext_framebuffer_object)
1129 qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR
1130 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1131 // GL_EXT_framebuffer_object (GL2-class hardware) - no depth stencil attachment, let it break stencil
1132 if (depthtexture && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR
1133 if (depthtexture && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR
1134 if (colortexture && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR
1135 if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR
1136 if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR
1137 if (colortexture4 && colortexture4->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR
1138 if (colortexture && colortexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR
1139 if (colortexture2 && colortexture2->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR
1140 if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR
1141 if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR
1144 if (colortexture4 && qglDrawBuffersARB)
1146 qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR
1147 qglReadBuffer(GL_NONE);CHECKGLERROR
1149 else if (colortexture3 && qglDrawBuffersARB)
1151 qglDrawBuffersARB(3, drawbuffers);CHECKGLERROR
1152 qglReadBuffer(GL_NONE);CHECKGLERROR
1154 else if (colortexture2 && qglDrawBuffersARB)
1156 qglDrawBuffersARB(2, drawbuffers);CHECKGLERROR
1157 qglReadBuffer(GL_NONE);CHECKGLERROR
1159 else if (colortexture && qglDrawBuffer)
1161 qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1162 qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR
1164 else if (qglDrawBuffer)
1166 qglDrawBuffer(GL_NONE);CHECKGLERROR
1167 qglReadBuffer(GL_NONE);CHECKGLERROR
1170 status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR
1171 if (status != GL_FRAMEBUFFER_COMPLETE)
1173 Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status);
1174 gl_state.framebufferobject = 0; // GL unbinds it for us
1175 qglDeleteFramebuffers(1, (GLuint*)&temp);
1185 void R_Mesh_DestroyFramebufferObject(int fbo)
1187 switch(vid.renderpath)
1189 case RENDERPATH_GL20:
1190 case RENDERPATH_GLES2:
1193 // GL clears the binding if we delete something bound
1194 if (gl_state.framebufferobject == fbo)
1195 gl_state.framebufferobject = 0;
1196 qglDeleteFramebuffers(1, (GLuint*)&fbo);
1202 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1206 rtexture_t *textures[5];
1207 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1208 textures[4] = depthtexture;
1209 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1210 for (j = 0;j < 5;j++)
1212 for (i = 0;i < vid.teximageunits;i++)
1213 if (gl_state.units[i].texture == textures[j])
1214 R_Mesh_TexBind(i, NULL);
1215 // set up framebuffer object or render targets for the active rendering API
1216 switch (vid.renderpath)
1218 case RENDERPATH_GL20:
1219 case RENDERPATH_GLES2:
1220 if (gl_state.framebufferobject != fbo)
1222 gl_state.framebufferobject = fbo;
1223 qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1229 static void GL_Backend_ResetState(void)
1232 gl_state.active = true;
1233 gl_state.depthtest = true;
1234 gl_state.alphatest = false;
1235 gl_state.alphafunc = GL_GEQUAL;
1236 gl_state.alphafuncvalue = 0.5f;
1237 gl_state.alphatocoverage = false;
1238 gl_state.blendfunc1 = GL_ONE;
1239 gl_state.blendfunc2 = GL_ZERO;
1240 gl_state.blend = false;
1241 gl_state.depthmask = GL_TRUE;
1242 gl_state.colormask = 15;
1243 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1244 gl_state.lockrange_first = 0;
1245 gl_state.lockrange_count = 0;
1246 gl_state.cullface = GL_FRONT;
1247 gl_state.cullfaceenable = false;
1248 gl_state.polygonoffset[0] = 0;
1249 gl_state.polygonoffset[1] = 0;
1250 gl_state.framebufferobject = 0;
1251 gl_state.depthfunc = GL_LEQUAL;
1253 switch(vid.renderpath)
1255 case RENDERPATH_GL20:
1256 case RENDERPATH_GLES2:
1258 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1259 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1260 qglDisable(GL_BLEND);CHECKGLERROR
1261 qglCullFace(gl_state.cullface);CHECKGLERROR
1262 qglDisable(GL_CULL_FACE);CHECKGLERROR
1263 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1264 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1265 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1266 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1267 if (vid.support.arb_vertex_buffer_object)
1269 qglBindBufferARB(GL_ARRAY_BUFFER, 0);
1270 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
1272 if (vid.support.ext_framebuffer_object)
1273 qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.defaultframebufferobject);
1274 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1275 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1276 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1277 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1278 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1279 gl_state.unit = MAX_TEXTUREUNITS;
1280 gl_state.clientunit = MAX_TEXTUREUNITS;
1281 for (i = 0;i < vid.teximageunits;i++)
1283 GL_ActiveTexture(i);
1284 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1285 if (vid.support.ext_texture_3d)
1287 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1289 if (vid.support.arb_texture_cube_map)
1291 qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
1294 for (i = 0;i < vid.texarrayunits;i++)
1297 qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1298 qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1305 void GL_ActiveTexture(unsigned int num)
1307 if (gl_state.unit != num)
1309 gl_state.unit = num;
1310 switch(vid.renderpath)
1312 case RENDERPATH_GL20:
1313 case RENDERPATH_GLES2:
1315 qglActiveTexture(GL_TEXTURE0 + gl_state.unit);
1322 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1324 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1326 qboolean blendenable;
1327 gl_state.blendfunc1 = blendfunc1;
1328 gl_state.blendfunc2 = blendfunc2;
1329 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1330 switch(vid.renderpath)
1332 case RENDERPATH_GL20:
1333 case RENDERPATH_GLES2:
1335 if (qglBlendFuncSeparate)
1337 qglBlendFuncSeparate(gl_state.blendfunc1, gl_state.blendfunc2, GL_ZERO, GL_ONE);CHECKGLERROR // ELUAN: Adreno 225 (and others) compositing workaround
1341 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1343 if (gl_state.blend != blendenable)
1345 gl_state.blend = blendenable;
1346 if (!gl_state.blend)
1348 qglDisable(GL_BLEND);CHECKGLERROR
1352 qglEnable(GL_BLEND);CHECKGLERROR
1360 void GL_DepthMask(int state)
1362 if (gl_state.depthmask != state)
1364 gl_state.depthmask = state;
1365 switch(vid.renderpath)
1367 case RENDERPATH_GL20:
1368 case RENDERPATH_GLES2:
1370 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1376 void GL_DepthTest(int state)
1378 if (gl_state.depthtest != state)
1380 gl_state.depthtest = state;
1381 switch(vid.renderpath)
1383 case RENDERPATH_GL20:
1384 case RENDERPATH_GLES2:
1386 if (gl_state.depthtest)
1388 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1392 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1399 void GL_DepthFunc(int state)
1401 if (gl_state.depthfunc != state)
1403 gl_state.depthfunc = state;
1404 switch(vid.renderpath)
1406 case RENDERPATH_GL20:
1407 case RENDERPATH_GLES2:
1409 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1415 void GL_DepthRange(float nearfrac, float farfrac)
1417 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1419 gl_state.depthrange[0] = nearfrac;
1420 gl_state.depthrange[1] = farfrac;
1421 switch(vid.renderpath)
1423 case RENDERPATH_GL20:
1424 case RENDERPATH_GLES2:
1426 qglDepthRangef(gl_state.depthrange[0], gl_state.depthrange[1]);
1428 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1435 void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int frontzfail, int frontzpass, int backfail, int backzfail, int backzpass, int frontcompare, int backcompare, int comparereference, int comparemask)
1437 switch (vid.renderpath)
1439 case RENDERPATH_GL20:
1440 case RENDERPATH_GLES2:
1444 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1448 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1450 if (vid.support.ati_separate_stencil)
1452 qglStencilMask(writemask);CHECKGLERROR
1453 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1454 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1455 qglStencilFuncSeparate(GL_FRONT, frontcompare, comparereference, comparereference);CHECKGLERROR
1456 qglStencilFuncSeparate(GL_BACK, backcompare, comparereference, comparereference);CHECKGLERROR
1458 else if (vid.support.ext_stencil_two_side)
1460 #if defined(GL_STENCIL_TEST_TWO_SIDE_EXT) && !defined(USE_GLES2)
1461 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1462 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1463 qglStencilMask(writemask);CHECKGLERROR
1464 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1465 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1466 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1467 qglStencilMask(writemask);CHECKGLERROR
1468 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1469 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1476 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1478 switch (vid.renderpath)
1480 case RENDERPATH_GL20:
1481 case RENDERPATH_GLES2:
1485 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1489 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1491 if (vid.support.ext_stencil_two_side)
1493 #ifdef GL_STENCIL_TEST_TWO_SIDE_EXT
1494 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1497 qglStencilMask(writemask);CHECKGLERROR
1498 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1499 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1505 void GL_PolygonOffset(float planeoffset, float depthoffset)
1507 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1509 gl_state.polygonoffset[0] = planeoffset;
1510 gl_state.polygonoffset[1] = depthoffset;
1511 switch(vid.renderpath)
1513 case RENDERPATH_GL20:
1514 case RENDERPATH_GLES2:
1515 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1521 void GL_SetMirrorState(qboolean state)
1523 if (v_flipped_state != state)
1525 v_flipped_state = state;
1526 if (gl_state.cullface == GL_BACK)
1527 gl_state.cullface = GL_FRONT;
1528 else if (gl_state.cullface == GL_FRONT)
1529 gl_state.cullface = GL_BACK;
1532 switch(vid.renderpath)
1534 case RENDERPATH_GL20:
1535 case RENDERPATH_GLES2:
1536 qglCullFace(gl_state.cullface);CHECKGLERROR
1542 void GL_CullFace(int state)
1546 if(state == GL_FRONT)
1548 else if(state == GL_BACK)
1552 switch(vid.renderpath)
1554 case RENDERPATH_GL20:
1555 case RENDERPATH_GLES2:
1558 if (state != GL_NONE)
1560 if (!gl_state.cullfaceenable)
1562 gl_state.cullfaceenable = true;
1563 qglEnable(GL_CULL_FACE);CHECKGLERROR
1565 if (gl_state.cullface != state)
1567 gl_state.cullface = state;
1568 qglCullFace(gl_state.cullface);CHECKGLERROR
1573 if (gl_state.cullfaceenable)
1575 gl_state.cullfaceenable = false;
1576 qglDisable(GL_CULL_FACE);CHECKGLERROR
1583 void GL_AlphaToCoverage(qboolean state)
1585 if (gl_state.alphatocoverage != state)
1587 gl_state.alphatocoverage = state;
1588 switch(vid.renderpath)
1590 case RENDERPATH_GLES2:
1592 case RENDERPATH_GL20:
1593 #ifdef GL_SAMPLE_ALPHA_TO_COVERAGE_ARB
1594 // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly
1596 if (gl_state.alphatocoverage)
1598 qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
1599 // qglEnable(GL_MULTISAMPLE_ARB);CHECKGLERROR
1603 qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR
1604 // qglDisable(GL_MULTISAMPLE_ARB);CHECKGLERROR
1612 void GL_ColorMask(int r, int g, int b, int a)
1614 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
1615 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
1616 if (gl_state.colormask != state)
1618 gl_state.colormask = state;
1619 switch(vid.renderpath)
1621 case RENDERPATH_GL20:
1622 case RENDERPATH_GLES2:
1624 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
1630 void GL_Color(float cr, float cg, float cb, float ca)
1632 if (gl_state.pointer_color_enabled || gl_state.color4f[0] != cr || gl_state.color4f[1] != cg || gl_state.color4f[2] != cb || gl_state.color4f[3] != ca)
1634 gl_state.color4f[0] = cr;
1635 gl_state.color4f[1] = cg;
1636 gl_state.color4f[2] = cb;
1637 gl_state.color4f[3] = ca;
1638 switch(vid.renderpath)
1640 case RENDERPATH_GL20:
1641 case RENDERPATH_GLES2:
1642 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
1648 void GL_Scissor (int x, int y, int width, int height)
1650 switch(vid.renderpath)
1652 case RENDERPATH_GL20:
1653 case RENDERPATH_GLES2:
1655 qglScissor(x, y,width,height);
1661 void GL_ScissorTest(int state)
1663 if (gl_state.scissortest != state)
1665 gl_state.scissortest = state;
1666 switch(vid.renderpath)
1668 case RENDERPATH_GL20:
1669 case RENDERPATH_GLES2:
1671 if(gl_state.scissortest)
1672 qglEnable(GL_SCISSOR_TEST);
1674 qglDisable(GL_SCISSOR_TEST);
1681 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
1683 // opaque black - if you want transparent black, you'll need to pass in a colorvalue
1684 static const float blackcolor[4] = {0.0f, 0.0f, 0.0f, 1.0f};
1685 // prevent warnings when trying to clear a buffer that does not exist
1687 colorvalue = blackcolor;
1690 mask &= ~GL_STENCIL_BUFFER_BIT;
1693 switch(vid.renderpath)
1695 case RENDERPATH_GL20:
1696 case RENDERPATH_GLES2:
1698 if (mask & GL_COLOR_BUFFER_BIT)
1700 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
1702 if (mask & GL_DEPTH_BUFFER_BIT)
1705 qglClearDepthf(depthvalue);CHECKGLERROR
1707 qglClearDepth(depthvalue);CHECKGLERROR
1710 if (mask & GL_STENCIL_BUFFER_BIT)
1712 qglClearStencil(stencilvalue);CHECKGLERROR
1714 qglClear(mask);CHECKGLERROR
1719 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
1721 switch(vid.renderpath)
1723 case RENDERPATH_GL20:
1724 case RENDERPATH_GLES2:
1733 qglReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
1734 for (i = 0;i < width * height * 4;i += 4)
1737 // g = outpixels[i+1];
1739 // a = outpixels[i+3];
1741 // outpixels[i+1] = g;
1743 // outpixels[i+3] = a;
1747 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
1753 // called at beginning of frame
1754 void R_Mesh_Start(void)
1757 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
1759 if (gl_printcheckerror.integer && !gl_paranoid.integer)
1761 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
1762 Cvar_SetValueQuick(&gl_paranoid, 1);
1766 static qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
1770 char compilelog[MAX_INPUTLINE];
1771 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
1774 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
1775 qglCompileShader(shaderobject);CHECKGLERROR
1776 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
1777 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
1778 if (compilelog[0] && ((strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error")) || ((strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")) && developer.integer) || developer_extra.integer))
1780 int i, j, pretextlines = 0;
1781 for (i = 0;i < numstrings - 1;i++)
1782 for (j = 0;strings[i][j];j++)
1783 if (strings[i][j] == '\n')
1785 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
1787 if (!shadercompiled)
1789 qglDeleteShader(shaderobject);CHECKGLERROR
1792 qglAttachShader(programobject, shaderobject);CHECKGLERROR
1793 qglDeleteShader(shaderobject);CHECKGLERROR
1797 unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **vertexstrings_list, int geometrystrings_count, const char **geometrystrings_list, int fragmentstrings_count, const char **fragmentstrings_list)
1799 GLint programlinked;
1800 GLuint programobject = 0;
1801 char linklog[MAX_INPUTLINE];
1804 programobject = qglCreateProgram();CHECKGLERROR
1808 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
1809 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
1810 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
1811 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
1812 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
1813 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
1814 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
1815 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
1816 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_SkeletalIndex");
1817 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_SkeletalWeight");
1819 if(vid.support.gl20shaders130)
1820 qglBindFragDataLocation(programobject, 0, "dp_FragColor");
1823 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
1826 #if defined(GL_GEOMETRY_SHADER) && !defined(USE_GLES2)
1827 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
1831 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
1834 qglLinkProgram(programobject);CHECKGLERROR
1835 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
1836 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
1841 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning") || developer_extra.integer)
1842 Con_DPrintf("program link log:\n%s\n", linklog);
1844 // software vertex shader is ok but software fragment shader is WAY
1845 // too slow, fail program if so.
1846 // NOTE: this string might be ATI specific, but that's ok because the
1847 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
1848 // software fragment shader due to low instruction and dependent
1850 if (strstr(linklog, "fragment shader will run in software"))
1851 programlinked = false;
1857 return programobject;
1859 qglDeleteProgram(programobject);CHECKGLERROR
1863 void GL_Backend_FreeProgram(unsigned int prog)
1866 qglDeleteProgram(prog);
1870 // renders triangles using vertices from the active arrays
1871 int paranoidblah = 0;
1872 void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, int element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, int element3s_bufferoffset)
1874 unsigned int numelements = numtriangles * 3;
1876 size_t bufferoffset3i;
1878 size_t bufferoffset3s;
1879 if (numvertices < 3 || numtriangles < 1)
1881 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
1882 Con_DPrintf("R_Mesh_Draw(%d, %d, %d, %d, %8p, %8p, %8x, %8p, %8p, %8x);\n", firstvertex, numvertices, firsttriangle, numtriangles, (void *)element3i, (void *)element3i_indexbuffer, (int)element3i_bufferoffset, (void *)element3s, (void *)element3s_indexbuffer, (int)element3s_bufferoffset);
1885 // adjust the pointers for firsttriangle
1887 element3i += firsttriangle * 3;
1888 if (element3i_indexbuffer)
1889 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
1891 element3s += firsttriangle * 3;
1892 if (element3s_indexbuffer)
1893 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
1894 switch(vid.renderpath)
1896 case RENDERPATH_GL20:
1897 case RENDERPATH_GLES2:
1898 // check if the user specified to ignore static index buffers
1899 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
1901 element3i_indexbuffer = NULL;
1902 element3s_indexbuffer = NULL;
1906 // upload a dynamic index buffer if needed
1909 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
1910 element3s_indexbuffer = R_BufferData_Store(numelements * sizeof(*element3s), (void *)element3s, R_BUFFERDATA_INDEX16, &element3s_bufferoffset);
1914 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
1915 element3i_indexbuffer = R_BufferData_Store(numelements * sizeof(*element3i), (void *)element3i, R_BUFFERDATA_INDEX32, &element3i_bufferoffset);
1917 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
1918 bufferoffset3i = element3i_bufferoffset;
1919 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
1920 bufferoffset3s = element3s_bufferoffset;
1921 r_refdef.stats[r_stat_draws]++;
1922 r_refdef.stats[r_stat_draws_vertices] += numvertices;
1923 r_refdef.stats[r_stat_draws_elements] += numelements;
1924 if (gl_paranoid.integer)
1927 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
1929 unsigned int j, size;
1931 // note: there's no validation done here on buffer objects because it
1932 // is somewhat difficult to get at the data, and gl_paranoid can be
1933 // used without buffer objects if the need arises
1934 // (the data could be gotten using glMapBuffer but it would be very
1935 // slow due to uncachable video memory reads)
1936 if (!qglIsEnabled(GL_VERTEX_ARRAY))
1937 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
1939 if (gl_state.pointer_vertex_pointer)
1940 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
1942 if (gl_state.pointer_color_enabled)
1944 if (!qglIsEnabled(GL_COLOR_ARRAY))
1945 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
1947 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
1948 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
1951 for (i = 0;i < vid.texarrayunits;i++)
1953 if (gl_state.units[i].arrayenabled)
1955 GL_ClientActiveTexture(i);
1956 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
1957 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
1959 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
1960 for (j = 0, size = numvertices * gl_state.units[i].arraycomponents, p = (int *)((float *)gl_state.units[i].pointer_texcoord + firstvertex * gl_state.units[i].arraycomponents);j < size;j++, p++)
1967 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
1969 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
1971 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
1978 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
1980 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
1982 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
1988 if (r_render.integer || r_refdef.draw2dstage)
1990 switch(vid.renderpath)
1992 case RENDERPATH_GL20:
1996 GL_BindEBO(bufferobject3s);
1998 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2000 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2006 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2010 else if (bufferobject3i)
2012 GL_BindEBO(bufferobject3i);
2014 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2016 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2022 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2030 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2032 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2038 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2046 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2048 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2054 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2060 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2064 case RENDERPATH_GLES2:
2065 // GLES does not have glDrawRangeElements so this is a bit shorter than the GL20 path
2068 GL_BindEBO(bufferobject3s);
2069 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2072 else if (bufferobject3i)
2074 GL_BindEBO(bufferobject3i);
2075 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2081 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2087 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2092 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2100 // restores backend state, used when done with 3D rendering
2101 void R_Mesh_Finish(void)
2103 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
2106 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isuniformbuffer, qboolean isdynamic, qboolean isindex16)
2108 r_meshbuffer_t *buffer;
2109 if (isuniformbuffer)
2111 if (!vid.support.arb_uniform_buffer_object)
2116 if (!vid.support.arb_vertex_buffer_object)
2118 if (!isdynamic && !(isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex))
2121 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2122 memset(buffer, 0, sizeof(*buffer));
2123 buffer->bufferobject = 0;
2124 buffer->devicebuffer = NULL;
2125 buffer->size = size;
2126 buffer->isindexbuffer = isindexbuffer;
2127 buffer->isuniformbuffer = isuniformbuffer;
2128 buffer->isdynamic = isdynamic;
2129 buffer->isindex16 = isindex16;
2130 strlcpy(buffer->name, name, sizeof(buffer->name));
2131 R_Mesh_UpdateMeshBuffer(buffer, data, size, false, 0);
2135 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size, qboolean subdata, size_t offset)
2139 if (buffer->isindexbuffer)
2141 r_refdef.stats[r_stat_indexbufferuploadcount]++;
2142 r_refdef.stats[r_stat_indexbufferuploadsize] += (int)size;
2146 r_refdef.stats[r_stat_vertexbufferuploadcount]++;
2147 r_refdef.stats[r_stat_vertexbufferuploadsize] += (int)size;
2150 buffer->size = size;
2151 switch(vid.renderpath)
2153 case RENDERPATH_GL20:
2154 case RENDERPATH_GLES2:
2155 if (!buffer->bufferobject)
2156 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
2157 if (buffer->isuniformbuffer)
2158 GL_BindUBO(buffer->bufferobject);
2159 else if (buffer->isindexbuffer)
2160 GL_BindEBO(buffer->bufferobject);
2162 GL_BindVBO(buffer->bufferobject);
2166 buffertype = buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER;
2167 #ifdef GL_UNIFORM_BUFFER
2168 if (buffer->isuniformbuffer)
2169 buffertype = GL_UNIFORM_BUFFER;
2172 qglBufferSubDataARB(buffertype, offset, size, data);
2174 qglBufferDataARB(buffertype, size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW);
2176 if (buffer->isuniformbuffer)
2182 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
2186 switch(vid.renderpath)
2188 case RENDERPATH_GL20:
2189 case RENDERPATH_GLES2:
2190 // GL clears the binding if we delete something bound
2191 if (gl_state.uniformbufferobject == buffer->bufferobject)
2192 gl_state.uniformbufferobject = 0;
2193 if (gl_state.vertexbufferobject == buffer->bufferobject)
2194 gl_state.vertexbufferobject = 0;
2195 if (gl_state.elementbufferobject == buffer->bufferobject)
2196 gl_state.elementbufferobject = 0;
2197 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
2200 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
2203 static const char *buffertypename[R_BUFFERDATA_COUNT] = {"vertex", "index16", "index32", "uniform"};
2204 void GL_Mesh_ListVBOs(qboolean printeach)
2209 int index16count, index16mem;
2210 int index32count, index32mem;
2211 int vertexcount, vertexmem;
2212 int uniformcount, uniformmem;
2213 int totalcount, totalmem;
2214 size_t bufferstat[R_BUFFERDATA_COUNT][2][2];
2215 r_meshbuffer_t *buffer;
2216 memset(bufferstat, 0, sizeof(bufferstat));
2217 endindex = (int)Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
2218 for (i = 0;i < endindex;i++)
2220 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
2223 if (buffer->isuniformbuffer)
2224 type = R_BUFFERDATA_UNIFORM;
2225 else if (buffer->isindexbuffer && buffer->isindex16)
2226 type = R_BUFFERDATA_INDEX16;
2227 else if (buffer->isindexbuffer)
2228 type = R_BUFFERDATA_INDEX32;
2230 type = R_BUFFERDATA_VERTEX;
2231 isdynamic = buffer->isdynamic;
2232 bufferstat[type][isdynamic][0]++;
2233 bufferstat[type][isdynamic][1] += buffer->size;
2235 Con_Printf("buffer #%i %s = %i bytes (%s %s)\n", i, buffer->name, (int)buffer->size, isdynamic ? "dynamic" : "static", buffertypename[type]);
2237 index16count = (int)(bufferstat[R_BUFFERDATA_INDEX16][0][0] + bufferstat[R_BUFFERDATA_INDEX16][1][0]);
2238 index16mem = (int)(bufferstat[R_BUFFERDATA_INDEX16][0][1] + bufferstat[R_BUFFERDATA_INDEX16][1][1]);
2239 index32count = (int)(bufferstat[R_BUFFERDATA_INDEX32][0][0] + bufferstat[R_BUFFERDATA_INDEX32][1][0]);
2240 index32mem = (int)(bufferstat[R_BUFFERDATA_INDEX32][0][1] + bufferstat[R_BUFFERDATA_INDEX32][1][1]);
2241 vertexcount = (int)(bufferstat[R_BUFFERDATA_VERTEX ][0][0] + bufferstat[R_BUFFERDATA_VERTEX ][1][0]);
2242 vertexmem = (int)(bufferstat[R_BUFFERDATA_VERTEX ][0][1] + bufferstat[R_BUFFERDATA_VERTEX ][1][1]);
2243 uniformcount = (int)(bufferstat[R_BUFFERDATA_UNIFORM][0][0] + bufferstat[R_BUFFERDATA_UNIFORM][1][0]);
2244 uniformmem = (int)(bufferstat[R_BUFFERDATA_UNIFORM][0][1] + bufferstat[R_BUFFERDATA_UNIFORM][1][1]);
2245 totalcount = index16count + index32count + vertexcount + uniformcount;
2246 totalmem = index16mem + index32mem + vertexmem + uniformmem;
2247 Con_Printf("%i 16bit indexbuffers totalling %i bytes (%.3f MB)\n%i 32bit indexbuffers totalling %i bytes (%.3f MB)\n%i vertexbuffers totalling %i bytes (%.3f MB)\n%i uniformbuffers totalling %i bytes (%.3f MB)\ncombined %i buffers totalling %i bytes (%.3fMB)\n", index16count, index16mem, index16mem / 10248576.0, index32count, index32mem, index32mem / 10248576.0, vertexcount, vertexmem, vertexmem / 10248576.0, uniformcount, uniformmem, uniformmem / 10248576.0, totalcount, totalmem, totalmem / 10248576.0);
2252 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
2254 switch(vid.renderpath)
2256 case RENDERPATH_GL20:
2257 case RENDERPATH_GLES2:
2258 if (gl_state.pointer_vertex_components != components || gl_state.pointer_vertex_gltype != gltype || gl_state.pointer_vertex_stride != stride || gl_state.pointer_vertex_pointer != pointer || gl_state.pointer_vertex_vertexbuffer != vertexbuffer || gl_state.pointer_vertex_offset != bufferoffset)
2260 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2261 gl_state.pointer_vertex_components = components;
2262 gl_state.pointer_vertex_gltype = gltype;
2263 gl_state.pointer_vertex_stride = stride;
2264 gl_state.pointer_vertex_pointer = pointer;
2265 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
2266 gl_state.pointer_vertex_offset = bufferoffset;
2268 GL_BindVBO(bufferobject);
2269 // LordHavoc: special flag added to gltype for unnormalized types
2270 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2276 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
2278 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
2279 // the pointer only.
2280 switch(vid.renderpath)
2282 case RENDERPATH_GL20:
2283 case RENDERPATH_GLES2:
2287 // caller wants color array enabled
2288 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2289 if (!gl_state.pointer_color_enabled)
2291 gl_state.pointer_color_enabled = true;
2293 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
2295 if (gl_state.pointer_color_components != components || gl_state.pointer_color_gltype != gltype || gl_state.pointer_color_stride != stride || gl_state.pointer_color_pointer != pointer || gl_state.pointer_color_vertexbuffer != vertexbuffer || gl_state.pointer_color_offset != bufferoffset)
2297 gl_state.pointer_color_components = components;
2298 gl_state.pointer_color_gltype = gltype;
2299 gl_state.pointer_color_stride = stride;
2300 gl_state.pointer_color_pointer = pointer;
2301 gl_state.pointer_color_vertexbuffer = vertexbuffer;
2302 gl_state.pointer_color_offset = bufferoffset;
2304 GL_BindVBO(bufferobject);
2305 // LordHavoc: special flag added to gltype for unnormalized types
2306 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2311 // caller wants color array disabled
2312 if (gl_state.pointer_color_enabled)
2314 gl_state.pointer_color_enabled = false;
2316 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
2317 // when color array is on the current color gets trashed, set it again
2318 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
2325 void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
2327 gltextureunit_t *unit = gl_state.units + unitnum;
2328 // update array settings
2329 // note: there is no need to check bufferobject here because all cases
2330 // that involve a valid bufferobject also supply a texcoord array
2331 switch(vid.renderpath)
2333 case RENDERPATH_GL20:
2334 case RENDERPATH_GLES2:
2338 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2339 // texture array unit is enabled, enable the array
2340 if (!unit->arrayenabled)
2342 unit->arrayenabled = true;
2343 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
2346 if (unit->pointer_texcoord_components != components || unit->pointer_texcoord_gltype != gltype || unit->pointer_texcoord_stride != stride || unit->pointer_texcoord_pointer != pointer || unit->pointer_texcoord_vertexbuffer != vertexbuffer || unit->pointer_texcoord_offset != bufferoffset)
2348 unit->pointer_texcoord_components = components;
2349 unit->pointer_texcoord_gltype = gltype;
2350 unit->pointer_texcoord_stride = stride;
2351 unit->pointer_texcoord_pointer = pointer;
2352 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
2353 unit->pointer_texcoord_offset = bufferoffset;
2354 GL_BindVBO(bufferobject);
2355 // LordHavoc: special flag added to gltype for unnormalized types
2356 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2361 // texture array unit is disabled, disable the array
2362 if (unit->arrayenabled)
2364 unit->arrayenabled = false;
2365 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
2372 int R_Mesh_TexBound(unsigned int unitnum, int id)
2374 gltextureunit_t *unit = gl_state.units + unitnum;
2375 if (unitnum >= vid.teximageunits)
2377 if (id == GL_TEXTURE_2D)
2379 if (id == GL_TEXTURE_3D)
2381 if (id == GL_TEXTURE_CUBE_MAP)
2382 return unit->tcubemap;
2386 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
2388 switch(vid.renderpath)
2390 case RENDERPATH_GL20:
2391 case RENDERPATH_GLES2:
2392 R_Mesh_TexBind(0, tex);
2393 GL_ActiveTexture(0);CHECKGLERROR
2394 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
2399 void R_Mesh_ClearBindingsForTexture(int texnum)
2401 gltextureunit_t *unit;
2402 unsigned int unitnum;
2403 // this doesn't really unbind the texture, but it does prevent a mistaken "do nothing" behavior on the next time this same texnum is bound on the same unit as the same type (this mainly affects r_shadow_bouncegrid because 3D textures are so rarely used)
2404 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
2406 unit = gl_state.units + unitnum;
2407 if (unit->t2d == texnum)
2409 if (unit->t3d == texnum)
2411 if (unit->tcubemap == texnum)
2412 unit->tcubemap = -1;
2416 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
2418 gltextureunit_t *unit = gl_state.units + unitnum;
2420 if (unitnum >= vid.teximageunits)
2422 if (unit->texture == tex)
2424 switch(vid.renderpath)
2426 case RENDERPATH_GL20:
2427 case RENDERPATH_GLES2:
2430 tex = r_texture_white;
2431 // not initialized enough yet...
2435 unit->texture = tex;
2436 texnum = R_GetTexture(tex);
2437 switch(tex->gltexturetypeenum)
2439 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
2440 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
2441 case GL_TEXTURE_CUBE_MAP: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP, unit->tcubemap);CHECKGLERROR}break;
2447 void R_Mesh_ResetTextureState(void)
2449 unsigned int unitnum;
2453 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
2454 R_Mesh_TexBind(unitnum, NULL);
2455 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
2456 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2461 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer, int bufferoffset)
2463 // upload temporary vertexbuffer for this rendering
2464 if (!gl_state.usevbo_staticvertex)
2465 vertexbuffer = NULL;
2466 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
2467 vertexbuffer = R_BufferData_Store(numvertices * sizeof(float[3]), (void *)vertex3f, R_BUFFERDATA_VERTEX, &bufferoffset);
2468 switch(vid.renderpath)
2470 case RENDERPATH_GL20:
2471 case RENDERPATH_GLES2:
2474 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, bufferoffset);
2475 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
2476 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2477 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2478 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2479 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2480 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2481 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2482 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2483 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2487 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
2488 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
2489 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2490 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2491 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2492 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2493 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2494 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2495 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2496 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2504 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
2507 size = sizeof(r_vertexgeneric_t) * numvertices;
2508 if (gl_state.preparevertices_tempdatamaxsize < size)
2510 gl_state.preparevertices_tempdatamaxsize = size;
2511 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
2513 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
2514 gl_state.preparevertices_numvertices = numvertices;
2515 return gl_state.preparevertices_vertexgeneric;
2518 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
2520 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL, 0);
2521 gl_state.preparevertices_vertexgeneric = NULL;
2522 gl_state.preparevertices_numvertices = 0;
2526 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
2529 r_vertexgeneric_t *vertex;
2530 switch(vid.renderpath)
2532 case RENDERPATH_GL20:
2533 case RENDERPATH_GLES2:
2534 if (gl_state.usevbo_dynamicvertex)
2536 r_meshbuffer_t *buffer_vertex3f = NULL;
2537 r_meshbuffer_t *buffer_color4f = NULL;
2538 r_meshbuffer_t *buffer_texcoord2f = NULL;
2539 int bufferoffset_vertex3f = 0;
2540 int bufferoffset_color4f = 0;
2541 int bufferoffset_texcoord2f = 0;
2542 buffer_color4f = R_BufferData_Store(numvertices * sizeof(float[4]), color4f , R_BUFFERDATA_VERTEX, &bufferoffset_color4f );
2543 buffer_vertex3f = R_BufferData_Store(numvertices * sizeof(float[3]), vertex3f , R_BUFFERDATA_VERTEX, &bufferoffset_vertex3f );
2544 buffer_texcoord2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoord2f, R_BUFFERDATA_VERTEX, &bufferoffset_texcoord2f);
2545 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(float[3]) , vertex3f , buffer_vertex3f , bufferoffset_vertex3f );
2546 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(float[4]) , color4f , buffer_color4f , bufferoffset_color4f );
2547 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(float[2]) , texcoord2f , buffer_texcoord2f , bufferoffset_texcoord2f );
2548 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 );
2549 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 );
2550 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 );
2551 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 );
2552 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 );
2553 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 );
2554 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 );
2556 else if (!vid.useinterleavedarrays)
2558 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
2559 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
2560 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
2561 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2562 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2563 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2564 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2565 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2566 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2567 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2573 // no quick path for this case, convert to vertex structs
2574 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
2575 for (i = 0;i < numvertices;i++)
2576 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
2579 for (i = 0;i < numvertices;i++)
2580 Vector4Copy(color4f + 4*i, vertex[i].color4f);
2584 for (i = 0;i < numvertices;i++)
2585 Vector4Copy(gl_state.color4f, vertex[i].color4f);
2588 for (i = 0;i < numvertices;i++)
2589 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
2590 R_Mesh_PrepareVertices_Generic_Unlock();
2591 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL, 0);
2594 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer, int bufferoffset)
2596 // upload temporary vertexbuffer for this rendering
2597 if (!gl_state.usevbo_staticvertex)
2598 vertexbuffer = NULL;
2599 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
2600 vertexbuffer = R_BufferData_Store(numvertices * sizeof(*vertex), (void *)vertex, R_BUFFERDATA_VERTEX, &bufferoffset);
2601 switch(vid.renderpath)
2603 case RENDERPATH_GL20:
2604 case RENDERPATH_GLES2:
2607 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
2608 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
2609 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
2610 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2611 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2612 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2613 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2614 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2615 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2616 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2620 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
2621 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
2622 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
2623 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2624 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2625 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2626 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2627 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2628 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2629 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2637 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
2640 size = sizeof(r_vertexmesh_t) * numvertices;
2641 if (gl_state.preparevertices_tempdatamaxsize < size)
2643 gl_state.preparevertices_tempdatamaxsize = size;
2644 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
2646 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
2647 gl_state.preparevertices_numvertices = numvertices;
2648 return gl_state.preparevertices_vertexmesh;
2651 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
2653 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL, 0);
2654 gl_state.preparevertices_vertexmesh = NULL;
2655 gl_state.preparevertices_numvertices = 0;
2659 void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f, const float *svector3f, const float *tvector3f, const float *normal3f, const float *color4f, const float *texcoordtexture2f, const float *texcoordlightmap2f)
2662 r_vertexmesh_t *vertex;
2663 switch(vid.renderpath)
2665 case RENDERPATH_GL20:
2666 case RENDERPATH_GLES2:
2667 if (gl_state.usevbo_dynamicvertex)
2669 r_meshbuffer_t *buffer_vertex3f = NULL;
2670 r_meshbuffer_t *buffer_color4f = NULL;
2671 r_meshbuffer_t *buffer_texcoordtexture2f = NULL;
2672 r_meshbuffer_t *buffer_svector3f = NULL;
2673 r_meshbuffer_t *buffer_tvector3f = NULL;
2674 r_meshbuffer_t *buffer_normal3f = NULL;
2675 r_meshbuffer_t *buffer_texcoordlightmap2f = NULL;
2676 int bufferoffset_vertex3f = 0;
2677 int bufferoffset_color4f = 0;
2678 int bufferoffset_texcoordtexture2f = 0;
2679 int bufferoffset_svector3f = 0;
2680 int bufferoffset_tvector3f = 0;
2681 int bufferoffset_normal3f = 0;
2682 int bufferoffset_texcoordlightmap2f = 0;
2683 buffer_color4f = R_BufferData_Store(numvertices * sizeof(float[4]), color4f , R_BUFFERDATA_VERTEX, &bufferoffset_color4f );
2684 buffer_vertex3f = R_BufferData_Store(numvertices * sizeof(float[3]), vertex3f , R_BUFFERDATA_VERTEX, &bufferoffset_vertex3f );
2685 buffer_svector3f = R_BufferData_Store(numvertices * sizeof(float[3]), svector3f , R_BUFFERDATA_VERTEX, &bufferoffset_svector3f );
2686 buffer_tvector3f = R_BufferData_Store(numvertices * sizeof(float[3]), tvector3f , R_BUFFERDATA_VERTEX, &bufferoffset_tvector3f );
2687 buffer_normal3f = R_BufferData_Store(numvertices * sizeof(float[3]), normal3f , R_BUFFERDATA_VERTEX, &bufferoffset_normal3f );
2688 buffer_texcoordtexture2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoordtexture2f , R_BUFFERDATA_VERTEX, &bufferoffset_texcoordtexture2f );
2689 buffer_texcoordlightmap2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoordlightmap2f, R_BUFFERDATA_VERTEX, &bufferoffset_texcoordlightmap2f);
2690 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(float[3]) , vertex3f , buffer_vertex3f , bufferoffset_vertex3f );
2691 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(float[4]) , color4f , buffer_color4f , bufferoffset_color4f );
2692 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(float[2]) , texcoordtexture2f , buffer_texcoordtexture2f , bufferoffset_texcoordtexture2f );
2693 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(float[3]) , svector3f , buffer_svector3f , bufferoffset_svector3f );
2694 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(float[3]) , tvector3f , buffer_tvector3f , bufferoffset_tvector3f );
2695 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(float[3]) , normal3f , buffer_normal3f , bufferoffset_normal3f );
2696 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(float[2]) , texcoordlightmap2f, buffer_texcoordlightmap2f, bufferoffset_texcoordlightmap2f);
2697 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 );
2698 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 );
2699 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 );
2701 else if (!vid.useinterleavedarrays)
2703 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
2704 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
2705 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
2706 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
2707 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
2708 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
2709 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
2710 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2711 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2712 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0);
2718 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
2719 for (i = 0;i < numvertices;i++)
2720 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
2722 for (i = 0;i < numvertices;i++)
2723 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
2725 for (i = 0;i < numvertices;i++)
2726 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
2728 for (i = 0;i < numvertices;i++)
2729 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
2732 for (i = 0;i < numvertices;i++)
2733 Vector4Copy(color4f + 4*i, vertex[i].color4f);
2737 for (i = 0;i < numvertices;i++)
2738 Vector4Copy(gl_state.color4f, vertex[i].color4f);
2740 if (texcoordtexture2f)
2741 for (i = 0;i < numvertices;i++)
2742 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
2743 if (texcoordlightmap2f)
2744 for (i = 0;i < numvertices;i++)
2745 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
2746 R_Mesh_PrepareVertices_Mesh_Unlock();
2747 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL, 0);
2750 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer, int bufferoffset)
2752 // upload temporary vertexbuffer for this rendering
2753 if (!gl_state.usevbo_staticvertex)
2754 vertexbuffer = NULL;
2755 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
2756 vertexbuffer = R_BufferData_Store(numvertices * sizeof(*vertex), (void *)vertex, R_BUFFERDATA_VERTEX, &bufferoffset);
2757 switch(vid.renderpath)
2759 case RENDERPATH_GL20:
2760 case RENDERPATH_GLES2:
2763 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
2764 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex));
2765 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
2766 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
2767 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
2768 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
2769 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
2770 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(*vertex), NULL, NULL, 0);
2771 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(*vertex), vertex->skeletalindex4ub , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->skeletalindex4ub - (unsigned char *)vertex));
2772 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->skeletalweight4ub , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->skeletalweight4ub - (unsigned char *)vertex));
2776 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
2777 R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , NULL, 0);
2778 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
2779 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
2780 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
2781 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
2782 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
2783 R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(*vertex), NULL, NULL, 0);
2784 R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(*vertex), vertex->skeletalindex4ub , NULL, 0);
2785 R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->skeletalweight4ub , NULL, 0);
2791 void GL_BlendEquationSubtract(qboolean negated)
2795 switch(vid.renderpath)
2797 case RENDERPATH_GL20:
2798 case RENDERPATH_GLES2:
2799 qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT);
2805 switch(vid.renderpath)
2807 case RENDERPATH_GL20:
2808 case RENDERPATH_GLES2:
2809 qglBlendEquationEXT(GL_FUNC_ADD);