cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"};
cvar_t gl_mesh_testarrayelement = {0, "gl_mesh_testarrayelement", "0", "use glBegin(GL_TRIANGLES);glArrayElement();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"};
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)"};
+cvar_t gl_mesh_prefer_short_elements = {0, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"};
cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"};
cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"};
cvar_t gl_dither = {CVAR_SAVE, "gl_dither", "1", "enables OpenGL dithering (16bit looks bad with this off)"};
cvar_t gl_lockarrays = {0, "gl_lockarrays", "0", "enables use of glLockArraysEXT, may cause glitches with some broken drivers, and may be slower than normal"};
cvar_t gl_lockarrays_minimumvertices = {0, "gl_lockarrays_minimumvertices", "1", "minimum number of vertices required for use of glLockArraysEXT, setting this too low may reduce performance"};
-cvar_t gl_vbo = {CVAR_SAVE, "gl_vbo", "1", "make use of GL_ARB_vertex_buffer_object extension to store static geometry in video memory for faster rendering"};
+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)"};
cvar_t v_flipped = {0, "v_flipped", "0", "mirror the screen (poor man's left handed mode)"};
qboolean v_flipped_state = false;
}
*/
-int polygonelements[(POLYGONELEMENTS_MAXPOINTS-2)*3];
-int quadelements[QUADELEMENTS_MAXQUADS*6];
+unsigned short polygonelements[(POLYGONELEMENTS_MAXPOINTS-2)*3];
+unsigned short quadelements[QUADELEMENTS_MAXQUADS*6];
void GL_Backend_AllocArrays(void)
{
Cvar_RegisterVariable(&gl_mesh_drawrangeelements);
Cvar_RegisterVariable(&gl_mesh_testarrayelement);
Cvar_RegisterVariable(&gl_mesh_testmanualfeeding);
+ Cvar_RegisterVariable(&gl_mesh_prefer_short_elements);
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");
m[1] = 0;
m[2] = 0;
m[3] = 0;
-
+
m[4] = 0;
m[5] = 2 * nearVal / (top - bottom);
m[6] = 0;
m[7] = 0;
-
+
m[8] = (right + left) / (right - left);
m[9] = (top + bottom) / (top - bottom);
m[10] = - (farVal + nearVal) / (farVal - nearVal);
Matrix4x4_FromArrayDoubleGL(&backend_projectmatrix, m);
}
-static void GL_BuildOrtho(double m[16], double left, double right, double bottom, double top, double near, double far)
+static void GL_BuildOrtho(double m[16], double left, double right, double bottom, double top, double zNear, double zFar)
{
m[0] = 2/(right - left);
m[1] = 0;
m[2] = 0;
m[3] = 0;
-
+
m[4] = 0;
m[5] = 2/(top - bottom);
m[6] = 0;
m[7] = 0;
-
+
m[8] = 0;
m[9] = 0;
- m[10] = -2/(far - near);
+ m[10] = -2/(zFar - zNear);
m[11] = 0;
m[12] = - (right + left)/(right - left);
m[13] = - (top + bottom)/(top - bottom);
- m[14] = - (far + near)/(far - near);
+ m[14] = - (zFar + zNear)/(zFar - zNear);
m[15] = 1;
}
// renders triangles using vertices from the active arrays
int paranoidblah = 0;
-void R_Mesh_Draw(int firstvertex, int numvertices, int numtriangles, const int *elements, int bufferobject, size_t bufferoffset)
+void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const unsigned short *element3s, int bufferobject3i, int bufferobject3s)
{
unsigned int numelements = numtriangles * 3;
if (numvertices < 3 || numtriangles < 1)
{
- Con_Printf("R_Mesh_Draw(%d, %d, %d, %8p, %i, %p);\n", firstvertex, numvertices, numtriangles, elements, bufferobject, (void *)bufferoffset);
+ if (numvertices < 0 || numtriangles < 0 || developer.integer >= 100)
+ Con_Printf("R_Mesh_Draw(%d, %d, %d, %d, %8p, %8p, %i, %i);\n", firstvertex, numvertices, firsttriangle, numtriangles, element3i, element3s, bufferobject3i, bufferobject3s);
return;
}
- if (gl_vbo.integer != 1)
- bufferobject = 0;
+ if (!gl_mesh_prefer_short_elements.integer)
+ {
+ if (element3i)
+ element3s = NULL;
+ if (bufferobject3i)
+ bufferobject3s = 0;
+ }
+ if (element3i)
+ element3i += firsttriangle * 3;
+ if (element3s)
+ element3s += firsttriangle * 3;
+ switch (gl_vbo.integer)
+ {
+ default:
+ case 0:
+ case 2:
+ bufferobject3i = bufferobject3s = 0;
+ break;
+ case 1:
+ break;
+ case 3:
+ if (firsttriangle)
+ bufferobject3i = bufferobject3s = 0;
+ break;
+ }
CHECKGLERROR
r_refdef.stats.meshes++;
r_refdef.stats.meshes_elements += numelements;
paranoidblah += *p;
}
}
- for (i = 0;i < (unsigned int) numtriangles * 3;i++)
+ if (element3i)
+ {
+ for (i = 0;i < (unsigned int) numtriangles * 3;i++)
+ {
+ if (element3i[i] < firstvertex || element3i[i] >= firstvertex + numvertices)
+ {
+ Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3i array\n", element3i[i], firstvertex, firstvertex + numvertices);
+ return;
+ }
+ }
+ }
+ if (element3s)
{
- if (elements[i] < firstvertex || elements[i] >= firstvertex + numvertices)
+ for (i = 0;i < (unsigned int) numtriangles * 3;i++)
{
- Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in elements list\n", elements[i], firstvertex, firstvertex + numvertices);
- return;
+ if (element3s[i] < firstvertex || element3s[i] >= firstvertex + numvertices)
+ {
+ Con_Printf("R_Mesh_Draw: invalid vertex index %i (outside range %i - %i) in element3s array\n", element3s[i], firstvertex, firstvertex + numvertices);
+ return;
+ }
}
}
CHECKGLERROR
CHECKGLERROR
if (gl_mesh_testmanualfeeding.integer)
{
- unsigned int i, j;
+ unsigned int i, j, element;
const GLfloat *p;
qglBegin(GL_TRIANGLES);
for (i = 0;i < (unsigned int) numtriangles * 3;i++)
{
+ element = element3i ? element3i[i] : element3s[i];
for (j = 0;j < backendarrayunits;j++)
{
if (gl_state.units[j].pointer_texcoord && gl_state.units[j].arrayenabled)
{
if (gl_state.units[j].arraycomponents == 4)
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
+ p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 4;
qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]);
}
else if (gl_state.units[j].arraycomponents == 3)
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
+ p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 3;
qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]);
}
else if (gl_state.units[j].arraycomponents == 2)
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
+ p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 2;
qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]);
}
else
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
+ p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 1;
qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]);
}
}
{
if (gl_state.units[j].arraycomponents == 4)
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 4;
+ p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 4;
qglTexCoord4f(p[0], p[1], p[2], p[3]);
}
else if (gl_state.units[j].arraycomponents == 3)
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 3;
+ p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 3;
qglTexCoord3f(p[0], p[1], p[2]);
}
else if (gl_state.units[j].arraycomponents == 2)
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 2;
+ p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 2;
qglTexCoord2f(p[0], p[1]);
}
else
{
- p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + elements[i] * 1;
+ p = ((const GLfloat *)(gl_state.units[j].pointer_texcoord)) + element * 1;
qglTexCoord1f(p[0]);
}
}
}
if (gl_state.pointer_color && gl_state.pointer_color_enabled)
{
- p = ((const GLfloat *)(gl_state.pointer_color)) + elements[i] * 4;
+ p = ((const GLfloat *)(gl_state.pointer_color)) + element * 4;
qglColor4f(p[0], p[1], p[2], p[3]);
}
- p = ((const GLfloat *)(gl_state.pointer_vertex)) + elements[i] * 3;
+ p = ((const GLfloat *)(gl_state.pointer_vertex)) + element * 3;
qglVertex3f(p[0], p[1], p[2]);
}
qglEnd();
{
int i;
qglBegin(GL_TRIANGLES);
- for (i = 0;i < numtriangles * 3;i++)
+ if (element3i)
{
- qglArrayElement(elements[i]);
+ for (i = 0;i < numtriangles * 3;i++)
+ qglArrayElement(element3i[i]);
+ }
+ else if (element3s)
+ {
+ for (i = 0;i < numtriangles * 3;i++)
+ qglArrayElement(element3s[i]);
}
qglEnd();
CHECKGLERROR
}
- else if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
+ else if (bufferobject3s)
{
- GL_BindEBO(bufferobject);
- qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, bufferobject ? (void *)bufferoffset : elements);
- CHECKGLERROR
+ GL_BindEBO(bufferobject3s);
+ if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
+ {
+ qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
+ CHECKGLERROR
+ }
+ else
+ {
+ qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3])));
+ CHECKGLERROR
+ }
}
- else
+ else if (bufferobject3i)
{
- GL_BindEBO(bufferobject);
- qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, bufferobject ? (void *)bufferoffset : elements);
- CHECKGLERROR
+ GL_BindEBO(bufferobject3i);
+ if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
+ {
+ qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
+ CHECKGLERROR
+ }
+ else
+ {
+ qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3])));
+ CHECKGLERROR
+ }
+ }
+ else if (element3s)
+ {
+ GL_BindEBO(0);
+ if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
+ {
+ qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_SHORT, element3s);
+ CHECKGLERROR
+ }
+ else
+ {
+ qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s);
+ CHECKGLERROR
+ }
+ }
+ else if (element3i)
+ {
+ GL_BindEBO(0);
+ if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL)
+ {
+ qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices, numelements, GL_UNSIGNED_INT, element3i);
+ CHECKGLERROR
+ }
+ else
+ {
+ qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i);
+ CHECKGLERROR
+ }
}
}
}
}
qglBufferDataARB(target, size, data, GL_STATIC_DRAW_ARB);
- info = Mem_ExpandableArray_AllocRecord(&gl_bufferobjectinfoarray);
+ info = (gl_bufferobjectinfo_t *) Mem_ExpandableArray_AllocRecord(&gl_bufferobjectinfoarray);
memset(info, 0, sizeof(*info));
info->target = target;
info->object = bufferobject;
endindex = Mem_ExpandableArray_IndexRange(&gl_bufferobjectinfoarray);
for (i = 0;i < endindex;i++)
{
- info = Mem_ExpandableArray_RecordAtIndex(&gl_bufferobjectinfoarray, i);
+ info = (gl_bufferobjectinfo_t *) Mem_ExpandableArray_RecordAtIndex(&gl_bufferobjectinfoarray, i);
if (!info)
continue;
if (info->object == bufferobject)
endindex = Mem_ExpandableArray_IndexRange(&gl_bufferobjectinfoarray);
for (i = 0;i < endindex;i++)
{
- info = Mem_ExpandableArray_RecordAtIndex(&gl_bufferobjectinfoarray, i);
+ info = (gl_bufferobjectinfo_t *) Mem_ExpandableArray_RecordAtIndex(&gl_bufferobjectinfoarray, i);
if (!info)
continue;
switch(info->target)
}
}
+static const double gl_identitymatrix[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
+
void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix)
{
gltextureunit_t *unit = gl_state.units + unitnum;
CHECKGLERROR
Matrix4x4_ToArrayDoubleGL(&unit->matrix, glmatrix);
GL_ActiveTexture(unitnum);
- GL_ClientActiveTexture(unitnum);
qglMatrixMode(GL_TEXTURE);CHECKGLERROR
qglLoadMatrixd(glmatrix);CHECKGLERROR
qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
unit->matrix = identitymatrix;
CHECKGLERROR
GL_ActiveTexture(unitnum);
- GL_ClientActiveTexture(unitnum);
qglMatrixMode(GL_TEXTURE);CHECKGLERROR
qglLoadIdentity();CHECKGLERROR
qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
unit->texmatrixenabled = false;
unit->matrix = identitymatrix;
CHECKGLERROR
- qglMatrixMode(GL_TEXTURE);CHECKGLERROR
GL_ActiveTexture(unitnum);
+ qglMatrixMode(GL_TEXTURE);CHECKGLERROR
qglLoadIdentity();CHECKGLERROR
qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
}
}
}
}
-
-void R_Mesh_Draw_ShowTris(int firstvertex, int numvertices, int numtriangles, const int *elements)
-{
- CHECKGLERROR
- qglBegin(GL_LINES);
- for (;numtriangles;numtriangles--, elements += 3)
- {
- qglArrayElement(elements[0]);qglArrayElement(elements[1]);
- qglArrayElement(elements[1]);qglArrayElement(elements[2]);
- qglArrayElement(elements[2]);qglArrayElement(elements[0]);
- }
- qglEnd();
- CHECKGLERROR
-}