// lightmapped wall
shaderfilename = "glsl/default.glsl";
permutation = SHADERPERMUTATION_USES_VERTEXSHADER | SHADERPERMUTATION_USES_FRAGMENTSHADER;
- if (r_glsl_deluxemapping.integer >= 1 && rsurface_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
+ if (r_glsl_deluxemapping.integer >= 1 && rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping)
{
// deluxemapping (light direction texture)
- if (rsurface_lightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
+ if (rsurface_uselightmaptexture && r_refdef.worldmodel && r_refdef.worldmodel->brushq3.deluxemapping && r_refdef.worldmodel->brushq3.deluxemapping_modelspace)
permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_MODELSPACE;
else
permutation |= SHADERPERMUTATION_MODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
VID_CheckExtensions();
// LordHavoc: report supported extensions
- Con_DPrintf("\nengine extensions: %s\n", vm_sv_extensions );
+ Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
// clear to black (loading plaque will be seen over this)
CHECKGLERROR
r_refdef.rtworld = r_shadow_realtime_world.integer;
r_refdef.rtworldshadows = r_shadow_realtime_world_shadows.integer && gl_stencil;
- r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer;
+ r_refdef.rtdlight = (r_shadow_realtime_world.integer || r_shadow_realtime_dlight.integer) && !gl_flashblend.integer && r_dynamic.integer;
r_refdef.rtdlightshadows = r_refdef.rtdlight && (r_refdef.rtworld ? r_shadow_realtime_world_dlightshadows.integer : r_shadow_realtime_dlight_shadows.integer) && gl_stencil;
r_refdef.lightmapintensity = r_refdef.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
if (r_showsurfaces.integer)
}
extern void R_DrawLightningBeams (void);
-extern void VM_AddPolygonsToMeshQueue (void);
+extern void VM_CL_AddPolygonsToMeshQueue (void);
extern void R_DrawPortals (void);
void R_RenderScene(void)
{
{
qglUseProgramObjectARB(0);CHECKGLERROR
}
- VM_AddPolygonsToMeshQueue();
+ VM_CL_AddPolygonsToMeshQueue();
if (r_drawportals.integer)
{
// pick a new currentskinframe if the material is animated
if (t->numskinframes >= 2)
t->currentskinframe = t->skinframes + ((int)(t->skinframerate * (cl.time - ent->frame2time)) % t->numskinframes);
+ if (t->backgroundnumskinframes >= 2)
+ t->backgroundcurrentskinframe = t->backgroundskinframes + ((int)(t->backgroundskinframerate * (cl.time - ent->frame2time)) % t->backgroundnumskinframes);
t->currentmaterialflags = t->basematerialflags;
t->currentalpha = ent->alpha;
t->currenttexmatrix = r_waterscrollmatrix;
else
t->currenttexmatrix = identitymatrix;
+ if (t->backgroundnumskinframes && !(t->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
+ t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
t->colormapping = VectorLength2(ent->colormap_pantscolor) + VectorLength2(ent->colormap_shirtcolor) >= (1.0f / 1048576.0f);
t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
t->glosstexture = r_texture_white;
+ t->backgroundbasetexture = t->backgroundnumskinframes ? ((!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base) : r_texture_white;
+ t->backgroundglosstexture = r_texture_white;
t->specularpower = r_shadow_glossexponent.value;
t->specularscale = 0;
if (r_shadow_gloss.integer > 0)
{
- if (t->currentskinframe->gloss)
+ if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
{
if (r_shadow_glossintensity.value > 0)
{
- t->glosstexture = t->currentskinframe->gloss;
+ t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_black;
+ t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_black;
t->specularscale = r_shadow_glossintensity.value;
}
}
const entity_render_t *rsurface_entity;
const model_t *rsurface_model;
texture_t *rsurface_texture;
-rtexture_t *rsurface_lightmaptexture;
+qboolean rsurface_uselightmaptexture;
rsurfmode_t rsurface_mode;
texture_t *rsurface_glsl_texture;
qboolean rsurface_glsl_uselightmap;
}
GL_AlphaTest(false);
rsurface_mode = RSURFMODE_NONE;
- rsurface_lightmaptexture = NULL;
+ rsurface_uselightmaptexture = false;
rsurface_texture = NULL;
rsurface_glsl_texture = NULL;
rsurface_glsl_uselightmap = false;
void RSurf_DrawBatch_Simple(int texturenumsurfaces, msurface_t **texturesurfacelist)
{
- int texturesurfaceindex;
+ int i, j;
const msurface_t *surface = texturesurfacelist[0];
- int firstvertex = surface->num_firstvertex;
- int endvertex = surface->num_firstvertex + surface->num_vertices;
+ const msurface_t *surface2;
+ int firstvertex;
+ int endvertex;
+ int numvertices;
+ int numtriangles;
+ // TODO: lock all array ranges before render, rather than on each surface
if (texturenumsurfaces == 1)
{
GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
#define MAXBATCHTRIANGLES 4096
int batchtriangles = 0;
int batchelements[MAXBATCHTRIANGLES*3];
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (i = 0;i < texturenumsurfaces;i = j)
{
- surface = texturesurfacelist[texturesurfaceindex];
- if (surface->num_triangles >= 256 || (batchtriangles == 0 && texturesurfaceindex + 1 >= texturenumsurfaces))
+ surface = texturesurfacelist[i];
+ j = i + 1;
+ if (surface->num_triangles > MAXBATCHTRIANGLES)
{
R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
continue;
}
- if (batchtriangles + surface->num_triangles > MAXBATCHTRIANGLES)
+ memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
+ batchtriangles = surface->num_triangles;
+ firstvertex = surface->num_firstvertex;
+ endvertex = surface->num_firstvertex + surface->num_vertices;
+ for (;j < texturenumsurfaces;j++)
{
- R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
- batchtriangles = 0;
- firstvertex = surface->num_firstvertex;
- endvertex = surface->num_firstvertex + surface->num_vertices;
- }
- else
- {
- firstvertex = min(firstvertex, surface->num_firstvertex);
- endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
+ surface2 = texturesurfacelist[j];
+ if (batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
+ break;
+ memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
+ batchtriangles += surface2->num_triangles;
+ firstvertex = min(firstvertex, surface2->num_firstvertex);
+ endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
}
- memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
- batchtriangles += surface->num_triangles;
+ surface2 = texturesurfacelist[j-1];
+ numvertices = endvertex - firstvertex;
+ R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
}
- if (batchtriangles)
- R_Mesh_Draw(firstvertex, endvertex - firstvertex, batchtriangles, batchelements);
}
else if (r_batchmode.integer == 1)
{
- int firsttriangle = 0;
- int endtriangle = -1;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (i = 0;i < texturenumsurfaces;i = j)
+ {
+ surface = texturesurfacelist[i];
+ for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
+ if (texturesurfacelist[j] != surface2)
+ break;
+ surface2 = texturesurfacelist[j-1];
+ numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
+ numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
+ GL_LockArrays(surface->num_firstvertex, numvertices);
+ R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
+ }
+ }
+ else
+ {
+ for (i = 0;i < texturenumsurfaces;i++)
{
- surface = texturesurfacelist[texturesurfaceindex];
- if (surface->num_firsttriangle != endtriangle)
+ surface = texturesurfacelist[i];
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
+ }
+ }
+}
+
+static void RSurf_DrawBatch_WithLightmapSwitching(int texturenumsurfaces, msurface_t **texturesurfacelist, int lightmaptexunit, int deluxemaptexunit)
+{
+ int i;
+ int j;
+ const msurface_t *surface = texturesurfacelist[0];
+ const msurface_t *surface2;
+ int firstvertex;
+ int endvertex;
+ int numvertices;
+ int numtriangles;
+ // TODO: lock all array ranges before render, rather than on each surface
+ if (texturenumsurfaces == 1)
+ {
+ R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
+ if (deluxemaptexunit >= 0)
+ R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
+ GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
+ }
+ else if (r_batchmode.integer == 2)
+ {
+ #define MAXBATCHTRIANGLES 4096
+ int batchtriangles = 0;
+ int batchelements[MAXBATCHTRIANGLES*3];
+ for (i = 0;i < texturenumsurfaces;i = j)
+ {
+ surface = texturesurfacelist[i];
+ R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
+ if (deluxemaptexunit >= 0)
+ R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
+ j = i + 1;
+ if (surface->num_triangles > MAXBATCHTRIANGLES)
{
- if (endtriangle > firsttriangle)
- {
- GL_LockArrays(firstvertex, endvertex - firstvertex);
- R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
- }
- firstvertex = surface->num_firstvertex;
- endvertex = surface->num_firstvertex + surface->num_vertices;
- firsttriangle = surface->num_firsttriangle;
+ R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
+ continue;
}
- else
+ memcpy(batchelements, rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle, surface->num_triangles * sizeof(int[3]));
+ batchtriangles = surface->num_triangles;
+ firstvertex = surface->num_firstvertex;
+ endvertex = surface->num_firstvertex + surface->num_vertices;
+ for (;j < texturenumsurfaces;j++)
{
- firstvertex = min(firstvertex, surface->num_firstvertex);
- endvertex = max(endvertex, surface->num_firstvertex + surface->num_vertices);
+ surface2 = texturesurfacelist[j];
+ if (surface2->lightmaptexture != surface->lightmaptexture || batchtriangles + surface2->num_triangles > MAXBATCHTRIANGLES)
+ break;
+ memcpy(batchelements + batchtriangles * 3, rsurface_model->surfmesh.data_element3i + 3 * surface2->num_firsttriangle, surface2->num_triangles * sizeof(int[3]));
+ batchtriangles += surface2->num_triangles;
+ firstvertex = min(firstvertex, surface2->num_firstvertex);
+ endvertex = max(endvertex, surface2->num_firstvertex + surface2->num_vertices);
}
- endtriangle = surface->num_firsttriangle + surface->num_triangles;
+ surface2 = texturesurfacelist[j-1];
+ numvertices = endvertex - firstvertex;
+ R_Mesh_Draw(firstvertex, numvertices, batchtriangles, batchelements);
}
- if (endtriangle > firsttriangle)
+ }
+ else if (r_batchmode.integer == 1)
+ {
+ for (i = 0;i < texturenumsurfaces;i = j)
{
- GL_LockArrays(firstvertex, endvertex - firstvertex);
- R_Mesh_Draw(firstvertex, endvertex - firstvertex, endtriangle - firsttriangle, (rsurface_model->surfmesh.data_element3i + 3 * firsttriangle));
+ surface = texturesurfacelist[i];
+ R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
+ if (deluxemaptexunit >= 0)
+ R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
+ for (j = i + 1, surface2 = surface + 1;j < texturenumsurfaces;j++, surface2++)
+ if (texturesurfacelist[j] != surface2 || texturesurfacelist[j]->lightmaptexture != surface->lightmaptexture)
+ break;
+ surface2 = texturesurfacelist[j-1];
+ numvertices = surface2->num_firstvertex + surface2->num_vertices - surface->num_firstvertex;
+ numtriangles = surface2->num_firsttriangle + surface2->num_triangles - surface->num_firsttriangle;
+ GL_LockArrays(surface->num_firstvertex, numvertices);
+ R_Mesh_Draw(surface->num_firstvertex, numvertices, numtriangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
}
}
else
{
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
+ for (i = 0;i < texturenumsurfaces;i++)
{
- surface = texturesurfacelist[texturesurfaceindex];
+ surface = texturesurfacelist[i];
+ R_Mesh_TexBind(lightmaptexunit, R_GetTexture(surface->lightmaptexture));
+ if (deluxemaptexunit >= 0)
+ R_Mesh_TexBind(deluxemaptexunit, R_GetTexture(surface->deluxemaptexture));
GL_LockArrays(surface->num_firstvertex, surface->num_vertices);
R_Mesh_Draw(surface->num_firstvertex, surface->num_vertices, surface->num_triangles, (rsurface_model->surfmesh.data_element3i + 3 * surface->num_firsttriangle));
}
rsurface_lightmapcolor4f = NULL;
}
}
- else if (lightmode >= 1 || !rsurface_lightmaptexture)
+ else if (lightmode >= 1 || !rsurface_uselightmaptexture)
{
if (texturesurfacelist[0]->lightmapinfo && texturesurfacelist[0]->lightmapinfo->stainsamples)
{
}
R_Mesh_ColorPointer(rsurface_lightmapcolor4f);
GL_Color(r, g, b, a);
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 0, -1);
+ else
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, msurface_t **texturesurfacelist)
{
+ GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
+ GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
if (rsurface_mode != RSURFMODE_SHOWSURFACES)
{
rsurface_mode = RSURFMODE_SHOWSURFACES;
// restore entity matrix
R_Mesh_Matrix(&rsurface_entity->matrix);
}
+ GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
+ GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
GL_DepthMask(true);
// LordHavoc: HalfLife maps have freaky skypolys so don't use
// skymasking on them, and Quake3 never did sky masking (unlike
static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, msurface_t **texturesurfacelist)
{
- int lightmode;
- // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
- lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
if (rsurface_mode != RSURFMODE_GLSL)
{
rsurface_mode = RSURFMODE_GLSL;
rsurface_glsl_uselightmap = false;
R_Mesh_ResetTextureState();
}
- if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != (rsurface_lightmaptexture != NULL))
+ if (rsurface_glsl_texture != rsurface_texture || rsurface_glsl_uselightmap != rsurface_uselightmaptexture)
{
+ int lightmode;
rsurface_glsl_texture = rsurface_texture;
- rsurface_glsl_uselightmap = rsurface_lightmaptexture != NULL;
+ rsurface_glsl_uselightmap = rsurface_uselightmaptexture;
+ GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
+ GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
GL_BlendFunc(rsurface_texture->currentlayers[0].blendfunc1, rsurface_texture->currentlayers[0].blendfunc2);
GL_DepthMask(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_BLENDED));
GL_Color(rsurface_entity->colormod[0], rsurface_entity->colormod[1], rsurface_entity->colormod[2], rsurface_texture->currentalpha);
+ // FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
+ lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
R_SetupSurfaceShader(vec3_origin, lightmode == 2);
//permutation_deluxemapping = permutation_lightmapping = R_SetupSurfaceShader(vec3_origin, lightmode == 2, false);
//if (r_glsl_deluxemapping.integer)
R_Mesh_TexCoordPointer(0, 2, rsurface_model->surfmesh.data_texcoordtexture2f);
R_Mesh_TexCoordPointer(4, 2, rsurface_model->surfmesh.data_texcoordlightmap2f);
GL_AlphaTest((rsurface_texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
+ RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
+ R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
+ R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
+ R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
+ if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
+ {
+ R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
+ R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
+ R_Mesh_ColorPointer(NULL);
+ }
+ else if (rsurface_uselightmaptexture)
+ {
+ R_Mesh_TexBind(7, R_GetTexture(texturesurfacelist[0]->lightmaptexture));
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
+ R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
+ R_Mesh_ColorPointer(NULL);
+ }
+ else
+ {
+ R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
+ if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
+ R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
+ R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
+ }
}
+ else
+ RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
if (!r_glsl_permutation)
return;
- RSurf_PrepareVerticesForBatch(true, true, texturenumsurfaces, texturesurfacelist);
- R_Mesh_TexCoordPointer(1, 3, rsurface_svector3f);
- R_Mesh_TexCoordPointer(2, 3, rsurface_tvector3f);
- R_Mesh_TexCoordPointer(3, 3, rsurface_normal3f);
- if (rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
- {
- R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
- if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
- R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
- R_Mesh_ColorPointer(NULL);
- }
- else if (rsurface_lightmaptexture)
- {
- R_Mesh_TexBind(7, R_GetTexture(rsurface_lightmaptexture));
- if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
- R_Mesh_TexBind(8, R_GetTexture(texturesurfacelist[0]->deluxemaptexture));
- R_Mesh_ColorPointer(NULL);
- }
+ if (rsurface_uselightmaptexture && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
+ RSurf_DrawBatch_WithLightmapSwitching(texturenumsurfaces, texturesurfacelist, 7, r_glsl_permutation->loc_Texture_Deluxemap >= 0 ? 8 : -1);
else
+ RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
+ if (rsurface_texture->backgroundnumskinframes && !(rsurface_texture->currentmaterialflags & MATERIALFLAG_TRANSPARENT))
{
- R_Mesh_TexBind(7, R_GetTexture(r_texture_white));
- if (r_glsl_permutation->loc_Texture_Deluxemap >= 0)
- R_Mesh_TexBind(8, R_GetTexture(r_texture_blanknormalmap));
- R_Mesh_ColorPointer(rsurface_model->surfmesh.data_lightmapcolor4f);
}
- RSurf_DrawBatch_Simple(texturenumsurfaces, texturesurfacelist);
}
static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, msurface_t **texturesurfacelist)
int layerindex;
const texturelayer_t *layer;
CHECKGLERROR
+ GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
+ GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
// FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
- lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
+ lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
if (rsurface_mode != RSURFMODE_MULTIPASS)
rsurface_mode = RSURFMODE_MULTIPASS;
RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
{
case TEXTURELAYERTYPE_LITTEXTURE:
memset(&m, 0, sizeof(m));
- if (lightmode >= 1 || !rsurface_lightmaptexture)
- m.tex[0] = R_GetTexture(r_texture_white);
- else
- m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
+ m.tex[0] = R_GetTexture(r_texture_white);
m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
m.tex[1] = R_GetTexture(layer->texture);
m.texmatrix[1] = layer->texmatrix;
int layerindex;
const texturelayer_t *layer;
CHECKGLERROR
+ GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
+ GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
// FIXME: identify models using a better check than rsurface_model->brush.shadowmesh
- lightmode = ((rsurface_entity->effects & EF_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
+ lightmode = ((rsurface_texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT) || rsurface_model->brush.shadowmesh) ? 0 : 2;
if (rsurface_mode != RSURFMODE_MULTIPASS)
rsurface_mode = RSURFMODE_MULTIPASS;
RSurf_PrepareVerticesForBatch(true, false, texturenumsurfaces, texturesurfacelist);
// two-pass lit texture with 2x rgbscale
// first the lightmap pass
memset(&m, 0, sizeof(m));
- if (lightmode >= 1 || !rsurface_lightmaptexture)
- m.tex[0] = R_GetTexture(r_texture_white);
- else
- m.tex[0] = R_GetTexture(rsurface_lightmaptexture);
+ m.tex[0] = R_GetTexture(r_texture_white);
m.pointer_texcoord[0] = rsurface_model->surfmesh.data_texcoordlightmap2f;
R_Mesh_TextureState(&m);
RSurf_DrawBatch_Lightmap(texturenumsurfaces, texturesurfacelist, 1, 1, 1, 1, lightmode, false, false);
r_shadow_rtlight = NULL;
r_refdef.stats.entities_surfaces += texturenumsurfaces;
CHECKGLERROR
- GL_DepthTest(!(rsurface_texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
- GL_CullFace(((rsurface_texture->textureflags & Q3TEXTUREFLAG_TWOSIDED) || (rsurface_entity->flags & RENDER_NOCULLFACE)) ? GL_NONE : GL_FRONT); // quake is backwards, this culls back faces
if (r_showsurfaces.integer)
R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist);
else if (rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)
RSurf_ActiveEntity(ent, true, r_glsl.integer && gl_support_fragment_shader);
batchcount = 0;
t = NULL;
+ rsurface_uselightmaptexture = false;
for (surfacelistindex = 0;surfacelistindex < numsurfaces;surfacelistindex++)
{
msurface_t *surface = ent->model->data_surfaces + surfacelist[surfacelistindex];
- if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
+ if (t != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
{
if (batchcount > 0)
if (!(rsurface_texture->currentmaterialflags & MATERIALFLAG_SKY)) // transparent sky is too difficult
R_DrawTextureSurfaceList(batchcount, texturesurfacelist);
batchcount = 0;
t = surface->texture;
- rsurface_lightmaptexture = surface->lightmaptexture;
+ rsurface_uselightmaptexture = (surface->lightmaptexture != NULL);
R_UpdateTextureInfo(ent, t);
rsurface_texture = t->currentframe;
}
extern void R_BuildLightMap(const entity_render_t *ent, msurface_t *surface);
void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
{
- int i, j, f, flagsmask;
+ int i, j, k, l, endj, f, flagsmask;
int counttriangles = 0;
+ msurface_t *surface, *endsurface, **surfacechain;
texture_t *t;
+ q3mbrush_t *brush;
model_t *model = ent->model;
+ const int *elements;
const int maxsurfacelist = 1024;
int numsurfacelist = 0;
msurface_t *surfacelist[1024];
+ vec3_t v;
if (model == NULL)
return;
// update light styles
if (!skysurfaces && model->brushq1.light_styleupdatechains)
{
- msurface_t *surface, **surfacechain;
for (i = 0;i < model->brushq1.light_styles;i++)
{
if (model->brushq1.light_stylevalue[i] != r_refdef.lightstylevalue[model->brushq1.light_style[i]])
flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
f = 0;
t = NULL;
- rsurface_lightmaptexture = NULL;
+ rsurface_uselightmaptexture = false;
rsurface_texture = NULL;
numsurfacelist = 0;
if (ent == r_refdef.worldentity)
{
- msurface_t *surface;
- for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+ j = model->firstmodelsurface;
+ endj = j + model->nummodelsurfaces;
+ while (j < endj)
{
- if (!r_viewcache.world_surfacevisible[j])
- continue;
- if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
+ // quickly skip over non-visible surfaces
+ for (;j < endj && !r_viewcache.world_surfacevisible[j];j++)
+ ;
+ // quickly iterate over visible surfaces
+ for (;j < endj && r_viewcache.world_surfacevisible[j];j++)
{
- if (numsurfacelist)
+ // process this surface
+ surface = model->data_surfaces + j;
+ // if texture or lightmap has changed, start a new batch
+ if (t != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
{
- R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
- numsurfacelist = 0;
+ if (numsurfacelist)
+ {
+ R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
+ numsurfacelist = 0;
+ }
+ t = surface->texture;
+ rsurface_uselightmaptexture = surface->lightmaptexture != NULL;
+ rsurface_texture = t->currentframe;
+ f = rsurface_texture->currentmaterialflags & flagsmask;
}
- t = surface->texture;
- rsurface_lightmaptexture = surface->lightmaptexture;
- rsurface_texture = t->currentframe;
- f = rsurface_texture->currentmaterialflags & flagsmask;
- }
- if (f && surface->num_triangles)
- {
- // if lightmap parameters changed, rebuild lightmap texture
- if (surface->cached_dlight)
- R_BuildLightMap(ent, surface);
- // add face to draw list
- surfacelist[numsurfacelist++] = surface;
- counttriangles += surface->num_triangles;
- if (numsurfacelist >= maxsurfacelist)
+ // if this surface fits the criteria, add it to the list
+ if (f && surface->num_triangles)
{
- R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
- numsurfacelist = 0;
+ // if lightmap parameters changed, rebuild lightmap texture
+ if (surface->cached_dlight)
+ R_BuildLightMap(ent, surface);
+ // add face to draw list
+ surfacelist[numsurfacelist++] = surface;
+ counttriangles += surface->num_triangles;
+ if (numsurfacelist >= maxsurfacelist)
+ {
+ R_QueueTextureSurfaceList(numsurfacelist, surfacelist);
+ numsurfacelist = 0;
+ }
}
}
}
}
else
{
- msurface_t *surface;
- for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
+ surface = model->data_surfaces + model->firstmodelsurface;
+ endsurface = surface + model->nummodelsurfaces;
+ for (;surface < endsurface;surface++)
{
- if (t != surface->texture || rsurface_lightmaptexture != surface->lightmaptexture)
+ // if texture or lightmap has changed, start a new batch
+ if (t != surface->texture || rsurface_uselightmaptexture != (surface->lightmaptexture != NULL))
{
if (numsurfacelist)
{
numsurfacelist = 0;
}
t = surface->texture;
- rsurface_lightmaptexture = surface->lightmaptexture;
+ rsurface_uselightmaptexture = (surface->lightmaptexture != NULL);
rsurface_texture = t->currentframe;
f = rsurface_texture->currentmaterialflags & flagsmask;
}
+ // if this surface fits the criteria, add it to the list
if (f && surface->num_triangles)
{
// if lightmap parameters changed, rebuild lightmap texture
if (r_showcollisionbrushes.integer && model->brush.num_brushes && !skysurfaces)
{
- int i;
- const msurface_t *surface;
- q3mbrush_t *brush;
CHECKGLERROR
R_Mesh_Matrix(&ent->matrix);
R_Mesh_ColorPointer(NULL);
if (r_showtris.integer || r_shownormals.integer)
{
- int k, l;
- msurface_t *surface;
- const int *elements;
- vec3_t v;
CHECKGLERROR
GL_DepthTest(!r_showdisabledepthtest.integer);
GL_DepthMask(true);