3 #include "cl_collision.h"
6 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
7 extern D3DCAPS9 vid_d3d9caps;
10 #define MAX_RENDERTARGETS 4
12 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
13 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)"};
14 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"};
15 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
16 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
18 cvar_t r_render = {0, "r_render", "1", "enables rendering 3D views (you want this on!)"};
19 cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
20 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
21 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
22 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
23 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)"};
24 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"};
25 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"};
26 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"};
28 cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
29 qboolean v_flipped_state = false;
31 r_viewport_t gl_viewport;
32 matrix4x4_t gl_modelmatrix;
33 matrix4x4_t gl_viewmatrix;
34 matrix4x4_t gl_modelviewmatrix;
35 matrix4x4_t gl_projectionmatrix;
36 matrix4x4_t gl_modelviewprojectionmatrix;
37 float gl_modelview16f[16];
38 float gl_modelviewprojection16f[16];
39 qboolean gl_modelmatrixchanged;
41 int gl_maxdrawrangeelementsvertices;
42 int gl_maxdrawrangeelementsindices;
47 void GL_PrintError(int errornumber, const char *filename, int linenumber)
51 #ifdef GL_INVALID_ENUM
53 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
56 #ifdef GL_INVALID_VALUE
57 case GL_INVALID_VALUE:
58 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
61 #ifdef GL_INVALID_OPERATION
62 case GL_INVALID_OPERATION:
63 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
66 #ifdef GL_STACK_OVERFLOW
67 case GL_STACK_OVERFLOW:
68 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
71 #ifdef GL_STACK_UNDERFLOW
72 case GL_STACK_UNDERFLOW:
73 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
76 #ifdef GL_OUT_OF_MEMORY
77 case GL_OUT_OF_MEMORY:
78 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
81 #ifdef GL_TABLE_TOO_LARGE
82 case GL_TABLE_TOO_LARGE:
83 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
86 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
87 case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
88 Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
92 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
98 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
100 void SCR_ScreenShot_f (void);
102 typedef struct gltextureunit_s
104 int pointer_texcoord_components;
105 int pointer_texcoord_gltype;
106 size_t pointer_texcoord_stride;
107 const void *pointer_texcoord_pointer;
108 const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
109 size_t pointer_texcoord_offset;
112 int t2d, t3d, tcubemap;
114 int rgbscale, alphascale;
116 int combinergb, combinealpha;
117 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
118 int texmatrixenabled;
123 typedef struct gl_state_s
131 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
135 float polygonoffset[2];
138 float alphafuncvalue;
141 unsigned int clientunit;
142 gltextureunit_t units[MAX_TEXTUREUNITS];
146 int vertexbufferobject;
147 int elementbufferobject;
148 int framebufferobject;
149 qboolean pointer_color_enabled;
151 int pointer_vertex_components;
152 int pointer_vertex_gltype;
153 size_t pointer_vertex_stride;
154 const void *pointer_vertex_pointer;
155 const r_meshbuffer_t *pointer_vertex_vertexbuffer;
156 size_t pointer_vertex_offset;
158 int pointer_color_components;
159 int pointer_color_gltype;
160 size_t pointer_color_stride;
161 const void *pointer_color_pointer;
162 const r_meshbuffer_t *pointer_color_vertexbuffer;
163 size_t pointer_color_offset;
165 void *preparevertices_tempdata;
166 size_t preparevertices_tempdatamaxsize;
167 r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
168 r_vertexgeneric_t *preparevertices_vertexgeneric;
169 r_vertexmesh_t *preparevertices_vertexmesh;
170 int preparevertices_numvertices;
172 r_meshbuffer_t *draw_dynamicindexbuffer;
174 qboolean usevbo_staticvertex;
175 qboolean usevbo_staticindex;
176 qboolean usevbo_dynamicvertex;
177 qboolean usevbo_dynamicindex;
179 memexpandablearray_t meshbufferarray;
184 // rtexture_t *d3drt_depthtexture;
185 // rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS];
186 IDirect3DSurface9 *d3drt_depthsurface;
187 IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS];
188 IDirect3DSurface9 *d3drt_backbufferdepthsurface;
189 IDirect3DSurface9 *d3drt_backbuffercolorsurface;
190 void *d3dvertexbuffer;
192 size_t d3dvertexsize;
197 static gl_state_t gl_state;
201 note: here's strip order for a terrain row:
208 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
210 *elements++ = i + row;
212 *elements++ = i + row + 1;
215 *elements++ = i + row + 1;
218 for (y = 0;y < rows - 1;y++)
220 for (x = 0;x < columns - 1;x++)
223 *elements++ = i + columns;
225 *elements++ = i + columns + 1;
228 *elements++ = i + columns + 1;
239 for (y = 0;y < rows - 1;y++)
241 for (x = 0;x < columns - 1;x++)
245 *elements++ = i + columns;
246 *elements++ = i + columns + 1;
247 *elements++ = i + columns;
248 *elements++ = i + columns + 1;
254 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
255 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
256 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
257 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
259 void GL_VBOStats_f(void)
261 GL_Mesh_ListVBOs(true);
264 static void GL_Backend_ResetState(void);
266 static void R_Mesh_InitVertexDeclarations(void);
267 static void R_Mesh_DestroyVertexDeclarations(void);
269 static void R_Mesh_SetUseVBO(void)
271 switch(vid.renderpath)
273 case RENDERPATH_GL11:
274 case RENDERPATH_GL13:
275 case RENDERPATH_GL20:
276 case RENDERPATH_CGGL:
277 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
278 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
279 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
280 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
282 case RENDERPATH_D3D9:
283 gl_state.usevbo_staticvertex = gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
284 gl_state.usevbo_dynamicvertex = gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo_dynamicindex.integer) || vid.forcevbo;
286 case RENDERPATH_D3D10:
287 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
289 case RENDERPATH_D3D11:
290 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
295 static void gl_backend_start(void)
297 memset(&gl_state, 0, sizeof(gl_state));
299 R_Mesh_InitVertexDeclarations();
302 Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
304 Con_DPrintf("OpenGL backend started.\n");
308 GL_Backend_ResetState();
310 switch(vid.renderpath)
312 case RENDERPATH_GL11:
313 case RENDERPATH_GL13:
314 case RENDERPATH_GL20:
315 case RENDERPATH_CGGL:
317 case RENDERPATH_D3D9:
319 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
320 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
323 case RENDERPATH_D3D10:
324 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
326 case RENDERPATH_D3D11:
327 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
332 static void gl_backend_shutdown(void)
334 Con_DPrint("OpenGL Backend shutting down\n");
336 switch(vid.renderpath)
338 case RENDERPATH_GL11:
339 case RENDERPATH_GL13:
340 case RENDERPATH_GL20:
341 case RENDERPATH_CGGL:
343 case RENDERPATH_D3D9:
345 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
346 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
349 case RENDERPATH_D3D10:
350 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
352 case RENDERPATH_D3D11:
353 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
357 if (gl_state.preparevertices_tempdata)
358 Mem_Free(gl_state.preparevertices_tempdata);
359 if (gl_state.preparevertices_dynamicvertexbuffer)
360 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
362 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
364 R_Mesh_DestroyVertexDeclarations();
366 memset(&gl_state, 0, sizeof(gl_state));
369 static void gl_backend_newmap(void)
373 static void gl_backend_devicelost(void)
376 r_meshbuffer_t *buffer;
378 gl_state.d3dvertexbuffer = NULL;
380 switch(vid.renderpath)
382 case RENDERPATH_GL11:
383 case RENDERPATH_GL13:
384 case RENDERPATH_GL20:
385 case RENDERPATH_CGGL:
387 case RENDERPATH_D3D9:
389 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
390 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
393 case RENDERPATH_D3D10:
394 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
396 case RENDERPATH_D3D11:
397 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
400 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
401 for (i = 0;i < endindex;i++)
403 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
404 if (!buffer || !buffer->isdynamic)
406 switch(vid.renderpath)
408 case RENDERPATH_GL11:
409 case RENDERPATH_GL13:
410 case RENDERPATH_GL20:
411 case RENDERPATH_CGGL:
413 case RENDERPATH_D3D9:
415 if (buffer->devicebuffer)
417 if (buffer->isindexbuffer)
418 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
420 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
421 buffer->devicebuffer = NULL;
425 case RENDERPATH_D3D10:
426 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
428 case RENDERPATH_D3D11:
429 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
435 static void gl_backend_devicerestored(void)
437 switch(vid.renderpath)
439 case RENDERPATH_GL11:
440 case RENDERPATH_GL13:
441 case RENDERPATH_GL20:
442 case RENDERPATH_CGGL:
444 case RENDERPATH_D3D9:
446 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
447 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
450 case RENDERPATH_D3D10:
451 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
453 case RENDERPATH_D3D11:
454 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
459 void gl_backend_init(void)
463 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
465 polygonelement3s[i * 3 + 0] = 0;
466 polygonelement3s[i * 3 + 1] = i + 1;
467 polygonelement3s[i * 3 + 2] = i + 2;
469 // elements for rendering a series of quads as triangles
470 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
472 quadelement3s[i * 6 + 0] = i * 4;
473 quadelement3s[i * 6 + 1] = i * 4 + 1;
474 quadelement3s[i * 6 + 2] = i * 4 + 2;
475 quadelement3s[i * 6 + 3] = i * 4;
476 quadelement3s[i * 6 + 4] = i * 4 + 2;
477 quadelement3s[i * 6 + 5] = i * 4 + 3;
480 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
481 polygonelement3i[i] = polygonelement3s[i];
482 for (i = 0;i < QUADELEMENTS_MAXQUADS*3;i++)
483 quadelement3i[i] = quadelement3s[i];
485 Cvar_RegisterVariable(&r_render);
486 Cvar_RegisterVariable(&r_renderview);
487 Cvar_RegisterVariable(&r_waterwarp);
488 Cvar_RegisterVariable(&gl_polyblend);
489 Cvar_RegisterVariable(&v_flipped);
490 Cvar_RegisterVariable(&gl_dither);
491 Cvar_RegisterVariable(&gl_vbo);
492 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
493 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
494 Cvar_RegisterVariable(&gl_paranoid);
495 Cvar_RegisterVariable(&gl_printcheckerror);
497 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
498 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
499 Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
501 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");
503 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
506 void GL_SetMirrorState(qboolean state);
508 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
512 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
513 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
515 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
517 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
518 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
519 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
521 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
524 static int bboxedges[12][2] =
543 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
545 int i, ix1, iy1, ix2, iy2;
546 float x1, y1, x2, y2;
557 scissor[0] = r_refdef.view.viewport.x;
558 scissor[1] = r_refdef.view.viewport.y;
559 scissor[2] = r_refdef.view.viewport.width;
560 scissor[3] = r_refdef.view.viewport.height;
562 // if view is inside the box, just say yes it's visible
563 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
566 x1 = y1 = x2 = y2 = 0;
568 // transform all corners that are infront of the nearclip plane
569 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
570 plane4f[3] = r_refdef.view.frustum[4].dist;
572 for (i = 0;i < 8;i++)
574 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
575 dist[i] = DotProduct4(corner[i], plane4f);
576 sign[i] = dist[i] > 0;
579 VectorCopy(corner[i], vertex[numvertices]);
583 // if some points are behind the nearclip, add clipped edge points to make
584 // sure that the scissor boundary is complete
585 if (numvertices > 0 && numvertices < 8)
587 // add clipped edge points
588 for (i = 0;i < 12;i++)
592 if (sign[j] != sign[k])
594 f = dist[j] / (dist[j] - dist[k]);
595 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
601 // if we have no points to check, it is behind the view plane
605 // if we have some points to transform, check what screen area is covered
606 x1 = y1 = x2 = y2 = 0;
608 //Con_Printf("%i vertices to transform...\n", numvertices);
609 for (i = 0;i < numvertices;i++)
611 VectorCopy(vertex[i], v);
612 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
613 //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]);
616 if (x1 > v2[0]) x1 = v2[0];
617 if (x2 < v2[0]) x2 = v2[0];
618 if (y1 > v2[1]) y1 = v2[1];
619 if (y2 < v2[1]) y2 = v2[1];
628 // now convert the scissor rectangle to integer screen coordinates
629 ix1 = (int)(x1 - 1.0f);
630 //iy1 = vid.height - (int)(y2 - 1.0f);
631 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
632 iy1 = (int)(y1 - 1.0f);
633 ix2 = (int)(x2 + 1.0f);
634 //iy2 = vid.height - (int)(y1 + 1.0f);
635 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
636 iy2 = (int)(y2 + 1.0f);
637 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
639 // clamp it to the screen
640 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
641 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
642 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
643 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
645 // if it is inside out, it's not visible
646 if (ix2 <= ix1 || iy2 <= iy1)
649 // the light area is visible, set up the scissor rectangle
652 scissor[2] = ix2 - ix1;
653 scissor[3] = iy2 - iy1;
655 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
656 switch(vid.renderpath)
658 case RENDERPATH_D3D9:
659 case RENDERPATH_D3D10:
660 case RENDERPATH_D3D11:
661 scissor[1] = vid.height - scissor[1] - scissor[3];
663 case RENDERPATH_GL11:
664 case RENDERPATH_GL13:
665 case RENDERPATH_GL20:
666 case RENDERPATH_CGGL:
674 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
678 float clipPlane[4], v3[3], v4[3];
681 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
683 VectorSet(normal, normalx, normaly, normalz);
684 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
685 VectorScale(normal, dist, v3);
686 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
687 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
688 clipPlane[3] = -DotProduct(v4, clipPlane);
692 // testing code for comparing results
694 VectorCopy4(clipPlane, clipPlane2);
695 R_EntityMatrix(&identitymatrix);
696 VectorSet(q, normal[0], normal[1], normal[2], -dist);
697 qglClipPlane(GL_CLIP_PLANE0, q);
698 qglGetClipPlane(GL_CLIP_PLANE0, q);
699 VectorCopy4(q, clipPlane);
703 // Calculate the clip-space corner point opposite the clipping plane
704 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
705 // transform it into camera space by multiplying it
706 // by the inverse of the projection matrix
707 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
708 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
710 q[3] = (1.0f + m[10]) / m[14];
712 // Calculate the scaled plane vector
713 d = 2.0f / DotProduct4(clipPlane, q);
715 // Replace the third row of the projection matrix
716 m[2] = clipPlane[0] * d;
717 m[6] = clipPlane[1] * d;
718 m[10] = clipPlane[2] * d + 1.0f;
719 m[14] = clipPlane[3] * d;
722 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)
724 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
726 memset(v, 0, sizeof(*v));
727 v->type = R_VIEWPORTTYPE_ORTHO;
728 v->cameramatrix = *cameramatrix;
735 memset(m, 0, sizeof(m));
736 m[0] = 2/(right - left);
737 m[5] = 2/(top - bottom);
738 m[10] = -2/(zFar - zNear);
739 m[12] = - (right + left)/(right - left);
740 m[13] = - (top + bottom)/(top - bottom);
741 m[14] = - (zFar + zNear)/(zFar - zNear);
743 switch(vid.renderpath)
745 case RENDERPATH_GL11:
746 case RENDERPATH_GL13:
747 case RENDERPATH_GL20:
748 case RENDERPATH_CGGL:
750 case RENDERPATH_D3D9:
751 case RENDERPATH_D3D10:
752 case RENDERPATH_D3D11:
753 m[10] = -1/(zFar - zNear);
754 m[14] = -zNear/(zFar-zNear);
757 v->screentodepth[0] = -farclip / (farclip - nearclip);
758 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
760 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
763 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
765 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
771 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
772 R_Viewport_TransformToScreen(v, test1, test2);
773 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
778 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)
780 matrix4x4_t tempmatrix, basematrix;
782 memset(v, 0, sizeof(*v));
784 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
785 v->cameramatrix = *cameramatrix;
792 memset(m, 0, sizeof(m));
793 m[0] = 1.0 / frustumx;
794 m[5] = 1.0 / frustumy;
795 m[10] = -(farclip + nearclip) / (farclip - nearclip);
797 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
798 v->screentodepth[0] = -farclip / (farclip - nearclip);
799 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
801 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
802 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
803 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
804 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
807 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
809 if(v_flipped.integer)
817 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
820 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)
822 matrix4x4_t tempmatrix, basematrix;
823 const float nudge = 1.0 - 1.0 / (1<<23);
825 memset(v, 0, sizeof(*v));
827 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
828 v->cameramatrix = *cameramatrix;
835 memset(m, 0, sizeof(m));
836 m[ 0] = 1.0 / frustumx;
837 m[ 5] = 1.0 / frustumy;
840 m[14] = -2 * nearclip * nudge;
841 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
842 v->screentodepth[1] = m[14] * -0.5;
844 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
845 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
846 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
847 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
850 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
852 if(v_flipped.integer)
860 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
863 float cubeviewmatrix[6][16] =
865 // standard cubemap projections
903 float rectviewmatrix[6][16] =
905 // sign-preserving cubemap projections
944 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
946 matrix4x4_t tempmatrix, basematrix;
948 memset(v, 0, sizeof(*v));
949 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
950 v->cameramatrix = *cameramatrix;
954 memset(m, 0, sizeof(m));
956 m[10] = -(farclip + nearclip) / (farclip - nearclip);
958 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
960 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
961 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
962 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
965 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
967 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
970 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)
972 matrix4x4_t tempmatrix, basematrix;
974 memset(v, 0, sizeof(*v));
975 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
976 v->cameramatrix = *cameramatrix;
977 v->x = (side & 1) * size;
978 v->y = (side >> 1) * size;
982 memset(m, 0, sizeof(m));
983 m[0] = m[5] = 1.0f * ((float)size - border) / size;
984 m[10] = -(farclip + nearclip) / (farclip - nearclip);
986 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
988 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
989 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
990 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
992 switch(vid.renderpath)
994 case RENDERPATH_GL20:
995 case RENDERPATH_CGGL:
996 case RENDERPATH_GL13:
997 case RENDERPATH_GL11:
999 case RENDERPATH_D3D9:
1002 case RENDERPATH_D3D10:
1003 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1005 case RENDERPATH_D3D11:
1006 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1011 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1013 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1016 void R_SetViewport(const r_viewport_t *v)
1021 // FIXME: v_flipped_state is evil, this probably breaks somewhere
1022 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1024 // copy over the matrices to our state
1025 gl_viewmatrix = v->viewmatrix;
1026 gl_projectionmatrix = v->projectmatrix;
1028 switch(vid.renderpath)
1030 case RENDERPATH_GL20:
1031 case RENDERPATH_CGGL:
1033 // qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1035 case RENDERPATH_GL13:
1036 case RENDERPATH_GL11:
1038 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1039 // Load the projection matrix into OpenGL
1040 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1041 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1042 qglLoadMatrixf(m);CHECKGLERROR
1043 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1045 case RENDERPATH_D3D9:
1048 D3DVIEWPORT9 d3dviewport;
1049 d3dviewport.X = gl_viewport.x;
1050 d3dviewport.Y = gl_viewport.y;
1051 d3dviewport.Width = gl_viewport.width;
1052 d3dviewport.Height = gl_viewport.height;
1053 d3dviewport.MinZ = gl_state.depthrange[0];
1054 d3dviewport.MaxZ = gl_state.depthrange[1];
1055 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1059 case RENDERPATH_D3D10:
1060 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1062 case RENDERPATH_D3D11:
1063 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1067 // force an update of the derived matrices
1068 gl_modelmatrixchanged = true;
1069 R_EntityMatrix(&gl_modelmatrix);
1072 void R_GetViewport(r_viewport_t *v)
1077 static void GL_BindVBO(int bufferobject)
1079 if (gl_state.vertexbufferobject != bufferobject)
1081 gl_state.vertexbufferobject = bufferobject;
1083 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1087 static void GL_BindEBO(int bufferobject)
1089 if (gl_state.elementbufferobject != bufferobject)
1091 gl_state.elementbufferobject = bufferobject;
1093 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1097 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1100 switch(vid.renderpath)
1102 case RENDERPATH_GL11:
1103 case RENDERPATH_GL13:
1104 case RENDERPATH_GL20:
1105 case RENDERPATH_CGGL:
1106 if (!vid.support.ext_framebuffer_object)
1108 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1109 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1110 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1111 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1112 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1113 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1114 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1116 case RENDERPATH_D3D9:
1117 case RENDERPATH_D3D10:
1118 case RENDERPATH_D3D11:
1124 void R_Mesh_DestroyFramebufferObject(int fbo)
1126 switch(vid.renderpath)
1128 case RENDERPATH_GL11:
1129 case RENDERPATH_GL13:
1130 case RENDERPATH_GL20:
1131 case RENDERPATH_CGGL:
1133 qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1135 case RENDERPATH_D3D9:
1136 case RENDERPATH_D3D10:
1137 case RENDERPATH_D3D11:
1143 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1145 // LordHavoc: for some weird reason the redundant SetDepthStencilSurface calls are necessary (otherwise the lights fail depth test, as if they were using the shadowmap depth surface and render target still)
1146 if (gl_state.d3drt_depthsurface == depthsurface && gl_state.d3drt_colorsurfaces[0] == colorsurface0 && gl_state.d3drt_colorsurfaces[1] == colorsurface1 && gl_state.d3drt_colorsurfaces[2] == colorsurface2 && gl_state.d3drt_colorsurfaces[3] == colorsurface3)
1149 gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1150 if (gl_state.d3drt_depthsurface != depthsurface)
1152 gl_state.d3drt_depthsurface = depthsurface;
1153 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1155 if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1157 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1158 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1160 if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1162 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1163 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1165 if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1167 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1168 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1170 if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1172 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1173 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1178 void R_Mesh_ResetRenderTargets(void)
1180 switch(vid.renderpath)
1182 case RENDERPATH_GL11:
1183 case RENDERPATH_GL13:
1184 case RENDERPATH_GL20:
1185 case RENDERPATH_CGGL:
1186 if (gl_state.framebufferobject)
1188 gl_state.framebufferobject = 0;
1189 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1192 case RENDERPATH_D3D9:
1194 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1197 case RENDERPATH_D3D10:
1198 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1200 case RENDERPATH_D3D11:
1201 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1206 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1210 rtexture_t *textures[5];
1211 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1212 textures[4] = depthtexture;
1213 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1214 for (j = 0;j < 5;j++)
1216 for (i = 0;i < vid.teximageunits;i++)
1217 if (gl_state.units[i].texture == textures[j])
1218 R_Mesh_TexBind(i, NULL);
1219 // set up framebuffer object or render targets for the active rendering API
1220 switch(vid.renderpath)
1222 case RENDERPATH_GL11:
1223 case RENDERPATH_GL13:
1224 case RENDERPATH_GL20:
1225 case RENDERPATH_CGGL:
1226 if (gl_state.framebufferobject != fbo)
1228 gl_state.framebufferobject = fbo;
1229 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1232 case RENDERPATH_D3D9:
1234 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1235 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1238 IDirect3DSurface9 *colorsurfaces[4];
1239 for (i = 0;i < 4;i++)
1241 colorsurfaces[i] = NULL;
1243 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1245 // set the render targets for real
1246 R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1247 // release the texture surface levels (they won't be lost while bound...)
1248 for (i = 0;i < 4;i++)
1250 IDirect3DSurface9_Release(colorsurfaces[i]);
1253 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1256 case RENDERPATH_D3D10:
1257 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1259 case RENDERPATH_D3D11:
1260 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1266 static int d3dcmpforglfunc(int f)
1270 case GL_NEVER: return D3DCMP_NEVER;
1271 case GL_LESS: return D3DCMP_LESS;
1272 case GL_EQUAL: return D3DCMP_EQUAL;
1273 case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1274 case GL_GREATER: return D3DCMP_GREATER;
1275 case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1276 case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1277 case GL_ALWAYS: return D3DCMP_ALWAYS;
1278 default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1282 static int d3dstencilopforglfunc(int f)
1286 case GL_KEEP: return D3DSTENCILOP_KEEP;
1287 case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1288 case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1289 default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1295 static void GL_Backend_ResetState(void)
1298 gl_state.active = true;
1299 gl_state.depthtest = true;
1300 gl_state.alphatest = false;
1301 gl_state.alphafunc = GL_GEQUAL;
1302 gl_state.alphafuncvalue = 0.5f;
1303 gl_state.blendfunc1 = GL_ONE;
1304 gl_state.blendfunc2 = GL_ZERO;
1305 gl_state.blend = false;
1306 gl_state.depthmask = GL_TRUE;
1307 gl_state.colormask = 15;
1308 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1309 gl_state.lockrange_first = 0;
1310 gl_state.lockrange_count = 0;
1311 gl_state.cullface = GL_NONE;
1312 gl_state.cullfaceenable = false;
1313 gl_state.polygonoffset[0] = 0;
1314 gl_state.polygonoffset[1] = 0;
1315 gl_state.framebufferobject = 0;
1316 gl_state.depthfunc = GL_LEQUAL;
1318 switch(vid.renderpath)
1320 case RENDERPATH_D3D9:
1323 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1324 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
1325 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
1326 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
1327 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1328 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1329 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1330 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1331 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1332 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1336 case RENDERPATH_D3D10:
1337 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1339 case RENDERPATH_D3D11:
1340 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1342 case RENDERPATH_GL20:
1343 case RENDERPATH_CGGL:
1346 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1347 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1348 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1349 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1350 qglDisable(GL_BLEND);CHECKGLERROR
1351 qglCullFace(gl_state.cullface);CHECKGLERROR
1352 qglDisable(GL_CULL_FACE);CHECKGLERROR
1353 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1354 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1355 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1356 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1358 if (vid.support.arb_vertex_buffer_object)
1360 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1361 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1364 if (vid.support.ext_framebuffer_object)
1366 qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1367 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1370 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1371 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1373 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1374 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1375 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1377 if (vid.support.ext_framebuffer_object)
1378 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1380 gl_state.unit = MAX_TEXTUREUNITS;
1381 gl_state.clientunit = MAX_TEXTUREUNITS;
1382 for (i = 0;i < vid.teximageunits;i++)
1384 GL_ActiveTexture(i);
1385 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1386 if (vid.support.ext_texture_3d)
1388 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1390 if (vid.support.arb_texture_cube_map)
1392 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1396 for (i = 0;i < vid.texarrayunits;i++)
1398 GL_ClientActiveTexture(i);
1400 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1401 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1405 case RENDERPATH_GL13:
1406 case RENDERPATH_GL11:
1409 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1410 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1411 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1412 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1413 qglDisable(GL_BLEND);CHECKGLERROR
1414 qglCullFace(gl_state.cullface);CHECKGLERROR
1415 qglDisable(GL_CULL_FACE);CHECKGLERROR
1416 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1417 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1418 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1419 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1421 if (vid.support.arb_vertex_buffer_object)
1423 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1424 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1427 if (vid.support.ext_framebuffer_object)
1429 qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1430 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1433 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1434 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1436 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1437 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1438 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1440 if (vid.support.ext_framebuffer_object)
1441 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1443 gl_state.unit = MAX_TEXTUREUNITS;
1444 gl_state.clientunit = MAX_TEXTUREUNITS;
1445 for (i = 0;i < vid.texunits;i++)
1447 GL_ActiveTexture(i);
1448 GL_ClientActiveTexture(i);
1449 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1450 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1451 if (vid.support.ext_texture_3d)
1453 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1454 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1456 if (vid.support.arb_texture_cube_map)
1458 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1459 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1462 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1463 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1464 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1465 qglLoadIdentity();CHECKGLERROR
1466 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1467 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1474 void GL_ActiveTexture(unsigned int num)
1476 if (gl_state.unit != num)
1478 gl_state.unit = num;
1479 switch(vid.renderpath)
1481 case RENDERPATH_GL11:
1482 case RENDERPATH_GL13:
1483 case RENDERPATH_GL20:
1484 case RENDERPATH_CGGL:
1485 if (qglActiveTexture)
1488 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1492 case RENDERPATH_D3D9:
1493 case RENDERPATH_D3D10:
1494 case RENDERPATH_D3D11:
1500 void GL_ClientActiveTexture(unsigned int num)
1502 if (gl_state.clientunit != num)
1504 gl_state.clientunit = num;
1505 switch(vid.renderpath)
1507 case RENDERPATH_GL11:
1508 case RENDERPATH_GL13:
1509 case RENDERPATH_GL20:
1510 case RENDERPATH_CGGL:
1511 if (qglActiveTexture)
1514 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1518 case RENDERPATH_D3D9:
1519 case RENDERPATH_D3D10:
1520 case RENDERPATH_D3D11:
1526 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1528 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1530 qboolean blendenable;
1531 gl_state.blendfunc1 = blendfunc1;
1532 gl_state.blendfunc2 = blendfunc2;
1533 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1534 switch(vid.renderpath)
1536 case RENDERPATH_GL11:
1537 case RENDERPATH_GL13:
1538 case RENDERPATH_GL20:
1539 case RENDERPATH_CGGL:
1541 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1542 if (gl_state.blend != blendenable)
1544 gl_state.blend = blendenable;
1545 if (!gl_state.blend)
1547 qglDisable(GL_BLEND);CHECKGLERROR
1551 qglEnable(GL_BLEND);CHECKGLERROR
1555 case RENDERPATH_D3D9:
1560 D3DBLEND d3dblendfunc[2];
1561 glblendfunc[0] = gl_state.blendfunc1;
1562 glblendfunc[1] = gl_state.blendfunc2;
1563 for (i = 0;i < 2;i++)
1565 switch(glblendfunc[i])
1567 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1568 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1569 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1570 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1571 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1572 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1573 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1574 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1575 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1576 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1579 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1580 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1581 if (gl_state.blend != blendenable)
1583 gl_state.blend = blendenable;
1584 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1589 case RENDERPATH_D3D10:
1590 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1592 case RENDERPATH_D3D11:
1593 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1599 void GL_DepthMask(int state)
1601 if (gl_state.depthmask != state)
1603 gl_state.depthmask = state;
1604 switch(vid.renderpath)
1606 case RENDERPATH_GL11:
1607 case RENDERPATH_GL13:
1608 case RENDERPATH_GL20:
1609 case RENDERPATH_CGGL:
1611 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1613 case RENDERPATH_D3D9:
1615 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1618 case RENDERPATH_D3D10:
1619 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1621 case RENDERPATH_D3D11:
1622 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1628 void GL_DepthTest(int state)
1630 if (gl_state.depthtest != state)
1632 gl_state.depthtest = state;
1633 switch(vid.renderpath)
1635 case RENDERPATH_GL11:
1636 case RENDERPATH_GL13:
1637 case RENDERPATH_GL20:
1638 case RENDERPATH_CGGL:
1640 if (gl_state.depthtest)
1642 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1646 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1649 case RENDERPATH_D3D9:
1651 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1654 case RENDERPATH_D3D10:
1655 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1657 case RENDERPATH_D3D11:
1658 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1664 void GL_DepthFunc(int state)
1666 if (gl_state.depthfunc != state)
1668 gl_state.depthfunc = state;
1669 switch(vid.renderpath)
1671 case RENDERPATH_GL11:
1672 case RENDERPATH_GL13:
1673 case RENDERPATH_GL20:
1674 case RENDERPATH_CGGL:
1676 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1678 case RENDERPATH_D3D9:
1680 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1683 case RENDERPATH_D3D10:
1684 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1686 case RENDERPATH_D3D11:
1687 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1693 void GL_DepthRange(float nearfrac, float farfrac)
1695 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1697 gl_state.depthrange[0] = nearfrac;
1698 gl_state.depthrange[1] = farfrac;
1699 switch(vid.renderpath)
1701 case RENDERPATH_GL11:
1702 case RENDERPATH_GL13:
1703 case RENDERPATH_GL20:
1704 case RENDERPATH_CGGL:
1705 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1707 case RENDERPATH_D3D9:
1710 D3DVIEWPORT9 d3dviewport;
1711 d3dviewport.X = gl_viewport.x;
1712 d3dviewport.Y = gl_viewport.y;
1713 d3dviewport.Width = gl_viewport.width;
1714 d3dviewport.Height = gl_viewport.height;
1715 d3dviewport.MinZ = gl_state.depthrange[0];
1716 d3dviewport.MaxZ = gl_state.depthrange[1];
1717 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1721 case RENDERPATH_D3D10:
1722 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1724 case RENDERPATH_D3D11:
1725 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1731 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)
1733 switch (vid.renderpath)
1735 case RENDERPATH_GL11:
1736 case RENDERPATH_GL13:
1737 case RENDERPATH_GL20:
1738 case RENDERPATH_CGGL:
1742 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1746 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1748 if (vid.support.ati_separate_stencil)
1750 qglStencilMask(writemask);CHECKGLERROR
1751 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1752 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1753 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1755 else if (vid.support.ext_stencil_two_side)
1757 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1758 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1759 qglStencilMask(writemask);CHECKGLERROR
1760 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1761 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1762 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1763 qglStencilMask(writemask);CHECKGLERROR
1764 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1765 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1768 case RENDERPATH_D3D9:
1770 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1771 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1772 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1773 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1774 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1775 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1776 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1777 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1778 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1779 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1780 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1781 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1782 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1785 case RENDERPATH_D3D10:
1786 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1788 case RENDERPATH_D3D11:
1789 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1794 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1796 switch (vid.renderpath)
1798 case RENDERPATH_GL11:
1799 case RENDERPATH_GL13:
1800 case RENDERPATH_GL20:
1801 case RENDERPATH_CGGL:
1805 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1809 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1811 if (vid.support.ext_stencil_two_side)
1813 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1815 qglStencilMask(writemask);CHECKGLERROR
1816 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1817 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1820 case RENDERPATH_D3D9:
1822 if (vid.support.ati_separate_stencil)
1823 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1824 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1825 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1826 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1827 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1828 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1829 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1830 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1831 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1834 case RENDERPATH_D3D10:
1835 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1837 case RENDERPATH_D3D11:
1838 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1843 void GL_PolygonOffset(float planeoffset, float depthoffset)
1845 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1847 gl_state.polygonoffset[0] = planeoffset;
1848 gl_state.polygonoffset[1] = depthoffset;
1849 switch(vid.renderpath)
1851 case RENDERPATH_GL11:
1852 case RENDERPATH_GL13:
1853 case RENDERPATH_GL20:
1854 case RENDERPATH_CGGL:
1855 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1857 case RENDERPATH_D3D9:
1859 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1860 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1863 case RENDERPATH_D3D10:
1864 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1866 case RENDERPATH_D3D11:
1867 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1873 void GL_SetMirrorState(qboolean state)
1875 if (v_flipped_state != state)
1877 v_flipped_state = state;
1878 if (gl_state.cullface == GL_BACK)
1879 gl_state.cullface = GL_FRONT;
1880 else if (gl_state.cullface == GL_FRONT)
1881 gl_state.cullface = GL_BACK;
1884 switch(vid.renderpath)
1886 case RENDERPATH_GL11:
1887 case RENDERPATH_GL13:
1888 case RENDERPATH_GL20:
1889 case RENDERPATH_CGGL:
1890 qglCullFace(gl_state.cullface);
1892 case RENDERPATH_D3D9:
1894 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
1897 case RENDERPATH_D3D10:
1898 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1900 case RENDERPATH_D3D11:
1901 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1907 void GL_CullFace(int state)
1911 if(state == GL_FRONT)
1913 else if(state == GL_BACK)
1917 switch(vid.renderpath)
1919 case RENDERPATH_GL11:
1920 case RENDERPATH_GL13:
1921 case RENDERPATH_GL20:
1922 case RENDERPATH_CGGL:
1925 if (state != GL_NONE)
1927 if (!gl_state.cullfaceenable)
1929 gl_state.cullfaceenable = true;
1930 qglEnable(GL_CULL_FACE);CHECKGLERROR
1932 if (gl_state.cullface != state)
1934 gl_state.cullface = state;
1935 qglCullFace(gl_state.cullface);CHECKGLERROR
1940 if (gl_state.cullfaceenable)
1942 gl_state.cullfaceenable = false;
1943 qglDisable(GL_CULL_FACE);CHECKGLERROR
1947 case RENDERPATH_D3D9:
1949 if (gl_state.cullface != state)
1951 gl_state.cullface = state;
1952 switch(gl_state.cullface)
1955 gl_state.cullfaceenable = false;
1956 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1959 gl_state.cullfaceenable = true;
1960 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
1963 gl_state.cullfaceenable = true;
1964 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
1970 case RENDERPATH_D3D10:
1971 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1973 case RENDERPATH_D3D11:
1974 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1979 void GL_AlphaTest(int state)
1981 if (gl_state.alphatest != state)
1983 gl_state.alphatest = state;
1984 switch(vid.renderpath)
1986 case RENDERPATH_GL11:
1987 case RENDERPATH_GL13:
1988 case RENDERPATH_GL20:
1989 case RENDERPATH_CGGL:
1991 if (gl_state.alphatest)
1993 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
1997 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2000 case RENDERPATH_D3D9:
2002 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
2005 case RENDERPATH_D3D10:
2006 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2008 case RENDERPATH_D3D11:
2009 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2015 void GL_AlphaFunc(int state, float value)
2017 if (gl_state.alphafunc != state || gl_state.alphafuncvalue != value)
2019 gl_state.alphafunc = state;
2020 gl_state.alphafuncvalue = value;
2021 switch(vid.renderpath)
2023 case RENDERPATH_GL11:
2024 case RENDERPATH_GL13:
2025 case RENDERPATH_GL20:
2026 case RENDERPATH_CGGL:
2028 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
2030 case RENDERPATH_D3D9:
2032 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
2033 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, value * 256.0f, 255));
2036 case RENDERPATH_D3D10:
2037 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2039 case RENDERPATH_D3D11:
2040 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2046 void GL_ColorMask(int r, int g, int b, int a)
2048 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2049 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2050 if (gl_state.colormask != state)
2052 gl_state.colormask = state;
2053 switch(vid.renderpath)
2055 case RENDERPATH_GL11:
2056 case RENDERPATH_GL13:
2057 case RENDERPATH_GL20:
2058 case RENDERPATH_CGGL:
2060 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2062 case RENDERPATH_D3D9:
2064 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2067 case RENDERPATH_D3D10:
2068 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2070 case RENDERPATH_D3D11:
2071 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2077 void GL_Color(float cr, float cg, float cb, float ca)
2079 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)
2081 gl_state.color4f[0] = cr;
2082 gl_state.color4f[1] = cg;
2083 gl_state.color4f[2] = cb;
2084 gl_state.color4f[3] = ca;
2085 switch(vid.renderpath)
2087 case RENDERPATH_GL11:
2088 case RENDERPATH_GL13:
2089 case RENDERPATH_GL20:
2090 case RENDERPATH_CGGL:
2092 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2095 case RENDERPATH_D3D9:
2096 case RENDERPATH_D3D10:
2097 case RENDERPATH_D3D11:
2098 // no equivalent in D3D
2104 void GL_Scissor (int x, int y, int width, int height)
2106 switch(vid.renderpath)
2108 case RENDERPATH_GL11:
2109 case RENDERPATH_GL13:
2110 case RENDERPATH_GL20:
2111 case RENDERPATH_CGGL:
2113 qglScissor(x, y,width,height);
2116 case RENDERPATH_D3D9:
2122 d3drect.right = x + width;
2123 d3drect.bottom = y + height;
2124 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2128 case RENDERPATH_D3D10:
2129 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2131 case RENDERPATH_D3D11:
2132 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2137 void GL_ScissorTest(int state)
2139 if (gl_state.scissortest != state)
2141 gl_state.scissortest = state;
2142 switch(vid.renderpath)
2144 case RENDERPATH_GL11:
2145 case RENDERPATH_GL13:
2146 case RENDERPATH_GL20:
2147 case RENDERPATH_CGGL:
2149 if(gl_state.scissortest)
2150 qglEnable(GL_SCISSOR_TEST);
2152 qglDisable(GL_SCISSOR_TEST);
2155 case RENDERPATH_D3D9:
2157 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2160 case RENDERPATH_D3D10:
2161 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2163 case RENDERPATH_D3D11:
2164 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2170 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2172 static const float blackcolor[4] = {0, 0, 0, 0};
2173 // prevent warnings when trying to clear a buffer that does not exist
2175 colorvalue = blackcolor;
2178 mask &= ~GL_STENCIL_BUFFER_BIT;
2181 switch(vid.renderpath)
2183 case RENDERPATH_GL11:
2184 case RENDERPATH_GL13:
2185 case RENDERPATH_GL20:
2186 case RENDERPATH_CGGL:
2188 if (mask & GL_COLOR_BUFFER_BIT)
2190 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2192 if (mask & GL_DEPTH_BUFFER_BIT)
2194 qglClearDepth(depthvalue);CHECKGLERROR
2196 if (mask & GL_STENCIL_BUFFER_BIT)
2198 qglClearStencil(stencilvalue);CHECKGLERROR
2200 qglClear(mask);CHECKGLERROR
2202 case RENDERPATH_D3D9:
2204 IDirect3DDevice9_Clear(vid_d3d9dev, 0, NULL, ((mask & GL_COLOR_BUFFER_BIT) ? D3DCLEAR_TARGET : 0) | ((mask & GL_STENCIL_BUFFER_BIT) ? D3DCLEAR_STENCIL : 0) | ((mask & GL_DEPTH_BUFFER_BIT) ? D3DCLEAR_ZBUFFER : 0), D3DCOLOR_COLORVALUE(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]), depthvalue, stencilvalue);
2207 case RENDERPATH_D3D10:
2208 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2210 case RENDERPATH_D3D11:
2211 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2216 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2218 switch(vid.renderpath)
2220 case RENDERPATH_GL11:
2221 case RENDERPATH_GL13:
2222 case RENDERPATH_GL20:
2223 case RENDERPATH_CGGL:
2225 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2227 case RENDERPATH_D3D9:
2230 // LordHavoc: we can't directly download the backbuffer because it may be
2231 // multisampled, and it may not be lockable, so we blit it to a lockable
2232 // surface of the same dimensions (but without multisample) to resolve the
2233 // multisample buffer to a normal image, and then lock that...
2234 IDirect3DSurface9 *stretchsurface = NULL;
2235 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2237 D3DLOCKED_RECT lockedrect;
2238 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2240 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2243 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2244 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2245 memcpy(outpixels + line * width * 4, row, width * 4);
2246 IDirect3DSurface9_UnlockRect(stretchsurface);
2249 IDirect3DSurface9_Release(stretchsurface);
2252 //IDirect3DSurface9 *syssurface = NULL;
2253 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2254 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2255 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2256 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2257 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2258 //IDirect3DSurface9_UnlockRect(syssurface);
2259 //IDirect3DSurface9_Release(syssurface);
2263 case RENDERPATH_D3D10:
2264 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2266 case RENDERPATH_D3D11:
2267 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2272 // called at beginning of frame
2273 void R_Mesh_Start(void)
2276 R_Mesh_ResetRenderTargets();
2278 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2280 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2281 Cvar_SetValueQuick(&gl_paranoid, 1);
2285 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2289 char compilelog[MAX_INPUTLINE];
2290 shaderobject = qglCreateShaderObjectARB(shadertypeenum);CHECKGLERROR
2293 qglShaderSourceARB(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2294 qglCompileShaderARB(shaderobject);CHECKGLERROR
2295 qglGetObjectParameterivARB(shaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &shadercompiled);CHECKGLERROR
2296 qglGetInfoLogARB(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2297 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2299 int i, j, pretextlines = 0;
2300 for (i = 0;i < numstrings - 1;i++)
2301 for (j = 0;strings[i][j];j++)
2302 if (strings[i][j] == '\n')
2304 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2306 if (!shadercompiled)
2308 qglDeleteObjectARB(shaderobject);CHECKGLERROR
2311 qglAttachObjectARB(programobject, shaderobject);CHECKGLERROR
2312 qglDeleteObjectARB(shaderobject);CHECKGLERROR
2316 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)
2318 GLint programlinked;
2319 GLuint programobject = 0;
2320 char linklog[MAX_INPUTLINE];
2323 programobject = qglCreateProgramObjectARB();CHECKGLERROR
2327 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER_ARB, "vertex", vertexstrings_count, vertexstrings_list))
2330 #ifdef GL_GEOMETRY_SHADER_ARB
2331 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER_ARB, "geometry", geometrystrings_count, geometrystrings_list))
2335 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER_ARB, "fragment", fragmentstrings_count, fragmentstrings_list))
2338 qglLinkProgramARB(programobject);CHECKGLERROR
2339 qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
2340 qglGetInfoLogARB(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2343 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2344 Con_DPrintf("program link log:\n%s\n", linklog);
2345 // software vertex shader is ok but software fragment shader is WAY
2346 // too slow, fail program if so.
2347 // NOTE: this string might be ATI specific, but that's ok because the
2348 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2349 // software fragment shader due to low instruction and dependent
2351 if (strstr(linklog, "fragment shader will run in software"))
2352 programlinked = false;
2356 return programobject;
2358 qglDeleteObjectARB(programobject);CHECKGLERROR
2362 void GL_Backend_FreeProgram(unsigned int prog)
2365 qglDeleteObjectARB(prog);
2369 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2374 for (i = 0;i < count;i++)
2375 *out++ = *in++ + offset;
2378 memcpy(out, in, sizeof(*out) * count);
2381 // renders triangles using vertices from the active arrays
2382 int paranoidblah = 0;
2383 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)
2385 unsigned int numelements = numtriangles * 3;
2387 size_t bufferoffset3i;
2389 size_t bufferoffset3s;
2390 if (numvertices < 3 || numtriangles < 1)
2392 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2393 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);
2396 if (!gl_mesh_prefer_short_elements.integer)
2400 if (element3i_indexbuffer)
2401 element3i_indexbuffer = NULL;
2403 // adjust the pointers for firsttriangle
2405 element3i += firsttriangle * 3;
2406 if (element3i_indexbuffer)
2407 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2409 element3s += firsttriangle * 3;
2410 if (element3s_indexbuffer)
2411 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2412 switch(vid.renderpath)
2414 case RENDERPATH_GL11:
2415 case RENDERPATH_GL13:
2416 case RENDERPATH_GL20:
2417 case RENDERPATH_CGGL:
2418 // check if the user specified to ignore static index buffers
2419 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2421 element3i_indexbuffer = NULL;
2422 element3s_indexbuffer = NULL;
2425 case RENDERPATH_D3D9:
2426 case RENDERPATH_D3D10:
2427 case RENDERPATH_D3D11:
2430 // upload a dynamic index buffer if needed
2433 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2435 if (gl_state.draw_dynamicindexbuffer)
2436 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2438 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2439 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2440 element3s_bufferoffset = 0;
2445 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2447 if (gl_state.draw_dynamicindexbuffer)
2448 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2450 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2451 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2452 element3i_bufferoffset = 0;
2455 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2456 bufferoffset3i = element3i_bufferoffset;
2457 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2458 bufferoffset3s = element3s_bufferoffset;
2459 r_refdef.stats.draws++;
2460 r_refdef.stats.draws_vertices += numvertices;
2461 r_refdef.stats.draws_elements += numelements;
2462 if (gl_paranoid.integer)
2465 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2467 unsigned int j, size;
2469 // note: there's no validation done here on buffer objects because it
2470 // is somewhat difficult to get at the data, and gl_paranoid can be
2471 // used without buffer objects if the need arises
2472 // (the data could be gotten using glMapBuffer but it would be very
2473 // slow due to uncachable video memory reads)
2474 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2475 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2477 if (gl_state.pointer_vertex_pointer)
2478 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2480 if (gl_state.pointer_color_enabled)
2482 if (!qglIsEnabled(GL_COLOR_ARRAY))
2483 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2485 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2486 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2489 for (i = 0;i < vid.texarrayunits;i++)
2491 if (gl_state.units[i].arrayenabled)
2493 GL_ClientActiveTexture(i);
2494 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2495 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2497 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2498 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++)
2505 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2507 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2509 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2516 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2518 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2520 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2526 if (r_render.integer || r_refdef.draw2dstage)
2528 switch(vid.renderpath)
2530 case RENDERPATH_GL11:
2531 case RENDERPATH_GL13:
2532 case RENDERPATH_GL20:
2533 case RENDERPATH_CGGL:
2535 if (gl_mesh_testmanualfeeding.integer)
2537 unsigned int i, j, element;
2539 qglBegin(GL_TRIANGLES);
2540 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2543 element = element3i[i];
2545 element = element3s[i];
2547 element = firstvertex + i;
2548 for (j = 0;j < vid.texarrayunits;j++)
2550 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2552 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2554 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2555 if (vid.texarrayunits > 1)
2557 if (gl_state.units[j].pointer_texcoord_components == 4)
2558 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2559 else if (gl_state.units[j].pointer_texcoord_components == 3)
2560 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2561 else if (gl_state.units[j].pointer_texcoord_components == 2)
2562 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2564 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2568 if (gl_state.units[j].pointer_texcoord_components == 4)
2569 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2570 else if (gl_state.units[j].pointer_texcoord_components == 3)
2571 qglTexCoord3f(p[0], p[1], p[2]);
2572 else if (gl_state.units[j].pointer_texcoord_components == 2)
2573 qglTexCoord2f(p[0], p[1]);
2575 qglTexCoord1f(p[0]);
2578 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2580 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2581 if (vid.texarrayunits > 1)
2583 if (gl_state.units[j].pointer_texcoord_components == 4)
2584 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2585 else if (gl_state.units[j].pointer_texcoord_components == 3)
2586 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2587 else if (gl_state.units[j].pointer_texcoord_components == 2)
2588 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2589 else if (gl_state.units[j].pointer_texcoord_components == 1)
2590 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2594 if (gl_state.units[j].pointer_texcoord_components == 4)
2595 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2596 else if (gl_state.units[j].pointer_texcoord_components == 3)
2597 qglTexCoord3f(s[0], s[1], s[2]);
2598 else if (gl_state.units[j].pointer_texcoord_components == 2)
2599 qglTexCoord2f(s[0], s[1]);
2600 else if (gl_state.units[j].pointer_texcoord_components == 1)
2601 qglTexCoord1f(s[0]);
2604 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2606 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2607 if (vid.texarrayunits > 1)
2609 if (gl_state.units[j].pointer_texcoord_components == 4)
2610 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2611 else if (gl_state.units[j].pointer_texcoord_components == 3)
2612 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2613 else if (gl_state.units[j].pointer_texcoord_components == 2)
2614 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2615 else if (gl_state.units[j].pointer_texcoord_components == 1)
2616 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2620 if (gl_state.units[j].pointer_texcoord_components == 4)
2621 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2622 else if (gl_state.units[j].pointer_texcoord_components == 3)
2623 qglTexCoord3f(sb[0], sb[1], sb[2]);
2624 else if (gl_state.units[j].pointer_texcoord_components == 2)
2625 qglTexCoord2f(sb[0], sb[1]);
2626 else if (gl_state.units[j].pointer_texcoord_components == 1)
2627 qglTexCoord1f(sb[0]);
2632 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2634 if (gl_state.pointer_color_gltype == GL_FLOAT)
2636 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2637 qglColor4f(p[0], p[1], p[2], p[3]);
2639 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2641 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2642 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2645 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2647 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2648 if (gl_state.pointer_vertex_components == 4)
2649 qglVertex4f(p[0], p[1], p[2], p[3]);
2650 else if (gl_state.pointer_vertex_components == 3)
2651 qglVertex3f(p[0], p[1], p[2]);
2653 qglVertex2f(p[0], p[1]);
2659 else if (bufferobject3s)
2661 GL_BindEBO(bufferobject3s);
2662 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2664 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2669 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2673 else if (bufferobject3i)
2675 GL_BindEBO(bufferobject3i);
2676 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2678 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2683 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2690 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2692 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2697 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2704 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2706 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2711 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2717 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2721 case RENDERPATH_D3D9:
2723 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2725 if (element3s_indexbuffer)
2727 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2728 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2730 else if (element3i_indexbuffer)
2732 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2733 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2736 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2741 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s + firsttriangle*3, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2743 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i + firsttriangle*3, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2745 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *) ((byte *) gl_state.d3dvertexdata + (numvertices * gl_state.d3dvertexsize)), gl_state.d3dvertexsize);
2749 case RENDERPATH_D3D10:
2750 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2752 case RENDERPATH_D3D11:
2753 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2759 // restores backend state, used when done with 3D rendering
2760 void R_Mesh_Finish(void)
2762 R_Mesh_ResetRenderTargets();
2765 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2767 r_meshbuffer_t *buffer;
2768 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
2770 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2771 memset(buffer, 0, sizeof(*buffer));
2772 buffer->bufferobject = 0;
2773 buffer->devicebuffer = NULL;
2775 buffer->isindexbuffer = isindexbuffer;
2776 buffer->isdynamic = isdynamic;
2777 buffer->isindex16 = isindex16;
2778 strlcpy(buffer->name, name, sizeof(buffer->name));
2779 R_Mesh_UpdateMeshBuffer(buffer, data, size);
2783 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
2787 if (buffer->isindexbuffer)
2789 r_refdef.stats.indexbufferuploadcount++;
2790 r_refdef.stats.indexbufferuploadsize += size;
2794 r_refdef.stats.vertexbufferuploadcount++;
2795 r_refdef.stats.vertexbufferuploadsize += size;
2797 switch(vid.renderpath)
2799 case RENDERPATH_GL11:
2800 case RENDERPATH_GL13:
2801 case RENDERPATH_GL20:
2802 case RENDERPATH_CGGL:
2803 if (!buffer->bufferobject)
2804 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
2805 if (buffer->isindexbuffer)
2806 GL_BindEBO(buffer->bufferobject);
2808 GL_BindVBO(buffer->bufferobject);
2809 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
2811 case RENDERPATH_D3D9:
2815 void *datapointer = NULL;
2816 if (buffer->isindexbuffer)
2818 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
2819 if (size > buffer->size || !buffer->devicebuffer)
2821 if (buffer->devicebuffer)
2822 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
2823 buffer->devicebuffer = NULL;
2824 if (FAILED(result = IDirect3DDevice9_CreateIndexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9indexbuffer, NULL)))
2825 Sys_Error("IDirect3DDevice9_CreateIndexBuffer(%p, %d, %x, %x, %x, %p, NULL) returned %x\n", vid_d3d9dev, (int)size, buffer->isdynamic ? (int)D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? (int)D3DFMT_INDEX16 : (int)D3DFMT_INDEX32, buffer->isdynamic ? (int)D3DPOOL_DEFAULT : (int)D3DPOOL_MANAGED, &d3d9indexbuffer, (int)result);
2826 buffer->devicebuffer = (void *)d3d9indexbuffer;
2827 buffer->size = size;
2829 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
2832 memcpy(datapointer, data, size);
2834 memset(datapointer, 0, size);
2835 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
2840 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
2841 if (size > buffer->size || !buffer->devicebuffer)
2843 if (buffer->devicebuffer)
2844 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
2845 buffer->devicebuffer = NULL;
2846 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
2847 Sys_Error("IDirect3DDevice9_CreateVertexBuffer(%p, %d, %x, %x, %x, %p, NULL) returned %x\n", vid_d3d9dev, (int)size, buffer->isdynamic ? (int)D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? (int)D3DPOOL_DEFAULT : (int)D3DPOOL_MANAGED, &d3d9vertexbuffer, (int)result);
2848 buffer->devicebuffer = (void *)d3d9vertexbuffer;
2849 buffer->size = size;
2851 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
2854 memcpy(datapointer, data, size);
2856 memset(datapointer, 0, size);
2857 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
2863 case RENDERPATH_D3D10:
2864 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2866 case RENDERPATH_D3D11:
2867 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2872 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
2876 switch(vid.renderpath)
2878 case RENDERPATH_GL11:
2879 case RENDERPATH_GL13:
2880 case RENDERPATH_GL20:
2881 case RENDERPATH_CGGL:
2882 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
2884 case RENDERPATH_D3D9:
2886 if (gl_state.d3dvertexbuffer == (void *)buffer)
2887 gl_state.d3dvertexbuffer = NULL;
2888 if (buffer->devicebuffer)
2890 if (buffer->isindexbuffer)
2891 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
2893 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
2894 buffer->devicebuffer = NULL;
2898 case RENDERPATH_D3D10:
2899 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2901 case RENDERPATH_D3D11:
2902 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2905 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
2908 void GL_Mesh_ListVBOs(qboolean printeach)
2911 size_t ebocount = 0, ebomemory = 0;
2912 size_t vbocount = 0, vbomemory = 0;
2913 r_meshbuffer_t *buffer;
2914 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
2915 for (i = 0;i < endindex;i++)
2917 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
2920 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)");}
2921 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)");}
2923 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);
2928 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
2930 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2931 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)
2933 gl_state.pointer_vertex_components = components;
2934 gl_state.pointer_vertex_gltype = gltype;
2935 gl_state.pointer_vertex_stride = stride;
2936 gl_state.pointer_vertex_pointer = pointer;
2937 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
2938 gl_state.pointer_vertex_offset = bufferoffset;
2940 GL_BindVBO(bufferobject);
2941 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2945 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
2947 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
2948 // the pointer only.
2951 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2952 // caller wants color array enabled
2953 if (!gl_state.pointer_color_enabled)
2955 gl_state.pointer_color_enabled = true;
2957 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
2959 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)
2961 gl_state.pointer_color_components = components;
2962 gl_state.pointer_color_gltype = gltype;
2963 gl_state.pointer_color_stride = stride;
2964 gl_state.pointer_color_pointer = pointer;
2965 gl_state.pointer_color_vertexbuffer = vertexbuffer;
2966 gl_state.pointer_color_offset = bufferoffset;
2968 GL_BindVBO(bufferobject);
2969 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2974 // caller wants color array disabled
2975 if (gl_state.pointer_color_enabled)
2977 gl_state.pointer_color_enabled = false;
2979 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
2980 // when color array is on the glColor gets trashed, set it again
2981 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
2986 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)
2988 gltextureunit_t *unit = gl_state.units + unitnum;
2989 // update array settings
2991 // note: there is no need to check bufferobject here because all cases
2992 // that involve a valid bufferobject also supply a texcoord array
2995 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2996 // texture array unit is enabled, enable the array
2997 if (!unit->arrayenabled)
2999 unit->arrayenabled = true;
3000 GL_ClientActiveTexture(unitnum);
3001 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3004 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)
3006 unit->pointer_texcoord_components = components;
3007 unit->pointer_texcoord_gltype = gltype;
3008 unit->pointer_texcoord_stride = stride;
3009 unit->pointer_texcoord_pointer = pointer;
3010 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3011 unit->pointer_texcoord_offset = bufferoffset;
3012 GL_ClientActiveTexture(unitnum);
3013 GL_BindVBO(bufferobject);
3014 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3019 // texture array unit is disabled, disable the array
3020 if (unit->arrayenabled)
3022 unit->arrayenabled = false;
3023 GL_ClientActiveTexture(unitnum);
3024 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3029 int R_Mesh_TexBound(unsigned int unitnum, int id)
3031 gltextureunit_t *unit = gl_state.units + unitnum;
3032 if (unitnum >= vid.teximageunits)
3034 if (id == GL_TEXTURE_2D)
3036 if (id == GL_TEXTURE_3D)
3038 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3039 return unit->tcubemap;
3043 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3045 switch(vid.renderpath)
3047 case RENDERPATH_GL11:
3048 case RENDERPATH_GL13:
3049 case RENDERPATH_GL20:
3050 case RENDERPATH_CGGL:
3051 R_Mesh_TexBind(0, tex);
3052 GL_ActiveTexture(0);CHECKGLERROR
3053 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3055 case RENDERPATH_D3D9:
3058 IDirect3DSurface9 *currentsurface = NULL;
3059 IDirect3DSurface9 *texturesurface = NULL;
3062 sourcerect.left = sx;
3063 sourcerect.top = sy;
3064 sourcerect.right = sx + width;
3065 sourcerect.bottom = sy + height;
3068 destrect.right = tx + width;
3069 destrect.bottom = ty + height;
3070 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3072 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3074 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3075 IDirect3DSurface9_Release(currentsurface);
3077 IDirect3DSurface9_Release(texturesurface);
3082 case RENDERPATH_D3D10:
3083 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3085 case RENDERPATH_D3D11:
3086 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3092 int d3drswrap[16] = {D3DRS_WRAP0, D3DRS_WRAP1, D3DRS_WRAP2, D3DRS_WRAP3, D3DRS_WRAP4, D3DRS_WRAP5, D3DRS_WRAP6, D3DRS_WRAP7, D3DRS_WRAP8, D3DRS_WRAP9, D3DRS_WRAP10, D3DRS_WRAP11, D3DRS_WRAP12, D3DRS_WRAP13, D3DRS_WRAP14, D3DRS_WRAP15};
3095 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3097 gltextureunit_t *unit = gl_state.units + unitnum;
3098 int tex2d, tex3d, texcubemap, texnum;
3099 if (unitnum >= vid.teximageunits)
3101 // if (unit->texture == tex)
3103 switch(vid.renderpath)
3105 case RENDERPATH_GL20:
3106 case RENDERPATH_CGGL:
3109 tex = r_texture_white;
3110 // not initialized enough yet...
3114 unit->texture = tex;
3115 texnum = R_GetTexture(tex);
3116 switch(tex->gltexturetypeenum)
3118 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3119 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3120 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;
3123 case RENDERPATH_GL13:
3124 case RENDERPATH_GL11:
3125 unit->texture = tex;
3131 texnum = R_GetTexture(tex);
3132 switch(tex->gltexturetypeenum)
3140 case GL_TEXTURE_CUBE_MAP_ARB:
3141 texcubemap = texnum;
3145 // update 2d texture binding
3146 if (unit->t2d != tex2d)
3148 GL_ActiveTexture(unitnum);
3153 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3160 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3164 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3166 // update 3d texture binding
3167 if (unit->t3d != tex3d)
3169 GL_ActiveTexture(unitnum);
3174 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3181 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3185 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3187 // update cubemap texture binding
3188 if (unit->tcubemap != texcubemap)
3190 GL_ActiveTexture(unitnum);
3193 if (unit->tcubemap == 0)
3195 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3202 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3205 unit->tcubemap = texcubemap;
3206 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3209 case RENDERPATH_D3D9:
3212 extern cvar_t gl_texture_anisotropy;
3215 tex = r_texture_white;
3216 // not initialized enough yet...
3220 if (unit->texture == tex)
3222 unit->texture = tex;
3223 // upload texture if needed
3225 R_RealGetTexture(tex);
3226 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3227 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3228 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3229 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3230 if (tex->d3daddressw)
3231 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3232 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3233 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3234 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3235 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3236 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3237 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3241 case RENDERPATH_D3D10:
3242 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3244 case RENDERPATH_D3D11:
3245 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3250 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3252 gltextureunit_t *unit = gl_state.units + unitnum;
3253 switch(vid.renderpath)
3255 case RENDERPATH_GL11:
3256 case RENDERPATH_GL13:
3257 case RENDERPATH_GL20:
3258 case RENDERPATH_CGGL:
3259 if (matrix && matrix->m[3][3])
3261 // texmatrix specified, check if it is different
3262 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3265 unit->texmatrixenabled = true;
3266 unit->matrix = *matrix;
3268 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3269 GL_ActiveTexture(unitnum);
3270 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3271 qglLoadMatrixf(glmatrix);CHECKGLERROR
3272 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3277 // no texmatrix specified, revert to identity
3278 if (unit->texmatrixenabled)
3280 unit->texmatrixenabled = false;
3281 unit->matrix = identitymatrix;
3283 GL_ActiveTexture(unitnum);
3284 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3285 qglLoadIdentity();CHECKGLERROR
3286 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3290 case RENDERPATH_D3D9:
3291 case RENDERPATH_D3D10:
3292 case RENDERPATH_D3D11:
3297 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3299 gltextureunit_t *unit = gl_state.units + unitnum;
3301 switch(vid.renderpath)
3303 case RENDERPATH_GL20:
3304 case RENDERPATH_CGGL:
3307 case RENDERPATH_GL13:
3308 // GL_ARB_texture_env_combine
3310 combinergb = GL_MODULATE;
3312 combinealpha = GL_MODULATE;
3317 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3319 if (combinergb == GL_DECAL)
3320 combinergb = GL_INTERPOLATE_ARB;
3321 if (unit->combine != GL_COMBINE_ARB)
3323 unit->combine = GL_COMBINE_ARB;
3324 GL_ActiveTexture(unitnum);
3325 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3326 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3328 if (unit->combinergb != combinergb)
3330 unit->combinergb = combinergb;
3331 GL_ActiveTexture(unitnum);
3332 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3334 if (unit->combinealpha != combinealpha)
3336 unit->combinealpha = combinealpha;
3337 GL_ActiveTexture(unitnum);
3338 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3340 if (unit->rgbscale != rgbscale)
3342 unit->rgbscale = rgbscale;
3343 GL_ActiveTexture(unitnum);
3344 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3346 if (unit->alphascale != alphascale)
3348 unit->alphascale = alphascale;
3349 GL_ActiveTexture(unitnum);
3350 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3355 if (unit->combine != combinergb)
3357 unit->combine = combinergb;
3358 GL_ActiveTexture(unitnum);
3359 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3363 case RENDERPATH_GL11:
3366 combinergb = GL_MODULATE;
3367 if (unit->combine != combinergb)
3369 unit->combine = combinergb;
3370 GL_ActiveTexture(unitnum);
3371 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3374 case RENDERPATH_D3D9:
3375 case RENDERPATH_D3D10:
3376 case RENDERPATH_D3D11:
3381 void R_Mesh_ResetTextureState(void)
3383 unsigned int unitnum;
3388 switch(vid.renderpath)
3390 case RENDERPATH_GL20:
3391 case RENDERPATH_CGGL:
3392 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3394 gltextureunit_t *unit = gl_state.units + unitnum;
3398 GL_ActiveTexture(unitnum);
3399 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3404 GL_ActiveTexture(unitnum);
3405 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3410 GL_ActiveTexture(unitnum);
3411 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3414 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3416 gltextureunit_t *unit = gl_state.units + unitnum;
3417 if (unit->arrayenabled)
3419 unit->arrayenabled = false;
3420 GL_ClientActiveTexture(unitnum);
3421 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3424 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3426 gltextureunit_t *unit = gl_state.units + unitnum;
3427 if (unit->texmatrixenabled)
3429 unit->texmatrixenabled = false;
3430 unit->matrix = identitymatrix;
3432 GL_ActiveTexture(unitnum);
3433 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3434 qglLoadIdentity();CHECKGLERROR
3435 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3439 case RENDERPATH_GL13:
3440 case RENDERPATH_GL11:
3441 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3443 gltextureunit_t *unit = gl_state.units + unitnum;
3447 GL_ActiveTexture(unitnum);
3448 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3449 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3454 GL_ActiveTexture(unitnum);
3455 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3456 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3461 GL_ActiveTexture(unitnum);
3462 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3463 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3465 if (unit->arrayenabled)
3467 unit->arrayenabled = false;
3468 GL_ClientActiveTexture(unitnum);
3469 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3471 if (unit->texmatrixenabled)
3473 unit->texmatrixenabled = false;
3474 unit->matrix = identitymatrix;
3476 GL_ActiveTexture(unitnum);
3477 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3478 qglLoadIdentity();CHECKGLERROR
3479 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3481 if (unit->combine != GL_MODULATE)
3483 unit->combine = GL_MODULATE;
3484 GL_ActiveTexture(unitnum);
3485 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3489 case RENDERPATH_D3D9:
3490 case RENDERPATH_D3D10:
3491 case RENDERPATH_D3D11:
3499 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3500 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3501 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3503 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3505 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3509 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3511 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3512 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3513 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3517 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3519 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3520 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3521 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3522 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3523 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3524 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3525 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3529 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3530 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3531 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3534 static void R_Mesh_InitVertexDeclarations(void)
3537 r_vertex3f_d3d9decl = NULL;
3538 r_vertexgeneric_d3d9decl = NULL;
3539 r_vertexmesh_d3d9decl = NULL;
3540 switch(vid.renderpath)
3542 case RENDERPATH_GL20:
3543 case RENDERPATH_CGGL:
3544 case RENDERPATH_GL13:
3545 case RENDERPATH_GL11:
3547 case RENDERPATH_D3D9:
3548 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3549 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3550 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3552 case RENDERPATH_D3D10:
3553 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3555 case RENDERPATH_D3D11:
3556 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3562 static void R_Mesh_DestroyVertexDeclarations(void)
3565 if (r_vertex3f_d3d9decl)
3566 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3567 r_vertex3f_d3d9decl = NULL;
3568 if (r_vertexgeneric_d3d9decl)
3569 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3570 r_vertexgeneric_d3d9decl = NULL;
3571 if (r_vertexmesh_d3d9decl)
3572 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3573 r_vertexmesh_d3d9decl = NULL;
3577 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3579 // upload temporary vertexbuffer for this rendering
3580 if (!gl_state.usevbo_staticvertex)
3581 vertexbuffer = NULL;
3582 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3584 if (gl_state.preparevertices_dynamicvertexbuffer)
3585 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3587 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3588 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3590 switch(vid.renderpath)
3592 case RENDERPATH_GL20:
3593 case RENDERPATH_CGGL:
3596 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3597 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3598 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3599 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3600 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3601 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3602 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3606 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3607 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3608 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3609 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3610 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3611 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3612 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3615 case RENDERPATH_GL13:
3618 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3619 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3620 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3621 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3625 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3626 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3627 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3628 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3631 case RENDERPATH_GL11:
3634 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3635 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3636 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3640 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3641 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3642 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3645 case RENDERPATH_D3D9:
3647 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3649 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3651 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3652 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3653 gl_state.d3dvertexdata = (void *)vertex3f;
3654 gl_state.d3dvertexsize = sizeof(float[3]);
3657 case RENDERPATH_D3D10:
3658 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3660 case RENDERPATH_D3D11:
3661 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3668 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
3671 size = sizeof(r_vertexgeneric_t) * numvertices;
3672 if (gl_state.preparevertices_tempdatamaxsize < size)
3674 gl_state.preparevertices_tempdatamaxsize = size;
3675 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3677 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
3678 gl_state.preparevertices_numvertices = numvertices;
3679 return gl_state.preparevertices_vertexgeneric;
3682 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
3684 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
3685 gl_state.preparevertices_vertexgeneric = NULL;
3686 gl_state.preparevertices_numvertices = 0;
3690 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
3693 r_vertexgeneric_t *vertex;
3694 switch(vid.renderpath)
3696 case RENDERPATH_GL20:
3697 case RENDERPATH_CGGL:
3698 if (!vid.useinterleavedarrays)
3700 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3701 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3702 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3703 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3704 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3705 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3706 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3710 case RENDERPATH_GL13:
3711 case RENDERPATH_GL11:
3712 if (!vid.useinterleavedarrays)
3714 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3715 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3716 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3717 if (vid.texunits >= 2)
3718 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3719 if (vid.texunits >= 3)
3720 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3724 case RENDERPATH_D3D9:
3725 case RENDERPATH_D3D10:
3726 case RENDERPATH_D3D11:
3730 // no quick path for this case, convert to vertex structs
3731 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
3732 for (i = 0;i < numvertices;i++)
3733 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
3736 for (i = 0;i < numvertices;i++)
3737 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
3741 float tempcolor4f[4];
3742 unsigned char tempcolor4ub[4];
3743 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
3744 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
3745 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
3746 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
3747 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
3748 for (i = 0;i < numvertices;i++)
3749 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
3752 for (i = 0;i < numvertices;i++)
3753 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
3754 R_Mesh_PrepareVertices_Generic_Unlock();
3755 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
3758 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
3760 // upload temporary vertexbuffer for this rendering
3761 if (!gl_state.usevbo_staticvertex)
3762 vertexbuffer = NULL;
3763 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3765 if (gl_state.preparevertices_dynamicvertexbuffer)
3766 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
3768 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
3769 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3771 switch(vid.renderpath)
3773 case RENDERPATH_GL20:
3774 case RENDERPATH_CGGL:
3777 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3778 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3779 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
3780 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3781 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3782 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3783 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3787 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3788 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
3789 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
3790 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3791 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3792 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3793 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3796 case RENDERPATH_GL13:
3799 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3800 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3801 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
3802 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3806 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3807 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
3808 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
3809 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3812 case RENDERPATH_GL11:
3815 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3816 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3817 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
3821 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3822 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
3823 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
3826 case RENDERPATH_D3D9:
3828 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
3830 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
3832 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3833 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3834 gl_state.d3dvertexdata = (void *)vertex;
3835 gl_state.d3dvertexsize = sizeof(*vertex);
3838 case RENDERPATH_D3D10:
3839 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3841 case RENDERPATH_D3D11:
3842 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3849 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
3852 size = sizeof(r_vertexmesh_t) * numvertices;
3853 if (gl_state.preparevertices_tempdatamaxsize < size)
3855 gl_state.preparevertices_tempdatamaxsize = size;
3856 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3858 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
3859 gl_state.preparevertices_numvertices = numvertices;
3860 return gl_state.preparevertices_vertexmesh;
3863 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
3865 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
3866 gl_state.preparevertices_vertexmesh = NULL;
3867 gl_state.preparevertices_numvertices = 0;
3871 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)
3874 r_vertexmesh_t *vertex;
3875 switch(vid.renderpath)
3877 case RENDERPATH_GL20:
3878 case RENDERPATH_CGGL:
3879 if (!vid.useinterleavedarrays)
3881 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3882 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3883 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
3884 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
3885 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
3886 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
3887 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
3891 case RENDERPATH_GL13:
3892 case RENDERPATH_GL11:
3893 if (!vid.useinterleavedarrays)
3895 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3896 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3897 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
3898 if (vid.texunits >= 2)
3899 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
3900 if (vid.texunits >= 3)
3901 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3905 case RENDERPATH_D3D9:
3906 case RENDERPATH_D3D10:
3907 case RENDERPATH_D3D11:
3911 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
3912 for (i = 0;i < numvertices;i++)
3913 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
3915 for (i = 0;i < numvertices;i++)
3916 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
3918 for (i = 0;i < numvertices;i++)
3919 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
3921 for (i = 0;i < numvertices;i++)
3922 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
3925 for (i = 0;i < numvertices;i++)
3926 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
3930 float tempcolor4f[4];
3931 unsigned char tempcolor4ub[4];
3932 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
3933 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
3934 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
3935 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
3936 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
3937 for (i = 0;i < numvertices;i++)
3938 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
3940 if (texcoordtexture2f)
3941 for (i = 0;i < numvertices;i++)
3942 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
3943 if (texcoordlightmap2f)
3944 for (i = 0;i < numvertices;i++)
3945 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
3946 R_Mesh_PrepareVertices_Mesh_Unlock();
3947 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
3950 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
3952 // upload temporary vertexbuffer for this rendering
3953 if (!gl_state.usevbo_staticvertex)
3954 vertexbuffer = NULL;
3955 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3957 if (gl_state.preparevertices_dynamicvertexbuffer)
3958 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
3960 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
3961 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3963 switch(vid.renderpath)
3965 case RENDERPATH_GL20:
3966 case RENDERPATH_CGGL:
3969 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3970 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3971 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
3972 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
3973 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
3974 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
3975 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
3979 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3980 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
3981 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
3982 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
3983 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
3984 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
3985 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
3988 case RENDERPATH_GL13:
3991 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3992 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3993 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
3994 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
3998 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3999 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4000 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4001 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4004 case RENDERPATH_GL11:
4007 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4008 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4009 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4013 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4014 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4015 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4018 case RENDERPATH_D3D9:
4020 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4022 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4024 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4025 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4026 gl_state.d3dvertexdata = (void *)vertex;
4027 gl_state.d3dvertexsize = sizeof(*vertex);
4030 case RENDERPATH_D3D10:
4031 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4033 case RENDERPATH_D3D11:
4034 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);