3 #include "cl_collision.h"
5 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
6 cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
7 cvar_t gl_mesh_prefer_short_elements = {CVAR_SAVE, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"};
8 cvar_t gl_mesh_separatearrays = {0, "gl_mesh_separatearrays", "1", "use several separate vertex arrays rather than one combined stream"};
9 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
10 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
12 cvar_t r_render = {0, "r_render", "1", "enables rendering 3D views (you want this on!)"};
13 cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
14 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
15 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
16 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
17 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)"};
18 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"};
19 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"};
20 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"};
22 cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
23 qboolean v_flipped_state = false;
25 r_viewport_t gl_viewport;
26 matrix4x4_t gl_modelmatrix;
27 matrix4x4_t gl_viewmatrix;
28 matrix4x4_t gl_modelviewmatrix;
29 matrix4x4_t gl_projectionmatrix;
30 matrix4x4_t gl_modelviewprojectionmatrix;
31 float gl_modelview16f[16];
32 float gl_modelviewprojection16f[16];
33 qboolean gl_modelmatrixchanged;
35 int gl_maxdrawrangeelementsvertices;
36 int gl_maxdrawrangeelementsindices;
41 void GL_PrintError(int errornumber, char *filename, int linenumber)
45 #ifdef GL_INVALID_ENUM
47 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
50 #ifdef GL_INVALID_VALUE
51 case GL_INVALID_VALUE:
52 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
55 #ifdef GL_INVALID_OPERATION
56 case GL_INVALID_OPERATION:
57 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
60 #ifdef GL_STACK_OVERFLOW
61 case GL_STACK_OVERFLOW:
62 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
65 #ifdef GL_STACK_UNDERFLOW
66 case GL_STACK_UNDERFLOW:
67 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
70 #ifdef GL_OUT_OF_MEMORY
71 case GL_OUT_OF_MEMORY:
72 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
75 #ifdef GL_TABLE_TOO_LARGE
76 case GL_TABLE_TOO_LARGE:
77 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
80 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
81 case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
82 Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
86 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
92 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
94 void SCR_ScreenShot_f (void);
96 typedef struct gltextureunit_s
98 int pointer_texcoord_components;
99 int pointer_texcoord_gltype;
100 size_t pointer_texcoord_stride;
101 const void *pointer_texcoord_pointer;
102 const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
103 size_t pointer_texcoord_offset;
105 int t2d, t3d, tcubemap, trectangle;
107 int rgbscale, alphascale;
109 int combinergb, combinealpha;
110 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
111 int texmatrixenabled;
116 typedef struct gl_state_s
124 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
127 float polygonoffset[2];
131 unsigned int clientunit;
132 gltextureunit_t units[MAX_TEXTUREUNITS];
136 int vertexbufferobject;
137 int elementbufferobject;
138 qboolean pointer_color_enabled;
140 int pointer_vertex_components;
141 int pointer_vertex_gltype;
142 size_t pointer_vertex_stride;
143 const void *pointer_vertex_pointer;
144 const r_meshbuffer_t *pointer_vertex_vertexbuffer;
145 size_t pointer_vertex_offset;
147 int pointer_color_components;
148 int pointer_color_gltype;
149 size_t pointer_color_stride;
150 const void *pointer_color_pointer;
151 const r_meshbuffer_t *pointer_color_vertexbuffer;
152 size_t pointer_color_offset;
154 void *preparevertices_tempdata;
155 size_t preparevertices_tempdatamaxsize;
156 r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
157 r_vertexposition_t *preparevertices_vertexposition;
158 r_vertexgeneric_t *preparevertices_vertexgeneric;
159 r_vertexmesh_t *preparevertices_vertexmesh;
160 int preparevertices_numvertices;
162 r_meshbuffer_t *draw_dynamicindexbuffer;
164 qboolean usevbo_staticvertex;
165 qboolean usevbo_staticindex;
166 qboolean usevbo_dynamicvertex;
167 qboolean usevbo_dynamicindex;
169 memexpandablearray_t meshbufferarray;
175 static gl_state_t gl_state;
179 note: here's strip order for a terrain row:
186 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
188 *elements++ = i + row;
190 *elements++ = i + row + 1;
193 *elements++ = i + row + 1;
196 for (y = 0;y < rows - 1;y++)
198 for (x = 0;x < columns - 1;x++)
201 *elements++ = i + columns;
203 *elements++ = i + columns + 1;
206 *elements++ = i + columns + 1;
217 for (y = 0;y < rows - 1;y++)
219 for (x = 0;x < columns - 1;x++)
223 *elements++ = i + columns;
224 *elements++ = i + columns + 1;
225 *elements++ = i + columns;
226 *elements++ = i + columns + 1;
232 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
233 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
234 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
235 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
237 void GL_VBOStats_f(void)
239 GL_Mesh_ListVBOs(true);
242 static void GL_Backend_ResetState(void);
244 static void gl_backend_start(void)
246 memset(&gl_state, 0, sizeof(gl_state));
248 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
249 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
250 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
251 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
252 Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
254 Con_DPrintf("OpenGL backend started.\n");
258 GL_Backend_ResetState();
261 static void gl_backend_shutdown(void)
263 Con_DPrint("OpenGL Backend shutting down\n");
265 if (gl_state.preparevertices_tempdata)
266 Mem_Free(gl_state.preparevertices_tempdata);
267 if (gl_state.preparevertices_dynamicvertexbuffer)
268 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
270 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
272 memset(&gl_state, 0, sizeof(gl_state));
275 static void gl_backend_newmap(void)
279 void gl_backend_init(void)
283 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
285 polygonelement3s[i * 3 + 0] = 0;
286 polygonelement3s[i * 3 + 1] = i + 1;
287 polygonelement3s[i * 3 + 2] = i + 2;
289 // elements for rendering a series of quads as triangles
290 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
292 quadelement3s[i * 6 + 0] = i * 4;
293 quadelement3s[i * 6 + 1] = i * 4 + 1;
294 quadelement3s[i * 6 + 2] = i * 4 + 2;
295 quadelement3s[i * 6 + 3] = i * 4;
296 quadelement3s[i * 6 + 4] = i * 4 + 2;
297 quadelement3s[i * 6 + 5] = i * 4 + 3;
300 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
301 polygonelement3i[i] = polygonelement3s[i];
302 for (i = 0;i < QUADELEMENTS_MAXQUADS*3;i++)
303 quadelement3i[i] = quadelement3s[i];
305 Cvar_RegisterVariable(&r_render);
306 Cvar_RegisterVariable(&r_renderview);
307 Cvar_RegisterVariable(&r_waterwarp);
308 Cvar_RegisterVariable(&gl_polyblend);
309 Cvar_RegisterVariable(&v_flipped);
310 Cvar_RegisterVariable(&gl_dither);
311 Cvar_RegisterVariable(&gl_vbo);
312 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
313 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
314 Cvar_RegisterVariable(&gl_paranoid);
315 Cvar_RegisterVariable(&gl_printcheckerror);
317 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
318 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
319 Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
320 Cvar_RegisterVariable(&gl_mesh_separatearrays);
322 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");
324 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap);
327 void GL_SetMirrorState(qboolean state);
329 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
333 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
334 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
336 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
337 out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
338 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
341 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
345 float clipPlane[4], v3[3], v4[3];
348 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
350 VectorSet(normal, normalx, normaly, normalz);
351 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
352 VectorScale(normal, dist, v3);
353 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
354 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
355 clipPlane[3] = -DotProduct(v4, clipPlane);
359 // testing code for comparing results
361 VectorCopy4(clipPlane, clipPlane2);
362 R_EntityMatrix(&identitymatrix);
363 VectorSet(q, normal[0], normal[1], normal[2], -dist);
364 qglClipPlane(GL_CLIP_PLANE0, q);
365 qglGetClipPlane(GL_CLIP_PLANE0, q);
366 VectorCopy4(q, clipPlane);
370 // Calculate the clip-space corner point opposite the clipping plane
371 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
372 // transform it into camera space by multiplying it
373 // by the inverse of the projection matrix
374 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
375 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
377 q[3] = (1.0f + m[10]) / m[14];
379 // Calculate the scaled plane vector
380 d = 2.0f / DotProduct4(clipPlane, q);
382 // Replace the third row of the projection matrix
383 m[2] = clipPlane[0] * d;
384 m[6] = clipPlane[1] * d;
385 m[10] = clipPlane[2] * d + 1.0f;
386 m[14] = clipPlane[3] * d;
389 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)
391 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
393 memset(v, 0, sizeof(*v));
394 v->type = R_VIEWPORTTYPE_ORTHO;
395 v->cameramatrix = *cameramatrix;
402 memset(m, 0, sizeof(m));
403 m[0] = 2/(right - left);
404 m[5] = 2/(top - bottom);
405 m[10] = -2/(zFar - zNear);
406 m[12] = - (right + left)/(right - left);
407 m[13] = - (top + bottom)/(top - bottom);
408 m[14] = - (zFar + zNear)/(zFar - zNear);
410 v->screentodepth[0] = -farclip / (farclip - nearclip);
411 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
413 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
416 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
418 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
424 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
425 R_Viewport_TransformToScreen(v, test1, test2);
426 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
431 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)
433 matrix4x4_t tempmatrix, basematrix;
435 memset(v, 0, sizeof(*v));
437 if(v_flipped.integer)
438 frustumx = -frustumx;
440 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
441 v->cameramatrix = *cameramatrix;
448 memset(m, 0, sizeof(m));
449 m[0] = 1.0 / frustumx;
450 m[5] = 1.0 / frustumy;
451 m[10] = -(farclip + nearclip) / (farclip - nearclip);
453 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
454 v->screentodepth[0] = -farclip / (farclip - nearclip);
455 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
457 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
458 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
459 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
460 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
463 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
465 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
468 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)
470 matrix4x4_t tempmatrix, basematrix;
471 const float nudge = 1.0 - 1.0 / (1<<23);
473 memset(v, 0, sizeof(*v));
475 if(v_flipped.integer)
476 frustumx = -frustumx;
478 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
479 v->cameramatrix = *cameramatrix;
486 memset(m, 0, sizeof(m));
487 m[ 0] = 1.0 / frustumx;
488 m[ 5] = 1.0 / frustumy;
491 m[14] = -2 * nearclip * nudge;
492 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
493 v->screentodepth[1] = m[14] * -0.5;
495 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
496 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
497 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
498 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
501 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
503 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
506 float cubeviewmatrix[6][16] =
508 // standard cubemap projections
546 float rectviewmatrix[6][16] =
548 // sign-preserving cubemap projections
587 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
589 matrix4x4_t tempmatrix, basematrix;
591 memset(v, 0, sizeof(*v));
592 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
593 v->cameramatrix = *cameramatrix;
597 memset(m, 0, sizeof(m));
599 m[10] = -(farclip + nearclip) / (farclip - nearclip);
601 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
603 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
604 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
605 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
608 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
610 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
613 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)
615 matrix4x4_t tempmatrix, basematrix;
617 memset(v, 0, sizeof(*v));
618 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
619 v->cameramatrix = *cameramatrix;
620 v->x = (side & 1) * size;
621 v->y = (side >> 1) * size;
625 memset(m, 0, sizeof(m));
626 m[0] = m[5] = 1.0f * ((float)size - border) / size;
627 m[10] = -(farclip + nearclip) / (farclip - nearclip);
629 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
631 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
632 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
633 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
636 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
638 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
641 void R_SetViewport(const r_viewport_t *v)
647 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
649 // FIXME: v_flipped_state is evil, this probably breaks somewhere
650 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
652 // copy over the matrices to our state
653 gl_viewmatrix = v->viewmatrix;
654 gl_projectionmatrix = v->projectmatrix;
656 switch(vid.renderpath)
658 case RENDERPATH_GL20:
659 case RENDERPATH_CGGL:
661 case RENDERPATH_GL13:
662 case RENDERPATH_GL11:
663 // Load the projection matrix into OpenGL
664 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
665 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
666 qglLoadMatrixf(m);CHECKGLERROR
667 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
671 // force an update of the derived matrices
672 gl_modelmatrixchanged = true;
673 R_EntityMatrix(&gl_modelmatrix);
676 void R_GetViewport(r_viewport_t *v)
681 static void GL_BindVBO(int bufferobject)
683 if (gl_state.vertexbufferobject != bufferobject)
685 gl_state.vertexbufferobject = bufferobject;
687 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);
692 static void GL_BindEBO(int bufferobject)
694 if (gl_state.elementbufferobject != bufferobject)
696 gl_state.elementbufferobject = bufferobject;
698 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);
703 static void GL_Backend_ResetState(void)
706 gl_state.active = true;
707 gl_state.depthtest = true;
708 gl_state.alphatest = false;
709 gl_state.blendfunc1 = GL_ONE;
710 gl_state.blendfunc2 = GL_ZERO;
711 gl_state.blend = false;
712 gl_state.depthmask = GL_TRUE;
713 gl_state.colormask = 15;
714 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
715 gl_state.lockrange_first = 0;
716 gl_state.lockrange_count = 0;
717 gl_state.cullface = v_flipped_state ? GL_BACK : GL_FRONT; // quake is backwards, this culls back faces
718 gl_state.cullfaceenable = true;
719 gl_state.polygonoffset[0] = 0;
720 gl_state.polygonoffset[1] = 0;
724 qglColorMask(1, 1, 1, 1);
725 qglAlphaFunc(GL_GEQUAL, 0.5);CHECKGLERROR
726 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
727 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
728 qglDisable(GL_BLEND);CHECKGLERROR
729 qglCullFace(gl_state.cullface);CHECKGLERROR
730 qglEnable(GL_CULL_FACE);CHECKGLERROR
731 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
732 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
733 qglDepthMask(gl_state.depthmask);CHECKGLERROR
734 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
736 if (vid.support.arb_vertex_buffer_object)
738 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
739 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
742 if (vid.support.ext_framebuffer_object)
744 qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
745 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
748 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
749 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
751 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
752 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
754 GL_Color(0, 0, 0, 0);
755 GL_Color(1, 1, 1, 1);
757 gl_state.unit = MAX_TEXTUREUNITS;
758 gl_state.clientunit = MAX_TEXTUREUNITS;
759 switch(vid.renderpath)
761 case RENDERPATH_GL20:
762 case RENDERPATH_CGGL:
763 for (i = 0;i < vid.teximageunits;i++)
766 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
767 if (vid.support.ext_texture_3d)
769 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
771 if (vid.support.arb_texture_cube_map)
773 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
775 if (vid.support.arb_texture_rectangle)
777 qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);CHECKGLERROR
781 for (i = 0;i < vid.texarrayunits;i++)
783 GL_ClientActiveTexture(i);
785 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
786 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
790 case RENDERPATH_GL13:
791 case RENDERPATH_GL11:
792 for (i = 0;i < vid.texunits;i++)
795 GL_ClientActiveTexture(i);
796 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
797 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
798 if (vid.support.ext_texture_3d)
800 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
801 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
803 if (vid.support.arb_texture_cube_map)
805 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
806 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
808 if (vid.support.arb_texture_rectangle)
810 qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR
811 qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);CHECKGLERROR
814 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
815 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
816 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
817 qglLoadIdentity();CHECKGLERROR
818 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
819 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
826 void GL_ActiveTexture(unsigned int num)
828 if (gl_state.unit != num)
831 if (qglActiveTexture)
834 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
840 void GL_ClientActiveTexture(unsigned int num)
842 if (gl_state.clientunit != num)
844 gl_state.clientunit = num;
845 if (qglActiveTexture)
848 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
854 void GL_BlendFunc(int blendfunc1, int blendfunc2)
856 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
859 qglBlendFunc(gl_state.blendfunc1 = blendfunc1, gl_state.blendfunc2 = blendfunc2);CHECKGLERROR
860 if (gl_state.blendfunc2 == GL_ZERO)
862 if (gl_state.blendfunc1 == GL_ONE)
867 qglDisable(GL_BLEND);CHECKGLERROR
875 qglEnable(GL_BLEND);CHECKGLERROR
884 qglEnable(GL_BLEND);CHECKGLERROR
890 void GL_DepthMask(int state)
892 if (gl_state.depthmask != state)
895 qglDepthMask(gl_state.depthmask = state);CHECKGLERROR
899 void GL_DepthTest(int state)
901 if (gl_state.depthtest != state)
903 gl_state.depthtest = state;
905 if (gl_state.depthtest)
907 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
911 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
916 void GL_DepthRange(float nearfrac, float farfrac)
918 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
920 gl_state.depthrange[0] = nearfrac;
921 gl_state.depthrange[1] = farfrac;
922 qglDepthRange(nearfrac, farfrac);
926 void GL_PolygonOffset(float planeoffset, float depthoffset)
928 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
930 gl_state.polygonoffset[0] = planeoffset;
931 gl_state.polygonoffset[1] = depthoffset;
932 qglPolygonOffset(planeoffset, depthoffset);
936 void GL_SetMirrorState(qboolean state)
938 if(!state != !v_flipped_state)
940 // change cull face mode!
941 if(gl_state.cullface == GL_BACK)
942 qglCullFace((gl_state.cullface = GL_FRONT));
943 else if(gl_state.cullface == GL_FRONT)
944 qglCullFace((gl_state.cullface = GL_BACK));
946 v_flipped_state = state;
949 void GL_CullFace(int state)
955 if(state == GL_FRONT)
957 else if(state == GL_BACK)
961 if (state != GL_NONE)
963 if (!gl_state.cullfaceenable)
965 gl_state.cullfaceenable = true;
966 qglEnable(GL_CULL_FACE);CHECKGLERROR
968 if (gl_state.cullface != state)
970 gl_state.cullface = state;
971 qglCullFace(gl_state.cullface);CHECKGLERROR
976 if (gl_state.cullfaceenable)
978 gl_state.cullfaceenable = false;
979 qglDisable(GL_CULL_FACE);CHECKGLERROR
984 void GL_AlphaTest(int state)
986 if (gl_state.alphatest != state)
988 gl_state.alphatest = state;
990 if (gl_state.alphatest)
992 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
996 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1001 void GL_ColorMask(int r, int g, int b, int a)
1003 int state = r*8 + g*4 + b*2 + a*1;
1004 if (gl_state.colormask != state)
1006 gl_state.colormask = state;
1008 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
1012 void GL_Color(float cr, float cg, float cb, float ca)
1014 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)
1016 gl_state.color4f[0] = cr;
1017 gl_state.color4f[1] = cg;
1018 gl_state.color4f[2] = cb;
1019 gl_state.color4f[3] = ca;
1021 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
1026 void GL_Scissor (int x, int y, int width, int height)
1029 qglScissor(x, y,width,height);
1033 void GL_ScissorTest(int state)
1035 if(gl_state.scissortest == state)
1039 if((gl_state.scissortest = state))
1040 qglEnable(GL_SCISSOR_TEST);
1042 qglDisable(GL_SCISSOR_TEST);
1046 void GL_Clear(int mask)
1049 qglClear(mask);CHECKGLERROR
1052 // called at beginning of frame
1053 void R_Mesh_Start(void)
1057 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
1058 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
1059 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
1060 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
1061 if (gl_printcheckerror.integer && !gl_paranoid.integer)
1063 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
1064 Cvar_SetValueQuick(&gl_paranoid, 1);
1068 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
1072 char compilelog[MAX_INPUTLINE];
1073 shaderobject = qglCreateShaderObjectARB(shadertypeenum);CHECKGLERROR
1076 qglShaderSourceARB(shaderobject, numstrings, strings, NULL);CHECKGLERROR
1077 qglCompileShaderARB(shaderobject);CHECKGLERROR
1078 qglGetObjectParameterivARB(shaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &shadercompiled);CHECKGLERROR
1079 qglGetInfoLogARB(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
1080 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
1082 int i, j, pretextlines = 0;
1083 for (i = 0;i < numstrings - 1;i++)
1084 for (j = 0;strings[i][j];j++)
1085 if (strings[i][j] == '\n')
1087 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
1089 if (!shadercompiled)
1091 qglDeleteObjectARB(shaderobject);CHECKGLERROR
1094 qglAttachObjectARB(programobject, shaderobject);CHECKGLERROR
1095 qglDeleteObjectARB(shaderobject);CHECKGLERROR
1099 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)
1101 GLint programlinked;
1102 GLuint programobject = 0;
1103 char linklog[MAX_INPUTLINE];
1106 programobject = qglCreateProgramObjectARB();CHECKGLERROR
1110 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER_ARB, "vertex", vertexstrings_count, vertexstrings_list))
1113 #ifdef GL_GEOMETRY_SHADER_ARB
1114 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER_ARB, "geometry", geometrystrings_count, geometrystrings_list))
1118 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER_ARB, "fragment", fragmentstrings_count, fragmentstrings_list))
1121 qglLinkProgramARB(programobject);CHECKGLERROR
1122 qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
1123 qglGetInfoLogARB(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
1126 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
1127 Con_DPrintf("program link log:\n%s\n", linklog);
1128 // software vertex shader is ok but software fragment shader is WAY
1129 // too slow, fail program if so.
1130 // NOTE: this string might be ATI specific, but that's ok because the
1131 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
1132 // software fragment shader due to low instruction and dependent
1134 if (strstr(linklog, "fragment shader will run in software"))
1135 programlinked = false;
1139 return programobject;
1141 qglDeleteObjectARB(programobject);CHECKGLERROR
1145 void GL_Backend_FreeProgram(unsigned int prog)
1148 qglDeleteObjectARB(prog);
1152 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
1157 for (i = 0;i < count;i++)
1158 *out++ = *in++ + offset;
1161 memcpy(out, in, sizeof(*out) * count);
1164 // renders triangles using vertices from the active arrays
1165 int paranoidblah = 0;
1166 void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, size_t element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, size_t element3s_bufferoffset)
1168 unsigned int numelements = numtriangles * 3;
1170 size_t bufferoffset3i;
1172 size_t bufferoffset3s;
1173 if (numvertices < 3 || numtriangles < 1)
1175 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
1176 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);
1179 if (gl_state.pointer_vertex_pointer == NULL)
1181 Con_DPrintf("R_Mesh_Draw with no vertex pointer!\n");
1184 if (!gl_mesh_prefer_short_elements.integer)
1188 if (element3i_indexbuffer)
1189 element3i_indexbuffer = NULL;
1191 // adjust the pointers for firsttriangle
1193 element3i += firsttriangle * 3;
1194 if (element3i_indexbuffer)
1195 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
1197 element3s += firsttriangle * 3;
1198 if (element3s_indexbuffer)
1199 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
1200 // check if the user specified to ignore static index buffers
1201 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
1203 element3i_indexbuffer = NULL;
1204 element3s_indexbuffer = NULL;
1206 // upload a dynamic index buffer if needed
1209 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
1211 if (gl_state.draw_dynamicindexbuffer)
1212 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
1214 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true);
1215 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
1216 element3s_bufferoffset = 0;
1221 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
1223 if (gl_state.draw_dynamicindexbuffer)
1224 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
1226 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true);
1227 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
1228 element3i_bufferoffset = 0;
1231 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
1232 bufferoffset3i = element3i_bufferoffset;
1233 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
1234 bufferoffset3s = element3s_bufferoffset;
1236 r_refdef.stats.meshes++;
1237 r_refdef.stats.meshes_elements += numelements;
1238 if (gl_paranoid.integer)
1241 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
1243 unsigned int j, size;
1245 // note: there's no validation done here on buffer objects because it
1246 // is somewhat difficult to get at the data, and gl_paranoid can be
1247 // used without buffer objects if the need arises
1248 // (the data could be gotten using glMapBuffer but it would be very
1249 // slow due to uncachable video memory reads)
1250 if (!qglIsEnabled(GL_VERTEX_ARRAY))
1251 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
1253 if (gl_state.pointer_vertex_pointer)
1254 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
1256 if (gl_state.pointer_color_enabled)
1258 if (!qglIsEnabled(GL_COLOR_ARRAY))
1259 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
1261 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
1262 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
1265 for (i = 0;i < vid.texarrayunits;i++)
1267 if (gl_state.units[i].arrayenabled)
1269 GL_ClientActiveTexture(i);
1270 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
1271 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
1273 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
1274 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++)
1281 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
1283 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
1285 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
1292 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
1294 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
1296 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
1303 if (r_render.integer || r_refdef.draw2dstage)
1306 if (gl_mesh_testmanualfeeding.integer)
1308 unsigned int i, j, element;
1310 qglBegin(GL_TRIANGLES);
1311 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
1314 element = element3i[i];
1316 element = element3s[i];
1318 element = firstvertex + i;
1319 for (j = 0;j < vid.texarrayunits;j++)
1321 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
1323 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
1325 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
1326 if (vid.texarrayunits > 1)
1328 if (gl_state.units[j].pointer_texcoord_components == 4)
1329 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
1330 else if (gl_state.units[j].pointer_texcoord_components == 3)
1331 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
1332 else if (gl_state.units[j].pointer_texcoord_components == 2)
1333 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
1335 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
1339 if (gl_state.units[j].pointer_texcoord_components == 4)
1340 qglTexCoord4f(p[0], p[1], p[2], p[3]);
1341 else if (gl_state.units[j].pointer_texcoord_components == 3)
1342 qglTexCoord3f(p[0], p[1], p[2]);
1343 else if (gl_state.units[j].pointer_texcoord_components == 2)
1344 qglTexCoord2f(p[0], p[1]);
1346 qglTexCoord1f(p[0]);
1349 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
1351 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
1352 if (vid.texarrayunits > 1)
1354 if (gl_state.units[j].pointer_texcoord_components == 4)
1355 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
1356 else if (gl_state.units[j].pointer_texcoord_components == 3)
1357 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
1358 else if (gl_state.units[j].pointer_texcoord_components == 2)
1359 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
1360 else if (gl_state.units[j].pointer_texcoord_components == 1)
1361 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
1365 if (gl_state.units[j].pointer_texcoord_components == 4)
1366 qglTexCoord4f(s[0], s[1], s[2], s[3]);
1367 else if (gl_state.units[j].pointer_texcoord_components == 3)
1368 qglTexCoord3f(s[0], s[1], s[2]);
1369 else if (gl_state.units[j].pointer_texcoord_components == 2)
1370 qglTexCoord2f(s[0], s[1]);
1371 else if (gl_state.units[j].pointer_texcoord_components == 1)
1372 qglTexCoord1f(s[0]);
1375 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
1377 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
1378 if (vid.texarrayunits > 1)
1380 if (gl_state.units[j].pointer_texcoord_components == 4)
1381 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
1382 else if (gl_state.units[j].pointer_texcoord_components == 3)
1383 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
1384 else if (gl_state.units[j].pointer_texcoord_components == 2)
1385 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
1386 else if (gl_state.units[j].pointer_texcoord_components == 1)
1387 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
1391 if (gl_state.units[j].pointer_texcoord_components == 4)
1392 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
1393 else if (gl_state.units[j].pointer_texcoord_components == 3)
1394 qglTexCoord3f(sb[0], sb[1], sb[2]);
1395 else if (gl_state.units[j].pointer_texcoord_components == 2)
1396 qglTexCoord2f(sb[0], sb[1]);
1397 else if (gl_state.units[j].pointer_texcoord_components == 1)
1398 qglTexCoord1f(sb[0]);
1403 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
1405 if (gl_state.pointer_color_gltype == GL_FLOAT)
1407 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
1408 qglColor4f(p[0], p[1], p[2], p[3]);
1410 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
1412 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
1413 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
1416 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
1418 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
1419 if (gl_state.pointer_vertex_components == 4)
1420 qglVertex4f(p[0], p[1], p[2], p[3]);
1421 else if (gl_state.pointer_vertex_components == 3)
1422 qglVertex3f(p[0], p[1], p[2]);
1424 qglVertex2f(p[0], p[1]);
1430 else if (bufferobject3s)
1432 GL_BindEBO(bufferobject3s);
1433 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
1435 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
1440 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
1444 else if (bufferobject3i)
1446 GL_BindEBO(bufferobject3i);
1447 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
1449 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
1454 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
1461 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
1463 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
1468 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
1475 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
1477 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
1482 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
1488 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
1494 // restores backend state, used when done with 3D rendering
1495 void R_Mesh_Finish(void)
1499 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic)
1501 int bufferobject = 0;
1502 void *devicebuffer = NULL;
1503 r_meshbuffer_t *buffer;
1504 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
1508 r_refdef.stats.indexbufferuploadcount++;
1509 r_refdef.stats.indexbufferuploadsize += size;
1513 r_refdef.stats.vertexbufferuploadcount++;
1514 r_refdef.stats.vertexbufferuploadsize += size;
1516 switch(vid.renderpath)
1518 case RENDERPATH_GL11:
1519 case RENDERPATH_GL13:
1520 case RENDERPATH_GL20:
1521 case RENDERPATH_CGGL:
1522 qglGenBuffersARB(1, (GLuint *)&bufferobject);
1524 GL_BindEBO(bufferobject);
1526 GL_BindVBO(bufferobject);
1527 qglBufferDataARB(isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
1530 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
1531 memset(buffer, 0, sizeof(*buffer));
1532 buffer->bufferobject = bufferobject;
1533 buffer->devicebuffer = devicebuffer;
1534 buffer->size = size;
1535 buffer->isindexbuffer = isindexbuffer;
1536 buffer->isdynamic = isdynamic;
1537 strlcpy(buffer->name, name, sizeof(buffer->name));
1541 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
1543 if (!buffer || (!buffer->bufferobject && !buffer->devicebuffer))
1545 if (buffer->isindexbuffer)
1547 r_refdef.stats.indexbufferuploadcount++;
1548 r_refdef.stats.indexbufferuploadsize += size;
1552 r_refdef.stats.vertexbufferuploadcount++;
1553 r_refdef.stats.vertexbufferuploadsize += size;
1555 switch(vid.renderpath)
1557 case RENDERPATH_GL11:
1558 case RENDERPATH_GL13:
1559 case RENDERPATH_GL20:
1560 case RENDERPATH_CGGL:
1561 if (buffer->isindexbuffer)
1562 GL_BindEBO(buffer->bufferobject);
1564 GL_BindVBO(buffer->bufferobject);
1565 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
1570 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
1574 switch(vid.renderpath)
1576 case RENDERPATH_GL11:
1577 case RENDERPATH_GL13:
1578 case RENDERPATH_GL20:
1579 case RENDERPATH_CGGL:
1580 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
1583 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
1586 void GL_Mesh_ListVBOs(qboolean printeach)
1589 size_t ebocount = 0, ebomemory = 0;
1590 size_t vbocount = 0, vbomemory = 0;
1591 r_meshbuffer_t *buffer;
1592 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
1593 for (i = 0;i < endindex;i++)
1595 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
1598 if (buffer->isindexbuffer) {ebocount++;ebomemory += buffer->size;if (printeach) Con_Printf("indexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");}
1599 else {vbocount++;vbomemory += buffer->size;if (printeach) Con_Printf("vertexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");}
1601 Con_Printf("vertex buffers: %i indexbuffers totalling %i bytes (%.3f MB), %i vertexbuffers totalling %i bytes (%.3f MB), combined %i bytes (%.3fMB)\n", (int)ebocount, (int)ebomemory, ebomemory / 1048576.0, (int)vbocount, (int)vbomemory, vbomemory / 1048576.0, (int)(ebomemory + vbomemory), (ebomemory + vbomemory) / 1048576.0);
1606 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
1608 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
1609 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)
1611 gl_state.pointer_vertex_components = components;
1612 gl_state.pointer_vertex_gltype = gltype;
1613 gl_state.pointer_vertex_stride = stride;
1614 gl_state.pointer_vertex_pointer = pointer;
1615 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
1616 gl_state.pointer_vertex_offset = bufferoffset;
1618 GL_BindVBO(bufferobject);
1619 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
1623 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
1625 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
1626 // the pointer only.
1629 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
1630 // caller wants color array enabled
1631 if (!gl_state.pointer_color_enabled)
1633 gl_state.pointer_color_enabled = true;
1635 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1637 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)
1639 gl_state.pointer_color_components = components;
1640 gl_state.pointer_color_gltype = gltype;
1641 gl_state.pointer_color_stride = stride;
1642 gl_state.pointer_color_pointer = pointer;
1643 gl_state.pointer_color_vertexbuffer = vertexbuffer;
1644 gl_state.pointer_color_offset = bufferoffset;
1646 GL_BindVBO(bufferobject);
1647 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
1652 // caller wants color array disabled
1653 if (gl_state.pointer_color_enabled)
1655 gl_state.pointer_color_enabled = false;
1657 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1658 // when color array is on the glColor gets trashed, set it again
1659 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
1664 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)
1666 gltextureunit_t *unit = gl_state.units + unitnum;
1667 // update array settings
1669 // note: there is no need to check bufferobject here because all cases
1670 // that involve a valid bufferobject also supply a texcoord array
1673 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
1674 // texture array unit is enabled, enable the array
1675 if (!unit->arrayenabled)
1677 unit->arrayenabled = true;
1678 GL_ClientActiveTexture(unitnum);
1679 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1682 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)
1684 unit->pointer_texcoord_components = components;
1685 unit->pointer_texcoord_gltype = gltype;
1686 unit->pointer_texcoord_stride = stride;
1687 unit->pointer_texcoord_pointer = pointer;
1688 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
1689 unit->pointer_texcoord_offset = bufferoffset;
1690 GL_ClientActiveTexture(unitnum);
1691 GL_BindVBO(bufferobject);
1692 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
1697 // texture array unit is disabled, disable the array
1698 if (unit->arrayenabled)
1700 unit->arrayenabled = false;
1701 GL_ClientActiveTexture(unitnum);
1702 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1707 int R_Mesh_TexBound(unsigned int unitnum, int id)
1709 gltextureunit_t *unit = gl_state.units + unitnum;
1710 if (unitnum >= vid.teximageunits)
1712 if (id == GL_TEXTURE_2D)
1714 if (id == GL_TEXTURE_3D)
1716 if (id == GL_TEXTURE_CUBE_MAP_ARB)
1717 return unit->tcubemap;
1718 if (id == GL_TEXTURE_RECTANGLE_ARB)
1719 return unit->trectangle;
1723 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
1725 R_Mesh_TexBind(0, tex);
1726 GL_ActiveTexture(0);CHECKGLERROR
1727 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
1730 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
1732 gltextureunit_t *unit = gl_state.units + unitnum;
1733 int tex2d, tex3d, texcubemap, texnum;
1734 if (unitnum >= vid.teximageunits)
1736 switch(vid.renderpath)
1738 case RENDERPATH_GL20:
1739 case RENDERPATH_CGGL:
1741 tex = r_texture_white;
1742 texnum = R_GetTexture(tex);
1743 switch(tex->gltexturetypeenum)
1745 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
1746 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
1747 case GL_TEXTURE_CUBE_MAP_ARB: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR}break;
1748 case GL_TEXTURE_RECTANGLE_ARB: if (unit->trectangle != texnum) {GL_ActiveTexture(unitnum);unit->trectangle = texnum;qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR}break;
1751 case RENDERPATH_GL13:
1752 case RENDERPATH_GL11:
1758 texnum = R_GetTexture(tex);
1759 switch(tex->gltexturetypeenum)
1767 case GL_TEXTURE_CUBE_MAP_ARB:
1768 texcubemap = texnum;
1772 // update 2d texture binding
1773 if (unit->t2d != tex2d)
1775 GL_ActiveTexture(unitnum);
1780 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
1787 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1791 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1793 // update 3d texture binding
1794 if (unit->t3d != tex3d)
1796 GL_ActiveTexture(unitnum);
1801 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
1808 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1812 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1814 // update cubemap texture binding
1815 if (unit->tcubemap != texcubemap)
1817 GL_ActiveTexture(unitnum);
1820 if (unit->tcubemap == 0)
1822 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1829 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1832 unit->tcubemap = texcubemap;
1833 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1839 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
1841 gltextureunit_t *unit = gl_state.units + unitnum;
1842 if (matrix && matrix->m[3][3])
1844 // texmatrix specified, check if it is different
1845 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
1848 unit->texmatrixenabled = true;
1849 unit->matrix = *matrix;
1851 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
1852 GL_ActiveTexture(unitnum);
1853 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1854 qglLoadMatrixf(glmatrix);CHECKGLERROR
1855 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1860 // no texmatrix specified, revert to identity
1861 if (unit->texmatrixenabled)
1863 unit->texmatrixenabled = false;
1864 unit->matrix = identitymatrix;
1866 GL_ActiveTexture(unitnum);
1867 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1868 qglLoadIdentity();CHECKGLERROR
1869 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1874 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
1876 gltextureunit_t *unit = gl_state.units + unitnum;
1878 switch(vid.renderpath)
1880 case RENDERPATH_GL20:
1881 case RENDERPATH_CGGL:
1884 case RENDERPATH_GL13:
1885 // GL_ARB_texture_env_combine
1887 combinergb = GL_MODULATE;
1889 combinealpha = GL_MODULATE;
1894 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
1896 if (combinergb == GL_DECAL)
1897 combinergb = GL_INTERPOLATE_ARB;
1898 if (unit->combine != GL_COMBINE_ARB)
1900 unit->combine = GL_COMBINE_ARB;
1901 GL_ActiveTexture(unitnum);
1902 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
1903 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
1905 if (unit->combinergb != combinergb)
1907 unit->combinergb = combinergb;
1908 GL_ActiveTexture(unitnum);
1909 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
1911 if (unit->combinealpha != combinealpha)
1913 unit->combinealpha = combinealpha;
1914 GL_ActiveTexture(unitnum);
1915 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
1917 if (unit->rgbscale != rgbscale)
1919 unit->rgbscale = rgbscale;
1920 GL_ActiveTexture(unitnum);
1921 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
1923 if (unit->alphascale != alphascale)
1925 unit->alphascale = alphascale;
1926 GL_ActiveTexture(unitnum);
1927 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
1932 if (unit->combine != combinergb)
1934 unit->combine = combinergb;
1935 GL_ActiveTexture(unitnum);
1936 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
1940 case RENDERPATH_GL11:
1943 combinergb = GL_MODULATE;
1944 if (unit->combine != combinergb)
1946 unit->combine = combinergb;
1947 GL_ActiveTexture(unitnum);
1948 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
1954 void R_Mesh_ResetTextureState(void)
1956 unsigned int unitnum;
1961 switch(vid.renderpath)
1963 case RENDERPATH_GL20:
1964 case RENDERPATH_CGGL:
1965 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
1967 gltextureunit_t *unit = gl_state.units + unitnum;
1971 GL_ActiveTexture(unitnum);
1972 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
1977 GL_ActiveTexture(unitnum);
1978 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
1983 GL_ActiveTexture(unitnum);
1984 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
1986 if (unit->trectangle)
1988 unit->trectangle = 0;
1989 GL_ActiveTexture(unitnum);
1990 qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR
1993 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
1995 gltextureunit_t *unit = gl_state.units + unitnum;
1996 if (unit->arrayenabled)
1998 unit->arrayenabled = false;
1999 GL_ClientActiveTexture(unitnum);
2000 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
2003 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
2005 gltextureunit_t *unit = gl_state.units + unitnum;
2006 if (unit->texmatrixenabled)
2008 unit->texmatrixenabled = false;
2009 unit->matrix = identitymatrix;
2011 GL_ActiveTexture(unitnum);
2012 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
2013 qglLoadIdentity();CHECKGLERROR
2014 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
2018 case RENDERPATH_GL13:
2019 case RENDERPATH_GL11:
2020 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
2022 gltextureunit_t *unit = gl_state.units + unitnum;
2026 GL_ActiveTexture(unitnum);
2027 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
2028 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
2033 GL_ActiveTexture(unitnum);
2034 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
2035 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
2040 GL_ActiveTexture(unitnum);
2041 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
2042 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
2044 if (unit->trectangle)
2046 unit->trectangle = 0;
2047 GL_ActiveTexture(unitnum);
2048 qglDisable(GL_TEXTURE_RECTANGLE_ARB);CHECKGLERROR
2049 qglBindTexture(GL_TEXTURE_RECTANGLE_ARB, unit->trectangle);CHECKGLERROR
2051 if (unit->arrayenabled)
2053 unit->arrayenabled = false;
2054 GL_ClientActiveTexture(unitnum);
2055 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
2057 if (unit->texmatrixenabled)
2059 unit->texmatrixenabled = false;
2060 unit->matrix = identitymatrix;
2062 GL_ActiveTexture(unitnum);
2063 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
2064 qglLoadIdentity();CHECKGLERROR
2065 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
2067 if (unit->combine != GL_MODULATE)
2069 unit->combine = GL_MODULATE;
2070 GL_ActiveTexture(unitnum);
2071 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
2080 r_vertexposition_t *R_Mesh_PrepareVertices_Position_Lock(int numvertices)
2083 size = sizeof(r_vertexposition_t) * numvertices;
2084 if (gl_state.preparevertices_tempdatamaxsize < size)
2086 gl_state.preparevertices_tempdatamaxsize = size;
2087 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
2089 gl_state.preparevertices_vertexposition = (r_vertexposition_t *)gl_state.preparevertices_tempdata;
2090 gl_state.preparevertices_numvertices = numvertices;
2091 return gl_state.preparevertices_vertexposition;
2094 qboolean R_Mesh_PrepareVertices_Position_Unlock(void)
2096 R_Mesh_PrepareVertices_Position(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexposition, NULL);
2097 gl_state.preparevertices_vertexposition = NULL;
2098 gl_state.preparevertices_numvertices = 0;
2102 void R_Mesh_PrepareVertices_Position_Arrays(int numvertices, const float *vertex3f)
2105 r_vertexposition_t *vertex;
2106 switch(vid.renderpath)
2108 case RENDERPATH_GL20:
2109 case RENDERPATH_CGGL:
2110 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
2111 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
2112 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2113 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2114 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2115 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2116 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2118 case RENDERPATH_GL13:
2119 case RENDERPATH_GL11:
2120 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
2121 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
2122 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2123 if (vid.texunits >= 2)
2124 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2125 if (vid.texunits >= 3)
2126 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2130 // no quick path for this case, convert to vertex structs
2131 vertex = R_Mesh_PrepareVertices_Position_Lock(numvertices);
2132 for (i = 0;i < numvertices;i++)
2133 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
2134 R_Mesh_PrepareVertices_Position_Unlock();
2135 R_Mesh_PrepareVertices_Position(numvertices, vertex, NULL);
2138 void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *vertex, const r_meshbuffer_t *vertexbuffer)
2140 // upload temporary vertexbuffer for this rendering
2141 if (!gl_state.usevbo_staticvertex)
2142 vertexbuffer = NULL;
2143 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
2145 if (gl_state.preparevertices_dynamicvertexbuffer)
2146 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
2148 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true);
2149 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
2153 switch(vid.renderpath)
2155 case RENDERPATH_GL20:
2156 case RENDERPATH_CGGL:
2157 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2158 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2159 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2160 case RENDERPATH_GL13:
2161 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2162 case RENDERPATH_GL11:
2163 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
2164 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
2165 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2170 switch(vid.renderpath)
2172 case RENDERPATH_GL20:
2173 case RENDERPATH_CGGL:
2174 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2175 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2176 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2177 case RENDERPATH_GL13:
2178 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2179 case RENDERPATH_GL11:
2180 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
2181 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
2182 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2189 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
2192 size = sizeof(r_vertexgeneric_t) * numvertices;
2193 if (gl_state.preparevertices_tempdatamaxsize < size)
2195 gl_state.preparevertices_tempdatamaxsize = size;
2196 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
2198 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
2199 gl_state.preparevertices_numvertices = numvertices;
2200 return gl_state.preparevertices_vertexgeneric;
2203 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
2205 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
2206 gl_state.preparevertices_vertexgeneric = NULL;
2207 gl_state.preparevertices_numvertices = 0;
2211 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
2214 r_vertexgeneric_t *vertex;
2215 switch(vid.renderpath)
2217 case RENDERPATH_GL20:
2218 case RENDERPATH_CGGL:
2219 if (gl_mesh_separatearrays.integer)
2221 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
2222 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
2223 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
2224 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2225 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2226 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2227 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2231 case RENDERPATH_GL13:
2232 case RENDERPATH_GL11:
2233 if (gl_mesh_separatearrays.integer)
2235 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
2236 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
2237 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
2238 if (vid.texunits >= 2)
2239 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2240 if (vid.texunits >= 3)
2241 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2247 // no quick path for this case, convert to vertex structs
2248 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
2249 for (i = 0;i < numvertices;i++)
2250 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
2253 for (i = 0;i < numvertices;i++)
2254 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
2258 float tempcolor4f[4];
2259 unsigned char tempcolor4ub[4];
2260 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
2261 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
2262 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
2263 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
2264 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
2265 for (i = 0;i < numvertices;i++)
2266 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
2269 for (i = 0;i < numvertices;i++)
2270 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
2271 R_Mesh_PrepareVertices_Generic_Unlock();
2272 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
2275 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
2277 // upload temporary vertexbuffer for this rendering
2278 if (!gl_state.usevbo_staticvertex)
2279 vertexbuffer = NULL;
2280 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
2282 if (gl_state.preparevertices_dynamicvertexbuffer)
2283 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
2285 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true);
2286 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
2290 switch(vid.renderpath)
2292 case RENDERPATH_GL20:
2293 case RENDERPATH_CGGL:
2294 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2295 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2296 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2297 case RENDERPATH_GL13:
2298 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2299 case RENDERPATH_GL11:
2300 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
2301 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
2302 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
2307 switch(vid.renderpath)
2309 case RENDERPATH_GL20:
2310 case RENDERPATH_CGGL:
2311 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2312 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2313 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2314 case RENDERPATH_GL13:
2315 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2316 case RENDERPATH_GL11:
2317 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
2318 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
2319 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
2326 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
2329 size = sizeof(r_vertexmesh_t) * numvertices;
2330 if (gl_state.preparevertices_tempdatamaxsize < size)
2332 gl_state.preparevertices_tempdatamaxsize = size;
2333 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
2335 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
2336 gl_state.preparevertices_numvertices = numvertices;
2337 return gl_state.preparevertices_vertexmesh;
2340 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
2342 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
2343 gl_state.preparevertices_vertexmesh = NULL;
2344 gl_state.preparevertices_numvertices = 0;
2348 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)
2351 r_vertexmesh_t *vertex;
2352 switch(vid.renderpath)
2354 case RENDERPATH_GL20:
2355 case RENDERPATH_CGGL:
2356 if (gl_mesh_separatearrays.integer)
2358 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
2359 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
2360 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
2361 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
2362 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
2363 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
2364 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
2368 case RENDERPATH_GL13:
2369 case RENDERPATH_GL11:
2370 if (gl_mesh_separatearrays.integer)
2372 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
2373 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
2374 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
2375 if (vid.texunits >= 2)
2376 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
2377 if (vid.texunits >= 3)
2378 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2384 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
2385 for (i = 0;i < numvertices;i++)
2386 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
2388 for (i = 0;i < numvertices;i++)
2389 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
2391 for (i = 0;i < numvertices;i++)
2392 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
2394 for (i = 0;i < numvertices;i++)
2395 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
2398 for (i = 0;i < numvertices;i++)
2399 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
2403 float tempcolor4f[4];
2404 unsigned char tempcolor4ub[4];
2405 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
2406 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
2407 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
2408 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
2409 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
2410 for (i = 0;i < numvertices;i++)
2411 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
2413 if (texcoordtexture2f)
2414 for (i = 0;i < numvertices;i++)
2415 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
2416 if (texcoordlightmap2f)
2417 for (i = 0;i < numvertices;i++)
2418 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
2419 R_Mesh_PrepareVertices_Mesh_Unlock();
2420 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
2423 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
2425 // upload temporary vertexbuffer for this rendering
2426 if (!gl_state.usevbo_staticvertex)
2427 vertexbuffer = NULL;
2428 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
2430 if (gl_state.preparevertices_dynamicvertexbuffer)
2431 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
2433 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true);
2434 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
2438 switch(vid.renderpath)
2440 case RENDERPATH_GL20:
2441 case RENDERPATH_CGGL:
2442 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
2443 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
2444 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
2445 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
2446 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
2447 R_Mesh_TexCoordPointer(3, 4, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
2448 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
2450 case RENDERPATH_GL13:
2451 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
2452 case RENDERPATH_GL11:
2453 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
2454 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
2455 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
2460 switch(vid.renderpath)
2462 case RENDERPATH_GL20:
2463 case RENDERPATH_CGGL:
2464 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
2465 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
2466 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
2467 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
2468 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
2469 R_Mesh_TexCoordPointer(3, 4, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
2470 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
2472 case RENDERPATH_GL13:
2473 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
2474 case RENDERPATH_GL11:
2475 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
2476 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
2477 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);