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_mesh_separatearrays = {0, "gl_mesh_separatearrays", "1", "use several separate vertex arrays rather than one combined stream"};
16 cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
17 cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
19 cvar_t r_render = {0, "r_render", "1", "enables rendering 3D views (you want this on!)"};
20 cvar_t r_renderview = {0, "r_renderview", "1", "enables rendering 3D views (you want this on!)"};
21 cvar_t r_waterwarp = {CVAR_SAVE, "r_waterwarp", "1", "warp view while underwater"};
22 cvar_t gl_polyblend = {CVAR_SAVE, "gl_polyblend", "1", "tints view while underwater, hurt, etc"};
23 cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
24 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)"};
25 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"};
26 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"};
27 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"};
29 cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
30 qboolean v_flipped_state = false;
32 r_viewport_t gl_viewport;
33 matrix4x4_t gl_modelmatrix;
34 matrix4x4_t gl_viewmatrix;
35 matrix4x4_t gl_modelviewmatrix;
36 matrix4x4_t gl_projectionmatrix;
37 matrix4x4_t gl_modelviewprojectionmatrix;
38 float gl_modelview16f[16];
39 float gl_modelviewprojection16f[16];
40 qboolean gl_modelmatrixchanged;
42 int gl_maxdrawrangeelementsvertices;
43 int gl_maxdrawrangeelementsindices;
48 void GL_PrintError(int errornumber, const char *filename, int linenumber)
52 #ifdef GL_INVALID_ENUM
54 Con_Printf("GL_INVALID_ENUM at %s:%i\n", filename, linenumber);
57 #ifdef GL_INVALID_VALUE
58 case GL_INVALID_VALUE:
59 Con_Printf("GL_INVALID_VALUE at %s:%i\n", filename, linenumber);
62 #ifdef GL_INVALID_OPERATION
63 case GL_INVALID_OPERATION:
64 Con_Printf("GL_INVALID_OPERATION at %s:%i\n", filename, linenumber);
67 #ifdef GL_STACK_OVERFLOW
68 case GL_STACK_OVERFLOW:
69 Con_Printf("GL_STACK_OVERFLOW at %s:%i\n", filename, linenumber);
72 #ifdef GL_STACK_UNDERFLOW
73 case GL_STACK_UNDERFLOW:
74 Con_Printf("GL_STACK_UNDERFLOW at %s:%i\n", filename, linenumber);
77 #ifdef GL_OUT_OF_MEMORY
78 case GL_OUT_OF_MEMORY:
79 Con_Printf("GL_OUT_OF_MEMORY at %s:%i\n", filename, linenumber);
82 #ifdef GL_TABLE_TOO_LARGE
83 case GL_TABLE_TOO_LARGE:
84 Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber);
87 #ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT
88 case GL_INVALID_FRAMEBUFFER_OPERATION_EXT:
89 Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber);
93 Con_Printf("GL UNKNOWN (%i) at %s:%i\n", errornumber, filename, linenumber);
99 #define BACKENDACTIVECHECK if (!gl_state.active) Sys_Error("GL backend function called when backend is not active");
101 void SCR_ScreenShot_f (void);
103 typedef struct gltextureunit_s
105 int pointer_texcoord_components;
106 int pointer_texcoord_gltype;
107 size_t pointer_texcoord_stride;
108 const void *pointer_texcoord_pointer;
109 const r_meshbuffer_t *pointer_texcoord_vertexbuffer;
110 size_t pointer_texcoord_offset;
113 int t2d, t3d, tcubemap;
115 int rgbscale, alphascale;
117 int combinergb, combinealpha;
118 // texmatrixenabled exists only to avoid unnecessary texmatrix compares
119 int texmatrixenabled;
124 typedef struct gl_state_s
132 int colormask; // stored as bottom 4 bits: r g b a (3 2 1 0 order)
136 float polygonoffset[2];
139 float alphafuncvalue;
142 unsigned int clientunit;
143 gltextureunit_t units[MAX_TEXTUREUNITS];
147 int vertexbufferobject;
148 int elementbufferobject;
149 int framebufferobject;
150 qboolean pointer_color_enabled;
152 int pointer_vertex_components;
153 int pointer_vertex_gltype;
154 size_t pointer_vertex_stride;
155 const void *pointer_vertex_pointer;
156 const r_meshbuffer_t *pointer_vertex_vertexbuffer;
157 size_t pointer_vertex_offset;
159 int pointer_color_components;
160 int pointer_color_gltype;
161 size_t pointer_color_stride;
162 const void *pointer_color_pointer;
163 const r_meshbuffer_t *pointer_color_vertexbuffer;
164 size_t pointer_color_offset;
166 void *preparevertices_tempdata;
167 size_t preparevertices_tempdatamaxsize;
168 r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
169 r_vertexposition_t *preparevertices_vertexposition;
170 r_vertexgeneric_t *preparevertices_vertexgeneric;
171 r_vertexmesh_t *preparevertices_vertexmesh;
172 int preparevertices_numvertices;
174 r_meshbuffer_t *draw_dynamicindexbuffer;
176 qboolean usevbo_staticvertex;
177 qboolean usevbo_staticindex;
178 qboolean usevbo_dynamicvertex;
179 qboolean usevbo_dynamicindex;
181 memexpandablearray_t meshbufferarray;
186 // rtexture_t *d3drt_depthtexture;
187 // rtexture_t *d3drt_colortextures[MAX_RENDERTARGETS];
188 IDirect3DSurface9 *d3drt_depthsurface;
189 IDirect3DSurface9 *d3drt_colorsurfaces[MAX_RENDERTARGETS];
190 IDirect3DSurface9 *d3drt_backbufferdepthsurface;
191 IDirect3DSurface9 *d3drt_backbuffercolorsurface;
192 void *d3dvertexbuffer;
194 size_t d3dvertexsize;
199 static gl_state_t gl_state;
203 note: here's strip order for a terrain row:
210 A0B, 01B, B1C, 12C, C2D, 23D, D3E, 34E
212 *elements++ = i + row;
214 *elements++ = i + row + 1;
217 *elements++ = i + row + 1;
220 for (y = 0;y < rows - 1;y++)
222 for (x = 0;x < columns - 1;x++)
225 *elements++ = i + columns;
227 *elements++ = i + columns + 1;
230 *elements++ = i + columns + 1;
241 for (y = 0;y < rows - 1;y++)
243 for (x = 0;x < columns - 1;x++)
247 *elements++ = i + columns;
248 *elements++ = i + columns + 1;
249 *elements++ = i + columns;
250 *elements++ = i + columns + 1;
256 int polygonelement3i[(POLYGONELEMENTS_MAXPOINTS-2)*3];
257 unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3];
258 int quadelement3i[QUADELEMENTS_MAXQUADS*6];
259 unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6];
261 void GL_VBOStats_f(void)
263 GL_Mesh_ListVBOs(true);
266 static void GL_Backend_ResetState(void);
268 static void R_Mesh_InitVertexDeclarations(void);
269 static void R_Mesh_DestroyVertexDeclarations(void);
271 static void R_Mesh_SetUseVBO(void)
273 switch(vid.renderpath)
275 case RENDERPATH_GL11:
276 case RENDERPATH_GL13:
277 case RENDERPATH_GL20:
278 case RENDERPATH_CGGL:
279 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
280 gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo;
281 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
282 gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo;
284 case RENDERPATH_D3D9:
285 gl_state.usevbo_staticvertex = gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
286 gl_state.usevbo_dynamicvertex = gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo_dynamicindex.integer) || vid.forcevbo;
288 case RENDERPATH_D3D10:
289 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
291 case RENDERPATH_D3D11:
292 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
297 static void gl_backend_start(void)
299 memset(&gl_state, 0, sizeof(gl_state));
301 R_Mesh_InitVertexDeclarations();
304 Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
306 Con_DPrintf("OpenGL backend started.\n");
310 GL_Backend_ResetState();
312 switch(vid.renderpath)
314 case RENDERPATH_GL11:
315 case RENDERPATH_GL13:
316 case RENDERPATH_GL20:
317 case RENDERPATH_CGGL:
319 case RENDERPATH_D3D9:
321 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
322 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
325 case RENDERPATH_D3D10:
326 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
328 case RENDERPATH_D3D11:
329 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
334 static void gl_backend_shutdown(void)
336 Con_DPrint("OpenGL Backend shutting down\n");
338 switch(vid.renderpath)
340 case RENDERPATH_GL11:
341 case RENDERPATH_GL13:
342 case RENDERPATH_GL20:
343 case RENDERPATH_CGGL:
345 case RENDERPATH_D3D9:
347 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
348 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
351 case RENDERPATH_D3D10:
352 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
354 case RENDERPATH_D3D11:
355 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
359 if (gl_state.preparevertices_tempdata)
360 Mem_Free(gl_state.preparevertices_tempdata);
361 if (gl_state.preparevertices_dynamicvertexbuffer)
362 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
364 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
366 R_Mesh_DestroyVertexDeclarations();
368 memset(&gl_state, 0, sizeof(gl_state));
371 static void gl_backend_newmap(void)
375 static void gl_backend_devicelost(void)
378 r_meshbuffer_t *buffer;
380 gl_state.d3dvertexbuffer = NULL;
382 switch(vid.renderpath)
384 case RENDERPATH_GL11:
385 case RENDERPATH_GL13:
386 case RENDERPATH_GL20:
387 case RENDERPATH_CGGL:
389 case RENDERPATH_D3D9:
391 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
392 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
395 case RENDERPATH_D3D10:
396 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
398 case RENDERPATH_D3D11:
399 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
402 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
403 for (i = 0;i < endindex;i++)
405 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
406 if (!buffer || !buffer->isdynamic)
408 switch(vid.renderpath)
410 case RENDERPATH_GL11:
411 case RENDERPATH_GL13:
412 case RENDERPATH_GL20:
413 case RENDERPATH_CGGL:
415 case RENDERPATH_D3D9:
417 if (buffer->devicebuffer)
419 if (buffer->isindexbuffer)
420 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
422 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
423 buffer->devicebuffer = NULL;
427 case RENDERPATH_D3D10:
428 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
430 case RENDERPATH_D3D11:
431 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
437 static void gl_backend_devicerestored(void)
439 switch(vid.renderpath)
441 case RENDERPATH_GL11:
442 case RENDERPATH_GL13:
443 case RENDERPATH_GL20:
444 case RENDERPATH_CGGL:
446 case RENDERPATH_D3D9:
448 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
449 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
452 case RENDERPATH_D3D10:
453 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
455 case RENDERPATH_D3D11:
456 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
461 void gl_backend_init(void)
465 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
467 polygonelement3s[i * 3 + 0] = 0;
468 polygonelement3s[i * 3 + 1] = i + 1;
469 polygonelement3s[i * 3 + 2] = i + 2;
471 // elements for rendering a series of quads as triangles
472 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
474 quadelement3s[i * 6 + 0] = i * 4;
475 quadelement3s[i * 6 + 1] = i * 4 + 1;
476 quadelement3s[i * 6 + 2] = i * 4 + 2;
477 quadelement3s[i * 6 + 3] = i * 4;
478 quadelement3s[i * 6 + 4] = i * 4 + 2;
479 quadelement3s[i * 6 + 5] = i * 4 + 3;
482 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
483 polygonelement3i[i] = polygonelement3s[i];
484 for (i = 0;i < QUADELEMENTS_MAXQUADS*3;i++)
485 quadelement3i[i] = quadelement3s[i];
487 Cvar_RegisterVariable(&r_render);
488 Cvar_RegisterVariable(&r_renderview);
489 Cvar_RegisterVariable(&r_waterwarp);
490 Cvar_RegisterVariable(&gl_polyblend);
491 Cvar_RegisterVariable(&v_flipped);
492 Cvar_RegisterVariable(&gl_dither);
493 Cvar_RegisterVariable(&gl_vbo);
494 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
495 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
496 Cvar_RegisterVariable(&gl_paranoid);
497 Cvar_RegisterVariable(&gl_printcheckerror);
499 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
500 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
501 Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
502 Cvar_RegisterVariable(&gl_mesh_separatearrays);
504 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");
506 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
509 void GL_SetMirrorState(qboolean state);
511 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
515 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
516 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
518 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
520 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
521 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
522 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
524 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
527 static int bboxedges[12][2] =
546 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
548 int i, ix1, iy1, ix2, iy2;
549 float x1, y1, x2, y2;
560 scissor[0] = r_refdef.view.viewport.x;
561 scissor[1] = r_refdef.view.viewport.y;
562 scissor[2] = r_refdef.view.viewport.width;
563 scissor[3] = r_refdef.view.viewport.height;
565 // if view is inside the box, just say yes it's visible
566 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
569 x1 = y1 = x2 = y2 = 0;
571 // transform all corners that are infront of the nearclip plane
572 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
573 plane4f[3] = r_refdef.view.frustum[4].dist;
575 for (i = 0;i < 8;i++)
577 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
578 dist[i] = DotProduct4(corner[i], plane4f);
579 sign[i] = dist[i] > 0;
582 VectorCopy(corner[i], vertex[numvertices]);
586 // if some points are behind the nearclip, add clipped edge points to make
587 // sure that the scissor boundary is complete
588 if (numvertices > 0 && numvertices < 8)
590 // add clipped edge points
591 for (i = 0;i < 12;i++)
595 if (sign[j] != sign[k])
597 f = dist[j] / (dist[j] - dist[k]);
598 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
604 // if we have no points to check, it is behind the view plane
608 // if we have some points to transform, check what screen area is covered
609 x1 = y1 = x2 = y2 = 0;
611 //Con_Printf("%i vertices to transform...\n", numvertices);
612 for (i = 0;i < numvertices;i++)
614 VectorCopy(vertex[i], v);
615 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
616 //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]);
619 if (x1 > v2[0]) x1 = v2[0];
620 if (x2 < v2[0]) x2 = v2[0];
621 if (y1 > v2[1]) y1 = v2[1];
622 if (y2 < v2[1]) y2 = v2[1];
631 // now convert the scissor rectangle to integer screen coordinates
632 ix1 = (int)(x1 - 1.0f);
633 //iy1 = vid.height - (int)(y2 - 1.0f);
634 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
635 iy1 = (int)(y1 - 1.0f);
636 ix2 = (int)(x2 + 1.0f);
637 //iy2 = vid.height - (int)(y1 + 1.0f);
638 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
639 iy2 = (int)(y2 + 1.0f);
640 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
642 // clamp it to the screen
643 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
644 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
645 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
646 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
648 // if it is inside out, it's not visible
649 if (ix2 <= ix1 || iy2 <= iy1)
652 // the light area is visible, set up the scissor rectangle
655 scissor[2] = ix2 - ix1;
656 scissor[3] = iy2 - iy1;
658 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
659 switch(vid.renderpath)
661 case RENDERPATH_D3D9:
662 case RENDERPATH_D3D10:
663 case RENDERPATH_D3D11:
664 scissor[1] = vid.height - scissor[1] - scissor[3];
666 case RENDERPATH_GL11:
667 case RENDERPATH_GL13:
668 case RENDERPATH_GL20:
669 case RENDERPATH_CGGL:
677 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
681 float clipPlane[4], v3[3], v4[3];
684 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
686 VectorSet(normal, normalx, normaly, normalz);
687 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
688 VectorScale(normal, dist, v3);
689 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
690 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
691 clipPlane[3] = -DotProduct(v4, clipPlane);
695 // testing code for comparing results
697 VectorCopy4(clipPlane, clipPlane2);
698 R_EntityMatrix(&identitymatrix);
699 VectorSet(q, normal[0], normal[1], normal[2], -dist);
700 qglClipPlane(GL_CLIP_PLANE0, q);
701 qglGetClipPlane(GL_CLIP_PLANE0, q);
702 VectorCopy4(q, clipPlane);
706 // Calculate the clip-space corner point opposite the clipping plane
707 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
708 // transform it into camera space by multiplying it
709 // by the inverse of the projection matrix
710 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
711 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
713 q[3] = (1.0f + m[10]) / m[14];
715 // Calculate the scaled plane vector
716 d = 2.0f / DotProduct4(clipPlane, q);
718 // Replace the third row of the projection matrix
719 m[2] = clipPlane[0] * d;
720 m[6] = clipPlane[1] * d;
721 m[10] = clipPlane[2] * d + 1.0f;
722 m[14] = clipPlane[3] * d;
725 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)
727 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
729 memset(v, 0, sizeof(*v));
730 v->type = R_VIEWPORTTYPE_ORTHO;
731 v->cameramatrix = *cameramatrix;
738 memset(m, 0, sizeof(m));
739 m[0] = 2/(right - left);
740 m[5] = 2/(top - bottom);
741 m[10] = -2/(zFar - zNear);
742 m[12] = - (right + left)/(right - left);
743 m[13] = - (top + bottom)/(top - bottom);
744 m[14] = - (zFar + zNear)/(zFar - zNear);
746 switch(vid.renderpath)
748 case RENDERPATH_GL11:
749 case RENDERPATH_GL13:
750 case RENDERPATH_GL20:
751 case RENDERPATH_CGGL:
753 case RENDERPATH_D3D9:
754 case RENDERPATH_D3D10:
755 case RENDERPATH_D3D11:
756 m[10] = -1/(zFar - zNear);
757 m[14] = -zNear/(zFar-zNear);
760 v->screentodepth[0] = -farclip / (farclip - nearclip);
761 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
763 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
766 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
768 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
774 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
775 R_Viewport_TransformToScreen(v, test1, test2);
776 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
781 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)
783 matrix4x4_t tempmatrix, basematrix;
785 memset(v, 0, sizeof(*v));
787 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
788 v->cameramatrix = *cameramatrix;
795 memset(m, 0, sizeof(m));
796 m[0] = 1.0 / frustumx;
797 m[5] = 1.0 / frustumy;
798 m[10] = -(farclip + nearclip) / (farclip - nearclip);
800 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
801 v->screentodepth[0] = -farclip / (farclip - nearclip);
802 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
804 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
805 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
806 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
807 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
810 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
812 if(v_flipped.integer)
820 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
823 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)
825 matrix4x4_t tempmatrix, basematrix;
826 const float nudge = 1.0 - 1.0 / (1<<23);
828 memset(v, 0, sizeof(*v));
830 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
831 v->cameramatrix = *cameramatrix;
838 memset(m, 0, sizeof(m));
839 m[ 0] = 1.0 / frustumx;
840 m[ 5] = 1.0 / frustumy;
843 m[14] = -2 * nearclip * nudge;
844 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
845 v->screentodepth[1] = m[14] * -0.5;
847 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
848 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
849 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
850 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
853 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
855 if(v_flipped.integer)
863 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
866 float cubeviewmatrix[6][16] =
868 // standard cubemap projections
906 float rectviewmatrix[6][16] =
908 // sign-preserving cubemap projections
947 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
949 matrix4x4_t tempmatrix, basematrix;
951 memset(v, 0, sizeof(*v));
952 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
953 v->cameramatrix = *cameramatrix;
957 memset(m, 0, sizeof(m));
959 m[10] = -(farclip + nearclip) / (farclip - nearclip);
961 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
963 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
964 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
965 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
968 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
970 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
973 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)
975 matrix4x4_t tempmatrix, basematrix;
977 memset(v, 0, sizeof(*v));
978 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
979 v->cameramatrix = *cameramatrix;
980 v->x = (side & 1) * size;
981 v->y = (side >> 1) * size;
985 memset(m, 0, sizeof(m));
986 m[0] = m[5] = 1.0f * ((float)size - border) / size;
987 m[10] = -(farclip + nearclip) / (farclip - nearclip);
989 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
991 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
992 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
993 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
995 switch(vid.renderpath)
997 case RENDERPATH_GL20:
998 case RENDERPATH_CGGL:
999 case RENDERPATH_GL13:
1000 case RENDERPATH_GL11:
1002 case RENDERPATH_D3D9:
1005 case RENDERPATH_D3D10:
1006 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1008 case RENDERPATH_D3D11:
1009 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1014 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1016 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1019 void R_SetViewport(const r_viewport_t *v)
1024 // FIXME: v_flipped_state is evil, this probably breaks somewhere
1025 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1027 // copy over the matrices to our state
1028 gl_viewmatrix = v->viewmatrix;
1029 gl_projectionmatrix = v->projectmatrix;
1031 switch(vid.renderpath)
1033 case RENDERPATH_GL20:
1034 case RENDERPATH_CGGL:
1036 // qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1038 case RENDERPATH_GL13:
1039 case RENDERPATH_GL11:
1041 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1042 // Load the projection matrix into OpenGL
1043 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1044 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1045 qglLoadMatrixf(m);CHECKGLERROR
1046 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1048 case RENDERPATH_D3D9:
1051 D3DVIEWPORT9 d3dviewport;
1052 d3dviewport.X = gl_viewport.x;
1053 d3dviewport.Y = gl_viewport.y;
1054 d3dviewport.Width = gl_viewport.width;
1055 d3dviewport.Height = gl_viewport.height;
1056 d3dviewport.MinZ = gl_state.depthrange[0];
1057 d3dviewport.MaxZ = gl_state.depthrange[1];
1058 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1062 case RENDERPATH_D3D10:
1063 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1065 case RENDERPATH_D3D11:
1066 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1070 // force an update of the derived matrices
1071 gl_modelmatrixchanged = true;
1072 R_EntityMatrix(&gl_modelmatrix);
1075 void R_GetViewport(r_viewport_t *v)
1080 static void GL_BindVBO(int bufferobject)
1082 if (gl_state.vertexbufferobject != bufferobject)
1084 gl_state.vertexbufferobject = bufferobject;
1086 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1090 static void GL_BindEBO(int bufferobject)
1092 if (gl_state.elementbufferobject != bufferobject)
1094 gl_state.elementbufferobject = bufferobject;
1096 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1100 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1103 switch(vid.renderpath)
1105 case RENDERPATH_GL11:
1106 case RENDERPATH_GL13:
1107 case RENDERPATH_GL20:
1108 case RENDERPATH_CGGL:
1109 if (!vid.support.ext_framebuffer_object)
1111 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1112 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1113 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1114 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1115 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1116 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1117 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1119 case RENDERPATH_D3D9:
1120 case RENDERPATH_D3D10:
1121 case RENDERPATH_D3D11:
1127 void R_Mesh_DestroyFramebufferObject(int fbo)
1129 switch(vid.renderpath)
1131 case RENDERPATH_GL11:
1132 case RENDERPATH_GL13:
1133 case RENDERPATH_GL20:
1134 case RENDERPATH_CGGL:
1136 qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1138 case RENDERPATH_D3D9:
1139 case RENDERPATH_D3D10:
1140 case RENDERPATH_D3D11:
1146 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1148 // 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)
1149 // 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)
1152 gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1153 // if (gl_state.d3drt_depthsurface != depthsurface)
1155 gl_state.d3drt_depthsurface = depthsurface;
1156 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1158 if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1160 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1161 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1163 if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1165 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1166 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1168 if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1170 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1171 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1173 if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1175 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1176 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1181 void R_Mesh_ResetRenderTargets(void)
1183 switch(vid.renderpath)
1185 case RENDERPATH_GL11:
1186 case RENDERPATH_GL13:
1187 case RENDERPATH_GL20:
1188 case RENDERPATH_CGGL:
1189 if (gl_state.framebufferobject)
1191 gl_state.framebufferobject = 0;
1192 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1195 case RENDERPATH_D3D9:
1197 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1200 case RENDERPATH_D3D10:
1201 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1203 case RENDERPATH_D3D11:
1204 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1209 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1213 rtexture_t *textures[5];
1214 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1215 textures[4] = depthtexture;
1216 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1217 for (j = 0;j < 5;j++)
1219 for (i = 0;i < vid.teximageunits;i++)
1220 if (gl_state.units[i].texture == textures[j])
1221 R_Mesh_TexBind(i, NULL);
1222 // set up framebuffer object or render targets for the active rendering API
1223 switch(vid.renderpath)
1225 case RENDERPATH_GL11:
1226 case RENDERPATH_GL13:
1227 case RENDERPATH_GL20:
1228 case RENDERPATH_CGGL:
1229 if (gl_state.framebufferobject != fbo)
1231 gl_state.framebufferobject = fbo;
1232 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1235 case RENDERPATH_D3D9:
1237 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1238 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1241 IDirect3DSurface9 *colorsurfaces[4];
1242 for (i = 0;i < 4;i++)
1244 colorsurfaces[i] = NULL;
1246 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1248 // set the render targets for real
1249 R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1250 // release the texture surface levels (they won't be lost while bound...)
1251 for (i = 0;i < 4;i++)
1253 IDirect3DSurface9_Release(colorsurfaces[i]);
1256 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1259 case RENDERPATH_D3D10:
1260 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1262 case RENDERPATH_D3D11:
1263 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1269 static int d3dcmpforglfunc(int f)
1273 case GL_NEVER: return D3DCMP_NEVER;
1274 case GL_LESS: return D3DCMP_LESS;
1275 case GL_EQUAL: return D3DCMP_EQUAL;
1276 case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1277 case GL_GREATER: return D3DCMP_GREATER;
1278 case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1279 case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1280 case GL_ALWAYS: return D3DCMP_ALWAYS;
1281 default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1285 static int d3dstencilopforglfunc(int f)
1289 case GL_KEEP: return D3DSTENCILOP_KEEP;
1290 case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1291 case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1292 default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1298 static void GL_Backend_ResetState(void)
1301 gl_state.active = true;
1302 gl_state.depthtest = true;
1303 gl_state.alphatest = false;
1304 gl_state.alphafunc = GL_GEQUAL;
1305 gl_state.alphafuncvalue = 0.5f;
1306 gl_state.blendfunc1 = GL_ONE;
1307 gl_state.blendfunc2 = GL_ZERO;
1308 gl_state.blend = false;
1309 gl_state.depthmask = GL_TRUE;
1310 gl_state.colormask = 15;
1311 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1312 gl_state.lockrange_first = 0;
1313 gl_state.lockrange_count = 0;
1314 gl_state.cullface = GL_NONE;
1315 gl_state.cullfaceenable = false;
1316 gl_state.polygonoffset[0] = 0;
1317 gl_state.polygonoffset[1] = 0;
1318 gl_state.framebufferobject = 0;
1319 gl_state.depthfunc = GL_LEQUAL;
1321 switch(vid.renderpath)
1323 case RENDERPATH_D3D9:
1326 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1327 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
1328 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
1329 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
1330 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1331 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1332 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1333 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1334 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1335 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1339 case RENDERPATH_D3D10:
1340 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1342 case RENDERPATH_D3D11:
1343 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1345 case RENDERPATH_GL20:
1346 case RENDERPATH_CGGL:
1349 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1350 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1351 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1352 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1353 qglDisable(GL_BLEND);CHECKGLERROR
1354 qglCullFace(gl_state.cullface);CHECKGLERROR
1355 qglDisable(GL_CULL_FACE);CHECKGLERROR
1356 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1357 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1358 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1359 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1361 if (vid.support.arb_vertex_buffer_object)
1363 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1364 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1367 if (vid.support.ext_framebuffer_object)
1369 qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1370 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1373 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1374 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1376 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1377 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1378 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1380 if (vid.support.ext_framebuffer_object)
1381 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1383 gl_state.unit = MAX_TEXTUREUNITS;
1384 gl_state.clientunit = MAX_TEXTUREUNITS;
1385 for (i = 0;i < vid.teximageunits;i++)
1387 GL_ActiveTexture(i);
1388 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1389 if (vid.support.ext_texture_3d)
1391 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1393 if (vid.support.arb_texture_cube_map)
1395 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1399 for (i = 0;i < vid.texarrayunits;i++)
1401 GL_ClientActiveTexture(i);
1403 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1404 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1408 case RENDERPATH_GL13:
1409 case RENDERPATH_GL11:
1412 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1413 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1414 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1415 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1416 qglDisable(GL_BLEND);CHECKGLERROR
1417 qglCullFace(gl_state.cullface);CHECKGLERROR
1418 qglDisable(GL_CULL_FACE);CHECKGLERROR
1419 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1420 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1421 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1422 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1424 if (vid.support.arb_vertex_buffer_object)
1426 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1427 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1430 if (vid.support.ext_framebuffer_object)
1432 qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1433 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1436 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1437 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1439 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1440 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1441 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1443 if (vid.support.ext_framebuffer_object)
1444 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1446 gl_state.unit = MAX_TEXTUREUNITS;
1447 gl_state.clientunit = MAX_TEXTUREUNITS;
1448 for (i = 0;i < vid.texunits;i++)
1450 GL_ActiveTexture(i);
1451 GL_ClientActiveTexture(i);
1452 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1453 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1454 if (vid.support.ext_texture_3d)
1456 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1457 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1459 if (vid.support.arb_texture_cube_map)
1461 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1462 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1465 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1466 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1467 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1468 qglLoadIdentity();CHECKGLERROR
1469 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1470 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1477 void GL_ActiveTexture(unsigned int num)
1479 if (gl_state.unit != num)
1481 gl_state.unit = num;
1482 switch(vid.renderpath)
1484 case RENDERPATH_GL11:
1485 case RENDERPATH_GL13:
1486 case RENDERPATH_GL20:
1487 case RENDERPATH_CGGL:
1488 if (qglActiveTexture)
1491 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1495 case RENDERPATH_D3D9:
1496 case RENDERPATH_D3D10:
1497 case RENDERPATH_D3D11:
1503 void GL_ClientActiveTexture(unsigned int num)
1505 if (gl_state.clientunit != num)
1507 gl_state.clientunit = num;
1508 switch(vid.renderpath)
1510 case RENDERPATH_GL11:
1511 case RENDERPATH_GL13:
1512 case RENDERPATH_GL20:
1513 case RENDERPATH_CGGL:
1514 if (qglActiveTexture)
1517 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1521 case RENDERPATH_D3D9:
1522 case RENDERPATH_D3D10:
1523 case RENDERPATH_D3D11:
1529 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1531 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1533 qboolean blendenable;
1534 gl_state.blendfunc1 = blendfunc1;
1535 gl_state.blendfunc2 = blendfunc2;
1536 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1537 switch(vid.renderpath)
1539 case RENDERPATH_GL11:
1540 case RENDERPATH_GL13:
1541 case RENDERPATH_GL20:
1542 case RENDERPATH_CGGL:
1544 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1545 if (gl_state.blend != blendenable)
1547 gl_state.blend = blendenable;
1548 if (!gl_state.blend)
1550 qglDisable(GL_BLEND);CHECKGLERROR
1554 qglEnable(GL_BLEND);CHECKGLERROR
1558 case RENDERPATH_D3D9:
1563 D3DBLEND d3dblendfunc[2];
1564 glblendfunc[0] = gl_state.blendfunc1;
1565 glblendfunc[1] = gl_state.blendfunc2;
1566 for (i = 0;i < 2;i++)
1568 switch(glblendfunc[i])
1570 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1571 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1572 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1573 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1574 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1575 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1576 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1577 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1578 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1579 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1582 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1583 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1584 if (gl_state.blend != blendenable)
1586 gl_state.blend = blendenable;
1587 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1592 case RENDERPATH_D3D10:
1593 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1595 case RENDERPATH_D3D11:
1596 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1602 void GL_DepthMask(int state)
1604 if (gl_state.depthmask != state)
1606 gl_state.depthmask = state;
1607 switch(vid.renderpath)
1609 case RENDERPATH_GL11:
1610 case RENDERPATH_GL13:
1611 case RENDERPATH_GL20:
1612 case RENDERPATH_CGGL:
1614 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1616 case RENDERPATH_D3D9:
1618 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1621 case RENDERPATH_D3D10:
1622 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1624 case RENDERPATH_D3D11:
1625 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1631 void GL_DepthTest(int state)
1633 if (gl_state.depthtest != state)
1635 gl_state.depthtest = state;
1636 switch(vid.renderpath)
1638 case RENDERPATH_GL11:
1639 case RENDERPATH_GL13:
1640 case RENDERPATH_GL20:
1641 case RENDERPATH_CGGL:
1643 if (gl_state.depthtest)
1645 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1649 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1652 case RENDERPATH_D3D9:
1654 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1657 case RENDERPATH_D3D10:
1658 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1660 case RENDERPATH_D3D11:
1661 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1667 void GL_DepthFunc(int state)
1669 if (gl_state.depthfunc != state)
1671 gl_state.depthfunc = state;
1672 switch(vid.renderpath)
1674 case RENDERPATH_GL11:
1675 case RENDERPATH_GL13:
1676 case RENDERPATH_GL20:
1677 case RENDERPATH_CGGL:
1679 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1681 case RENDERPATH_D3D9:
1683 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1686 case RENDERPATH_D3D10:
1687 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1689 case RENDERPATH_D3D11:
1690 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1696 void GL_DepthRange(float nearfrac, float farfrac)
1698 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1700 gl_state.depthrange[0] = nearfrac;
1701 gl_state.depthrange[1] = farfrac;
1702 switch(vid.renderpath)
1704 case RENDERPATH_GL11:
1705 case RENDERPATH_GL13:
1706 case RENDERPATH_GL20:
1707 case RENDERPATH_CGGL:
1708 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1710 case RENDERPATH_D3D9:
1713 D3DVIEWPORT9 d3dviewport;
1714 d3dviewport.X = gl_viewport.x;
1715 d3dviewport.Y = gl_viewport.y;
1716 d3dviewport.Width = gl_viewport.width;
1717 d3dviewport.Height = gl_viewport.height;
1718 d3dviewport.MinZ = gl_state.depthrange[0];
1719 d3dviewport.MaxZ = gl_state.depthrange[1];
1720 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1724 case RENDERPATH_D3D10:
1725 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1727 case RENDERPATH_D3D11:
1728 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1734 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)
1736 switch (vid.renderpath)
1738 case RENDERPATH_GL11:
1739 case RENDERPATH_GL13:
1740 case RENDERPATH_GL20:
1741 case RENDERPATH_CGGL:
1745 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1749 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1751 if (vid.support.ati_separate_stencil)
1753 qglStencilMask(writemask);CHECKGLERROR
1754 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1755 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1756 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1758 else if (vid.support.ext_stencil_two_side)
1760 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1761 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1762 qglStencilMask(writemask);CHECKGLERROR
1763 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1764 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1765 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1766 qglStencilMask(writemask);CHECKGLERROR
1767 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1768 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1771 case RENDERPATH_D3D9:
1773 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1774 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1775 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1776 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1777 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1778 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1779 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1780 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1781 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1782 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1783 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1784 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1785 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1788 case RENDERPATH_D3D10:
1789 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1791 case RENDERPATH_D3D11:
1792 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1797 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1799 switch (vid.renderpath)
1801 case RENDERPATH_GL11:
1802 case RENDERPATH_GL13:
1803 case RENDERPATH_GL20:
1804 case RENDERPATH_CGGL:
1808 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1812 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1814 if (vid.support.ext_stencil_two_side)
1816 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1818 qglStencilMask(writemask);CHECKGLERROR
1819 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1820 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1823 case RENDERPATH_D3D9:
1825 if (vid.support.ati_separate_stencil)
1826 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1827 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1828 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1829 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1830 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1831 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1832 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1833 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1834 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1837 case RENDERPATH_D3D10:
1838 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1840 case RENDERPATH_D3D11:
1841 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1846 void GL_PolygonOffset(float planeoffset, float depthoffset)
1848 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
1850 gl_state.polygonoffset[0] = planeoffset;
1851 gl_state.polygonoffset[1] = depthoffset;
1852 switch(vid.renderpath)
1854 case RENDERPATH_GL11:
1855 case RENDERPATH_GL13:
1856 case RENDERPATH_GL20:
1857 case RENDERPATH_CGGL:
1858 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1860 case RENDERPATH_D3D9:
1862 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1863 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1866 case RENDERPATH_D3D10:
1867 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1869 case RENDERPATH_D3D11:
1870 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1876 void GL_SetMirrorState(qboolean state)
1878 if (v_flipped_state != state)
1880 v_flipped_state = state;
1881 if (gl_state.cullface == GL_BACK)
1882 gl_state.cullface = GL_FRONT;
1883 else if (gl_state.cullface == GL_FRONT)
1884 gl_state.cullface = GL_BACK;
1887 switch(vid.renderpath)
1889 case RENDERPATH_GL11:
1890 case RENDERPATH_GL13:
1891 case RENDERPATH_GL20:
1892 case RENDERPATH_CGGL:
1893 qglCullFace(gl_state.cullface);
1895 case RENDERPATH_D3D9:
1897 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
1900 case RENDERPATH_D3D10:
1901 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1903 case RENDERPATH_D3D11:
1904 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1910 void GL_CullFace(int state)
1914 if(state == GL_FRONT)
1916 else if(state == GL_BACK)
1920 switch(vid.renderpath)
1922 case RENDERPATH_GL11:
1923 case RENDERPATH_GL13:
1924 case RENDERPATH_GL20:
1925 case RENDERPATH_CGGL:
1928 if (state != GL_NONE)
1930 if (!gl_state.cullfaceenable)
1932 gl_state.cullfaceenable = true;
1933 qglEnable(GL_CULL_FACE);CHECKGLERROR
1935 if (gl_state.cullface != state)
1937 gl_state.cullface = state;
1938 qglCullFace(gl_state.cullface);CHECKGLERROR
1943 if (gl_state.cullfaceenable)
1945 gl_state.cullfaceenable = false;
1946 qglDisable(GL_CULL_FACE);CHECKGLERROR
1950 case RENDERPATH_D3D9:
1952 if (gl_state.cullface != state)
1954 gl_state.cullface = state;
1955 switch(gl_state.cullface)
1958 gl_state.cullfaceenable = false;
1959 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1962 gl_state.cullfaceenable = true;
1963 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
1966 gl_state.cullfaceenable = true;
1967 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
1973 case RENDERPATH_D3D10:
1974 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1976 case RENDERPATH_D3D11:
1977 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1982 void GL_AlphaTest(int state)
1984 if (gl_state.alphatest != state)
1986 gl_state.alphatest = state;
1987 switch(vid.renderpath)
1989 case RENDERPATH_GL11:
1990 case RENDERPATH_GL13:
1991 case RENDERPATH_GL20:
1992 case RENDERPATH_CGGL:
1994 if (gl_state.alphatest)
1996 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2000 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2003 case RENDERPATH_D3D9:
2005 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
2008 case RENDERPATH_D3D10:
2009 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2011 case RENDERPATH_D3D11:
2012 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2018 void GL_AlphaFunc(int state, float value)
2020 if (gl_state.alphafunc != state || gl_state.alphafuncvalue != value)
2022 gl_state.alphafunc = state;
2023 gl_state.alphafuncvalue = value;
2024 switch(vid.renderpath)
2026 case RENDERPATH_GL11:
2027 case RENDERPATH_GL13:
2028 case RENDERPATH_GL20:
2029 case RENDERPATH_CGGL:
2031 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
2033 case RENDERPATH_D3D9:
2035 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
2036 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, value * 256.0f, 255));
2039 case RENDERPATH_D3D10:
2040 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2042 case RENDERPATH_D3D11:
2043 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2049 void GL_ColorMask(int r, int g, int b, int a)
2051 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2052 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2053 if (gl_state.colormask != state)
2055 gl_state.colormask = state;
2056 switch(vid.renderpath)
2058 case RENDERPATH_GL11:
2059 case RENDERPATH_GL13:
2060 case RENDERPATH_GL20:
2061 case RENDERPATH_CGGL:
2063 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2065 case RENDERPATH_D3D9:
2067 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2070 case RENDERPATH_D3D10:
2071 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2073 case RENDERPATH_D3D11:
2074 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2080 void GL_Color(float cr, float cg, float cb, float ca)
2082 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)
2084 gl_state.color4f[0] = cr;
2085 gl_state.color4f[1] = cg;
2086 gl_state.color4f[2] = cb;
2087 gl_state.color4f[3] = ca;
2088 switch(vid.renderpath)
2090 case RENDERPATH_GL11:
2091 case RENDERPATH_GL13:
2092 case RENDERPATH_GL20:
2093 case RENDERPATH_CGGL:
2095 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2098 case RENDERPATH_D3D9:
2099 case RENDERPATH_D3D10:
2100 case RENDERPATH_D3D11:
2101 // no equivalent in D3D
2107 void GL_Scissor (int x, int y, int width, int height)
2109 switch(vid.renderpath)
2111 case RENDERPATH_GL11:
2112 case RENDERPATH_GL13:
2113 case RENDERPATH_GL20:
2114 case RENDERPATH_CGGL:
2116 qglScissor(x, y,width,height);
2119 case RENDERPATH_D3D9:
2125 d3drect.right = x + width;
2126 d3drect.bottom = y + height;
2127 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2131 case RENDERPATH_D3D10:
2132 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2134 case RENDERPATH_D3D11:
2135 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2140 void GL_ScissorTest(int state)
2142 if (gl_state.scissortest != state)
2144 gl_state.scissortest = state;
2145 switch(vid.renderpath)
2147 case RENDERPATH_GL11:
2148 case RENDERPATH_GL13:
2149 case RENDERPATH_GL20:
2150 case RENDERPATH_CGGL:
2152 if(gl_state.scissortest)
2153 qglEnable(GL_SCISSOR_TEST);
2155 qglDisable(GL_SCISSOR_TEST);
2158 case RENDERPATH_D3D9:
2160 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2163 case RENDERPATH_D3D10:
2164 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2166 case RENDERPATH_D3D11:
2167 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2173 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2175 static const float blackcolor[4] = {0, 0, 0, 0};
2176 // prevent warnings when trying to clear a buffer that does not exist
2178 colorvalue = blackcolor;
2181 mask &= ~GL_STENCIL_BUFFER_BIT;
2184 switch(vid.renderpath)
2186 case RENDERPATH_GL11:
2187 case RENDERPATH_GL13:
2188 case RENDERPATH_GL20:
2189 case RENDERPATH_CGGL:
2191 if (mask & GL_COLOR_BUFFER_BIT)
2193 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2195 if (mask & GL_DEPTH_BUFFER_BIT)
2197 qglClearDepth(depthvalue);CHECKGLERROR
2199 if (mask & GL_STENCIL_BUFFER_BIT)
2201 qglClearStencil(stencilvalue);CHECKGLERROR
2203 qglClear(mask);CHECKGLERROR
2205 case RENDERPATH_D3D9:
2207 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);
2210 case RENDERPATH_D3D10:
2211 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2213 case RENDERPATH_D3D11:
2214 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2219 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2221 switch(vid.renderpath)
2223 case RENDERPATH_GL11:
2224 case RENDERPATH_GL13:
2225 case RENDERPATH_GL20:
2226 case RENDERPATH_CGGL:
2228 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2230 case RENDERPATH_D3D9:
2233 // LordHavoc: we can't directly download the backbuffer because it may be
2234 // multisampled, and it may not be lockable, so we blit it to a lockable
2235 // surface of the same dimensions (but without multisample) to resolve the
2236 // multisample buffer to a normal image, and then lock that...
2237 IDirect3DSurface9 *stretchsurface = NULL;
2238 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2240 D3DLOCKED_RECT lockedrect;
2241 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2243 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2246 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2247 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2248 memcpy(outpixels + line * width * 4, row, width * 4);
2249 IDirect3DSurface9_UnlockRect(stretchsurface);
2252 IDirect3DSurface9_Release(stretchsurface);
2255 //IDirect3DSurface9 *syssurface = NULL;
2256 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2257 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2258 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2259 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2260 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2261 //IDirect3DSurface9_UnlockRect(syssurface);
2262 //IDirect3DSurface9_Release(syssurface);
2266 case RENDERPATH_D3D10:
2267 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2269 case RENDERPATH_D3D11:
2270 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2275 // called at beginning of frame
2276 void R_Mesh_Start(void)
2279 R_Mesh_ResetRenderTargets();
2281 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2283 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2284 Cvar_SetValueQuick(&gl_paranoid, 1);
2288 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2292 char compilelog[MAX_INPUTLINE];
2293 shaderobject = qglCreateShaderObjectARB(shadertypeenum);CHECKGLERROR
2296 qglShaderSourceARB(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2297 qglCompileShaderARB(shaderobject);CHECKGLERROR
2298 qglGetObjectParameterivARB(shaderobject, GL_OBJECT_COMPILE_STATUS_ARB, &shadercompiled);CHECKGLERROR
2299 qglGetInfoLogARB(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2300 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2302 int i, j, pretextlines = 0;
2303 for (i = 0;i < numstrings - 1;i++)
2304 for (j = 0;strings[i][j];j++)
2305 if (strings[i][j] == '\n')
2307 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2309 if (!shadercompiled)
2311 qglDeleteObjectARB(shaderobject);CHECKGLERROR
2314 qglAttachObjectARB(programobject, shaderobject);CHECKGLERROR
2315 qglDeleteObjectARB(shaderobject);CHECKGLERROR
2319 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)
2321 GLint programlinked;
2322 GLuint programobject = 0;
2323 char linklog[MAX_INPUTLINE];
2326 programobject = qglCreateProgramObjectARB();CHECKGLERROR
2330 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER_ARB, "vertex", vertexstrings_count, vertexstrings_list))
2333 #ifdef GL_GEOMETRY_SHADER_ARB
2334 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER_ARB, "geometry", geometrystrings_count, geometrystrings_list))
2338 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER_ARB, "fragment", fragmentstrings_count, fragmentstrings_list))
2341 qglLinkProgramARB(programobject);CHECKGLERROR
2342 qglGetObjectParameterivARB(programobject, GL_OBJECT_LINK_STATUS_ARB, &programlinked);CHECKGLERROR
2343 qglGetInfoLogARB(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2346 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2347 Con_DPrintf("program link log:\n%s\n", linklog);
2348 // software vertex shader is ok but software fragment shader is WAY
2349 // too slow, fail program if so.
2350 // NOTE: this string might be ATI specific, but that's ok because the
2351 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2352 // software fragment shader due to low instruction and dependent
2354 if (strstr(linklog, "fragment shader will run in software"))
2355 programlinked = false;
2359 return programobject;
2361 qglDeleteObjectARB(programobject);CHECKGLERROR
2365 void GL_Backend_FreeProgram(unsigned int prog)
2368 qglDeleteObjectARB(prog);
2372 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2377 for (i = 0;i < count;i++)
2378 *out++ = *in++ + offset;
2381 memcpy(out, in, sizeof(*out) * count);
2384 // renders triangles using vertices from the active arrays
2385 int paranoidblah = 0;
2386 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)
2388 unsigned int numelements = numtriangles * 3;
2390 size_t bufferoffset3i;
2392 size_t bufferoffset3s;
2393 if (numvertices < 3 || numtriangles < 1)
2395 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2396 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);
2399 if (!gl_mesh_prefer_short_elements.integer)
2403 if (element3i_indexbuffer)
2404 element3i_indexbuffer = NULL;
2406 // adjust the pointers for firsttriangle
2408 element3i += firsttriangle * 3;
2409 if (element3i_indexbuffer)
2410 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2412 element3s += firsttriangle * 3;
2413 if (element3s_indexbuffer)
2414 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2415 switch(vid.renderpath)
2417 case RENDERPATH_GL11:
2418 case RENDERPATH_GL13:
2419 case RENDERPATH_GL20:
2420 case RENDERPATH_CGGL:
2421 // check if the user specified to ignore static index buffers
2422 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2424 element3i_indexbuffer = NULL;
2425 element3s_indexbuffer = NULL;
2428 case RENDERPATH_D3D9:
2429 case RENDERPATH_D3D10:
2430 case RENDERPATH_D3D11:
2433 // upload a dynamic index buffer if needed
2436 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2438 if (gl_state.draw_dynamicindexbuffer)
2439 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2441 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2442 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2443 element3s_bufferoffset = 0;
2448 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2450 if (gl_state.draw_dynamicindexbuffer)
2451 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2453 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2454 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2455 element3i_bufferoffset = 0;
2458 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2459 bufferoffset3i = element3i_bufferoffset;
2460 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2461 bufferoffset3s = element3s_bufferoffset;
2462 r_refdef.stats.meshes++;
2463 r_refdef.stats.meshes_elements += numelements;
2464 if (gl_paranoid.integer)
2467 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2469 unsigned int j, size;
2471 // note: there's no validation done here on buffer objects because it
2472 // is somewhat difficult to get at the data, and gl_paranoid can be
2473 // used without buffer objects if the need arises
2474 // (the data could be gotten using glMapBuffer but it would be very
2475 // slow due to uncachable video memory reads)
2476 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2477 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2479 if (gl_state.pointer_vertex_pointer)
2480 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2482 if (gl_state.pointer_color_enabled)
2484 if (!qglIsEnabled(GL_COLOR_ARRAY))
2485 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2487 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2488 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2491 for (i = 0;i < vid.texarrayunits;i++)
2493 if (gl_state.units[i].arrayenabled)
2495 GL_ClientActiveTexture(i);
2496 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2497 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2499 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2500 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++)
2507 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2509 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2511 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2518 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2520 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2522 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2528 if (r_render.integer || r_refdef.draw2dstage)
2530 switch(vid.renderpath)
2532 case RENDERPATH_GL11:
2533 case RENDERPATH_GL13:
2534 case RENDERPATH_GL20:
2535 case RENDERPATH_CGGL:
2537 if (gl_mesh_testmanualfeeding.integer)
2539 unsigned int i, j, element;
2541 qglBegin(GL_TRIANGLES);
2542 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2545 element = element3i[i];
2547 element = element3s[i];
2549 element = firstvertex + i;
2550 for (j = 0;j < vid.texarrayunits;j++)
2552 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2554 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2556 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2557 if (vid.texarrayunits > 1)
2559 if (gl_state.units[j].pointer_texcoord_components == 4)
2560 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2561 else if (gl_state.units[j].pointer_texcoord_components == 3)
2562 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2563 else if (gl_state.units[j].pointer_texcoord_components == 2)
2564 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2566 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2570 if (gl_state.units[j].pointer_texcoord_components == 4)
2571 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2572 else if (gl_state.units[j].pointer_texcoord_components == 3)
2573 qglTexCoord3f(p[0], p[1], p[2]);
2574 else if (gl_state.units[j].pointer_texcoord_components == 2)
2575 qglTexCoord2f(p[0], p[1]);
2577 qglTexCoord1f(p[0]);
2580 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2582 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2583 if (vid.texarrayunits > 1)
2585 if (gl_state.units[j].pointer_texcoord_components == 4)
2586 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2587 else if (gl_state.units[j].pointer_texcoord_components == 3)
2588 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2589 else if (gl_state.units[j].pointer_texcoord_components == 2)
2590 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2591 else if (gl_state.units[j].pointer_texcoord_components == 1)
2592 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2596 if (gl_state.units[j].pointer_texcoord_components == 4)
2597 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2598 else if (gl_state.units[j].pointer_texcoord_components == 3)
2599 qglTexCoord3f(s[0], s[1], s[2]);
2600 else if (gl_state.units[j].pointer_texcoord_components == 2)
2601 qglTexCoord2f(s[0], s[1]);
2602 else if (gl_state.units[j].pointer_texcoord_components == 1)
2603 qglTexCoord1f(s[0]);
2606 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2608 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2609 if (vid.texarrayunits > 1)
2611 if (gl_state.units[j].pointer_texcoord_components == 4)
2612 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2613 else if (gl_state.units[j].pointer_texcoord_components == 3)
2614 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2615 else if (gl_state.units[j].pointer_texcoord_components == 2)
2616 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2617 else if (gl_state.units[j].pointer_texcoord_components == 1)
2618 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2622 if (gl_state.units[j].pointer_texcoord_components == 4)
2623 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2624 else if (gl_state.units[j].pointer_texcoord_components == 3)
2625 qglTexCoord3f(sb[0], sb[1], sb[2]);
2626 else if (gl_state.units[j].pointer_texcoord_components == 2)
2627 qglTexCoord2f(sb[0], sb[1]);
2628 else if (gl_state.units[j].pointer_texcoord_components == 1)
2629 qglTexCoord1f(sb[0]);
2634 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2636 if (gl_state.pointer_color_gltype == GL_FLOAT)
2638 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2639 qglColor4f(p[0], p[1], p[2], p[3]);
2641 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2643 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2644 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2647 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2649 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2650 if (gl_state.pointer_vertex_components == 4)
2651 qglVertex4f(p[0], p[1], p[2], p[3]);
2652 else if (gl_state.pointer_vertex_components == 3)
2653 qglVertex3f(p[0], p[1], p[2]);
2655 qglVertex2f(p[0], p[1]);
2661 else if (bufferobject3s)
2663 GL_BindEBO(bufferobject3s);
2664 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2666 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2671 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2675 else if (bufferobject3i)
2677 GL_BindEBO(bufferobject3i);
2678 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2680 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2685 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2692 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2694 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2699 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2706 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2708 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2713 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2719 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2723 case RENDERPATH_D3D9:
2725 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2727 if (element3s_indexbuffer)
2729 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2730 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2732 else if (element3i_indexbuffer)
2734 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2735 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2738 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2743 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s + firsttriangle*3, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2745 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i + firsttriangle*3, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2747 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *) ((byte *) gl_state.d3dvertexdata + (numvertices * gl_state.d3dvertexsize)), gl_state.d3dvertexsize);
2751 case RENDERPATH_D3D10:
2752 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2754 case RENDERPATH_D3D11:
2755 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2761 // restores backend state, used when done with 3D rendering
2762 void R_Mesh_Finish(void)
2764 R_Mesh_ResetRenderTargets();
2767 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
2769 r_meshbuffer_t *buffer;
2770 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
2772 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
2773 memset(buffer, 0, sizeof(*buffer));
2774 buffer->bufferobject = 0;
2775 buffer->devicebuffer = NULL;
2777 buffer->isindexbuffer = isindexbuffer;
2778 buffer->isdynamic = isdynamic;
2779 buffer->isindex16 = isindex16;
2780 strlcpy(buffer->name, name, sizeof(buffer->name));
2781 R_Mesh_UpdateMeshBuffer(buffer, data, size);
2785 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
2789 if (buffer->isindexbuffer)
2791 r_refdef.stats.indexbufferuploadcount++;
2792 r_refdef.stats.indexbufferuploadsize += size;
2796 r_refdef.stats.vertexbufferuploadcount++;
2797 r_refdef.stats.vertexbufferuploadsize += size;
2799 switch(vid.renderpath)
2801 case RENDERPATH_GL11:
2802 case RENDERPATH_GL13:
2803 case RENDERPATH_GL20:
2804 case RENDERPATH_CGGL:
2805 if (!buffer->bufferobject)
2806 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
2807 if (buffer->isindexbuffer)
2808 GL_BindEBO(buffer->bufferobject);
2810 GL_BindVBO(buffer->bufferobject);
2811 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
2813 case RENDERPATH_D3D9:
2817 void *datapointer = NULL;
2818 if (buffer->isindexbuffer)
2820 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
2821 if (size > buffer->size || !buffer->devicebuffer)
2823 if (buffer->devicebuffer)
2824 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
2825 buffer->devicebuffer = NULL;
2826 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)))
2827 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);
2828 buffer->devicebuffer = (void *)d3d9indexbuffer;
2829 buffer->size = size;
2831 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
2834 memcpy(datapointer, data, size);
2836 memset(datapointer, 0, size);
2837 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
2842 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
2843 if (size > buffer->size || !buffer->devicebuffer)
2845 if (buffer->devicebuffer)
2846 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
2847 buffer->devicebuffer = NULL;
2848 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
2849 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);
2850 buffer->devicebuffer = (void *)d3d9vertexbuffer;
2851 buffer->size = size;
2853 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
2856 memcpy(datapointer, data, size);
2858 memset(datapointer, 0, size);
2859 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
2865 case RENDERPATH_D3D10:
2866 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2868 case RENDERPATH_D3D11:
2869 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2874 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
2878 switch(vid.renderpath)
2880 case RENDERPATH_GL11:
2881 case RENDERPATH_GL13:
2882 case RENDERPATH_GL20:
2883 case RENDERPATH_CGGL:
2884 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
2886 case RENDERPATH_D3D9:
2888 if (gl_state.d3dvertexbuffer == (void *)buffer)
2889 gl_state.d3dvertexbuffer = NULL;
2890 if (buffer->devicebuffer)
2892 if (buffer->isindexbuffer)
2893 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
2895 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
2896 buffer->devicebuffer = NULL;
2900 case RENDERPATH_D3D10:
2901 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2903 case RENDERPATH_D3D11:
2904 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2907 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
2910 void GL_Mesh_ListVBOs(qboolean printeach)
2913 size_t ebocount = 0, ebomemory = 0;
2914 size_t vbocount = 0, vbomemory = 0;
2915 r_meshbuffer_t *buffer;
2916 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
2917 for (i = 0;i < endindex;i++)
2919 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
2922 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)");}
2923 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)");}
2925 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);
2930 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
2932 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2933 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)
2935 gl_state.pointer_vertex_components = components;
2936 gl_state.pointer_vertex_gltype = gltype;
2937 gl_state.pointer_vertex_stride = stride;
2938 gl_state.pointer_vertex_pointer = pointer;
2939 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
2940 gl_state.pointer_vertex_offset = bufferoffset;
2942 GL_BindVBO(bufferobject);
2943 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2947 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
2949 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
2950 // the pointer only.
2953 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2954 // caller wants color array enabled
2955 if (!gl_state.pointer_color_enabled)
2957 gl_state.pointer_color_enabled = true;
2959 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
2961 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)
2963 gl_state.pointer_color_components = components;
2964 gl_state.pointer_color_gltype = gltype;
2965 gl_state.pointer_color_stride = stride;
2966 gl_state.pointer_color_pointer = pointer;
2967 gl_state.pointer_color_vertexbuffer = vertexbuffer;
2968 gl_state.pointer_color_offset = bufferoffset;
2970 GL_BindVBO(bufferobject);
2971 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
2976 // caller wants color array disabled
2977 if (gl_state.pointer_color_enabled)
2979 gl_state.pointer_color_enabled = false;
2981 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
2982 // when color array is on the glColor gets trashed, set it again
2983 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
2988 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)
2990 gltextureunit_t *unit = gl_state.units + unitnum;
2991 // update array settings
2993 // note: there is no need to check bufferobject here because all cases
2994 // that involve a valid bufferobject also supply a texcoord array
2997 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
2998 // texture array unit is enabled, enable the array
2999 if (!unit->arrayenabled)
3001 unit->arrayenabled = true;
3002 GL_ClientActiveTexture(unitnum);
3003 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3006 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)
3008 unit->pointer_texcoord_components = components;
3009 unit->pointer_texcoord_gltype = gltype;
3010 unit->pointer_texcoord_stride = stride;
3011 unit->pointer_texcoord_pointer = pointer;
3012 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3013 unit->pointer_texcoord_offset = bufferoffset;
3014 GL_ClientActiveTexture(unitnum);
3015 GL_BindVBO(bufferobject);
3016 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3021 // texture array unit is disabled, disable the array
3022 if (unit->arrayenabled)
3024 unit->arrayenabled = false;
3025 GL_ClientActiveTexture(unitnum);
3026 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3031 int R_Mesh_TexBound(unsigned int unitnum, int id)
3033 gltextureunit_t *unit = gl_state.units + unitnum;
3034 if (unitnum >= vid.teximageunits)
3036 if (id == GL_TEXTURE_2D)
3038 if (id == GL_TEXTURE_3D)
3040 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3041 return unit->tcubemap;
3045 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3047 switch(vid.renderpath)
3049 case RENDERPATH_GL11:
3050 case RENDERPATH_GL13:
3051 case RENDERPATH_GL20:
3052 case RENDERPATH_CGGL:
3053 R_Mesh_TexBind(0, tex);
3054 GL_ActiveTexture(0);CHECKGLERROR
3055 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3057 case RENDERPATH_D3D9:
3060 IDirect3DSurface9 *currentsurface = NULL;
3061 IDirect3DSurface9 *texturesurface = NULL;
3064 sourcerect.left = sx;
3065 sourcerect.top = sy;
3066 sourcerect.right = sx + width;
3067 sourcerect.bottom = sy + height;
3070 destrect.right = tx + width;
3071 destrect.bottom = ty + height;
3072 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3074 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3076 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3077 IDirect3DSurface9_Release(currentsurface);
3079 IDirect3DSurface9_Release(texturesurface);
3084 case RENDERPATH_D3D10:
3085 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3087 case RENDERPATH_D3D11:
3088 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3094 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};
3097 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3099 gltextureunit_t *unit = gl_state.units + unitnum;
3100 int tex2d, tex3d, texcubemap, texnum;
3101 if (unitnum >= vid.teximageunits)
3103 // if (unit->texture == tex)
3105 switch(vid.renderpath)
3107 case RENDERPATH_GL20:
3108 case RENDERPATH_CGGL:
3111 tex = r_texture_white;
3112 // not initialized enough yet...
3116 unit->texture = tex;
3117 texnum = R_GetTexture(tex);
3118 switch(tex->gltexturetypeenum)
3120 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3121 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3122 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;
3125 case RENDERPATH_GL13:
3126 case RENDERPATH_GL11:
3127 unit->texture = tex;
3133 texnum = R_GetTexture(tex);
3134 switch(tex->gltexturetypeenum)
3142 case GL_TEXTURE_CUBE_MAP_ARB:
3143 texcubemap = texnum;
3147 // update 2d texture binding
3148 if (unit->t2d != tex2d)
3150 GL_ActiveTexture(unitnum);
3155 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3162 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3166 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3168 // update 3d texture binding
3169 if (unit->t3d != tex3d)
3171 GL_ActiveTexture(unitnum);
3176 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3183 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3187 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3189 // update cubemap texture binding
3190 if (unit->tcubemap != texcubemap)
3192 GL_ActiveTexture(unitnum);
3195 if (unit->tcubemap == 0)
3197 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3204 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3207 unit->tcubemap = texcubemap;
3208 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3211 case RENDERPATH_D3D9:
3214 extern cvar_t gl_texture_anisotropy;
3217 tex = r_texture_white;
3218 // not initialized enough yet...
3222 if (unit->texture == tex)
3224 unit->texture = tex;
3225 // upload texture if needed
3227 R_RealGetTexture(tex);
3228 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3229 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3230 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3231 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3232 if (tex->d3daddressw)
3233 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3234 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3235 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3236 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3237 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3238 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3239 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3243 case RENDERPATH_D3D10:
3244 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3246 case RENDERPATH_D3D11:
3247 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3252 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3254 gltextureunit_t *unit = gl_state.units + unitnum;
3255 switch(vid.renderpath)
3257 case RENDERPATH_GL11:
3258 case RENDERPATH_GL13:
3259 case RENDERPATH_GL20:
3260 case RENDERPATH_CGGL:
3261 if (matrix && matrix->m[3][3])
3263 // texmatrix specified, check if it is different
3264 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3267 unit->texmatrixenabled = true;
3268 unit->matrix = *matrix;
3270 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3271 GL_ActiveTexture(unitnum);
3272 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3273 qglLoadMatrixf(glmatrix);CHECKGLERROR
3274 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3279 // no texmatrix specified, revert to identity
3280 if (unit->texmatrixenabled)
3282 unit->texmatrixenabled = false;
3283 unit->matrix = identitymatrix;
3285 GL_ActiveTexture(unitnum);
3286 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3287 qglLoadIdentity();CHECKGLERROR
3288 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3292 case RENDERPATH_D3D9:
3293 case RENDERPATH_D3D10:
3294 case RENDERPATH_D3D11:
3299 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3301 gltextureunit_t *unit = gl_state.units + unitnum;
3303 switch(vid.renderpath)
3305 case RENDERPATH_GL20:
3306 case RENDERPATH_CGGL:
3309 case RENDERPATH_GL13:
3310 // GL_ARB_texture_env_combine
3312 combinergb = GL_MODULATE;
3314 combinealpha = GL_MODULATE;
3319 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3321 if (combinergb == GL_DECAL)
3322 combinergb = GL_INTERPOLATE_ARB;
3323 if (unit->combine != GL_COMBINE_ARB)
3325 unit->combine = GL_COMBINE_ARB;
3326 GL_ActiveTexture(unitnum);
3327 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3328 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3330 if (unit->combinergb != combinergb)
3332 unit->combinergb = combinergb;
3333 GL_ActiveTexture(unitnum);
3334 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3336 if (unit->combinealpha != combinealpha)
3338 unit->combinealpha = combinealpha;
3339 GL_ActiveTexture(unitnum);
3340 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3342 if (unit->rgbscale != rgbscale)
3344 unit->rgbscale = rgbscale;
3345 GL_ActiveTexture(unitnum);
3346 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3348 if (unit->alphascale != alphascale)
3350 unit->alphascale = alphascale;
3351 GL_ActiveTexture(unitnum);
3352 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3357 if (unit->combine != combinergb)
3359 unit->combine = combinergb;
3360 GL_ActiveTexture(unitnum);
3361 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3365 case RENDERPATH_GL11:
3368 combinergb = GL_MODULATE;
3369 if (unit->combine != combinergb)
3371 unit->combine = combinergb;
3372 GL_ActiveTexture(unitnum);
3373 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3376 case RENDERPATH_D3D9:
3377 case RENDERPATH_D3D10:
3378 case RENDERPATH_D3D11:
3383 void R_Mesh_ResetTextureState(void)
3385 unsigned int unitnum;
3390 switch(vid.renderpath)
3392 case RENDERPATH_GL20:
3393 case RENDERPATH_CGGL:
3394 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3396 gltextureunit_t *unit = gl_state.units + unitnum;
3400 GL_ActiveTexture(unitnum);
3401 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3406 GL_ActiveTexture(unitnum);
3407 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3412 GL_ActiveTexture(unitnum);
3413 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3416 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3418 gltextureunit_t *unit = gl_state.units + unitnum;
3419 if (unit->arrayenabled)
3421 unit->arrayenabled = false;
3422 GL_ClientActiveTexture(unitnum);
3423 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3426 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3428 gltextureunit_t *unit = gl_state.units + unitnum;
3429 if (unit->texmatrixenabled)
3431 unit->texmatrixenabled = false;
3432 unit->matrix = identitymatrix;
3434 GL_ActiveTexture(unitnum);
3435 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3436 qglLoadIdentity();CHECKGLERROR
3437 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3441 case RENDERPATH_GL13:
3442 case RENDERPATH_GL11:
3443 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3445 gltextureunit_t *unit = gl_state.units + unitnum;
3449 GL_ActiveTexture(unitnum);
3450 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3451 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3456 GL_ActiveTexture(unitnum);
3457 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3458 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3463 GL_ActiveTexture(unitnum);
3464 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3465 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3467 if (unit->arrayenabled)
3469 unit->arrayenabled = false;
3470 GL_ClientActiveTexture(unitnum);
3471 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3473 if (unit->texmatrixenabled)
3475 unit->texmatrixenabled = false;
3476 unit->matrix = identitymatrix;
3478 GL_ActiveTexture(unitnum);
3479 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3480 qglLoadIdentity();CHECKGLERROR
3481 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3483 if (unit->combine != GL_MODULATE)
3485 unit->combine = GL_MODULATE;
3486 GL_ActiveTexture(unitnum);
3487 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3491 case RENDERPATH_D3D9:
3492 case RENDERPATH_D3D10:
3493 case RENDERPATH_D3D11:
3501 //#define r_vertexposition_d3d9fvf (D3DFVF_XYZ)
3502 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3503 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3505 D3DVERTEXELEMENT9 r_vertexposition_d3d9elements[] =
3507 {0, (int)((size_t)&((r_vertexposition_t *)0)->vertex3f), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3511 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3513 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3514 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3515 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3519 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3521 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3522 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3523 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3524 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3525 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3526 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3527 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3531 IDirect3DVertexDeclaration9 *r_vertexposition_d3d9decl;
3532 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3533 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3536 static void R_Mesh_InitVertexDeclarations(void)
3539 r_vertexposition_d3d9decl = NULL;
3540 r_vertexgeneric_d3d9decl = NULL;
3541 r_vertexmesh_d3d9decl = NULL;
3542 switch(vid.renderpath)
3544 case RENDERPATH_GL20:
3545 case RENDERPATH_CGGL:
3546 case RENDERPATH_GL13:
3547 case RENDERPATH_GL11:
3549 case RENDERPATH_D3D9:
3550 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexposition_d3d9elements, &r_vertexposition_d3d9decl);
3551 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3552 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3554 case RENDERPATH_D3D10:
3555 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3557 case RENDERPATH_D3D11:
3558 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3564 static void R_Mesh_DestroyVertexDeclarations(void)
3567 if (r_vertexposition_d3d9decl)
3568 IDirect3DVertexDeclaration9_Release(r_vertexposition_d3d9decl);
3569 r_vertexposition_d3d9decl = NULL;
3570 if (r_vertexgeneric_d3d9decl)
3571 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3572 r_vertexgeneric_d3d9decl = NULL;
3573 if (r_vertexmesh_d3d9decl)
3574 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3575 r_vertexmesh_d3d9decl = NULL;
3579 r_vertexposition_t *R_Mesh_PrepareVertices_Position_Lock(int numvertices)
3582 size = sizeof(r_vertexposition_t) * numvertices;
3583 if (gl_state.preparevertices_tempdatamaxsize < size)
3585 gl_state.preparevertices_tempdatamaxsize = size;
3586 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3588 gl_state.preparevertices_vertexposition = (r_vertexposition_t *)gl_state.preparevertices_tempdata;
3589 gl_state.preparevertices_numvertices = numvertices;
3590 return gl_state.preparevertices_vertexposition;
3593 qboolean R_Mesh_PrepareVertices_Position_Unlock(void)
3595 R_Mesh_PrepareVertices_Position(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexposition, NULL);
3596 gl_state.preparevertices_vertexposition = NULL;
3597 gl_state.preparevertices_numvertices = 0;
3601 void R_Mesh_PrepareVertices_Position_Arrays(int numvertices, const float *vertex3f)
3604 r_vertexposition_t *vertex;
3605 switch(vid.renderpath)
3607 case RENDERPATH_GL20:
3608 case RENDERPATH_CGGL:
3609 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3610 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3611 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3612 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3613 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3614 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3615 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3617 case RENDERPATH_GL13:
3618 case RENDERPATH_GL11:
3619 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3620 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3621 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3622 if (vid.texunits >= 2)
3623 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3624 if (vid.texunits >= 3)
3625 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3627 case RENDERPATH_D3D9:
3629 gl_state.d3dvertexbuffer = NULL;
3630 gl_state.d3dvertexdata = (void *)vertex3f;
3631 gl_state.d3dvertexsize = sizeof(float[3]);
3634 case RENDERPATH_D3D10:
3635 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3637 case RENDERPATH_D3D11:
3638 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3642 // no quick path for this case, convert to vertex structs
3643 vertex = R_Mesh_PrepareVertices_Position_Lock(numvertices);
3644 for (i = 0;i < numvertices;i++)
3645 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
3646 R_Mesh_PrepareVertices_Position_Unlock();
3647 R_Mesh_PrepareVertices_Position(numvertices, vertex, NULL);
3650 void R_Mesh_PrepareVertices_Position(int numvertices, const r_vertexposition_t *vertex, const r_meshbuffer_t *vertexbuffer)
3652 // upload temporary vertexbuffer for this rendering
3653 if (!gl_state.usevbo_staticvertex)
3654 vertexbuffer = NULL;
3655 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3657 if (gl_state.preparevertices_dynamicvertexbuffer)
3658 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
3660 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
3661 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3663 switch(vid.renderpath)
3665 case RENDERPATH_GL20:
3666 case RENDERPATH_CGGL:
3669 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3670 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3671 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3672 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3673 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3674 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3675 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3679 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3680 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3681 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3682 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3683 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3684 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3685 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3688 case RENDERPATH_GL13:
3691 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3692 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3693 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3694 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3698 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3699 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3700 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3701 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3704 case RENDERPATH_GL11:
3707 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3708 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3709 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3713 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3714 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3715 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3718 case RENDERPATH_D3D9:
3720 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexposition_d3d9decl);
3722 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
3724 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3725 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3726 gl_state.d3dvertexdata = (void *)vertex;
3727 gl_state.d3dvertexsize = sizeof(*vertex);
3730 case RENDERPATH_D3D10:
3731 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3733 case RENDERPATH_D3D11:
3734 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3741 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
3744 size = sizeof(r_vertexgeneric_t) * numvertices;
3745 if (gl_state.preparevertices_tempdatamaxsize < size)
3747 gl_state.preparevertices_tempdatamaxsize = size;
3748 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3750 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
3751 gl_state.preparevertices_numvertices = numvertices;
3752 return gl_state.preparevertices_vertexgeneric;
3755 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
3757 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
3758 gl_state.preparevertices_vertexgeneric = NULL;
3759 gl_state.preparevertices_numvertices = 0;
3763 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
3766 r_vertexgeneric_t *vertex;
3767 switch(vid.renderpath)
3769 case RENDERPATH_GL20:
3770 case RENDERPATH_CGGL:
3771 if (gl_mesh_separatearrays.integer)
3773 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3774 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3775 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3776 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3777 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3778 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3779 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3783 case RENDERPATH_GL13:
3784 case RENDERPATH_GL11:
3785 if (gl_mesh_separatearrays.integer)
3787 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3788 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3789 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
3790 if (vid.texunits >= 2)
3791 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3792 if (vid.texunits >= 3)
3793 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3797 case RENDERPATH_D3D9:
3798 case RENDERPATH_D3D10:
3799 case RENDERPATH_D3D11:
3803 // no quick path for this case, convert to vertex structs
3804 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
3805 for (i = 0;i < numvertices;i++)
3806 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
3809 for (i = 0;i < numvertices;i++)
3810 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
3814 float tempcolor4f[4];
3815 unsigned char tempcolor4ub[4];
3816 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
3817 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
3818 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
3819 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
3820 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
3821 for (i = 0;i < numvertices;i++)
3822 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
3825 for (i = 0;i < numvertices;i++)
3826 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
3827 R_Mesh_PrepareVertices_Generic_Unlock();
3828 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
3831 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
3833 // upload temporary vertexbuffer for this rendering
3834 if (!gl_state.usevbo_staticvertex)
3835 vertexbuffer = NULL;
3836 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3838 if (gl_state.preparevertices_dynamicvertexbuffer)
3839 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
3841 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
3842 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3844 switch(vid.renderpath)
3846 case RENDERPATH_GL20:
3847 case RENDERPATH_CGGL:
3850 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3851 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3852 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
3853 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3854 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3855 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3856 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3860 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3861 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
3862 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
3863 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3864 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3865 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3866 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3869 case RENDERPATH_GL13:
3872 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3873 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3874 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
3875 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3879 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3880 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
3881 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
3882 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3885 case RENDERPATH_GL11:
3888 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
3889 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
3890 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
3894 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
3895 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
3896 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
3899 case RENDERPATH_D3D9:
3901 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
3903 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
3905 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3906 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3907 gl_state.d3dvertexdata = (void *)vertex;
3908 gl_state.d3dvertexsize = sizeof(*vertex);
3911 case RENDERPATH_D3D10:
3912 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3914 case RENDERPATH_D3D11:
3915 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3922 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
3925 size = sizeof(r_vertexmesh_t) * numvertices;
3926 if (gl_state.preparevertices_tempdatamaxsize < size)
3928 gl_state.preparevertices_tempdatamaxsize = size;
3929 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
3931 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
3932 gl_state.preparevertices_numvertices = numvertices;
3933 return gl_state.preparevertices_vertexmesh;
3936 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
3938 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
3939 gl_state.preparevertices_vertexmesh = NULL;
3940 gl_state.preparevertices_numvertices = 0;
3944 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)
3947 r_vertexmesh_t *vertex;
3948 switch(vid.renderpath)
3950 case RENDERPATH_GL20:
3951 case RENDERPATH_CGGL:
3952 if (gl_mesh_separatearrays.integer)
3954 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3955 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3956 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
3957 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
3958 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
3959 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
3960 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
3964 case RENDERPATH_GL13:
3965 case RENDERPATH_GL11:
3966 if (gl_mesh_separatearrays.integer)
3968 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
3969 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
3970 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
3971 if (vid.texunits >= 2)
3972 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
3973 if (vid.texunits >= 3)
3974 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3978 case RENDERPATH_D3D9:
3979 case RENDERPATH_D3D10:
3980 case RENDERPATH_D3D11:
3984 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
3985 for (i = 0;i < numvertices;i++)
3986 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
3988 for (i = 0;i < numvertices;i++)
3989 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
3991 for (i = 0;i < numvertices;i++)
3992 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
3994 for (i = 0;i < numvertices;i++)
3995 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
3998 for (i = 0;i < numvertices;i++)
3999 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
4003 float tempcolor4f[4];
4004 unsigned char tempcolor4ub[4];
4005 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
4006 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
4007 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
4008 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
4009 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
4010 for (i = 0;i < numvertices;i++)
4011 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
4013 if (texcoordtexture2f)
4014 for (i = 0;i < numvertices;i++)
4015 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4016 if (texcoordlightmap2f)
4017 for (i = 0;i < numvertices;i++)
4018 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4019 R_Mesh_PrepareVertices_Mesh_Unlock();
4020 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4023 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4025 // upload temporary vertexbuffer for this rendering
4026 if (!gl_state.usevbo_staticvertex)
4027 vertexbuffer = NULL;
4028 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4030 if (gl_state.preparevertices_dynamicvertexbuffer)
4031 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4033 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4034 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4036 switch(vid.renderpath)
4038 case RENDERPATH_GL20:
4039 case RENDERPATH_CGGL:
4042 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4043 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4044 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4045 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4046 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4047 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4048 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4052 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4053 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4054 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4055 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4056 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4057 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4058 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4061 case RENDERPATH_GL13:
4064 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4065 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4066 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4067 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4071 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4072 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4073 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4074 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4077 case RENDERPATH_GL11:
4080 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4081 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4082 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4086 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4087 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4088 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4091 case RENDERPATH_D3D9:
4093 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4095 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4097 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4098 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4099 gl_state.d3dvertexdata = (void *)vertex;
4100 gl_state.d3dvertexsize = sizeof(*vertex);
4103 case RENDERPATH_D3D10:
4104 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4106 case RENDERPATH_D3D11:
4107 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);