mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2024-11-10 07:21:58 +00:00
Load world and brush models into a VBO, and draw it in batches in R_DrawTextureChains_Multitexture. Uses the same immediate mode code as before if VBOs are not available, or if "-novbo" used at the command line. I only touched R_DrawTextureChains_Multitexture because it's usually the main bottleneck aside from alias model rendering.
This seems to help fps a fair bit on maps with a lot of world polys like jam2_tronyn. Tried on a few computers with intel and nvidia gpus, windows, mac os, linux, and there's always at least some fps improvement. Best case was 70fps -> 96fps on jam2_tronyn, on OS X + nvidia 650gt. Interested to hear how this works for amd gpu's, just do a timedemo with and without "-novbo". Only downside is I had to disable the fast path in Vid_Toggle_f() because at least with SDL1, the vbo no longer works after a toggle. So as a result, fullscreen toggles with alt-enter are slightly slower. git-svn-id: svn://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@1018 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
parent
b2c3363718
commit
e0680cb6d3
6 changed files with 267 additions and 14 deletions
|
@ -155,6 +155,8 @@ typedef struct msurface_s
|
||||||
struct msurface_s *texturechain;
|
struct msurface_s *texturechain;
|
||||||
|
|
||||||
mtexinfo_t *texinfo;
|
mtexinfo_t *texinfo;
|
||||||
|
|
||||||
|
int vbo_firstvert; // index of this surface's first vert in the VBO
|
||||||
|
|
||||||
// lighting info
|
// lighting info
|
||||||
int dlightframe;
|
int dlightframe;
|
||||||
|
|
|
@ -273,7 +273,8 @@ void R_NewMap (void)
|
||||||
R_ClearParticles ();
|
R_ClearParticles ();
|
||||||
|
|
||||||
GL_BuildLightmaps ();
|
GL_BuildLightmaps ();
|
||||||
|
GL_BuildVBOs ();
|
||||||
|
|
||||||
r_framecount = 0; //johnfitz -- paranoid?
|
r_framecount = 0; //johnfitz -- paranoid?
|
||||||
r_visframecount = 0; //johnfitz -- paranoid?
|
r_visframecount = 0; //johnfitz -- paranoid?
|
||||||
|
|
||||||
|
|
|
@ -92,9 +92,15 @@ qboolean gl_swap_control = false; //johnfitz
|
||||||
qboolean gl_anisotropy_able = false; //johnfitz
|
qboolean gl_anisotropy_able = false; //johnfitz
|
||||||
float gl_max_anisotropy; //johnfitz
|
float gl_max_anisotropy; //johnfitz
|
||||||
qboolean gl_texture_NPOT = false; //ericw
|
qboolean gl_texture_NPOT = false; //ericw
|
||||||
|
qboolean gl_vbo_able = false; //ericw
|
||||||
|
|
||||||
PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc = NULL; //johnfitz
|
PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc = NULL; //johnfitz
|
||||||
PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc = NULL; //johnfitz
|
PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc = NULL; //johnfitz
|
||||||
|
PFNGLCLIENTACTIVETEXTUREARBPROC GL_ClientActiveTextureFunc = NULL; //ericw
|
||||||
|
PFNGLBINDBUFFERARBPROC GL_BindBufferFunc = NULL; //ericw
|
||||||
|
PFNGLBUFFERDATAARBPROC GL_BufferDataFunc = NULL; //ericw
|
||||||
|
PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc = NULL; //ericw
|
||||||
|
PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc = NULL; //ericw
|
||||||
|
|
||||||
//====================================
|
//====================================
|
||||||
|
|
||||||
|
@ -634,6 +640,7 @@ static void VID_Restart (void)
|
||||||
|
|
||||||
GL_Init ();
|
GL_Init ();
|
||||||
TexMgr_ReloadImages ();
|
TexMgr_ReloadImages ();
|
||||||
|
GL_BuildVBOs ();
|
||||||
GL_SetupState ();
|
GL_SetupState ();
|
||||||
|
|
||||||
//warpimages needs to be recalculated
|
//warpimages needs to be recalculated
|
||||||
|
@ -788,6 +795,28 @@ static qboolean GL_ParseExtensionList (const char *list, const char *name)
|
||||||
static void GL_CheckExtensions (void)
|
static void GL_CheckExtensions (void)
|
||||||
{
|
{
|
||||||
int swap_control;
|
int swap_control;
|
||||||
|
|
||||||
|
//
|
||||||
|
// ARB_vertex_buffer_object
|
||||||
|
//
|
||||||
|
if (COM_CheckParm("-novbo"))
|
||||||
|
Con_Warning ("Vertex buffer objects disabled at command line\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL_BindBufferFunc = (PFNGLBINDBUFFERARBPROC) SDL_GL_GetProcAddress("glBindBufferARB");
|
||||||
|
GL_BufferDataFunc = (PFNGLBUFFERDATAARBPROC) SDL_GL_GetProcAddress("glBufferDataARB");
|
||||||
|
GL_DeleteBuffersFunc = (PFNGLDELETEBUFFERSARBPROC) SDL_GL_GetProcAddress("glDeleteBuffersARB");
|
||||||
|
GL_GenBuffersFunc = (PFNGLGENBUFFERSARBPROC) SDL_GL_GetProcAddress("glGenBuffersARB");
|
||||||
|
if (GL_BindBufferFunc && GL_BufferDataFunc && GL_DeleteBuffersFunc && GL_GenBuffersFunc)
|
||||||
|
{
|
||||||
|
Con_Printf("FOUND: ARB_vertex_buffer_object\n");
|
||||||
|
gl_vbo_able = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Con_Warning ("ARB_vertex_buffer_object not available\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// multitexture
|
// multitexture
|
||||||
//
|
//
|
||||||
|
@ -797,7 +826,8 @@ static void GL_CheckExtensions (void)
|
||||||
{
|
{
|
||||||
GL_MTexCoord2fFunc = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
|
GL_MTexCoord2fFunc = (PFNGLMULTITEXCOORD2FARBPROC) SDL_GL_GetProcAddress("glMultiTexCoord2fARB");
|
||||||
GL_SelectTextureFunc = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
|
GL_SelectTextureFunc = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB");
|
||||||
if (GL_MTexCoord2fFunc && GL_SelectTextureFunc)
|
GL_ClientActiveTextureFunc = (PFNGLCLIENTACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glClientActiveTextureARB");
|
||||||
|
if (GL_MTexCoord2fFunc && GL_SelectTextureFunc && GL_ClientActiveTextureFunc)
|
||||||
{
|
{
|
||||||
Con_Printf("FOUND: ARB_multitexture\n");
|
Con_Printf("FOUND: ARB_multitexture\n");
|
||||||
gl_mtexable = true;
|
gl_mtexable = true;
|
||||||
|
@ -1376,7 +1406,13 @@ void VID_Init (void)
|
||||||
// new proc by S.A., called by alt-return key binding.
|
// new proc by S.A., called by alt-return key binding.
|
||||||
void VID_Toggle (void)
|
void VID_Toggle (void)
|
||||||
{
|
{
|
||||||
static qboolean vid_toggle_works = true;
|
// disabling the fast path because with SDL 1.2 it invalidates VBOs (using them
|
||||||
|
// causes a crash, sugesting that the fullscreen toggle created a new GL context,
|
||||||
|
// although texture objects remain valid for some reason).
|
||||||
|
//
|
||||||
|
// SDL2 does promise window resizes / fullscreen changes preserve the GL context,
|
||||||
|
// so we could use the fast path with SDL2. --ericw
|
||||||
|
static qboolean vid_toggle_works = false;
|
||||||
qboolean toggleWorked;
|
qboolean toggleWorked;
|
||||||
|
|
||||||
S_ClearBuffer ();
|
S_ClearBuffer ();
|
||||||
|
|
|
@ -154,6 +154,7 @@ extern qboolean mtexenabled;
|
||||||
extern qboolean gl_mtexable;
|
extern qboolean gl_mtexable;
|
||||||
extern PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc;
|
extern PFNGLMULTITEXCOORD2FARBPROC GL_MTexCoord2fFunc;
|
||||||
extern PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc;
|
extern PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc;
|
||||||
|
extern PFNGLCLIENTACTIVETEXTUREARBPROC GL_ClientActiveTextureFunc;
|
||||||
|
|
||||||
//johnfitz -- anisotropic filtering
|
//johnfitz -- anisotropic filtering
|
||||||
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
#define GL_TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
|
||||||
|
@ -161,6 +162,14 @@ extern PFNGLACTIVETEXTUREARBPROC GL_SelectTextureFunc;
|
||||||
extern float gl_max_anisotropy;
|
extern float gl_max_anisotropy;
|
||||||
extern qboolean gl_anisotropy_able;
|
extern qboolean gl_anisotropy_able;
|
||||||
|
|
||||||
|
//ericw -- VBO
|
||||||
|
extern PFNGLBINDBUFFERARBPROC GL_BindBufferFunc;
|
||||||
|
extern PFNGLBUFFERDATAARBPROC GL_BufferDataFunc;
|
||||||
|
extern PFNGLDELETEBUFFERSARBPROC GL_DeleteBuffersFunc;
|
||||||
|
extern PFNGLGENBUFFERSARBPROC GL_GenBuffersFunc;
|
||||||
|
extern qboolean gl_vbo_able;
|
||||||
|
//ericw
|
||||||
|
|
||||||
//ericw -- NPOT texture support
|
//ericw -- NPOT texture support
|
||||||
extern qboolean gl_texture_NPOT;
|
extern qboolean gl_texture_NPOT;
|
||||||
|
|
||||||
|
@ -265,6 +274,7 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain
|
||||||
|
|
||||||
void R_RenderDlights (void);
|
void R_RenderDlights (void);
|
||||||
void GL_BuildLightmaps (void);
|
void GL_BuildLightmaps (void);
|
||||||
|
void GL_BuildVBOs (void);
|
||||||
void R_RebuildAllLightmaps (void);
|
void R_RebuildAllLightmaps (void);
|
||||||
|
|
||||||
int R_LightPoint (vec3_t p);
|
int R_LightPoint (vec3_t p);
|
||||||
|
|
|
@ -950,6 +950,90 @@ void GL_BuildLightmaps (void)
|
||||||
//johnfitz
|
//johnfitz
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
=============================================================
|
||||||
|
|
||||||
|
VBO support
|
||||||
|
|
||||||
|
=============================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
static GLuint gl_bmodel_vbo = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
==================
|
||||||
|
GL_BuildVBOs
|
||||||
|
|
||||||
|
Deletes gl_bmodel_vbo if it already exists, then rebuilds it with all
|
||||||
|
surfaces from world + all brush models
|
||||||
|
==================
|
||||||
|
*/
|
||||||
|
void GL_BuildVBOs (void)
|
||||||
|
{
|
||||||
|
unsigned int numverts, varray_bytes, varray_index;
|
||||||
|
int i, j;
|
||||||
|
qmodel_t *m;
|
||||||
|
float *varray;
|
||||||
|
|
||||||
|
if (!(gl_vbo_able && gl_mtexable))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// ask GL for a name for our VBO
|
||||||
|
GL_DeleteBuffersFunc (1, &gl_bmodel_vbo);
|
||||||
|
GL_GenBuffersFunc (1, &gl_bmodel_vbo);
|
||||||
|
|
||||||
|
// count all verts in all models
|
||||||
|
numverts = 0;
|
||||||
|
for (j=1 ; j<MAX_MODELS ; j++)
|
||||||
|
{
|
||||||
|
m = cl.model_precache[j];
|
||||||
|
if (!m || m->name[0] == '*' || m->type != mod_brush)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i=0 ; i<m->numsurfaces ; i++)
|
||||||
|
{
|
||||||
|
numverts += m->surfaces[i].numedges;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// build vertex array
|
||||||
|
varray_bytes = VERTEXSIZE * sizeof(float) * numverts;
|
||||||
|
varray = (float *) malloc (varray_bytes);
|
||||||
|
varray_index = 0;
|
||||||
|
|
||||||
|
for (j=1 ; j<MAX_MODELS ; j++)
|
||||||
|
{
|
||||||
|
m = cl.model_precache[j];
|
||||||
|
if (!m || m->name[0] == '*' || m->type != mod_brush)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i=0 ; i<m->numsurfaces ; i++)
|
||||||
|
{
|
||||||
|
msurface_t *s = &m->surfaces[i];
|
||||||
|
s->vbo_firstvert = varray_index;
|
||||||
|
memcpy (&varray[VERTEXSIZE * varray_index], s->polys->verts, VERTEXSIZE * sizeof(float) * s->numedges);
|
||||||
|
varray_index += s->numedges;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// upload to GPU
|
||||||
|
GL_BindBufferFunc (GL_ARRAY_BUFFER, gl_bmodel_vbo);
|
||||||
|
GL_BufferDataFunc (GL_ARRAY_BUFFER, varray_bytes, varray, GL_STATIC_DRAW);
|
||||||
|
free (varray);
|
||||||
|
|
||||||
|
// setup vertex array. this will need to move if we use vertex arrays for other things
|
||||||
|
glVertexPointer (3, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0));
|
||||||
|
glEnableClientState (GL_VERTEX_ARRAY);
|
||||||
|
|
||||||
|
GL_ClientActiveTextureFunc (GL_TEXTURE0_ARB);
|
||||||
|
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 3);
|
||||||
|
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||||
|
|
||||||
|
GL_ClientActiveTextureFunc (GL_TEXTURE1_ARB);
|
||||||
|
glTexCoordPointer (2, GL_FLOAT, VERTEXSIZE * sizeof(float), ((float *)0) + 5);
|
||||||
|
glEnableClientState (GL_TEXTURE_COORD_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
===============
|
===============
|
||||||
R_AddDynamicLights
|
R_AddDynamicLights
|
||||||
|
|
142
Quake/r_world.c
142
Quake/r_world.c
|
@ -410,6 +410,121 @@ void R_DrawTextureChains_Glow (qmodel_t *model, entity_t *ent, texchain_t chain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//==============================================================================
|
||||||
|
//
|
||||||
|
// VBO SUPPORT
|
||||||
|
//
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
R_MultitexturedDrawGLPoly
|
||||||
|
|
||||||
|
Fallback immediate mode code to draw a multitexutred glpoly_t
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static void R_MultitexturedDrawGLPoly (glpoly_t *p)
|
||||||
|
{
|
||||||
|
float *v;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
glBegin(GL_POLYGON);
|
||||||
|
v = p->verts[0];
|
||||||
|
for (j=0 ; j<p->numverts ; j++, v+= VERTEXSIZE)
|
||||||
|
{
|
||||||
|
GL_MTexCoord2fFunc (GL_TEXTURE0_ARB, v[3], v[4]);
|
||||||
|
GL_MTexCoord2fFunc (GL_TEXTURE1_ARB, v[5], v[6]);
|
||||||
|
glVertex3fv (v);
|
||||||
|
}
|
||||||
|
glEnd ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int R_NumTriangleIndicesForSurf (msurface_t *s)
|
||||||
|
{
|
||||||
|
return 3 * (s->numedges - 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
R_TriangleIndicesForSurf
|
||||||
|
|
||||||
|
Writes out the triangle indices needed to draw s as a triangle list.
|
||||||
|
The number of indices it will write is given by R_NumTriangleIndicesForSurf.
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static void R_TriangleIndicesForSurf (msurface_t *s, unsigned int *dest)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i=2; i<s->numedges; i++)
|
||||||
|
{
|
||||||
|
*dest++ = s->vbo_firstvert;
|
||||||
|
*dest++ = s->vbo_firstvert + i - 1;
|
||||||
|
*dest++ = s->vbo_firstvert + i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define MAX_BATCH_SIZE 4096
|
||||||
|
|
||||||
|
static unsigned int vbo_indices[MAX_BATCH_SIZE];
|
||||||
|
static unsigned int num_vbo_indices;
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
R_ClearBatch
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static void R_ClearBatch ()
|
||||||
|
{
|
||||||
|
if (!(gl_vbo_able && gl_mtexable)) return;
|
||||||
|
|
||||||
|
num_vbo_indices = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
R_FlushBatch
|
||||||
|
|
||||||
|
Draw the current batch if non-empty and clears it, ready for more R_BatchSurface calls.
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static void R_FlushBatch ()
|
||||||
|
{
|
||||||
|
if (!(gl_vbo_able && gl_mtexable)) return;
|
||||||
|
|
||||||
|
if (num_vbo_indices > 0)
|
||||||
|
{
|
||||||
|
glDrawElements (GL_TRIANGLES, num_vbo_indices, GL_UNSIGNED_INT, vbo_indices);
|
||||||
|
num_vbo_indices = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
================
|
||||||
|
R_BatchSurface
|
||||||
|
|
||||||
|
Add the surface to the current batch, or just draw it immediately if we're not
|
||||||
|
using VBOs.
|
||||||
|
================
|
||||||
|
*/
|
||||||
|
static void R_BatchSurface (msurface_t *s)
|
||||||
|
{
|
||||||
|
int num_surf_indices;
|
||||||
|
|
||||||
|
if (!(gl_vbo_able && gl_mtexable))
|
||||||
|
{
|
||||||
|
R_MultitexturedDrawGLPoly (s->polys);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
num_surf_indices = R_NumTriangleIndicesForSurf (s);
|
||||||
|
|
||||||
|
if (num_vbo_indices + num_surf_indices > MAX_BATCH_SIZE)
|
||||||
|
R_FlushBatch();
|
||||||
|
|
||||||
|
R_TriangleIndicesForSurf (s, &vbo_indices[num_vbo_indices]);
|
||||||
|
num_vbo_indices += num_surf_indices;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
================
|
================
|
||||||
R_DrawTextureChains_Multitexture -- johnfitz
|
R_DrawTextureChains_Multitexture -- johnfitz
|
||||||
|
@ -417,11 +532,11 @@ R_DrawTextureChains_Multitexture -- johnfitz
|
||||||
*/
|
*/
|
||||||
void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_t chain)
|
void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_t chain)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i;
|
||||||
msurface_t *s;
|
msurface_t *s;
|
||||||
texture_t *t;
|
texture_t *t;
|
||||||
float *v;
|
|
||||||
qboolean bound;
|
qboolean bound;
|
||||||
|
int lastlightmap;
|
||||||
|
|
||||||
for (i=0 ; i<model->numtextures ; i++)
|
for (i=0 ; i<model->numtextures ; i++)
|
||||||
{
|
{
|
||||||
|
@ -430,7 +545,10 @@ void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_
|
||||||
if (!t || !t->texturechains[chain] || t->texturechains[chain]->flags & (SURF_DRAWTILED | SURF_NOTEXTURE))
|
if (!t || !t->texturechains[chain] || t->texturechains[chain]->flags & (SURF_DRAWTILED | SURF_NOTEXTURE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
R_ClearBatch ();
|
||||||
|
|
||||||
bound = false;
|
bound = false;
|
||||||
|
lastlightmap = 0; // avoid compiler warning
|
||||||
for (s = t->texturechains[chain]; s; s = s->texturechain)
|
for (s = t->texturechains[chain]; s; s = s->texturechain)
|
||||||
if (!s->culled)
|
if (!s->culled)
|
||||||
{
|
{
|
||||||
|
@ -443,20 +561,22 @@ void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_
|
||||||
|
|
||||||
GL_EnableMultitexture(); // selects TEXTURE1
|
GL_EnableMultitexture(); // selects TEXTURE1
|
||||||
bound = true;
|
bound = true;
|
||||||
|
lastlightmap = s->lightmaptexturenum;
|
||||||
}
|
}
|
||||||
R_RenderDynamicLightmaps (s);
|
R_RenderDynamicLightmaps (s);
|
||||||
|
|
||||||
|
if (s->lightmaptexturenum != lastlightmap)
|
||||||
|
R_FlushBatch ();
|
||||||
|
|
||||||
GL_Bind (lightmap_textures[s->lightmaptexturenum]);
|
GL_Bind (lightmap_textures[s->lightmaptexturenum]);
|
||||||
glBegin(GL_POLYGON);
|
lastlightmap = s->lightmaptexturenum;
|
||||||
v = s->polys->verts[0];
|
R_BatchSurface (s);
|
||||||
for (j=0 ; j<s->polys->numverts ; j++, v+= VERTEXSIZE)
|
|
||||||
{
|
|
||||||
GL_MTexCoord2fFunc (GL_TEXTURE0_ARB, v[3], v[4]);
|
|
||||||
GL_MTexCoord2fFunc (GL_TEXTURE1_ARB, v[5], v[6]);
|
|
||||||
glVertex3fv (v);
|
|
||||||
}
|
|
||||||
glEnd ();
|
|
||||||
rs_brushpasses++;
|
rs_brushpasses++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
R_FlushBatch ();
|
||||||
|
|
||||||
GL_DisableMultitexture(); // selects TEXTURE0
|
GL_DisableMultitexture(); // selects TEXTURE0
|
||||||
|
|
||||||
if (bound && t->texturechains[chain]->flags & SURF_DRAWFENCE)
|
if (bound && t->texturechains[chain]->flags & SURF_DRAWFENCE)
|
||||||
|
|
Loading…
Reference in a new issue