- if (texture->currentmaterialflags & MATERIALFLAG_WALL)
- {
- dolightmap = (ent->flags & RENDER_LIGHT);
- dobase = true;
- doambient = r_ambient.value > 0;
- dodetail = texture->skin.detail != NULL && r_detailtextures.integer != 0;
- doglow = texture->skin.glow != NULL;
- dofog = fogenabled;
- // multitexture cases
- if (r_textureunits.integer >= 2 && gl_combine.integer && dobase && dolightmap)
- {
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_DepthMask(true);
- GL_DepthTest(true);
- GL_Color(1, 1, 1, 1);
- GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(texture->skin.base);
- dobase = false;
- m.texrgbscale[1] = 2;
- dolightmap = false;
- if (r_textureunits.integer >= 4 && !doambient && dodetail && doglow)
- {
- m.tex[2] = R_GetTexture(texture->skin.detail);
- m.texrgbscale[2] = 2;
- dodetail = false;
- m.tex[3] = R_GetTexture(texture->skin.glow);
- m.texcombinergb[3] = GL_ADD;
- doglow = false;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.tex[1] = R_GetTexture(surface->lightmaptexture);
- m.pointer_vertex = surface->mesh.data_vertex3f;
- m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
- m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
- m.pointer_texcoord[2] = surface->mesh.data_texcoorddetail2f;
- m.pointer_texcoord[3] = surface->mesh.data_texcoordtexture2f;
- R_Mesh_State(&m);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- }
- else if (r_textureunits.integer >= 3 && !doambient && dodetail)
- {
- m.tex[2] = R_GetTexture(texture->skin.detail);
- m.texrgbscale[2] = 2;
- dodetail = false;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.tex[1] = R_GetTexture(surface->lightmaptexture);
- m.pointer_vertex = surface->mesh.data_vertex3f;
- m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
- m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
- m.pointer_texcoord[2] = surface->mesh.data_texcoorddetail2f;
- R_Mesh_State(&m);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- }
- else if (r_textureunits.integer >= 3 && !doambient && !dodetail && doglow)
- {
- m.tex[2] = R_GetTexture(texture->skin.glow);
- m.texcombinergb[2] = GL_ADD;
- doglow = false;
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.tex[1] = R_GetTexture(surface->lightmaptexture);
- m.pointer_vertex = surface->mesh.data_vertex3f;
- m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
- m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
- m.pointer_texcoord[2] = surface->mesh.data_texcoordtexture2f;
- R_Mesh_State(&m);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- }
- else
- {
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.tex[1] = R_GetTexture(surface->lightmaptexture);
- m.pointer_vertex = surface->mesh.data_vertex3f;
- m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
- m.pointer_texcoord[1] = surface->mesh.data_texcoordlightmap2f;
- R_Mesh_State(&m);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- }
- }
- // anything not handled above
- if (dobase)
- {
- GL_BlendFunc(GL_ONE, GL_ZERO);
- GL_DepthMask(true);
- GL_DepthTest(true);
- GL_Color(1, 1, 1, 1);
- if (ent->flags & RENDER_LIGHT)
- GL_Color(r_lightmapintensity * ent->colormod[0], r_lightmapintensity * ent->colormod[1], r_lightmapintensity * ent->colormod[2], 1);
- else
- GL_Color(ent->colormod[0], ent->colormod[1], ent->colormod[2], 1);
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(texture->skin.base);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.pointer_vertex = surface->mesh.data_vertex3f;
- m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
- R_Mesh_State(&m);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- }
- GL_DepthMask(false);
- if (dolightmap)
- {
- GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
- GL_DepthMask(false);
- GL_DepthTest(true);
- GL_Color(1, 1, 1, 1);
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(texture->skin.base);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.tex[0] = R_GetTexture(surface->lightmaptexture);
- m.pointer_vertex = surface->mesh.data_vertex3f;
- m.pointer_texcoord[0] = surface->mesh.data_texcoordlightmap2f;
- R_Mesh_State(&m);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- }
- if (doambient)
- {
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
- GL_DepthMask(false);
- GL_DepthTest(true);
- memset(&m, 0, sizeof(m));
- GL_Color(r_ambient.value * (1.0f / 128.0f) * ent->colormod[0], r_ambient.value * (1.0f / 128.0f) * ent->colormod[1], r_ambient.value * (1.0f / 128.0f) * ent->colormod[2], 1);
- m.tex[0] = R_GetTexture(texture->skin.base);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.pointer_vertex = surface->mesh.data_vertex3f;
- m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
- R_Mesh_State(&m);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- }
- if (dodetail)
- {
- GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
- GL_DepthMask(false);
- GL_DepthTest(true);
- GL_Color(1, 1, 1, 1);
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(texture->skin.detail);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.pointer_vertex = surface->mesh.data_vertex3f;
- m.pointer_texcoord[0] = surface->mesh.data_texcoorddetail2f;
- R_Mesh_State(&m);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- }
- if (doglow)
- {
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
- GL_DepthMask(false);
- GL_DepthTest(true);
- GL_Color(1, 1, 1, 1);
- memset(&m, 0, sizeof(m));
- m.tex[0] = R_GetTexture(texture->skin.glow);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.pointer_vertex = surface->mesh.data_vertex3f;
- m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
- R_Mesh_State(&m);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- }
- if (dofog)
- {
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- GL_DepthMask(false);
- GL_DepthTest(true);
- memset(&m, 0, sizeof(m));
- m.pointer_color = varray_color4f;
- m.tex[0] = R_GetTexture(texture->skin.glow);
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.pointer_vertex = surface->mesh.data_vertex3f;
- if (m.tex[0])
- m.pointer_texcoord[0] = surface->mesh.data_texcoordtexture2f;
- R_Mesh_State(&m);
- RSurf_FogPassColors_Vertex3f_Color4f(surface->mesh.data_vertex3f, varray_color4f, fogcolor[0], fogcolor[1], fogcolor[2], 1, 1, surface->mesh.num_vertices, modelorg);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- }
- return;
- }
- if (texture->currentmaterialflags & MATERIALFLAG_WATER)
- {
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- RSurfShader_Transparent_Callback(ent, surface - ent->model->brush.data_surfaces);
- }
- return;
- }
- if (texture->currentmaterialflags & MATERIALFLAG_SKY)
- {
- if (skyrendernow)
- {
- skyrendernow = false;
- if (skyrendermasked)
- R_Sky();
- }
- // LordHavoc: HalfLife maps have freaky skypolys...
- if (!ent->model->brush.ishlbsp)
- {
- R_Mesh_Matrix(&ent->matrix);
- GL_Color(fogcolor[0], fogcolor[1], fogcolor[2], 1);
- if (skyrendermasked)
- {
- // depth-only (masking)
- GL_ColorMask(0,0,0,0);
- // just to make sure that braindead drivers don't draw anything
- // despite that colormask...
- GL_BlendFunc(GL_ZERO, GL_ONE);
- }
- else
- {
- // fog sky
- GL_BlendFunc(GL_ONE, GL_ZERO);
- }
- GL_DepthMask(true);
- GL_DepthTest(true);
- memset(&m, 0, sizeof(m));
- for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
- {
- surface = texturesurfacelist[texturesurfaceindex];
- m.pointer_vertex = surface->mesh.data_vertex3f;
- R_Mesh_State(&m);
- GL_LockArrays(0, surface->mesh.num_vertices);
- R_Mesh_Draw(surface->mesh.num_vertices, surface->mesh.num_triangles, surface->mesh.data_element3i);
- GL_LockArrays(0, 0);
- }
- GL_ColorMask(r_refdef.colormask[0], r_refdef.colormask[1], r_refdef.colormask[2], 1);
- }
- return;
- }
-}
-
-void R_DrawSurfaces(entity_render_t *ent, qboolean skysurfaces)
-{
- int i, j, f, flagsmask;
- msurface_t *surface, **surfacechain;
- texture_t *t, *texture;
- model_t *model = ent->model;
- vec3_t modelorg;
- const int maxsurfacelist = 1024;
- int numsurfacelist = 0;
- msurface_t *surfacelist[1024];
- if (model == NULL)
- return;
- R_Mesh_Matrix(&ent->matrix);
- Matrix4x4_Transform(&ent->inversematrix, r_vieworigin, modelorg);
-
- if (ent != r_refdef.worldentity)
- {
- // because bmodels can be reused, we have to clear dlightframe every time
- surface = model->brush.data_surfaces + model->firstmodelsurface;
- for (i = 0;i < model->nummodelsurfaces;i++, surface++)
- surface->dlightframe = -1;
- }
-
- // update light styles
- if (!skysurfaces)
- {
- if (r_dynamic.integer && !r_rtdlight)
- R_MarkLights(ent);
- for (i = 0;i < model->brushq1.light_styles;i++)
- {
- if (model->brushq1.light_stylevalue[i] != d_lightstylevalue[model->brushq1.light_style[i]])
- {
- model->brushq1.light_stylevalue[i] = d_lightstylevalue[model->brushq1.light_style[i]];
- if ((surfacechain = model->brushq1.light_styleupdatechains[i]))
- for (;(surface = *surfacechain);surfacechain++)
- surface->cached_dlight = true;
- }
- }
- }
-
- R_UpdateAllTextureInfo(ent);
- flagsmask = skysurfaces ? MATERIALFLAG_SKY : (MATERIALFLAG_WATER | MATERIALFLAG_WALL);
- f = 0;
- t = NULL;
- numsurfacelist = 0;
- for (i = 0, j = model->firstmodelsurface;i < model->nummodelsurfaces;i++, j++)
- {
- if (ent != r_refdef.worldentity || r_worldsurfacevisible[j])
- {
- surface = model->brush.data_surfaces + j;
- if (t != surface->texture)
- {
- if (numsurfacelist)
- {
- R_DrawSurfaceList(ent, texture, numsurfacelist, surfacelist);
- numsurfacelist = 0;
- }
- t = surface->texture;
- f = t->currentmaterialflags & flagsmask;
- texture = t->currentframe;
- }
- if (f)
- {
- // add face to draw list and update lightmap if necessary
- if (surface->cached_dlight && surface->lightmaptexture != NULL)
- R_BuildLightMap(ent, surface);
- surfacelist[numsurfacelist++] = surface;
- if (numsurfacelist >= maxsurfacelist)
- {
- R_DrawSurfaceList(ent, texture, numsurfacelist, surfacelist);
- numsurfacelist = 0;
- }
- }
- }
- }
- if (numsurfacelist)
- R_DrawSurfaceList(ent, texture, numsurfacelist, surfacelist);
-}
-
-static void R_DrawPortal_Callback(const void *calldata1, int calldata2)
-{
- int i;
- float *v;
- rmeshstate_t m;
- const mportal_t *portal = calldata1;
- GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- GL_DepthMask(false);
- GL_DepthTest(true);
- R_Mesh_Matrix(&r_identitymatrix);
-
- memset(&m, 0, sizeof(m));
- m.pointer_vertex = varray_vertex3f;
- R_Mesh_State(&m);
-
- i = calldata2;
- GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f),
- ((i & 0x0038) >> 3) * (1.0f / 7.0f),
- ((i & 0x01C0) >> 6) * (1.0f / 7.0f),
- 0.125f);
- if (PlaneDiff(r_vieworigin, (&portal->plane)) < 0)
- {
- for (i = portal->numpoints - 1, v = varray_vertex3f;i >= 0;i--, v += 3)
- VectorCopy(portal->points[i].position, v);
- }
- else
- for (i = 0, v = varray_vertex3f;i < portal->numpoints;i++, v += 3)
- VectorCopy(portal->points[i].position, v);
- GL_LockArrays(0, portal->numpoints);
- R_Mesh_Draw(portal->numpoints, portal->numpoints - 2, polygonelements);
- GL_LockArrays(0, 0);
-}
-
-// LordHavoc: this is just a nice debugging tool, very slow
-static void R_DrawPortals(void)
-{
- int i, portalnum;
- mportal_t *portal;
- float center[3], f;
- model_t *model = r_refdef.worldmodel;
- if (model == NULL)
- return;
- for (portalnum = 0, portal = model->brush.data_portals;portalnum < model->brush.num_portals;portalnum++, portal++)
- {
- if (portal->numpoints <= POLYGONELEMENTS_MAXPOINTS)
- if (!R_CullBox(portal->mins, portal->maxs))
- {
- VectorClear(center);
- for (i = 0;i < portal->numpoints;i++)
- VectorAdd(center, portal->points[i].position, center);
- f = ixtable[portal->numpoints];
- VectorScale(center, f, center);
- R_MeshQueue_AddTransparent(center, R_DrawPortal_Callback, portal, portalnum);
- }
- }
-}
-
-void R_WorldVisibility(void)
-{
- int i, j, *mark;
- mleaf_t *leaf;
- mleaf_t *viewleaf;
- model_t *model = r_refdef.worldmodel;
-
- if (!model)
- return;
-
- // if possible find the leaf the view origin is in
- viewleaf = model->brushq1.PointInLeaf ? model->brushq1.PointInLeaf(model, r_vieworigin) : NULL;
- // if possible fetch the visible cluster bits
- if (model->brush.FatPVS)
- model->brush.FatPVS(model, r_vieworigin, 2, r_pvsbits, sizeof(r_pvsbits));
-
- // clear the visible surface and leaf flags arrays
- memset(r_worldsurfacevisible, 0, model->brush.num_surfaces);
- memset(r_worldleafvisible, 0, model->brush.num_leafs);
-
- // if the user prefers surfaceworldnode (testing?) or the viewleaf could
- // not be found, or the viewleaf is not part of the visible world
- // (floating around in the void), use the pvs method
- if (r_surfaceworldnode.integer || !viewleaf || viewleaf->clusterindex < 0)
- {
- // pvs method:
- // similar to quake's RecursiveWorldNode but without cache misses
- for (j = 0, leaf = model->brush.data_leafs;j < model->brush.num_leafs;j++, leaf++)
- {
- // if leaf is in current pvs and on the screen, mark its surfaces
- if (CHECKPVSBIT(r_pvsbits, leaf->clusterindex) && !R_CullBox(leaf->mins, leaf->maxs))
- {
- c_leafs++;
- r_worldleafvisible[j] = true;
- if (leaf->numleafsurfaces)
- for (i = 0, mark = leaf->firstleafsurface;i < leaf->numleafsurfaces;i++, mark++)
- r_worldsurfacevisible[*mark] = true;
- }
- }
- }
- else