/* * R_AddSurfaceToDrawList * * Note that dlit may be true even if dlightBits is 0, indicating there's at least potentially one * dynamically light surface for the drawSurf. */ static void R_AddSurfaceToDrawList( const entity_t *e, const msurface_t *surf, const mfog_t *fog, unsigned int dlightBits, unsigned shadowBits, float dist ) { shader_t *shader; drawSurfaceBSP_t *drawSurf = surf->drawSurf; portalSurface_t *portalSurface = NULL; bool lightmapped; unsigned drawOrder; if( r_drawworld->integer == 2 ) { shader = rsh.envShader; } else { shader = surf->shader; if( shader->flags & SHADER_SKY ) { bool addSurf = true, addSlice = false; if( R_FASTSKY() ) { return; } if( R_ClipSkySurface( surf ) ) { if( rn.refdef.rdflags & RDF_SKYPORTALINVIEW ) { // for skyportals, generate portal surface and // also add BSP surface to skybox if it's fogged to render // the fog hull later portalSurface = R_AddSkyportalSurface( e, shader, drawSurf ); addSurf = portalSurface != NULL && surf->fog != NULL; addSlice = portalSurface != NULL; } if( addSurf ) { addSlice = R_AddSkySurfToDrawList( surf, portalSurface ); } if( addSlice ) { R_AddSurfaceVBOSlice( surf, 0 ); } } rn.numVisSurfaces++; return; } } lightmapped = surf->superLightStyle != NULL && surf->superLightStyle->lightmapNum[0] >= 0; drawOrder = R_PackOpaqueOrder( e, shader, lightmapped, dlightBits != 0 ); if( drawSurf->visFrame != rf.frameCount ) { if( shader->flags & SHADER_PORTAL ) { // draw portals in front-to-back order dist = 1024 - dist / 100.0f; if( dist < 1 ) dist = 1; portalSurface = R_AddPortalSurface( e, surf->mesh, surf->mins, surf->maxs, shader, drawSurf ); } else { // just ignore the distance since we're drawing batched geometry anyway dist = 0; } drawSurf->visFrame = rf.frameCount; drawSurf->listSurf = R_AddSurfToDrawList( rn.meshlist, e, fog, shader, dist, drawOrder, portalSurface, drawSurf ); if( !drawSurf->listSurf ) { return; } if( portalSurface && !( shader->flags & (SHADER_PORTAL_CAPTURE|SHADER_PORTAL_CAPTURE2) ) ) { R_AddSurfToDrawList( rn.portalmasklist, e, NULL, rsh.skyShader, 0, 0, NULL, drawSurf ); } } else { if( !drawSurf->listSurf ) { return; } // update (OR) the dlightbit R_UpdateDrawListSurf( drawSurf->listSurf, drawOrder ); } // keep track of the actual vbo chunk we need to render R_AddSurfaceVBOSlice( surf, 0 ); // dynamic lights that affect the surface if( dlightBits ) { // ignore dlights that have already been marked as affectors if( drawSurf->dlightFrame == rsc.frameCount ) { drawSurf->dlightBits |= dlightBits; } else { drawSurf->dlightBits = dlightBits; drawSurf->dlightFrame = rsc.frameCount; } } // shadows that are projected onto the surface if( shadowBits ) { R_AddSurfaceVBOSlice( surf, rsh.worldBrushModel->numDrawSurfaces ); // ignore shadows that have already been marked as affectors if( drawSurf->shadowFrame == rsc.frameCount ) { drawSurf->shadowBits |= shadowBits; } else { drawSurf->shadowBits = shadowBits; drawSurf->shadowFrame = rsc.frameCount; } } rf.stats.c_brush_polys++; rn.numVisSurfaces++; }
/* * R_ClipSkySurface */ static void R_ClipSkySurface(int nump, vec3_t vecs, int stage) { const float *norm; float *v; boolean_t front, back; float d, e; float dists[MAX_CLIP_VERTS]; int sides[MAX_CLIP_VERTS]; vec3_t newv[2][MAX_CLIP_VERTS]; int newc[2]; int i, j; if (nump > MAX_CLIP_VERTS - 2) Com_Error(ERR_DROP, "R_ClipSkyPoly: MAX_CLIP_VERTS"); if (stage == 6) { // fully clipped, so draw it R_DrawSkySurface(nump, vecs); return; } front = back = false; norm = skyclip[stage]; for (i = 0, v = vecs; i < nump; i++, v += 3) { d = DotProduct(v, norm); if (d > ON_EPSILON) { front = true; sides[i] = SIDE_FRONT; } else if (d < -ON_EPSILON) { back = true; sides[i] = SIDE_BACK; } else sides[i] = SIDE_BOTH; dists[i] = d; } if (!front || !back) { // not clipped R_ClipSkySurface(nump, vecs, stage + 1); return; } // clip it sides[i] = sides[0]; dists[i] = dists[0]; VectorCopy(vecs, (vecs + (i * 3))); newc[0] = newc[1] = 0; for (i = 0, v = vecs; i < nump; i++, v += 3) { switch (sides[i]) { case SIDE_FRONT: VectorCopy(v, newv[0][newc[0]]); newc[0]++; break; case SIDE_BACK: VectorCopy(v, newv[1][newc[1]]); newc[1]++; break; case SIDE_BOTH: VectorCopy(v, newv[0][newc[0]]); newc[0]++; VectorCopy(v, newv[1][newc[1]]); newc[1]++; break; } if (sides[i] == SIDE_BOTH || sides[i + 1] == SIDE_BOTH || sides[i + 1] == sides[i]) continue; d = dists[i] / (dists[i] - dists[i + 1]); for (j = 0; j < 3; j++) { e = v[j] + d * (v[j + 3] - v[j]); newv[0][newc[0]][j] = e; newv[1][newc[1]][j] = e; } newc[0]++; newc[1]++; } // continue R_ClipSkySurface(newc[0], newv[0][0], stage + 1); R_ClipSkySurface(newc[1], newv[1][0], stage + 1); }