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__);