3 #include "cl_collision.h"
4 #include "dpsoftrast.h"
7 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
8 extern D3DCAPS9 vid_d3d9caps;
11 #define MAX_RENDERTARGETS 4
13 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
14 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)"};
15 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"};
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 int defaultframebufferobject; // deal with platforms that use a non-zero default fbo
151 qboolean pointer_color_enabled;
153 int pointer_vertex_components;
154 int pointer_vertex_gltype;
155 size_t pointer_vertex_stride;
156 const void *pointer_vertex_pointer;
157 const r_meshbuffer_t *pointer_vertex_vertexbuffer;
158 size_t pointer_vertex_offset;
160 int pointer_color_components;
161 int pointer_color_gltype;
162 size_t pointer_color_stride;
163 const void *pointer_color_pointer;
164 const r_meshbuffer_t *pointer_color_vertexbuffer;
165 size_t pointer_color_offset;
167 void *preparevertices_tempdata;
168 size_t preparevertices_tempdatamaxsize;
169 r_meshbuffer_t *preparevertices_dynamicvertexbuffer;
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__);
294 case RENDERPATH_SOFT:
295 gl_state.usevbo_staticvertex = false;
296 gl_state.usevbo_staticindex = false;
297 gl_state.usevbo_dynamicvertex = false;
298 gl_state.usevbo_dynamicindex = false;
300 case RENDERPATH_GLES2:
301 gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo;
302 gl_state.usevbo_staticindex = false;
303 gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo;
304 gl_state.usevbo_dynamicindex = false;
309 static void gl_backend_start(void)
311 memset(&gl_state, 0, sizeof(gl_state));
313 R_Mesh_InitVertexDeclarations();
316 Mem_ExpandableArray_NewArray(&gl_state.meshbufferarray, r_main_mempool, sizeof(r_meshbuffer_t), 128);
318 Con_DPrintf("OpenGL backend started.\n");
322 GL_Backend_ResetState();
324 switch(vid.renderpath)
326 case RENDERPATH_GL11:
327 case RENDERPATH_GL13:
328 case RENDERPATH_GL20:
329 case RENDERPATH_CGGL:
330 case RENDERPATH_GLES2:
331 // fetch current fbo here (default fbo is not 0 on some GLES devices)
332 if (vid.support.ext_framebuffer_object)
333 qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &gl_state.defaultframebufferobject);
335 case RENDERPATH_D3D9:
337 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
338 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
341 case RENDERPATH_D3D10:
342 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
344 case RENDERPATH_D3D11:
345 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
347 case RENDERPATH_SOFT:
352 static void gl_backend_shutdown(void)
354 Con_DPrint("OpenGL Backend shutting down\n");
356 switch(vid.renderpath)
358 case RENDERPATH_GL11:
359 case RENDERPATH_GL13:
360 case RENDERPATH_GL20:
361 case RENDERPATH_CGGL:
362 case RENDERPATH_SOFT:
363 case RENDERPATH_GLES2:
365 case RENDERPATH_D3D9:
367 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
368 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
371 case RENDERPATH_D3D10:
372 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
374 case RENDERPATH_D3D11:
375 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
379 if (gl_state.preparevertices_tempdata)
380 Mem_Free(gl_state.preparevertices_tempdata);
381 if (gl_state.preparevertices_dynamicvertexbuffer)
382 R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer);
384 Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray);
386 R_Mesh_DestroyVertexDeclarations();
388 memset(&gl_state, 0, sizeof(gl_state));
391 static void gl_backend_newmap(void)
395 static void gl_backend_devicelost(void)
398 r_meshbuffer_t *buffer;
400 gl_state.d3dvertexbuffer = NULL;
402 switch(vid.renderpath)
404 case RENDERPATH_GL11:
405 case RENDERPATH_GL13:
406 case RENDERPATH_GL20:
407 case RENDERPATH_CGGL:
408 case RENDERPATH_SOFT:
409 case RENDERPATH_GLES2:
411 case RENDERPATH_D3D9:
413 IDirect3DSurface9_Release(gl_state.d3drt_backbufferdepthsurface);
414 IDirect3DSurface9_Release(gl_state.d3drt_backbuffercolorsurface);
417 case RENDERPATH_D3D10:
418 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
420 case RENDERPATH_D3D11:
421 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
424 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
425 for (i = 0;i < endindex;i++)
427 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
428 if (!buffer || !buffer->isdynamic)
430 switch(vid.renderpath)
432 case RENDERPATH_GL11:
433 case RENDERPATH_GL13:
434 case RENDERPATH_GL20:
435 case RENDERPATH_CGGL:
436 case RENDERPATH_SOFT:
437 case RENDERPATH_GLES2:
439 case RENDERPATH_D3D9:
441 if (buffer->devicebuffer)
443 if (buffer->isindexbuffer)
444 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
446 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
447 buffer->devicebuffer = NULL;
451 case RENDERPATH_D3D10:
452 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
454 case RENDERPATH_D3D11:
455 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
461 static void gl_backend_devicerestored(void)
463 switch(vid.renderpath)
465 case RENDERPATH_GL11:
466 case RENDERPATH_GL13:
467 case RENDERPATH_GL20:
468 case RENDERPATH_CGGL:
469 case RENDERPATH_SOFT:
470 case RENDERPATH_GLES2:
472 case RENDERPATH_D3D9:
474 IDirect3DDevice9_GetDepthStencilSurface(vid_d3d9dev, &gl_state.d3drt_backbufferdepthsurface);
475 IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, &gl_state.d3drt_backbuffercolorsurface);
478 case RENDERPATH_D3D10:
479 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
481 case RENDERPATH_D3D11:
482 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
487 void gl_backend_init(void)
491 for (i = 0;i < POLYGONELEMENTS_MAXPOINTS - 2;i++)
493 polygonelement3s[i * 3 + 0] = 0;
494 polygonelement3s[i * 3 + 1] = i + 1;
495 polygonelement3s[i * 3 + 2] = i + 2;
497 // elements for rendering a series of quads as triangles
498 for (i = 0;i < QUADELEMENTS_MAXQUADS;i++)
500 quadelement3s[i * 6 + 0] = i * 4;
501 quadelement3s[i * 6 + 1] = i * 4 + 1;
502 quadelement3s[i * 6 + 2] = i * 4 + 2;
503 quadelement3s[i * 6 + 3] = i * 4;
504 quadelement3s[i * 6 + 4] = i * 4 + 2;
505 quadelement3s[i * 6 + 5] = i * 4 + 3;
508 for (i = 0;i < (POLYGONELEMENTS_MAXPOINTS - 2)*3;i++)
509 polygonelement3i[i] = polygonelement3s[i];
510 for (i = 0;i < QUADELEMENTS_MAXQUADS*6;i++)
511 quadelement3i[i] = quadelement3s[i];
513 Cvar_RegisterVariable(&r_render);
514 Cvar_RegisterVariable(&r_renderview);
515 Cvar_RegisterVariable(&r_waterwarp);
516 Cvar_RegisterVariable(&gl_polyblend);
517 Cvar_RegisterVariable(&v_flipped);
518 Cvar_RegisterVariable(&gl_dither);
519 Cvar_RegisterVariable(&gl_vbo);
520 Cvar_RegisterVariable(&gl_vbo_dynamicvertex);
521 Cvar_RegisterVariable(&gl_vbo_dynamicindex);
522 Cvar_RegisterVariable(&gl_paranoid);
523 Cvar_RegisterVariable(&gl_printcheckerror);
525 Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
526 Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
527 Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
529 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");
531 R_RegisterModule("GL_Backend", gl_backend_start, gl_backend_shutdown, gl_backend_newmap, gl_backend_devicelost, gl_backend_devicerestored);
534 void GL_SetMirrorState(qboolean state);
536 void R_Viewport_TransformToScreen(const r_viewport_t *v, const vec4_t in, vec4_t out)
540 Matrix4x4_Transform4 (&v->viewmatrix, in, temp);
541 Matrix4x4_Transform4 (&v->projectmatrix, temp, out);
543 out[0] = v->x + (out[0] * iw + 1.0f) * v->width * 0.5f;
545 // for an odd reason, inverting this is wrong for R_Shadow_ScissorForBBox (we then get badly scissored lights)
546 //out[1] = v->y + v->height - (out[1] * iw + 1.0f) * v->height * 0.5f;
547 out[1] = v->y + (out[1] * iw + 1.0f) * v->height * 0.5f;
549 out[2] = v->z + (out[2] * iw + 1.0f) * v->depth * 0.5f;
552 static int bboxedges[12][2] =
571 qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor)
573 int i, ix1, iy1, ix2, iy2;
574 float x1, y1, x2, y2;
585 scissor[0] = r_refdef.view.viewport.x;
586 scissor[1] = r_refdef.view.viewport.y;
587 scissor[2] = r_refdef.view.viewport.width;
588 scissor[3] = r_refdef.view.viewport.height;
590 // if view is inside the box, just say yes it's visible
591 if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs))
594 x1 = y1 = x2 = y2 = 0;
596 // transform all corners that are infront of the nearclip plane
597 VectorNegate(r_refdef.view.frustum[4].normal, plane4f);
598 plane4f[3] = r_refdef.view.frustum[4].dist;
600 for (i = 0;i < 8;i++)
602 Vector4Set(corner[i], (i & 1) ? maxs[0] : mins[0], (i & 2) ? maxs[1] : mins[1], (i & 4) ? maxs[2] : mins[2], 1);
603 dist[i] = DotProduct4(corner[i], plane4f);
604 sign[i] = dist[i] > 0;
607 VectorCopy(corner[i], vertex[numvertices]);
611 // if some points are behind the nearclip, add clipped edge points to make
612 // sure that the scissor boundary is complete
613 if (numvertices > 0 && numvertices < 8)
615 // add clipped edge points
616 for (i = 0;i < 12;i++)
620 if (sign[j] != sign[k])
622 f = dist[j] / (dist[j] - dist[k]);
623 VectorLerp(corner[j], f, corner[k], vertex[numvertices]);
629 // if we have no points to check, it is behind the view plane
633 // if we have some points to transform, check what screen area is covered
634 x1 = y1 = x2 = y2 = 0;
636 //Con_Printf("%i vertices to transform...\n", numvertices);
637 for (i = 0;i < numvertices;i++)
639 VectorCopy(vertex[i], v);
640 R_Viewport_TransformToScreen(&r_refdef.view.viewport, v, v2);
641 //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]);
644 if (x1 > v2[0]) x1 = v2[0];
645 if (x2 < v2[0]) x2 = v2[0];
646 if (y1 > v2[1]) y1 = v2[1];
647 if (y2 < v2[1]) y2 = v2[1];
656 // now convert the scissor rectangle to integer screen coordinates
657 ix1 = (int)(x1 - 1.0f);
658 //iy1 = vid.height - (int)(y2 - 1.0f);
659 //iy1 = r_refdef.view.viewport.width + 2 * r_refdef.view.viewport.x - (int)(y2 - 1.0f);
660 iy1 = (int)(y1 - 1.0f);
661 ix2 = (int)(x2 + 1.0f);
662 //iy2 = vid.height - (int)(y1 + 1.0f);
663 //iy2 = r_refdef.view.viewport.height + 2 * r_refdef.view.viewport.y - (int)(y1 + 1.0f);
664 iy2 = (int)(y2 + 1.0f);
665 //Con_Printf("%f %f %f %f\n", x1, y1, x2, y2);
667 // clamp it to the screen
668 if (ix1 < r_refdef.view.viewport.x) ix1 = r_refdef.view.viewport.x;
669 if (iy1 < r_refdef.view.viewport.y) iy1 = r_refdef.view.viewport.y;
670 if (ix2 > r_refdef.view.viewport.x + r_refdef.view.viewport.width) ix2 = r_refdef.view.viewport.x + r_refdef.view.viewport.width;
671 if (iy2 > r_refdef.view.viewport.y + r_refdef.view.viewport.height) iy2 = r_refdef.view.viewport.y + r_refdef.view.viewport.height;
673 // if it is inside out, it's not visible
674 if (ix2 <= ix1 || iy2 <= iy1)
677 // the light area is visible, set up the scissor rectangle
680 scissor[2] = ix2 - ix1;
681 scissor[3] = iy2 - iy1;
683 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
684 switch(vid.renderpath)
686 case RENDERPATH_D3D9:
687 case RENDERPATH_D3D10:
688 case RENDERPATH_D3D11:
689 scissor[1] = vid.height - scissor[1] - scissor[3];
691 case RENDERPATH_GL11:
692 case RENDERPATH_GL13:
693 case RENDERPATH_GL20:
694 case RENDERPATH_CGGL:
695 case RENDERPATH_SOFT:
696 case RENDERPATH_GLES2:
704 static void R_Viewport_ApplyNearClipPlaneFloatGL(const r_viewport_t *v, float *m, float normalx, float normaly, float normalz, float dist)
708 float clipPlane[4], v3[3], v4[3];
711 // This is inspired by Oblique Depth Projection from http://www.terathon.com/code/oblique.php
713 VectorSet(normal, normalx, normaly, normalz);
714 Matrix4x4_Transform3x3(&v->viewmatrix, normal, clipPlane);
715 VectorScale(normal, dist, v3);
716 Matrix4x4_Transform(&v->viewmatrix, v3, v4);
717 // FIXME: LordHavoc: I think this can be done more efficiently somehow but I can't remember the technique
718 clipPlane[3] = -DotProduct(v4, clipPlane);
722 // testing code for comparing results
724 VectorCopy4(clipPlane, clipPlane2);
725 R_EntityMatrix(&identitymatrix);
726 VectorSet(q, normal[0], normal[1], normal[2], -dist);
727 qglClipPlane(GL_CLIP_PLANE0, q);
728 qglGetClipPlane(GL_CLIP_PLANE0, q);
729 VectorCopy4(q, clipPlane);
733 // Calculate the clip-space corner point opposite the clipping plane
734 // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and
735 // transform it into camera space by multiplying it
736 // by the inverse of the projection matrix
737 q[0] = ((clipPlane[0] < 0.0f ? -1.0f : clipPlane[0] > 0.0f ? 1.0f : 0.0f) + m[8]) / m[0];
738 q[1] = ((clipPlane[1] < 0.0f ? -1.0f : clipPlane[1] > 0.0f ? 1.0f : 0.0f) + m[9]) / m[5];
740 q[3] = (1.0f + m[10]) / m[14];
742 // Calculate the scaled plane vector
743 d = 2.0f / DotProduct4(clipPlane, q);
745 // Replace the third row of the projection matrix
746 m[2] = clipPlane[0] * d;
747 m[6] = clipPlane[1] * d;
748 m[10] = clipPlane[2] * d + 1.0f;
749 m[14] = clipPlane[3] * d;
752 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)
754 float left = x1, right = x2, bottom = y2, top = y1, zNear = nearclip, zFar = farclip;
756 memset(v, 0, sizeof(*v));
757 v->type = R_VIEWPORTTYPE_ORTHO;
758 v->cameramatrix = *cameramatrix;
765 memset(m, 0, sizeof(m));
766 m[0] = 2/(right - left);
767 m[5] = 2/(top - bottom);
768 m[10] = -2/(zFar - zNear);
769 m[12] = - (right + left)/(right - left);
770 m[13] = - (top + bottom)/(top - bottom);
771 m[14] = - (zFar + zNear)/(zFar - zNear);
773 switch(vid.renderpath)
775 case RENDERPATH_GL11:
776 case RENDERPATH_GL13:
777 case RENDERPATH_GL20:
778 case RENDERPATH_CGGL:
779 case RENDERPATH_SOFT:
780 case RENDERPATH_GLES2:
782 case RENDERPATH_D3D9:
783 case RENDERPATH_D3D10:
784 case RENDERPATH_D3D11:
785 m[10] = -1/(zFar - zNear);
786 m[14] = -zNear/(zFar-zNear);
789 v->screentodepth[0] = -farclip / (farclip - nearclip);
790 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
792 Matrix4x4_Invert_Full(&v->viewmatrix, &v->cameramatrix);
795 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
797 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
803 Vector4Set(test1, (x1+x2)*0.5f, (y1+y2)*0.5f, 0.0f, 1.0f);
804 R_Viewport_TransformToScreen(v, test1, test2);
805 Con_Printf("%f %f %f -> %f %f %f\n", test1[0], test1[1], test1[2], test2[0], test2[1], test2[2]);
810 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)
812 matrix4x4_t tempmatrix, basematrix;
814 memset(v, 0, sizeof(*v));
816 v->type = R_VIEWPORTTYPE_PERSPECTIVE;
817 v->cameramatrix = *cameramatrix;
824 memset(m, 0, sizeof(m));
825 m[0] = 1.0 / frustumx;
826 m[5] = 1.0 / frustumy;
827 m[10] = -(farclip + nearclip) / (farclip - nearclip);
829 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
830 v->screentodepth[0] = -farclip / (farclip - nearclip);
831 v->screentodepth[1] = farclip * nearclip / (farclip - nearclip);
833 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
834 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
835 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
836 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
839 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
841 if(v_flipped.integer)
849 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
852 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)
854 matrix4x4_t tempmatrix, basematrix;
855 const float nudge = 1.0 - 1.0 / (1<<23);
857 memset(v, 0, sizeof(*v));
859 v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
860 v->cameramatrix = *cameramatrix;
867 memset(m, 0, sizeof(m));
868 m[ 0] = 1.0 / frustumx;
869 m[ 5] = 1.0 / frustumy;
872 m[14] = -2 * nearclip * nudge;
873 v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
874 v->screentodepth[1] = m[14] * -0.5;
876 Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
877 Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
878 Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
879 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
882 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
884 if(v_flipped.integer)
892 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
895 float cubeviewmatrix[6][16] =
897 // standard cubemap projections
935 float rectviewmatrix[6][16] =
937 // sign-preserving cubemap projections
976 void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
978 matrix4x4_t tempmatrix, basematrix;
980 memset(v, 0, sizeof(*v));
981 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
982 v->cameramatrix = *cameramatrix;
986 memset(m, 0, sizeof(m));
988 m[10] = -(farclip + nearclip) / (farclip - nearclip);
990 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
992 Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
993 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
994 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
997 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
999 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1002 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)
1004 matrix4x4_t tempmatrix, basematrix;
1006 memset(v, 0, sizeof(*v));
1007 v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
1008 v->cameramatrix = *cameramatrix;
1009 v->x = (side & 1) * size;
1010 v->y = (side >> 1) * size;
1014 memset(m, 0, sizeof(m));
1015 m[0] = m[5] = 1.0f * ((float)size - border) / size;
1016 m[10] = -(farclip + nearclip) / (farclip - nearclip);
1018 m[14] = -2 * nearclip * farclip / (farclip - nearclip);
1020 Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
1021 Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
1022 Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
1024 switch(vid.renderpath)
1026 case RENDERPATH_GL20:
1027 case RENDERPATH_CGGL:
1028 case RENDERPATH_GL13:
1029 case RENDERPATH_GL11:
1030 case RENDERPATH_SOFT:
1031 case RENDERPATH_GLES2:
1033 case RENDERPATH_D3D9:
1036 case RENDERPATH_D3D10:
1037 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1039 case RENDERPATH_D3D11:
1040 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1045 R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
1047 Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
1050 void R_SetViewport(const r_viewport_t *v)
1055 // FIXME: v_flipped_state is evil, this probably breaks somewhere
1056 GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
1058 // copy over the matrices to our state
1059 gl_viewmatrix = v->viewmatrix;
1060 gl_projectionmatrix = v->projectmatrix;
1062 switch(vid.renderpath)
1064 case RENDERPATH_CGGL:
1065 case RENDERPATH_GL13:
1066 case RENDERPATH_GL11:
1068 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1069 // Load the projection matrix into OpenGL
1070 qglMatrixMode(GL_PROJECTION);CHECKGLERROR
1071 Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m);
1072 qglLoadMatrixf(m);CHECKGLERROR
1073 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1075 case RENDERPATH_D3D9:
1078 D3DVIEWPORT9 d3dviewport;
1079 d3dviewport.X = gl_viewport.x;
1080 d3dviewport.Y = gl_viewport.y;
1081 d3dviewport.Width = gl_viewport.width;
1082 d3dviewport.Height = gl_viewport.height;
1083 d3dviewport.MinZ = gl_state.depthrange[0];
1084 d3dviewport.MaxZ = gl_state.depthrange[1];
1085 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1089 case RENDERPATH_D3D10:
1090 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1092 case RENDERPATH_D3D11:
1093 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1095 case RENDERPATH_SOFT:
1096 DPSOFTRAST_Viewport(v->x, v->y, v->width, v->height);
1098 case RENDERPATH_GL20:
1099 case RENDERPATH_GLES2:
1101 qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
1105 // force an update of the derived matrices
1106 gl_modelmatrixchanged = true;
1107 R_EntityMatrix(&gl_modelmatrix);
1110 void R_GetViewport(r_viewport_t *v)
1115 static void GL_BindVBO(int bufferobject)
1117 if (gl_state.vertexbufferobject != bufferobject)
1119 gl_state.vertexbufferobject = bufferobject;
1121 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1125 static void GL_BindEBO(int bufferobject)
1127 if (gl_state.elementbufferobject != bufferobject)
1129 gl_state.elementbufferobject = bufferobject;
1131 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR
1135 int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1138 switch(vid.renderpath)
1140 case RENDERPATH_GL11:
1141 case RENDERPATH_GL13:
1142 case RENDERPATH_GL20:
1143 case RENDERPATH_CGGL:
1144 case RENDERPATH_GLES2:
1145 if (!vid.support.ext_framebuffer_object)
1147 qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR
1148 R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL);
1149 if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR
1150 if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR
1151 if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR
1152 if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR
1153 if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR
1155 case RENDERPATH_D3D9:
1156 case RENDERPATH_D3D10:
1157 case RENDERPATH_D3D11:
1159 case RENDERPATH_SOFT:
1165 void R_Mesh_DestroyFramebufferObject(int fbo)
1167 switch(vid.renderpath)
1169 case RENDERPATH_GL11:
1170 case RENDERPATH_GL13:
1171 case RENDERPATH_GL20:
1172 case RENDERPATH_CGGL:
1173 case RENDERPATH_GLES2:
1175 qglDeleteFramebuffersEXT(1, (GLuint*)&fbo);
1177 case RENDERPATH_D3D9:
1178 case RENDERPATH_D3D10:
1179 case RENDERPATH_D3D11:
1181 case RENDERPATH_SOFT:
1187 void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
1189 // 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)
1190 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)
1193 gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
1194 if (gl_state.d3drt_depthsurface != depthsurface)
1196 gl_state.d3drt_depthsurface = depthsurface;
1197 IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
1199 if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
1201 gl_state.d3drt_colorsurfaces[0] = colorsurface0;
1202 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
1204 if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
1206 gl_state.d3drt_colorsurfaces[1] = colorsurface1;
1207 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
1209 if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
1211 gl_state.d3drt_colorsurfaces[2] = colorsurface2;
1212 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
1214 if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
1216 gl_state.d3drt_colorsurfaces[3] = colorsurface3;
1217 IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
1222 void R_Mesh_ResetRenderTargets(void)
1224 switch(vid.renderpath)
1226 case RENDERPATH_GL11:
1227 case RENDERPATH_GL13:
1228 case RENDERPATH_GL20:
1229 case RENDERPATH_CGGL:
1230 case RENDERPATH_GLES2:
1231 if (gl_state.framebufferobject)
1233 gl_state.framebufferobject = 0;
1234 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1237 case RENDERPATH_D3D9:
1239 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1242 case RENDERPATH_D3D10:
1243 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1245 case RENDERPATH_D3D11:
1246 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1248 case RENDERPATH_SOFT:
1249 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1254 void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
1258 rtexture_t *textures[5];
1259 Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
1260 textures[4] = depthtexture;
1261 // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
1262 for (j = 0;j < 5;j++)
1264 for (i = 0;i < vid.teximageunits;i++)
1265 if (gl_state.units[i].texture == textures[j])
1266 R_Mesh_TexBind(i, NULL);
1267 // set up framebuffer object or render targets for the active rendering API
1268 switch(vid.renderpath)
1270 case RENDERPATH_GL11:
1271 case RENDERPATH_GL13:
1272 case RENDERPATH_GL20:
1273 case RENDERPATH_CGGL:
1274 case RENDERPATH_GLES2:
1275 if (gl_state.framebufferobject != fbo)
1277 gl_state.framebufferobject = fbo;
1278 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
1281 case RENDERPATH_D3D9:
1283 // set up the new render targets, a NULL depthtexture intentionally binds nothing
1284 // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
1287 IDirect3DSurface9 *colorsurfaces[4];
1288 for (i = 0;i < 4;i++)
1290 colorsurfaces[i] = NULL;
1292 IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]);
1294 // set the render targets for real
1295 R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]);
1296 // release the texture surface levels (they won't be lost while bound...)
1297 for (i = 0;i < 4;i++)
1299 IDirect3DSurface9_Release(colorsurfaces[i]);
1302 R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL);
1305 case RENDERPATH_D3D10:
1306 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1308 case RENDERPATH_D3D11:
1309 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1311 case RENDERPATH_SOFT:
1315 unsigned int *pointers[5];
1316 memset(pointers, 0, sizeof(pointers));
1317 for (i = 0;i < 5;i++)
1318 pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
1319 width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1320 height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
1321 DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
1324 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1330 static int d3dcmpforglfunc(int f)
1334 case GL_NEVER: return D3DCMP_NEVER;
1335 case GL_LESS: return D3DCMP_LESS;
1336 case GL_EQUAL: return D3DCMP_EQUAL;
1337 case GL_LEQUAL: return D3DCMP_LESSEQUAL;
1338 case GL_GREATER: return D3DCMP_GREATER;
1339 case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
1340 case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
1341 case GL_ALWAYS: return D3DCMP_ALWAYS;
1342 default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
1346 static int d3dstencilopforglfunc(int f)
1350 case GL_KEEP: return D3DSTENCILOP_KEEP;
1351 case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
1352 case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
1353 default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
1359 static void GL_Backend_ResetState(void)
1362 gl_state.active = true;
1363 gl_state.depthtest = true;
1364 gl_state.alphatest = false;
1365 gl_state.alphafunc = GL_GEQUAL;
1366 gl_state.alphafuncvalue = 0.5f;
1367 gl_state.blendfunc1 = GL_ONE;
1368 gl_state.blendfunc2 = GL_ZERO;
1369 gl_state.blend = false;
1370 gl_state.depthmask = GL_TRUE;
1371 gl_state.colormask = 15;
1372 gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
1373 gl_state.lockrange_first = 0;
1374 gl_state.lockrange_count = 0;
1375 gl_state.cullface = GL_FRONT;
1376 gl_state.cullfaceenable = false;
1377 gl_state.polygonoffset[0] = 0;
1378 gl_state.polygonoffset[1] = 0;
1379 gl_state.framebufferobject = 0;
1380 gl_state.depthfunc = GL_LEQUAL;
1382 switch(vid.renderpath)
1384 case RENDERPATH_D3D9:
1387 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
1388 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
1389 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc));
1390 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255));
1391 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
1392 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1393 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1394 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1395 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
1396 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
1400 case RENDERPATH_D3D10:
1401 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1403 case RENDERPATH_D3D11:
1404 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1406 case RENDERPATH_CGGL:
1409 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1410 // qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1411 // qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1412 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1413 qglDisable(GL_BLEND);CHECKGLERROR
1414 qglCullFace(gl_state.cullface);CHECKGLERROR
1415 qglDisable(GL_CULL_FACE);CHECKGLERROR
1416 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1417 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1418 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1419 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1421 if (vid.support.arb_vertex_buffer_object)
1423 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1424 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1427 if (vid.support.ext_framebuffer_object)
1429 qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1430 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1433 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1434 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1436 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1437 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1438 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1440 if (vid.support.ext_framebuffer_object)
1441 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1443 gl_state.unit = MAX_TEXTUREUNITS;
1444 gl_state.clientunit = MAX_TEXTUREUNITS;
1445 for (i = 0;i < vid.teximageunits;i++)
1447 GL_ActiveTexture(i);
1448 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1449 if (vid.support.ext_texture_3d)
1451 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1453 if (vid.support.arb_texture_cube_map)
1455 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1459 for (i = 0;i < vid.texarrayunits;i++)
1461 GL_ClientActiveTexture(i);
1463 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1464 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1468 case RENDERPATH_GL13:
1469 case RENDERPATH_GL11:
1472 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1473 qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1474 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1475 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1476 qglDisable(GL_BLEND);CHECKGLERROR
1477 qglCullFace(gl_state.cullface);CHECKGLERROR
1478 qglDisable(GL_CULL_FACE);CHECKGLERROR
1479 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1480 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1481 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1482 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1484 if (vid.support.arb_vertex_buffer_object)
1486 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1487 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1490 if (vid.support.ext_framebuffer_object)
1492 //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
1493 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
1496 qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
1497 qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
1499 qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
1500 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
1501 qglColor4f(1, 1, 1, 1);CHECKGLERROR
1503 if (vid.support.ext_framebuffer_object)
1504 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject);
1506 gl_state.unit = MAX_TEXTUREUNITS;
1507 gl_state.clientunit = MAX_TEXTUREUNITS;
1508 for (i = 0;i < vid.texunits;i++)
1510 GL_ActiveTexture(i);
1511 GL_ClientActiveTexture(i);
1512 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
1513 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1514 if (vid.support.ext_texture_3d)
1516 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
1517 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1519 if (vid.support.arb_texture_cube_map)
1521 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
1522 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1525 qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR
1526 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
1527 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
1528 qglLoadIdentity();CHECKGLERROR
1529 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
1530 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
1534 case RENDERPATH_SOFT:
1535 DPSOFTRAST_ColorMask(1,1,1,1);
1536 DPSOFTRAST_AlphaTest(gl_state.alphatest);
1537 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1538 DPSOFTRAST_CullFace(gl_state.cullface);
1539 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1540 DPSOFTRAST_DepthMask(gl_state.depthmask);
1541 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1542 DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
1543 DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
1545 case RENDERPATH_GL20:
1546 case RENDERPATH_GLES2:
1548 qglColorMask(1, 1, 1, 1);CHECKGLERROR
1549 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1550 qglDisable(GL_BLEND);CHECKGLERROR
1551 qglCullFace(gl_state.cullface);CHECKGLERROR
1552 qglDisable(GL_CULL_FACE);CHECKGLERROR
1553 qglDepthFunc(GL_LEQUAL);CHECKGLERROR
1554 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1555 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1556 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
1557 // if (vid.renderpath == RENDERPATH_GL20)
1559 // qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR
1560 // qglDisable(GL_ALPHA_TEST);CHECKGLERROR
1562 if (vid.support.arb_vertex_buffer_object)
1564 qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
1565 qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0);
1567 if (vid.support.ext_framebuffer_object)
1568 qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject);
1569 qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
1570 qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
1571 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
1572 qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
1573 qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
1574 gl_state.unit = MAX_TEXTUREUNITS;
1575 gl_state.clientunit = MAX_TEXTUREUNITS;
1576 for (i = 0;i < vid.teximageunits;i++)
1578 GL_ActiveTexture(i);
1579 qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
1580 if (vid.support.ext_texture_3d)
1582 qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
1584 if (vid.support.arb_texture_cube_map)
1586 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR
1589 for (i = 0;i < vid.texarrayunits;i++)
1592 qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
1593 qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
1600 void GL_ActiveTexture(unsigned int num)
1602 if (gl_state.unit != num)
1604 gl_state.unit = num;
1605 switch(vid.renderpath)
1607 case RENDERPATH_GL11:
1608 case RENDERPATH_GL13:
1609 case RENDERPATH_GL20:
1610 case RENDERPATH_CGGL:
1611 case RENDERPATH_GLES2:
1612 if (qglActiveTexture)
1615 qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit);
1619 case RENDERPATH_D3D9:
1620 case RENDERPATH_D3D10:
1621 case RENDERPATH_D3D11:
1623 case RENDERPATH_SOFT:
1629 void GL_ClientActiveTexture(unsigned int num)
1631 if (gl_state.clientunit != num)
1633 gl_state.clientunit = num;
1634 switch(vid.renderpath)
1636 case RENDERPATH_GL11:
1637 case RENDERPATH_GL13:
1638 case RENDERPATH_CGGL:
1639 if (qglActiveTexture)
1642 qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit);
1646 case RENDERPATH_D3D9:
1647 case RENDERPATH_D3D10:
1648 case RENDERPATH_D3D11:
1650 case RENDERPATH_SOFT:
1652 case RENDERPATH_GL20:
1653 case RENDERPATH_GLES2:
1659 void GL_BlendFunc(int blendfunc1, int blendfunc2)
1661 if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
1663 qboolean blendenable;
1664 gl_state.blendfunc1 = blendfunc1;
1665 gl_state.blendfunc2 = blendfunc2;
1666 blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
1667 switch(vid.renderpath)
1669 case RENDERPATH_GL11:
1670 case RENDERPATH_GL13:
1671 case RENDERPATH_GL20:
1672 case RENDERPATH_CGGL:
1673 case RENDERPATH_GLES2:
1675 qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
1676 if (gl_state.blend != blendenable)
1678 gl_state.blend = blendenable;
1679 if (!gl_state.blend)
1681 qglDisable(GL_BLEND);CHECKGLERROR
1685 qglEnable(GL_BLEND);CHECKGLERROR
1689 case RENDERPATH_D3D9:
1694 D3DBLEND d3dblendfunc[2];
1695 glblendfunc[0] = gl_state.blendfunc1;
1696 glblendfunc[1] = gl_state.blendfunc2;
1697 for (i = 0;i < 2;i++)
1699 switch(glblendfunc[i])
1701 case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
1702 case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
1703 case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
1704 case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
1705 case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
1706 case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
1707 case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
1708 case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
1709 case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
1710 case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
1713 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
1714 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
1715 if (gl_state.blend != blendenable)
1717 gl_state.blend = blendenable;
1718 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
1723 case RENDERPATH_D3D10:
1724 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1726 case RENDERPATH_D3D11:
1727 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1729 case RENDERPATH_SOFT:
1730 DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
1736 void GL_DepthMask(int state)
1738 if (gl_state.depthmask != state)
1740 gl_state.depthmask = state;
1741 switch(vid.renderpath)
1743 case RENDERPATH_GL11:
1744 case RENDERPATH_GL13:
1745 case RENDERPATH_GL20:
1746 case RENDERPATH_CGGL:
1747 case RENDERPATH_GLES2:
1749 qglDepthMask(gl_state.depthmask);CHECKGLERROR
1751 case RENDERPATH_D3D9:
1753 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
1756 case RENDERPATH_D3D10:
1757 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1759 case RENDERPATH_D3D11:
1760 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1762 case RENDERPATH_SOFT:
1763 DPSOFTRAST_DepthMask(gl_state.depthmask);
1769 void GL_DepthTest(int state)
1771 if (gl_state.depthtest != state)
1773 gl_state.depthtest = state;
1774 switch(vid.renderpath)
1776 case RENDERPATH_GL11:
1777 case RENDERPATH_GL13:
1778 case RENDERPATH_GL20:
1779 case RENDERPATH_CGGL:
1780 case RENDERPATH_GLES2:
1782 if (gl_state.depthtest)
1784 qglEnable(GL_DEPTH_TEST);CHECKGLERROR
1788 qglDisable(GL_DEPTH_TEST);CHECKGLERROR
1791 case RENDERPATH_D3D9:
1793 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
1796 case RENDERPATH_D3D10:
1797 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1799 case RENDERPATH_D3D11:
1800 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1802 case RENDERPATH_SOFT:
1803 DPSOFTRAST_DepthTest(gl_state.depthtest);
1809 void GL_DepthFunc(int state)
1811 if (gl_state.depthfunc != state)
1813 gl_state.depthfunc = state;
1814 switch(vid.renderpath)
1816 case RENDERPATH_GL11:
1817 case RENDERPATH_GL13:
1818 case RENDERPATH_GL20:
1819 case RENDERPATH_CGGL:
1820 case RENDERPATH_GLES2:
1822 qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
1824 case RENDERPATH_D3D9:
1826 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
1829 case RENDERPATH_D3D10:
1830 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1832 case RENDERPATH_D3D11:
1833 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1835 case RENDERPATH_SOFT:
1836 DPSOFTRAST_DepthFunc(gl_state.depthfunc);
1842 void GL_DepthRange(float nearfrac, float farfrac)
1844 if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
1846 gl_state.depthrange[0] = nearfrac;
1847 gl_state.depthrange[1] = farfrac;
1848 switch(vid.renderpath)
1850 case RENDERPATH_GL11:
1851 case RENDERPATH_GL13:
1852 case RENDERPATH_GL20:
1853 case RENDERPATH_CGGL:
1854 case RENDERPATH_GLES2:
1855 qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1857 case RENDERPATH_D3D9:
1860 D3DVIEWPORT9 d3dviewport;
1861 d3dviewport.X = gl_viewport.x;
1862 d3dviewport.Y = gl_viewport.y;
1863 d3dviewport.Width = gl_viewport.width;
1864 d3dviewport.Height = gl_viewport.height;
1865 d3dviewport.MinZ = gl_state.depthrange[0];
1866 d3dviewport.MaxZ = gl_state.depthrange[1];
1867 IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
1871 case RENDERPATH_D3D10:
1872 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1874 case RENDERPATH_D3D11:
1875 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1877 case RENDERPATH_SOFT:
1878 DPSOFTRAST_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
1884 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)
1886 switch (vid.renderpath)
1888 case RENDERPATH_GL11:
1889 case RENDERPATH_GL13:
1890 case RENDERPATH_GL20:
1891 case RENDERPATH_CGGL:
1892 case RENDERPATH_GLES2:
1896 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1900 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1902 if (vid.support.ati_separate_stencil)
1904 qglStencilMask(writemask);CHECKGLERROR
1905 qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
1906 qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR
1907 qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR
1909 else if (vid.support.ext_stencil_two_side)
1911 qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1912 qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR
1913 qglStencilMask(writemask);CHECKGLERROR
1914 qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
1915 qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
1916 qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
1917 qglStencilMask(writemask);CHECKGLERROR
1918 qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
1919 qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
1922 case RENDERPATH_D3D9:
1924 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1925 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1926 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1927 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
1928 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
1929 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
1930 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
1931 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
1932 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
1933 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
1934 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
1935 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1936 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1939 case RENDERPATH_D3D10:
1940 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1942 case RENDERPATH_D3D11:
1943 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945 case RENDERPATH_SOFT:
1946 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1951 void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
1953 switch (vid.renderpath)
1955 case RENDERPATH_GL11:
1956 case RENDERPATH_GL13:
1957 case RENDERPATH_GL20:
1958 case RENDERPATH_CGGL:
1959 case RENDERPATH_GLES2:
1963 qglEnable(GL_STENCIL_TEST);CHECKGLERROR
1967 qglDisable(GL_STENCIL_TEST);CHECKGLERROR
1969 if (vid.support.ext_stencil_two_side)
1971 qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR
1973 qglStencilMask(writemask);CHECKGLERROR
1974 qglStencilOp(fail, zfail, zpass);CHECKGLERROR
1975 qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
1978 case RENDERPATH_D3D9:
1980 if (vid.support.ati_separate_stencil)
1981 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
1982 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
1983 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
1984 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
1985 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
1986 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
1987 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
1988 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
1989 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
1992 case RENDERPATH_D3D10:
1993 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1995 case RENDERPATH_D3D11:
1996 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1998 case RENDERPATH_SOFT:
1999 //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2004 void GL_PolygonOffset(float planeoffset, float depthoffset)
2006 if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
2008 gl_state.polygonoffset[0] = planeoffset;
2009 gl_state.polygonoffset[1] = depthoffset;
2010 switch(vid.renderpath)
2012 case RENDERPATH_GL11:
2013 case RENDERPATH_GL13:
2014 case RENDERPATH_GL20:
2015 case RENDERPATH_CGGL:
2016 case RENDERPATH_GLES2:
2017 qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
2019 case RENDERPATH_D3D9:
2021 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
2022 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
2025 case RENDERPATH_D3D10:
2026 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2028 case RENDERPATH_D3D11:
2029 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2031 case RENDERPATH_SOFT:
2032 DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
2038 void GL_SetMirrorState(qboolean state)
2040 if (v_flipped_state != state)
2042 v_flipped_state = state;
2043 if (gl_state.cullface == GL_BACK)
2044 gl_state.cullface = GL_FRONT;
2045 else if (gl_state.cullface == GL_FRONT)
2046 gl_state.cullface = GL_BACK;
2049 switch(vid.renderpath)
2051 case RENDERPATH_GL11:
2052 case RENDERPATH_GL13:
2053 case RENDERPATH_GL20:
2054 case RENDERPATH_CGGL:
2055 case RENDERPATH_GLES2:
2056 qglCullFace(gl_state.cullface);CHECKGLERROR
2058 case RENDERPATH_D3D9:
2060 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
2063 case RENDERPATH_D3D10:
2064 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2066 case RENDERPATH_D3D11:
2067 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2069 case RENDERPATH_SOFT:
2070 DPSOFTRAST_CullFace(gl_state.cullface);
2076 void GL_CullFace(int state)
2080 if(state == GL_FRONT)
2082 else if(state == GL_BACK)
2086 switch(vid.renderpath)
2088 case RENDERPATH_GL11:
2089 case RENDERPATH_GL13:
2090 case RENDERPATH_GL20:
2091 case RENDERPATH_CGGL:
2092 case RENDERPATH_GLES2:
2095 if (state != GL_NONE)
2097 if (!gl_state.cullfaceenable)
2099 gl_state.cullfaceenable = true;
2100 qglEnable(GL_CULL_FACE);CHECKGLERROR
2102 if (gl_state.cullface != state)
2104 gl_state.cullface = state;
2105 qglCullFace(gl_state.cullface);CHECKGLERROR
2110 if (gl_state.cullfaceenable)
2112 gl_state.cullfaceenable = false;
2113 qglDisable(GL_CULL_FACE);CHECKGLERROR
2117 case RENDERPATH_D3D9:
2119 if (gl_state.cullface != state)
2121 gl_state.cullface = state;
2122 switch(gl_state.cullface)
2125 gl_state.cullfaceenable = false;
2126 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE);
2129 gl_state.cullfaceenable = true;
2130 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CCW);
2133 gl_state.cullfaceenable = true;
2134 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_CW);
2140 case RENDERPATH_D3D10:
2141 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2143 case RENDERPATH_D3D11:
2144 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2146 case RENDERPATH_SOFT:
2147 if (gl_state.cullface != state)
2149 gl_state.cullface = state;
2150 gl_state.cullfaceenable = state != GL_NONE ? true : false;
2151 DPSOFTRAST_CullFace(gl_state.cullface);
2157 void GL_AlphaTest(int state)
2159 if (gl_state.alphatest != state)
2161 gl_state.alphatest = state;
2162 switch(vid.renderpath)
2164 case RENDERPATH_GL11:
2165 case RENDERPATH_GL13:
2166 // only fixed function uses alpha test, other paths use pixel kill capability in shaders
2168 if (gl_state.alphatest)
2170 qglEnable(GL_ALPHA_TEST);CHECKGLERROR
2174 qglDisable(GL_ALPHA_TEST);CHECKGLERROR
2177 case RENDERPATH_D3D9:
2179 // IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest);
2182 case RENDERPATH_D3D10:
2184 case RENDERPATH_D3D11:
2186 case RENDERPATH_SOFT:
2187 // DPSOFTRAST_AlphaTest(gl_state.alphatest);
2189 case RENDERPATH_CGGL:
2190 case RENDERPATH_GL20:
2191 case RENDERPATH_GLES2:
2197 void GL_ColorMask(int r, int g, int b, int a)
2199 // NOTE: this matches D3DCOLORWRITEENABLE_RED, GREEN, BLUE, ALPHA
2200 int state = (r ? 1 : 0) | (g ? 2 : 0) | (b ? 4 : 0) | (a ? 8 : 0);
2201 if (gl_state.colormask != state)
2203 gl_state.colormask = state;
2204 switch(vid.renderpath)
2206 case RENDERPATH_GL11:
2207 case RENDERPATH_GL13:
2208 case RENDERPATH_GL20:
2209 case RENDERPATH_CGGL:
2210 case RENDERPATH_GLES2:
2212 qglColorMask((GLboolean)r, (GLboolean)g, (GLboolean)b, (GLboolean)a);CHECKGLERROR
2214 case RENDERPATH_D3D9:
2216 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, state);
2219 case RENDERPATH_D3D10:
2220 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2222 case RENDERPATH_D3D11:
2223 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2225 case RENDERPATH_SOFT:
2226 DPSOFTRAST_ColorMask(r, g, b, a);
2232 void GL_Color(float cr, float cg, float cb, float ca)
2234 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)
2236 gl_state.color4f[0] = cr;
2237 gl_state.color4f[1] = cg;
2238 gl_state.color4f[2] = cb;
2239 gl_state.color4f[3] = ca;
2240 switch(vid.renderpath)
2242 case RENDERPATH_GL11:
2243 case RENDERPATH_GL13:
2244 case RENDERPATH_CGGL:
2246 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);
2249 case RENDERPATH_D3D9:
2250 case RENDERPATH_D3D10:
2251 case RENDERPATH_D3D11:
2252 // no equivalent in D3D
2254 case RENDERPATH_SOFT:
2255 DPSOFTRAST_Color4f(cr, cg, cb, ca);
2257 case RENDERPATH_GL20:
2258 case RENDERPATH_GLES2:
2259 qglVertexAttrib4f(GLSLATTRIB_COLOR, cr, cg, cb, ca);
2265 void GL_Scissor (int x, int y, int width, int height)
2267 switch(vid.renderpath)
2269 case RENDERPATH_GL11:
2270 case RENDERPATH_GL13:
2271 case RENDERPATH_GL20:
2272 case RENDERPATH_CGGL:
2273 case RENDERPATH_GLES2:
2275 qglScissor(x, y,width,height);
2278 case RENDERPATH_D3D9:
2284 d3drect.right = x + width;
2285 d3drect.bottom = y + height;
2286 IDirect3DDevice9_SetScissorRect(vid_d3d9dev, &d3drect);
2290 case RENDERPATH_D3D10:
2291 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2293 case RENDERPATH_D3D11:
2294 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2296 case RENDERPATH_SOFT:
2297 DPSOFTRAST_Scissor(x, y, width, height);
2302 void GL_ScissorTest(int state)
2304 if (gl_state.scissortest != state)
2306 gl_state.scissortest = state;
2307 switch(vid.renderpath)
2309 case RENDERPATH_GL11:
2310 case RENDERPATH_GL13:
2311 case RENDERPATH_GL20:
2312 case RENDERPATH_CGGL:
2313 case RENDERPATH_GLES2:
2315 if(gl_state.scissortest)
2316 qglEnable(GL_SCISSOR_TEST);
2318 qglDisable(GL_SCISSOR_TEST);
2321 case RENDERPATH_D3D9:
2323 IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SCISSORTESTENABLE, gl_state.scissortest);
2326 case RENDERPATH_D3D10:
2327 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2329 case RENDERPATH_D3D11:
2330 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2332 case RENDERPATH_SOFT:
2333 DPSOFTRAST_ScissorTest(gl_state.scissortest);
2339 void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue)
2341 static const float blackcolor[4] = {0, 0, 0, 0};
2342 // prevent warnings when trying to clear a buffer that does not exist
2344 colorvalue = blackcolor;
2347 mask &= ~GL_STENCIL_BUFFER_BIT;
2350 switch(vid.renderpath)
2352 case RENDERPATH_GL11:
2353 case RENDERPATH_GL13:
2354 case RENDERPATH_GL20:
2355 case RENDERPATH_CGGL:
2356 case RENDERPATH_GLES2:
2358 if (mask & GL_COLOR_BUFFER_BIT)
2360 qglClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);CHECKGLERROR
2362 if (mask & GL_DEPTH_BUFFER_BIT)
2364 qglClearDepth(depthvalue);CHECKGLERROR
2366 if (mask & GL_STENCIL_BUFFER_BIT)
2368 qglClearStencil(stencilvalue);CHECKGLERROR
2370 qglClear(mask);CHECKGLERROR
2372 case RENDERPATH_D3D9:
2374 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);
2377 case RENDERPATH_D3D10:
2378 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2380 case RENDERPATH_D3D11:
2381 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2383 case RENDERPATH_SOFT:
2384 if (mask & GL_COLOR_BUFFER_BIT)
2385 DPSOFTRAST_ClearColor(colorvalue[0], colorvalue[1], colorvalue[2], colorvalue[3]);
2386 if (mask & GL_DEPTH_BUFFER_BIT)
2387 DPSOFTRAST_ClearDepth(depthvalue);
2392 void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpixels)
2394 switch(vid.renderpath)
2396 case RENDERPATH_GL11:
2397 case RENDERPATH_GL13:
2398 case RENDERPATH_GL20:
2399 case RENDERPATH_CGGL:
2400 case RENDERPATH_GLES2:
2402 qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR
2404 case RENDERPATH_D3D9:
2407 // LordHavoc: we can't directly download the backbuffer because it may be
2408 // multisampled, and it may not be lockable, so we blit it to a lockable
2409 // surface of the same dimensions (but without multisample) to resolve the
2410 // multisample buffer to a normal image, and then lock that...
2411 IDirect3DSurface9 *stretchsurface = NULL;
2412 if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &stretchsurface, NULL)))
2414 D3DLOCKED_RECT lockedrect;
2415 if (!FAILED(IDirect3DDevice9_StretchRect(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, NULL, stretchsurface, NULL, D3DTEXF_POINT)))
2417 if (!FAILED(IDirect3DSurface9_LockRect(stretchsurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2420 unsigned char *row = (unsigned char *)lockedrect.pBits + x * 4 + lockedrect.Pitch * (vid.height - 1 - y);
2421 for (line = 0;line < height;line++, row -= lockedrect.Pitch)
2422 memcpy(outpixels + line * width * 4, row, width * 4);
2423 IDirect3DSurface9_UnlockRect(stretchsurface);
2426 IDirect3DSurface9_Release(stretchsurface);
2429 //IDirect3DSurface9 *syssurface = NULL;
2430 //if (!FAILED(IDirect3DDevice9_CreateRenderTarget(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, FALSE, &stretchsurface, NULL)))
2431 //if (!FAILED(IDirect3DDevice9_CreateOffscreenPlainSurface(vid_d3d9dev, vid.width, vid.height, D3DFMT_A8R8G8B8, D3DPOOL_SCRATCH, &syssurface, NULL)))
2432 //IDirect3DDevice9_GetRenderTargetData(vid_d3d9dev, gl_state.d3drt_backbuffercolorsurface, syssurface);
2433 //if (!FAILED(IDirect3DDevice9_GetFrontBufferData(vid_d3d9dev, 0, syssurface)))
2434 //if (!FAILED(IDirect3DSurface9_LockRect(syssurface, &lockedrect, NULL, D3DLOCK_READONLY)))
2435 //IDirect3DSurface9_UnlockRect(syssurface);
2436 //IDirect3DSurface9_Release(syssurface);
2440 case RENDERPATH_D3D10:
2441 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2443 case RENDERPATH_D3D11:
2444 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2446 case RENDERPATH_SOFT:
2447 DPSOFTRAST_GetPixelsBGRA(x, y, width, height, outpixels);
2452 // called at beginning of frame
2453 void R_Mesh_Start(void)
2456 R_Mesh_ResetRenderTargets();
2458 if (gl_printcheckerror.integer && !gl_paranoid.integer)
2460 Con_Printf("WARNING: gl_printcheckerror is on but gl_paranoid is off, turning it on...\n");
2461 Cvar_SetValueQuick(&gl_paranoid, 1);
2465 qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings)
2469 char compilelog[MAX_INPUTLINE];
2470 shaderobject = qglCreateShader(shadertypeenum);CHECKGLERROR
2473 qglShaderSource(shaderobject, numstrings, strings, NULL);CHECKGLERROR
2474 qglCompileShader(shaderobject);CHECKGLERROR
2475 qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR
2476 qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR
2477 if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")))
2479 int i, j, pretextlines = 0;
2480 for (i = 0;i < numstrings - 1;i++)
2481 for (j = 0;strings[i][j];j++)
2482 if (strings[i][j] == '\n')
2484 Con_Printf("%s shader compile log:\n%s\n(line offset for any above warnings/errors: %i)\n", shadertype, compilelog, pretextlines);
2486 if (!shadercompiled)
2488 qglDeleteShader(shaderobject);CHECKGLERROR
2491 qglAttachShader(programobject, shaderobject);CHECKGLERROR
2492 qglDeleteShader(shaderobject);CHECKGLERROR
2496 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)
2498 GLint programlinked;
2499 GLuint programobject = 0;
2500 char linklog[MAX_INPUTLINE];
2503 programobject = qglCreateProgram();CHECKGLERROR
2507 qglBindAttribLocation(programobject, GLSLATTRIB_POSITION , "Attrib_Position" );
2508 qglBindAttribLocation(programobject, GLSLATTRIB_COLOR , "Attrib_Color" );
2509 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD0, "Attrib_TexCoord0");
2510 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD1, "Attrib_TexCoord1");
2511 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD2, "Attrib_TexCoord2");
2512 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3");
2513 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4");
2514 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5");
2515 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6");
2516 qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7");
2518 if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list))
2521 #ifdef GL_GEOMETRY_SHADER
2522 if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list))
2526 if (fragmentstrings_count && !GL_Backend_CompileShader(programobject, GL_FRAGMENT_SHADER, "fragment", fragmentstrings_count, fragmentstrings_list))
2529 qglLinkProgram(programobject);CHECKGLERROR
2530 qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR
2531 qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR
2534 if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning"))
2535 Con_DPrintf("program link log:\n%s\n", linklog);
2536 // software vertex shader is ok but software fragment shader is WAY
2537 // too slow, fail program if so.
2538 // NOTE: this string might be ATI specific, but that's ok because the
2539 // ATI R300 chip (Radeon 9500-9800/X300) is the most likely to use a
2540 // software fragment shader due to low instruction and dependent
2542 if (strstr(linklog, "fragment shader will run in software"))
2543 programlinked = false;
2547 return programobject;
2549 qglDeleteProgram(programobject);CHECKGLERROR
2553 void GL_Backend_FreeProgram(unsigned int prog)
2556 qglDeleteProgram(prog);
2560 void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset)
2565 for (i = 0;i < count;i++)
2566 *out++ = *in++ + offset;
2569 memcpy(out, in, sizeof(*out) * count);
2572 // renders triangles using vertices from the active arrays
2573 int paranoidblah = 0;
2574 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)
2576 unsigned int numelements = numtriangles * 3;
2578 size_t bufferoffset3i;
2580 size_t bufferoffset3s;
2581 if (numvertices < 3 || numtriangles < 1)
2583 if (numvertices < 0 || numtriangles < 0 || developer_extra.integer)
2584 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);
2587 if (!gl_mesh_prefer_short_elements.integer)
2591 if (element3i_indexbuffer)
2592 element3i_indexbuffer = NULL;
2594 // adjust the pointers for firsttriangle
2596 element3i += firsttriangle * 3;
2597 if (element3i_indexbuffer)
2598 element3i_bufferoffset += firsttriangle * 3 * sizeof(*element3i);
2600 element3s += firsttriangle * 3;
2601 if (element3s_indexbuffer)
2602 element3s_bufferoffset += firsttriangle * 3 * sizeof(*element3s);
2603 switch(vid.renderpath)
2605 case RENDERPATH_GL11:
2606 case RENDERPATH_GL13:
2607 case RENDERPATH_GL20:
2608 case RENDERPATH_CGGL:
2609 case RENDERPATH_GLES2:
2610 // check if the user specified to ignore static index buffers
2611 if (!gl_state.usevbo_staticindex || (gl_vbo.integer == 3 && !vid.forcevbo && (element3i_bufferoffset || element3s_bufferoffset)))
2613 element3i_indexbuffer = NULL;
2614 element3s_indexbuffer = NULL;
2617 case RENDERPATH_D3D9:
2618 case RENDERPATH_D3D10:
2619 case RENDERPATH_D3D11:
2621 case RENDERPATH_SOFT:
2624 // upload a dynamic index buffer if needed
2627 if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex)
2629 if (gl_state.draw_dynamicindexbuffer)
2630 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s));
2632 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true);
2633 element3s_indexbuffer = gl_state.draw_dynamicindexbuffer;
2634 element3s_bufferoffset = 0;
2639 if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex)
2641 if (gl_state.draw_dynamicindexbuffer)
2642 R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i));
2644 gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false);
2645 element3i_indexbuffer = gl_state.draw_dynamicindexbuffer;
2646 element3i_bufferoffset = 0;
2649 bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0;
2650 bufferoffset3i = element3i_bufferoffset;
2651 bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0;
2652 bufferoffset3s = element3s_bufferoffset;
2653 r_refdef.stats.draws++;
2654 r_refdef.stats.draws_vertices += numvertices;
2655 r_refdef.stats.draws_elements += numelements;
2656 if (gl_paranoid.integer)
2659 // LordHavoc: disabled this - it needs to be updated to handle components and gltype and stride in each array
2661 unsigned int j, size;
2663 // note: there's no validation done here on buffer objects because it
2664 // is somewhat difficult to get at the data, and gl_paranoid can be
2665 // used without buffer objects if the need arises
2666 // (the data could be gotten using glMapBuffer but it would be very
2667 // slow due to uncachable video memory reads)
2668 if (!qglIsEnabled(GL_VERTEX_ARRAY))
2669 Con_Print("R_Mesh_Draw: vertex array not enabled\n");
2671 if (gl_state.pointer_vertex_pointer)
2672 for (j = 0, size = numvertices * 3, p = (int *)((float *)gl_state.pointer_vertex + firstvertex * 3);j < size;j++, p++)
2674 if (gl_state.pointer_color_enabled)
2676 if (!qglIsEnabled(GL_COLOR_ARRAY))
2677 Con_Print("R_Mesh_Draw: color array set but not enabled\n");
2679 if (gl_state.pointer_color && gl_state.pointer_color_enabled)
2680 for (j = 0, size = numvertices * 4, p = (int *)((float *)gl_state.pointer_color + firstvertex * 4);j < size;j++, p++)
2683 for (i = 0;i < vid.texarrayunits;i++)
2685 if (gl_state.units[i].arrayenabled)
2687 GL_ClientActiveTexture(i);
2688 if (!qglIsEnabled(GL_TEXTURE_COORD_ARRAY))
2689 Con_Print("R_Mesh_Draw: texcoord array set but not enabled\n");
2691 if (gl_state.units[i].pointer_texcoord && gl_state.units[i].arrayenabled)
2692 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++)
2699 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2701 if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
2703 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
2710 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2712 if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
2714 Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
2720 if (r_render.integer || r_refdef.draw2dstage)
2722 switch(vid.renderpath)
2724 case RENDERPATH_GL11:
2725 case RENDERPATH_GL13:
2726 case RENDERPATH_GL20:
2727 case RENDERPATH_CGGL:
2729 if (gl_mesh_testmanualfeeding.integer)
2731 unsigned int i, j, element;
2733 qglBegin(GL_TRIANGLES);
2734 for (i = 0;i < (unsigned int) numtriangles * 3;i++)
2737 element = element3i[i];
2739 element = element3s[i];
2741 element = firstvertex + i;
2742 for (j = 0;j < vid.texarrayunits;j++)
2744 if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled)
2746 if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT)
2748 p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2749 if (vid.texarrayunits > 1)
2751 if (gl_state.units[j].pointer_texcoord_components == 4)
2752 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
2753 else if (gl_state.units[j].pointer_texcoord_components == 3)
2754 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
2755 else if (gl_state.units[j].pointer_texcoord_components == 2)
2756 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
2758 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
2762 if (gl_state.units[j].pointer_texcoord_components == 4)
2763 qglTexCoord4f(p[0], p[1], p[2], p[3]);
2764 else if (gl_state.units[j].pointer_texcoord_components == 3)
2765 qglTexCoord3f(p[0], p[1], p[2]);
2766 else if (gl_state.units[j].pointer_texcoord_components == 2)
2767 qglTexCoord2f(p[0], p[1]);
2769 qglTexCoord1f(p[0]);
2772 else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT)
2774 const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2775 if (vid.texarrayunits > 1)
2777 if (gl_state.units[j].pointer_texcoord_components == 4)
2778 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]);
2779 else if (gl_state.units[j].pointer_texcoord_components == 3)
2780 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]);
2781 else if (gl_state.units[j].pointer_texcoord_components == 2)
2782 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]);
2783 else if (gl_state.units[j].pointer_texcoord_components == 1)
2784 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]);
2788 if (gl_state.units[j].pointer_texcoord_components == 4)
2789 qglTexCoord4f(s[0], s[1], s[2], s[3]);
2790 else if (gl_state.units[j].pointer_texcoord_components == 3)
2791 qglTexCoord3f(s[0], s[1], s[2]);
2792 else if (gl_state.units[j].pointer_texcoord_components == 2)
2793 qglTexCoord2f(s[0], s[1]);
2794 else if (gl_state.units[j].pointer_texcoord_components == 1)
2795 qglTexCoord1f(s[0]);
2798 else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE)
2800 const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride);
2801 if (vid.texarrayunits > 1)
2803 if (gl_state.units[j].pointer_texcoord_components == 4)
2804 qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]);
2805 else if (gl_state.units[j].pointer_texcoord_components == 3)
2806 qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]);
2807 else if (gl_state.units[j].pointer_texcoord_components == 2)
2808 qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]);
2809 else if (gl_state.units[j].pointer_texcoord_components == 1)
2810 qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]);
2814 if (gl_state.units[j].pointer_texcoord_components == 4)
2815 qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]);
2816 else if (gl_state.units[j].pointer_texcoord_components == 3)
2817 qglTexCoord3f(sb[0], sb[1], sb[2]);
2818 else if (gl_state.units[j].pointer_texcoord_components == 2)
2819 qglTexCoord2f(sb[0], sb[1]);
2820 else if (gl_state.units[j].pointer_texcoord_components == 1)
2821 qglTexCoord1f(sb[0]);
2826 if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4)
2828 if (gl_state.pointer_color_gltype == GL_FLOAT)
2830 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2831 qglColor4f(p[0], p[1], p[2], p[3]);
2833 else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE)
2835 const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride);
2836 qglColor4ub(ub[0], ub[1], ub[2], ub[3]);
2839 if (gl_state.pointer_vertex_gltype == GL_FLOAT)
2841 p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride);
2842 if (gl_state.pointer_vertex_components == 4)
2843 qglVertex4f(p[0], p[1], p[2], p[3]);
2844 else if (gl_state.pointer_vertex_components == 3)
2845 qglVertex3f(p[0], p[1], p[2]);
2847 qglVertex2f(p[0], p[1]);
2853 else if (bufferobject3s)
2855 GL_BindEBO(bufferobject3s);
2856 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2858 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s);
2863 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
2867 else if (bufferobject3i)
2869 GL_BindEBO(bufferobject3i);
2870 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2872 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i);
2877 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
2884 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2886 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s);
2891 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2898 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
2900 qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i);
2905 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2911 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
2915 case RENDERPATH_D3D9:
2917 if (gl_state.d3dvertexbuffer && ((element3s && element3s_indexbuffer) || (element3i && element3i_indexbuffer)))
2919 if (element3s_indexbuffer)
2921 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3s_indexbuffer->devicebuffer);
2922 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3s_bufferoffset>>1, numtriangles);
2924 else if (element3i_indexbuffer)
2926 IDirect3DDevice9_SetIndices(vid_d3d9dev, (IDirect3DIndexBuffer9 *)element3i_indexbuffer->devicebuffer);
2927 IDirect3DDevice9_DrawIndexedPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, 0, firstvertex, numvertices, element3i_bufferoffset>>2, numtriangles);
2930 IDirect3DDevice9_DrawPrimitive(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices);
2935 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3s, D3DFMT_INDEX16, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2937 IDirect3DDevice9_DrawIndexedPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, firstvertex, numvertices, numtriangles, element3i, D3DFMT_INDEX32, gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2939 IDirect3DDevice9_DrawPrimitiveUP(vid_d3d9dev, D3DPT_TRIANGLELIST, numvertices, (void *)gl_state.d3dvertexdata, gl_state.d3dvertexsize);
2943 case RENDERPATH_D3D10:
2944 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2946 case RENDERPATH_D3D11:
2947 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2949 case RENDERPATH_SOFT:
2950 DPSOFTRAST_DrawTriangles(firstvertex, numvertices, numtriangles, element3i, element3s);
2952 case RENDERPATH_GLES2:
2953 // GLES does not have glDrawRangeElements, and generally
2954 // underperforms with index buffers, so this code path is
2955 // relatively straightforward...
2957 if (gl_paranoid.integer)
2959 int r, prog, enabled, i;
2960 GLsizei attriblength;
2963 GLchar attribname[1024];
2964 r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR
2965 if (r != GL_FRAMEBUFFER_COMPLETE_EXT)
2966 Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject);
2967 #ifndef GL_CURRENT_PROGRAM
2968 #define GL_CURRENT_PROGRAM 0x8B8D
2970 qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR
2971 if (r < 0 || r > 10000)
2972 Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r);
2974 for (i = 0;i < 8;i++)
2976 qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR
2979 qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR
2980 Con_DPrintf("prog %i position %i length %i size %04X type %i name \"%s\"\n", prog, i, (int)attriblength, (int)attribsize, (int)attribtype, (char *)attribname);
2986 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
2991 qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
2996 qglDrawArrays(GL_TRIANGLES, firstvertex, numvertices);
3004 // restores backend state, used when done with 3D rendering
3005 void R_Mesh_Finish(void)
3007 R_Mesh_ResetRenderTargets();
3010 r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16)
3012 r_meshbuffer_t *buffer;
3013 if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)))
3015 buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray);
3016 memset(buffer, 0, sizeof(*buffer));
3017 buffer->bufferobject = 0;
3018 buffer->devicebuffer = NULL;
3020 buffer->isindexbuffer = isindexbuffer;
3021 buffer->isdynamic = isdynamic;
3022 buffer->isindex16 = isindex16;
3023 strlcpy(buffer->name, name, sizeof(buffer->name));
3024 R_Mesh_UpdateMeshBuffer(buffer, data, size);
3028 void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size)
3032 if (buffer->isindexbuffer)
3034 r_refdef.stats.indexbufferuploadcount++;
3035 r_refdef.stats.indexbufferuploadsize += size;
3039 r_refdef.stats.vertexbufferuploadcount++;
3040 r_refdef.stats.vertexbufferuploadsize += size;
3042 switch(vid.renderpath)
3044 case RENDERPATH_GL11:
3045 case RENDERPATH_GL13:
3046 case RENDERPATH_GL20:
3047 case RENDERPATH_CGGL:
3048 case RENDERPATH_GLES2:
3049 if (!buffer->bufferobject)
3050 qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject);
3051 if (buffer->isindexbuffer)
3052 GL_BindEBO(buffer->bufferobject);
3054 GL_BindVBO(buffer->bufferobject);
3055 qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB);
3057 case RENDERPATH_D3D9:
3061 void *datapointer = NULL;
3062 if (buffer->isindexbuffer)
3064 IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer;
3065 if (size > buffer->size || !buffer->devicebuffer)
3067 if (buffer->devicebuffer)
3068 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer);
3069 buffer->devicebuffer = NULL;
3070 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)))
3071 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);
3072 buffer->devicebuffer = (void *)d3d9indexbuffer;
3073 buffer->size = size;
3075 if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3078 memcpy(datapointer, data, size);
3080 memset(datapointer, 0, size);
3081 IDirect3DIndexBuffer9_Unlock(d3d9indexbuffer);
3086 IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer;
3087 if (size > buffer->size || !buffer->devicebuffer)
3089 if (buffer->devicebuffer)
3090 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer);
3091 buffer->devicebuffer = NULL;
3092 if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL)))
3093 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);
3094 buffer->devicebuffer = (void *)d3d9vertexbuffer;
3095 buffer->size = size;
3097 if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0)))
3100 memcpy(datapointer, data, size);
3102 memset(datapointer, 0, size);
3103 IDirect3DVertexBuffer9_Unlock(d3d9vertexbuffer);
3109 case RENDERPATH_D3D10:
3110 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3112 case RENDERPATH_D3D11:
3113 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3115 case RENDERPATH_SOFT:
3120 void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer)
3124 switch(vid.renderpath)
3126 case RENDERPATH_GL11:
3127 case RENDERPATH_GL13:
3128 case RENDERPATH_GL20:
3129 case RENDERPATH_CGGL:
3130 case RENDERPATH_GLES2:
3131 qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject);
3133 case RENDERPATH_D3D9:
3135 if (gl_state.d3dvertexbuffer == (void *)buffer)
3136 gl_state.d3dvertexbuffer = NULL;
3137 if (buffer->devicebuffer)
3139 if (buffer->isindexbuffer)
3140 IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9 *)buffer->devicebuffer);
3142 IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9 *)buffer->devicebuffer);
3143 buffer->devicebuffer = NULL;
3147 case RENDERPATH_D3D10:
3148 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3150 case RENDERPATH_D3D11:
3151 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3153 case RENDERPATH_SOFT:
3156 Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer);
3159 void GL_Mesh_ListVBOs(qboolean printeach)
3162 size_t ebocount = 0, ebomemory = 0;
3163 size_t vbocount = 0, vbomemory = 0;
3164 r_meshbuffer_t *buffer;
3165 endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray);
3166 for (i = 0;i < endindex;i++)
3168 buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i);
3171 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)");}
3172 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)");}
3174 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);
3179 void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3181 switch(vid.renderpath)
3183 case RENDERPATH_GL11:
3184 case RENDERPATH_GL13:
3185 case RENDERPATH_CGGL:
3186 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)
3188 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3189 gl_state.pointer_vertex_components = components;
3190 gl_state.pointer_vertex_gltype = gltype;
3191 gl_state.pointer_vertex_stride = stride;
3192 gl_state.pointer_vertex_pointer = pointer;
3193 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3194 gl_state.pointer_vertex_offset = bufferoffset;
3196 GL_BindVBO(bufferobject);
3197 qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3200 case RENDERPATH_GL20:
3201 case RENDERPATH_GLES2:
3202 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)
3204 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3205 gl_state.pointer_vertex_components = components;
3206 gl_state.pointer_vertex_gltype = gltype;
3207 gl_state.pointer_vertex_stride = stride;
3208 gl_state.pointer_vertex_pointer = pointer;
3209 gl_state.pointer_vertex_vertexbuffer = vertexbuffer;
3210 gl_state.pointer_vertex_offset = bufferoffset;
3212 GL_BindVBO(bufferobject);
3213 qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3216 case RENDERPATH_D3D9:
3217 case RENDERPATH_D3D10:
3218 case RENDERPATH_D3D11:
3219 case RENDERPATH_SOFT:
3224 void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
3226 // note: vertexbuffer may be non-NULL even if pointer is NULL, so check
3227 // the pointer only.
3228 switch(vid.renderpath)
3230 case RENDERPATH_GL11:
3231 case RENDERPATH_GL13:
3232 case RENDERPATH_CGGL:
3236 // caller wants color array enabled
3237 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3238 if (!gl_state.pointer_color_enabled)
3240 gl_state.pointer_color_enabled = true;
3242 qglEnableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3244 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)
3246 gl_state.pointer_color_components = components;
3247 gl_state.pointer_color_gltype = gltype;
3248 gl_state.pointer_color_stride = stride;
3249 gl_state.pointer_color_pointer = pointer;
3250 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3251 gl_state.pointer_color_offset = bufferoffset;
3253 GL_BindVBO(bufferobject);
3254 qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3259 // caller wants color array disabled
3260 if (gl_state.pointer_color_enabled)
3262 gl_state.pointer_color_enabled = false;
3264 qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
3265 // when color array is on the glColor gets trashed, set it again
3266 qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3270 case RENDERPATH_GL20:
3271 case RENDERPATH_GLES2:
3275 // caller wants color array enabled
3276 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3277 if (!gl_state.pointer_color_enabled)
3279 gl_state.pointer_color_enabled = true;
3281 qglEnableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3283 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)
3285 gl_state.pointer_color_components = components;
3286 gl_state.pointer_color_gltype = gltype;
3287 gl_state.pointer_color_stride = stride;
3288 gl_state.pointer_color_pointer = pointer;
3289 gl_state.pointer_color_vertexbuffer = vertexbuffer;
3290 gl_state.pointer_color_offset = bufferoffset;
3292 GL_BindVBO(bufferobject);
3293 qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3298 // caller wants color array disabled
3299 if (gl_state.pointer_color_enabled)
3301 gl_state.pointer_color_enabled = false;
3303 qglDisableVertexAttribArray(GLSLATTRIB_COLOR);CHECKGLERROR
3304 // when color array is on the glColor gets trashed, set it again
3305 qglVertexAttrib4f(GLSLATTRIB_COLOR, gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR
3309 case RENDERPATH_D3D9:
3310 case RENDERPATH_D3D10:
3311 case RENDERPATH_D3D11:
3312 case RENDERPATH_SOFT:
3317 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)
3319 gltextureunit_t *unit = gl_state.units + unitnum;
3320 // update array settings
3321 // note: there is no need to check bufferobject here because all cases
3322 // that involve a valid bufferobject also supply a texcoord array
3323 switch(vid.renderpath)
3325 case RENDERPATH_GL11:
3326 case RENDERPATH_GL13:
3327 case RENDERPATH_CGGL:
3331 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3332 // texture array unit is enabled, enable the array
3333 if (!unit->arrayenabled)
3335 unit->arrayenabled = true;
3336 GL_ClientActiveTexture(unitnum);
3337 qglEnableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3340 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)
3342 unit->pointer_texcoord_components = components;
3343 unit->pointer_texcoord_gltype = gltype;
3344 unit->pointer_texcoord_stride = stride;
3345 unit->pointer_texcoord_pointer = pointer;
3346 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3347 unit->pointer_texcoord_offset = bufferoffset;
3348 GL_ClientActiveTexture(unitnum);
3349 GL_BindVBO(bufferobject);
3350 qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3355 // texture array unit is disabled, disable the array
3356 if (unit->arrayenabled)
3358 unit->arrayenabled = false;
3359 GL_ClientActiveTexture(unitnum);
3360 qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
3364 case RENDERPATH_GL20:
3365 case RENDERPATH_GLES2:
3369 int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0;
3370 // texture array unit is enabled, enable the array
3371 if (!unit->arrayenabled)
3373 unit->arrayenabled = true;
3374 qglEnableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3377 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)
3379 unit->pointer_texcoord_components = components;
3380 unit->pointer_texcoord_gltype = gltype;
3381 unit->pointer_texcoord_stride = stride;
3382 unit->pointer_texcoord_pointer = pointer;
3383 unit->pointer_texcoord_vertexbuffer = vertexbuffer;
3384 unit->pointer_texcoord_offset = bufferoffset;
3385 GL_BindVBO(bufferobject);
3386 qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR
3391 // texture array unit is disabled, disable the array
3392 if (unit->arrayenabled)
3394 unit->arrayenabled = false;
3395 qglDisableVertexAttribArray(unitnum+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
3399 case RENDERPATH_D3D9:
3400 case RENDERPATH_D3D10:
3401 case RENDERPATH_D3D11:
3402 case RENDERPATH_SOFT:
3407 int R_Mesh_TexBound(unsigned int unitnum, int id)
3409 gltextureunit_t *unit = gl_state.units + unitnum;
3410 if (unitnum >= vid.teximageunits)
3412 if (id == GL_TEXTURE_2D)
3414 if (id == GL_TEXTURE_3D)
3416 if (id == GL_TEXTURE_CUBE_MAP_ARB)
3417 return unit->tcubemap;
3421 void R_Mesh_CopyToTexture(rtexture_t *tex, int tx, int ty, int sx, int sy, int width, int height)
3423 switch(vid.renderpath)
3425 case RENDERPATH_GL11:
3426 case RENDERPATH_GL13:
3427 case RENDERPATH_GL20:
3428 case RENDERPATH_CGGL:
3429 case RENDERPATH_GLES2:
3430 R_Mesh_TexBind(0, tex);
3431 GL_ActiveTexture(0);CHECKGLERROR
3432 qglCopyTexSubImage2D(GL_TEXTURE_2D, 0, tx, ty, sx, sy, width, height);CHECKGLERROR
3434 case RENDERPATH_D3D9:
3437 IDirect3DSurface9 *currentsurface = NULL;
3438 IDirect3DSurface9 *texturesurface = NULL;
3441 sourcerect.left = sx;
3442 sourcerect.top = sy;
3443 sourcerect.right = sx + width;
3444 sourcerect.bottom = sy + height;
3447 destrect.right = tx + width;
3448 destrect.bottom = ty + height;
3449 if (!FAILED(IDirect3DTexture9_GetSurfaceLevel(((IDirect3DTexture9 *)tex->d3dtexture), 0, &texturesurface)))
3451 if (!FAILED(IDirect3DDevice9_GetRenderTarget(vid_d3d9dev, 0, ¤tsurface)))
3453 IDirect3DDevice9_StretchRect(vid_d3d9dev, currentsurface, &sourcerect, texturesurface, &destrect, D3DTEXF_NONE);
3454 IDirect3DSurface9_Release(currentsurface);
3456 IDirect3DSurface9_Release(texturesurface);
3461 case RENDERPATH_D3D10:
3462 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3464 case RENDERPATH_D3D11:
3465 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3467 case RENDERPATH_SOFT:
3468 DPSOFTRAST_CopyRectangleToTexture(tex->texnum, 0, tx, ty, sx, sy, width, height);
3474 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};
3477 void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex)
3479 gltextureunit_t *unit = gl_state.units + unitnum;
3480 int tex2d, tex3d, texcubemap, texnum;
3481 if (unitnum >= vid.teximageunits)
3483 // if (unit->texture == tex)
3485 switch(vid.renderpath)
3487 case RENDERPATH_GL20:
3488 case RENDERPATH_CGGL:
3489 case RENDERPATH_GLES2:
3492 tex = r_texture_white;
3493 // not initialized enough yet...
3497 unit->texture = tex;
3498 texnum = R_GetTexture(tex);
3499 switch(tex->gltexturetypeenum)
3501 case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break;
3502 case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break;
3503 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;
3506 case RENDERPATH_GL13:
3507 case RENDERPATH_GL11:
3508 unit->texture = tex;
3514 texnum = R_GetTexture(tex);
3515 switch(tex->gltexturetypeenum)
3523 case GL_TEXTURE_CUBE_MAP_ARB:
3524 texcubemap = texnum;
3528 // update 2d texture binding
3529 if (unit->t2d != tex2d)
3531 GL_ActiveTexture(unitnum);
3536 qglEnable(GL_TEXTURE_2D);CHECKGLERROR
3543 qglDisable(GL_TEXTURE_2D);CHECKGLERROR
3547 qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR
3549 // update 3d texture binding
3550 if (unit->t3d != tex3d)
3552 GL_ActiveTexture(unitnum);
3557 qglEnable(GL_TEXTURE_3D);CHECKGLERROR
3564 qglDisable(GL_TEXTURE_3D);CHECKGLERROR
3568 qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR
3570 // update cubemap texture binding
3571 if (unit->tcubemap != texcubemap)
3573 GL_ActiveTexture(unitnum);
3576 if (unit->tcubemap == 0)
3578 qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3585 qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR
3588 unit->tcubemap = texcubemap;
3589 qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR
3592 case RENDERPATH_D3D9:
3595 extern cvar_t gl_texture_anisotropy;
3598 tex = r_texture_white;
3599 // not initialized enough yet...
3603 // upload texture if needed
3605 if (unit->texture == tex)
3607 unit->texture = tex;
3608 IDirect3DDevice9_SetTexture(vid_d3d9dev, unitnum, (IDirect3DBaseTexture9*)tex->d3dtexture);
3609 //IDirect3DDevice9_SetRenderState(vid_d3d9dev, d3drswrap[unitnum], (tex->flags & TEXF_CLAMP) ? (D3DWRAPCOORD_0 | D3DWRAPCOORD_1 | D3DWRAPCOORD_2) : 0);
3610 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSU, tex->d3daddressu);
3611 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSV, tex->d3daddressv);
3612 if (tex->d3daddressw)
3613 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_ADDRESSW, tex->d3daddressw);
3614 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAGFILTER, tex->d3dmagfilter);
3615 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MINFILTER, tex->d3dminfilter);
3616 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPFILTER, tex->d3dmipfilter);
3617 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MIPMAPLODBIAS, tex->d3dmipmaplodbias);
3618 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXMIPLEVEL, tex->d3dmaxmiplevelfilter);
3619 IDirect3DDevice9_SetSamplerState(vid_d3d9dev, unitnum, D3DSAMP_MAXANISOTROPY, gl_texture_anisotropy.integer);
3623 case RENDERPATH_D3D10:
3624 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3626 case RENDERPATH_D3D11:
3627 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3629 case RENDERPATH_SOFT:
3632 tex = r_texture_white;
3633 // not initialized enough yet...
3637 texnum = R_GetTexture(tex);
3638 if (unit->texture == tex)
3640 unit->texture = tex;
3641 DPSOFTRAST_SetTexture(unitnum, texnum);
3646 void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
3648 gltextureunit_t *unit = gl_state.units + unitnum;
3649 switch(vid.renderpath)
3651 case RENDERPATH_GL11:
3652 case RENDERPATH_GL13:
3653 case RENDERPATH_GL20:
3654 case RENDERPATH_CGGL:
3655 case RENDERPATH_GLES2:
3656 if (matrix && matrix->m[3][3])
3658 // texmatrix specified, check if it is different
3659 if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t)))
3662 unit->texmatrixenabled = true;
3663 unit->matrix = *matrix;
3665 Matrix4x4_ToArrayFloatGL(&unit->matrix, glmatrix);
3666 GL_ActiveTexture(unitnum);
3667 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3668 qglLoadMatrixf(glmatrix);CHECKGLERROR
3669 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3674 // no texmatrix specified, revert to identity
3675 if (unit->texmatrixenabled)
3677 unit->texmatrixenabled = false;
3678 unit->matrix = identitymatrix;
3680 GL_ActiveTexture(unitnum);
3681 qglMatrixMode(GL_TEXTURE);CHECKGLERROR
3682 qglLoadIdentity();CHECKGLERROR
3683 qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
3687 case RENDERPATH_D3D9:
3688 case RENDERPATH_D3D10:
3689 case RENDERPATH_D3D11:
3691 case RENDERPATH_SOFT:
3696 void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale)
3698 gltextureunit_t *unit = gl_state.units + unitnum;
3700 switch(vid.renderpath)
3702 case RENDERPATH_GL20:
3703 case RENDERPATH_CGGL:
3704 case RENDERPATH_GLES2:
3707 case RENDERPATH_GL13:
3708 // GL_ARB_texture_env_combine
3710 combinergb = GL_MODULATE;
3712 combinealpha = GL_MODULATE;
3717 if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1)
3719 if (combinergb == GL_DECAL)
3720 combinergb = GL_INTERPOLATE_ARB;
3721 if (unit->combine != GL_COMBINE_ARB)
3723 unit->combine = GL_COMBINE_ARB;
3724 GL_ActiveTexture(unitnum);
3725 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR
3726 qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode
3728 if (unit->combinergb != combinergb)
3730 unit->combinergb = combinergb;
3731 GL_ActiveTexture(unitnum);
3732 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR
3734 if (unit->combinealpha != combinealpha)
3736 unit->combinealpha = combinealpha;
3737 GL_ActiveTexture(unitnum);
3738 qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR
3740 if (unit->rgbscale != rgbscale)
3742 unit->rgbscale = rgbscale;
3743 GL_ActiveTexture(unitnum);
3744 qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR
3746 if (unit->alphascale != alphascale)
3748 unit->alphascale = alphascale;
3749 GL_ActiveTexture(unitnum);
3750 qglTexEnvi(GL_TEXTURE_ENV, GL_ALPHA_SCALE, unit->alphascale);CHECKGLERROR
3755 if (unit->combine != combinergb)
3757 unit->combine = combinergb;
3758 GL_ActiveTexture(unitnum);
3759 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3763 case RENDERPATH_GL11:
3766 combinergb = GL_MODULATE;
3767 if (unit->combine != combinergb)
3769 unit->combine = combinergb;
3770 GL_ActiveTexture(unitnum);
3771 qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, unit->combine);CHECKGLERROR
3774 case RENDERPATH_D3D9:
3775 case RENDERPATH_D3D10:
3776 case RENDERPATH_D3D11:
3778 case RENDERPATH_SOFT:
3783 void R_Mesh_ResetTextureState(void)
3785 unsigned int unitnum;
3789 for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
3790 R_Mesh_TexBind(unitnum, NULL);
3791 for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
3792 R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3793 switch(vid.renderpath)
3795 case RENDERPATH_GL20:
3796 case RENDERPATH_CGGL:
3797 case RENDERPATH_GLES2:
3798 case RENDERPATH_D3D9:
3799 case RENDERPATH_D3D10:
3800 case RENDERPATH_D3D11:
3801 case RENDERPATH_SOFT:
3803 case RENDERPATH_GL13:
3804 case RENDERPATH_GL11:
3805 for (unitnum = 0;unitnum < vid.texunits;unitnum++)
3807 R_Mesh_TexCombine(unitnum, GL_MODULATE, GL_MODULATE, 1, 1);
3808 R_Mesh_TexMatrix(unitnum, NULL);
3817 //#define r_vertex3f_d3d9fvf (D3DFVF_XYZ)
3818 //#define r_vertexgeneric_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1)
3819 //#define r_vertexmesh_d3d9fvf (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX5 | D3DFVF_TEXCOORDSIZE1(3) | D3DFVF_TEXCOORDSIZE2(3) | D3DFVF_TEXCOORDSIZE3(3))
3821 D3DVERTEXELEMENT9 r_vertex3f_d3d9elements[] =
3823 {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3827 D3DVERTEXELEMENT9 r_vertexgeneric_d3d9elements[] =
3829 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3830 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3831 {0, (int)((size_t)&((r_vertexgeneric_t *)0)->texcoord2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3835 D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] =
3837 {0, (int)((size_t)&((r_vertexmesh_t *)0)->vertex3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
3838 {0, (int)((size_t)&((r_vertexmesh_t *)0)->color4ub ), D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0},
3839 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordtexture2f ), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
3840 {0, (int)((size_t)&((r_vertexmesh_t *)0)->svector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1},
3841 {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2},
3842 {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3},
3843 {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4},
3847 IDirect3DVertexDeclaration9 *r_vertex3f_d3d9decl;
3848 IDirect3DVertexDeclaration9 *r_vertexgeneric_d3d9decl;
3849 IDirect3DVertexDeclaration9 *r_vertexmesh_d3d9decl;
3852 static void R_Mesh_InitVertexDeclarations(void)
3855 r_vertex3f_d3d9decl = NULL;
3856 r_vertexgeneric_d3d9decl = NULL;
3857 r_vertexmesh_d3d9decl = NULL;
3858 switch(vid.renderpath)
3860 case RENDERPATH_GL20:
3861 case RENDERPATH_CGGL:
3862 case RENDERPATH_GL13:
3863 case RENDERPATH_GL11:
3864 case RENDERPATH_GLES2:
3866 case RENDERPATH_D3D9:
3867 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9elements, &r_vertex3f_d3d9decl);
3868 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9elements, &r_vertexgeneric_d3d9decl);
3869 IDirect3DDevice9_CreateVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9elements, &r_vertexmesh_d3d9decl);
3871 case RENDERPATH_D3D10:
3872 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3874 case RENDERPATH_D3D11:
3875 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3877 case RENDERPATH_SOFT:
3883 static void R_Mesh_DestroyVertexDeclarations(void)
3886 if (r_vertex3f_d3d9decl)
3887 IDirect3DVertexDeclaration9_Release(r_vertex3f_d3d9decl);
3888 r_vertex3f_d3d9decl = NULL;
3889 if (r_vertexgeneric_d3d9decl)
3890 IDirect3DVertexDeclaration9_Release(r_vertexgeneric_d3d9decl);
3891 r_vertexgeneric_d3d9decl = NULL;
3892 if (r_vertexmesh_d3d9decl)
3893 IDirect3DVertexDeclaration9_Release(r_vertexmesh_d3d9decl);
3894 r_vertexmesh_d3d9decl = NULL;
3898 void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer)
3900 // upload temporary vertexbuffer for this rendering
3901 if (!gl_state.usevbo_staticvertex)
3902 vertexbuffer = NULL;
3903 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
3905 if (gl_state.preparevertices_dynamicvertexbuffer)
3906 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3]));
3908 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false);
3909 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
3911 switch(vid.renderpath)
3913 case RENDERPATH_GL20:
3914 case RENDERPATH_CGGL:
3915 case RENDERPATH_GLES2:
3918 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3919 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3920 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3921 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3922 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3923 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3924 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3928 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3929 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3930 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3931 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3932 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3933 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3934 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3937 case RENDERPATH_GL13:
3940 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3941 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3942 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3943 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3947 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3948 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3949 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3950 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3953 case RENDERPATH_GL11:
3956 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3957 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3958 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3962 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0);
3963 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0);
3964 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
3967 case RENDERPATH_D3D9:
3969 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl);
3971 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3]));
3973 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
3974 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
3975 gl_state.d3dvertexdata = (void *)vertex3f;
3976 gl_state.d3dvertexsize = sizeof(float[3]);
3979 case RENDERPATH_D3D10:
3980 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3982 case RENDERPATH_D3D11:
3983 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3985 case RENDERPATH_SOFT:
3986 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
3987 DPSOFTRAST_SetColorPointer(NULL, 0);
3988 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), NULL);
3989 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
3990 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
3991 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
3992 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
3999 r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices)
4002 size = sizeof(r_vertexgeneric_t) * numvertices;
4003 if (gl_state.preparevertices_tempdatamaxsize < size)
4005 gl_state.preparevertices_tempdatamaxsize = size;
4006 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4008 gl_state.preparevertices_vertexgeneric = (r_vertexgeneric_t *)gl_state.preparevertices_tempdata;
4009 gl_state.preparevertices_numvertices = numvertices;
4010 return gl_state.preparevertices_vertexgeneric;
4013 qboolean R_Mesh_PrepareVertices_Generic_Unlock(void)
4015 R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL);
4016 gl_state.preparevertices_vertexgeneric = NULL;
4017 gl_state.preparevertices_numvertices = 0;
4021 void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3f, const float *color4f, const float *texcoord2f)
4024 r_vertexgeneric_t *vertex;
4025 switch(vid.renderpath)
4027 case RENDERPATH_GL20:
4028 case RENDERPATH_CGGL:
4029 case RENDERPATH_GLES2:
4030 if (!vid.useinterleavedarrays)
4032 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4033 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4034 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4035 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4036 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4037 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4038 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4042 case RENDERPATH_GL13:
4043 case RENDERPATH_GL11:
4044 if (!vid.useinterleavedarrays)
4046 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4047 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4048 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoord2f, NULL, 0);
4049 if (vid.texunits >= 2)
4050 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4051 if (vid.texunits >= 3)
4052 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4056 case RENDERPATH_D3D9:
4057 case RENDERPATH_D3D10:
4058 case RENDERPATH_D3D11:
4060 case RENDERPATH_SOFT:
4061 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4062 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4063 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoord2f);
4064 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(float[2]), NULL);
4065 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(float[2]), NULL);
4066 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(float[2]), NULL);
4067 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), NULL);
4071 // no quick path for this case, convert to vertex structs
4072 vertex = R_Mesh_PrepareVertices_Generic_Lock(numvertices);
4073 for (i = 0;i < numvertices;i++)
4074 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4077 for (i = 0;i < numvertices;i++)
4078 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
4082 float tempcolor4f[4];
4083 unsigned char tempcolor4ub[4];
4084 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
4085 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
4086 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
4087 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
4088 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
4089 for (i = 0;i < numvertices;i++)
4090 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
4093 for (i = 0;i < numvertices;i++)
4094 Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f);
4095 R_Mesh_PrepareVertices_Generic_Unlock();
4096 R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL);
4099 void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer)
4101 // upload temporary vertexbuffer for this rendering
4102 if (!gl_state.usevbo_staticvertex)
4103 vertexbuffer = NULL;
4104 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4106 if (gl_state.preparevertices_dynamicvertexbuffer)
4107 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4109 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4110 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4112 switch(vid.renderpath)
4114 case RENDERPATH_GL20:
4115 case RENDERPATH_CGGL:
4116 case RENDERPATH_GLES2:
4119 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4120 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4121 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4122 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4123 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4124 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4125 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4129 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4130 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4131 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4132 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4133 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4134 R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4135 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4138 case RENDERPATH_GL13:
4141 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4142 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4143 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4144 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4148 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4149 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4150 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4151 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4154 case RENDERPATH_GL11:
4157 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4158 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4159 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex));
4163 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4164 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4165 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , NULL, 0);
4168 case RENDERPATH_D3D9:
4170 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl);
4172 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4174 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4175 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4176 gl_state.d3dvertexdata = (void *)vertex;
4177 gl_state.d3dvertexsize = sizeof(*vertex);
4180 case RENDERPATH_D3D10:
4181 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4183 case RENDERPATH_D3D11:
4184 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4186 case RENDERPATH_SOFT:
4187 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4188 DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
4189 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoord2f);
4190 DPSOFTRAST_SetTexCoordPointer(1, 2, sizeof(*vertex), NULL);
4191 DPSOFTRAST_SetTexCoordPointer(2, 2, sizeof(*vertex), NULL);
4192 DPSOFTRAST_SetTexCoordPointer(3, 2, sizeof(*vertex), NULL);
4193 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), NULL);
4200 r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices)
4203 size = sizeof(r_vertexmesh_t) * numvertices;
4204 if (gl_state.preparevertices_tempdatamaxsize < size)
4206 gl_state.preparevertices_tempdatamaxsize = size;
4207 gl_state.preparevertices_tempdata = Mem_Realloc(r_main_mempool, gl_state.preparevertices_tempdata, gl_state.preparevertices_tempdatamaxsize);
4209 gl_state.preparevertices_vertexmesh = (r_vertexmesh_t *)gl_state.preparevertices_tempdata;
4210 gl_state.preparevertices_numvertices = numvertices;
4211 return gl_state.preparevertices_vertexmesh;
4214 qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void)
4216 R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL);
4217 gl_state.preparevertices_vertexmesh = NULL;
4218 gl_state.preparevertices_numvertices = 0;
4222 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)
4225 r_vertexmesh_t *vertex;
4226 switch(vid.renderpath)
4228 case RENDERPATH_GL20:
4229 case RENDERPATH_CGGL:
4230 case RENDERPATH_GLES2:
4231 if (!vid.useinterleavedarrays)
4233 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4234 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4235 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4236 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), svector3f, NULL, 0);
4237 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0);
4238 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0);
4239 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4243 case RENDERPATH_GL13:
4244 case RENDERPATH_GL11:
4245 if (!vid.useinterleavedarrays)
4247 R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0);
4248 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0);
4249 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), texcoordtexture2f, NULL, 0);
4250 if (vid.texunits >= 2)
4251 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0);
4252 if (vid.texunits >= 3)
4253 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
4257 case RENDERPATH_D3D9:
4258 case RENDERPATH_D3D10:
4259 case RENDERPATH_D3D11:
4261 case RENDERPATH_SOFT:
4262 DPSOFTRAST_SetVertexPointer(vertex3f, sizeof(float[3]));
4263 DPSOFTRAST_SetColorPointer(color4f, sizeof(float[4]));
4264 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(float[2]), texcoordtexture2f);
4265 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(float[3]), svector3f);
4266 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(float[3]), tvector3f);
4267 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(float[3]), normal3f);
4268 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(float[2]), texcoordlightmap2f);
4272 vertex = R_Mesh_PrepareVertices_Mesh_Lock(numvertices);
4273 for (i = 0;i < numvertices;i++)
4274 VectorCopy(vertex3f + 3*i, vertex[i].vertex3f);
4276 for (i = 0;i < numvertices;i++)
4277 VectorCopy(svector3f + 3*i, vertex[i].svector3f);
4279 for (i = 0;i < numvertices;i++)
4280 VectorCopy(tvector3f + 3*i, vertex[i].tvector3f);
4282 for (i = 0;i < numvertices;i++)
4283 VectorCopy(normal3f + 3*i, vertex[i].normal3f);
4286 for (i = 0;i < numvertices;i++)
4287 Vector4Scale(color4f + 4*i, 255.0f, vertex[i].color4ub);
4291 float tempcolor4f[4];
4292 unsigned char tempcolor4ub[4];
4293 Vector4Scale(gl_state.color4f, 255.0f, tempcolor4f);
4294 tempcolor4ub[0] = (unsigned char)bound(0.0f, tempcolor4f[0], 255.0f);
4295 tempcolor4ub[1] = (unsigned char)bound(0.0f, tempcolor4f[1], 255.0f);
4296 tempcolor4ub[2] = (unsigned char)bound(0.0f, tempcolor4f[2], 255.0f);
4297 tempcolor4ub[3] = (unsigned char)bound(0.0f, tempcolor4f[3], 255.0f);
4298 for (i = 0;i < numvertices;i++)
4299 Vector4Copy(tempcolor4ub, vertex[i].color4ub);
4301 if (texcoordtexture2f)
4302 for (i = 0;i < numvertices;i++)
4303 Vector2Copy(texcoordtexture2f + 2*i, vertex[i].texcoordtexture2f);
4304 if (texcoordlightmap2f)
4305 for (i = 0;i < numvertices;i++)
4306 Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f);
4307 R_Mesh_PrepareVertices_Mesh_Unlock();
4308 R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL);
4311 void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer)
4313 // upload temporary vertexbuffer for this rendering
4314 if (!gl_state.usevbo_staticvertex)
4315 vertexbuffer = NULL;
4316 if (!vertexbuffer && gl_state.usevbo_dynamicvertex)
4318 if (gl_state.preparevertices_dynamicvertexbuffer)
4319 R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex));
4321 gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false);
4322 vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer;
4324 switch(vid.renderpath)
4326 case RENDERPATH_GL20:
4327 case RENDERPATH_CGGL:
4328 case RENDERPATH_GLES2:
4331 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4332 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4333 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4334 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex));
4335 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex));
4336 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex));
4337 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4341 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4342 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4343 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4344 R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , NULL, 0);
4345 R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0);
4346 R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0);
4347 R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4350 case RENDERPATH_GL13:
4353 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4354 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4355 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4356 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex));
4360 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4361 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4362 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4363 R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0);
4366 case RENDERPATH_GL11:
4369 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex));
4370 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , vertexbuffer, (int)((unsigned char *)vertex->color4ub - (unsigned char *)vertex));
4371 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex));
4375 R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , NULL, 0);
4376 R_Mesh_ColorPointer( 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->color4ub , NULL, 0);
4377 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , NULL, 0);
4380 case RENDERPATH_D3D9:
4382 IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl);
4384 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex));
4386 IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0);
4387 gl_state.d3dvertexbuffer = (void *)vertexbuffer;
4388 gl_state.d3dvertexdata = (void *)vertex;
4389 gl_state.d3dvertexsize = sizeof(*vertex);
4392 case RENDERPATH_D3D10:
4393 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4395 case RENDERPATH_D3D11:
4396 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4398 case RENDERPATH_SOFT:
4399 DPSOFTRAST_SetVertexPointer(vertex->vertex3f, sizeof(*vertex));
4400 DPSOFTRAST_SetColorPointer4ub(vertex->color4ub, sizeof(*vertex));
4401 DPSOFTRAST_SetTexCoordPointer(0, 2, sizeof(*vertex), vertex->texcoordtexture2f);
4402 DPSOFTRAST_SetTexCoordPointer(1, 3, sizeof(*vertex), vertex->svector3f);
4403 DPSOFTRAST_SetTexCoordPointer(2, 3, sizeof(*vertex), vertex->tvector3f);
4404 DPSOFTRAST_SetTexCoordPointer(3, 3, sizeof(*vertex), vertex->normal3f);
4405 DPSOFTRAST_SetTexCoordPointer(4, 2, sizeof(*vertex), vertex->texcoordlightmap2f);