/* ================= R_DrawSkyChain ================= */ void R_DrawSkyChain (msurface_t *s) { msurface_t *fa; int i; vec3_t verts[MAX_CLIP_VERTS]; glpoly_t *p; c_sky = 0; GL_Bind(solidskytexture); // calculate vertex values for sky box for (fa=s ; fa ; fa=fa->texturechain) { for (p=fa->polys ; p ; p=p->next) { for (i=0 ; i<p->numverts ; i++) { VectorSubtract (p->verts[i], r_origin, verts[i]); } ClipSkyPolygon (p->numverts, verts[0], 0); } } }
/* ================= R_AddSkySurface ================= */ void R_AddSkySurface (const msurface_t *fa) { int i; vec3_t verts[MAX_CLIP_VERTS]; const glpoly_t *p; // calculate vertex values for sky box for (i = 0, p = fa->polys; i < p->numverts; i++) VectorSubtract (p->verts[i], r_origin, verts[i]); ClipSkyPolygon (p->numverts, verts[0], 0); }
static void RB_ClipSkyPolygons( const shaderCommands_t* input ) { vec3_t p[4]; // need one extra point for clipping ClearSkyBox(); for ( int i = 0; i < input->numIndexes; i += 3 ) { VectorSubtract( input->xyz[input->indexes[i+0]], backEnd.viewParms.or.origin, p[0] ); VectorSubtract( input->xyz[input->indexes[i+1]], backEnd.viewParms.or.origin, p[1] ); VectorSubtract( input->xyz[input->indexes[i+2]], backEnd.viewParms.or.origin, p[2] ); ClipSkyPolygon( 3, p[0], 0 ); } }
/* * RB_ClipSkyPolygons */ void RB_ClipSkyPolygons(shaderCommands_t *input) { Vec3 p[5]; /* need one extra point for clipping */ int i, j; ClearSkyBox(); for(i = 0; i < input->numIndexes; i += 3){ for(j = 0; j < 3; j++) subv3(input->xyz[input->indexes[i+j]], backEnd.viewParms.or.origin, p[j]); ClipSkyPolygon(3, p[0], 0); } }
/* ================ Tess_ClipSkyPolygons ================ */ void Tess_ClipSkyPolygons() { vec3_t p[ 5 ]; // need one extra point for clipping unsigned int i, j; ClearSkyBox(); for ( i = 0; i < tess.numIndexes; i += 3 ) { for ( j = 0; j < 3; j++ ) { VectorSubtract( tess.xyz[ tess.indexes[ i + j ] ], backEnd.viewParms.orientation.origin, p[ j ] ); } ClipSkyPolygon( 3, p[ 0 ], 0 ); } }
void RB_ClipSkyPolygons( shaderCommands_t *input ) { vector3 p[5]; // need one extra point for clipping int i, j; ClearSkyBox(); for ( i = 0; i < input->numIndexes; i += 3 ) { for (j = 0 ; j < 3 ; j++) { VectorSubtract( &input->xyz[input->indexes[i+j]], &backEnd.viewParms.or.origin, &p[j] ); } ClipSkyPolygon( 3, &p[0], 0 ); } }
/* R_DrawSkyChain */ void R_DrawSkyChain ( msurface_t *s ) { msurface_t *fa; int i; vec3_t verts[MAX_CLIP_VERTS]; glpoly_t *p; if (r_sky->value) { c_sky = 0; GL_Bind(solidskytexture); // calculate vertex values for sky box for (fa=s ; fa ; fa=fa->texturechain) { for (p=fa->polys ; p ; p=p->next) { for (i=0 ; i<p->numverts ; i++) { VectorSubtract (p->verts[i], r_origin, verts[i]); } ClipSkyPolygon (p->numverts, verts[0], 0); } } } else { GL_DisableMultitexture(); // used when gl_texsort is on GL_Bind(solidskytexture); speedscale = realtime*8; speedscale -= (int)speedscale & ~127 ; for (fa=s ; fa ; fa=fa->texturechain) EmitSkyPolys (fa); glEnable (GL_BLEND); GL_Bind (alphaskytexture); speedscale = realtime*16; speedscale -= (int)speedscale & ~127 ; for ( fa=s ; fa != NULL ; fa = fa->texturechain ) EmitSkyPolys (fa); glDisable (GL_BLEND); } }
/* ================= R_AddSkySurface ================= */ void R_AddSkySurface( mface_t *fa ) { int i; vec3_t verts[MAX_CLIP_VERTS]; msurfedge_t *surfedge; mvertex_t *vert; medge_t *edge; if( fa->numsurfedges > MAX_CLIP_VERTS ) { Com_Error( ERR_DROP, "%s: too many verts", __func__ ); } // calculate vertex values for sky box surfedge = fa->firstsurfedge; for( i = 0; i < fa->numsurfedges; i++, surfedge++ ) { edge = surfedge->edge; vert = edge->v[surfedge->vert]; VectorSubtract (vert->point, glr.fd.vieworg, verts[i]); } ClipSkyPolygon (fa->numsurfedges, verts[0], 0); }
/* * R_ClipSkySurface */ bool R_ClipSkySurface( drawSurfaceSky_t *drawSurf, const msurface_t *surf ) { int i; const vec4_t *vert; const elem_t *elem; const mesh_t *mesh; vec3_t verts[4]; int axis = -1; // calculate vertex values for sky box mesh = &surf->mesh; elem = mesh->elems; vert = mesh->xyzArray; for( i = 0; i < mesh->numElems; i += 3, elem += 3 ) { VectorSubtract( vert[elem[0]], rn.viewOrigin, verts[0] ); VectorSubtract( vert[elem[1]], rn.viewOrigin, verts[1] ); VectorSubtract( vert[elem[2]], rn.viewOrigin, verts[2] ); ClipSkyPolygon( drawSurf, 3, verts[0], 0, &axis ); } return axis != -1; }
/* * R_AddSkyToDrawList */ void R_AddSkyToDrawList( const msurface_t *fa ) { int i; vec3_t *vert; elem_t *elem; mesh_t *mesh; vec3_t verts[4]; // calculate vertex values for sky box r_warpFace = fa; r_warpFaceVis = qfalse; mesh = fa->mesh; elem = mesh->elems; vert = mesh->xyzArray; for( i = 0; i < mesh->numElems; i += 3, elem += 3 ) { VectorSubtract( vert[elem[0]], rn.viewOrigin, verts[0] ); VectorSubtract( vert[elem[1]], rn.viewOrigin, verts[1] ); VectorSubtract( vert[elem[2]], rn.viewOrigin, verts[2] ); ClipSkyPolygon( 3, verts[0], 0 ); } if( r_warpFaceVis ) { if( fa->fog ) { rn.skyFog = fa->fog; } else if( r_worldbrushmodel->globalfog ) { rn.skyFog = r_worldbrushmodel->globalfog; } // there should be only one sky drawSurf in the list if( !rn.skyShader ) { rn.skyShader = fa->shader; R_AddDSurfToDrawList( rsc.worldent, NULL, fa->shader, 0, r_warpFaceAxis, NULL, &r_skySurf ); } } }
/* ================ ClipSkyPolygon ================ */ static void ClipSkyPolygon (int nump, bvec3_t vecs, int stage) { bfixed *norm; bfixed *v; qboolean front, back; bfixed d, e; bfixed dists[MAX_CLIP_VERTS]; int sides[MAX_CLIP_VERTS]; bvec3_t newv[2][MAX_CLIP_VERTS]; int newc[2]; int i, j; if (nump > MAX_CLIP_VERTS-2) ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS"); if (stage == 6) { // fully clipped, so draw it AddSkyPolygon (nump, vecs); return; } front = back = qfalse; norm = sky_clip[stage]; for (i=0, v = vecs ; i<nump ; i++, v+=3) { d = FIXED_VEC3DOT (v, norm); if (d > ON_EPSILON) { front = qtrue; sides[i] = SIDE_FRONT; } else if (d < -ON_EPSILON) { back = qtrue; sides[i] = SIDE_BACK; } else sides[i] = SIDE_ON; dists[i] = d; } if (!front || !back) { // not clipped ClipSkyPolygon (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_ON: VectorCopy (v, newv[0][newc[0]]); newc[0]++; VectorCopy (v, newv[1][newc[1]]); newc[1]++; break; } if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || 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 ClipSkyPolygon (newc[0], newv[0][0], stage+1); ClipSkyPolygon (newc[1], newv[1][0], stage+1); }
static void ClipSkyPolygon (int nump, vec3_t vecs, int stage) { float *norm; float *v; qboolean 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) Sys_Error ("%s: MAX_CLIP_VERTS", __thisfunc__); if (stage == 6) { // fully clipped, so draw it DrawSkyPolygon (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_ON; dists[i] = d; } if (!front || !back) { // not clipped ClipSkyPolygon (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_ON: VectorCopy (v, newv[0][newc[0]]); newc[0]++; VectorCopy (v, newv[1][newc[1]]); newc[1]++; break; } if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || 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 ClipSkyPolygon (newc[0], newv[0][0], stage+1); ClipSkyPolygon (newc[1], newv[1][0], stage+1); }
void Sky_Render(DrawCallList *drawCallList, vec3 cameraPosition, float zMax, const SkySurface &surface) { assert(drawCallList); const bool shouldDrawSkyBox = surface.material->sky.outerbox[0] && surface.material->sky.outerbox[0] != Texture::getDefault(); const bool shouldDrawCloudBox = surface.material->sky.cloudHeight > 0 && surface.material->stages[0].active; if (!shouldDrawSkyBox && !shouldDrawCloudBox) return; // Clear sky box. for (size_t i = 0; i < 6; i++) { sky_mins[0][i] = sky_mins[1][i] = 9999; sky_maxs[0][i] = sky_maxs[1][i] = -9999; } // Clip sky polygons. for (size_t i = 0; i < surface.vertices.size(); i += 3) { vec3 p[5]; // need one extra point for clipping for (size_t j = 0 ; j < 3 ; j++) { p[j] = surface.vertices[i + j].pos - cameraPosition; } ClipSkyPolygon(3, p, 0); } // Draw the skybox. if (shouldDrawSkyBox) { for (int i = 0; i < 6; i++) { uint32_t nVertices, nIndices; sky_min = 0; sky_max = 1; memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) ); if (!TessellateSkyBoxSide(i, nullptr, nullptr, &nVertices, &nIndices, cameraPosition, zMax)) continue; DrawCall dc; if (!bgfx::allocTransientBuffers(&dc.vb.transientHandle, Vertex::decl, nVertices, &dc.ib.transientHandle, nIndices)) { WarnOnce(WarnOnceId::TransientBuffer); return; } sky_min = 0; sky_max = 1; memset( s_skyTexCoords, 0, sizeof( s_skyTexCoords ) ); TessellateSkyBoxSide(i, (Vertex *)dc.vb.transientHandle.data, (uint16_t *)dc.ib.transientHandle.data, nullptr, nullptr, cameraPosition, zMax); dc.vb.type = dc.ib.type = DrawCall::BufferType::Transient; dc.vb.nVertices = nVertices; dc.ib.nIndices = nIndices; dc.flags = DrawCallFlags::Sky | DrawCallFlags::Skybox; dc.material = surface.material; dc.skyboxSide = i; dc.state |= BGFX_STATE_DEPTH_TEST_LEQUAL; // Write depth as 1. dc.zOffset = 1.0f; dc.zScale = 0.0f; drawCallList->push_back(dc); } } // Draw the clouds. if (shouldDrawCloudBox) { uint32_t nVertices, nIndices; TessellateCloudBox(nullptr, nullptr, &nVertices, &nIndices, cameraPosition, zMax); DrawCall dc; if (!bgfx::allocTransientBuffers(&dc.vb.transientHandle, Vertex::decl, nVertices, &dc.ib.transientHandle, nIndices)) { WarnOnce(WarnOnceId::TransientBuffer); return; } TessellateCloudBox((Vertex *)dc.vb.transientHandle.data, (uint16_t *)dc.ib.transientHandle.data, nullptr, nullptr, cameraPosition, zMax); dc.vb.type = dc.ib.type = DrawCall::BufferType::Transient; dc.vb.nVertices = nVertices; dc.ib.nIndices = nIndices; dc.flags = DrawCallFlags::Sky; dc.material = surface.material; dc.sort = 1; // Render after the skybox. // Write depth as 1. dc.zOffset = 1.0f; dc.zScale = 0.0f; drawCallList->push_back(dc); } }
static void ClipSkyPolygon(int nump, vec3 *vecs, int stage) { bool front, back; float d, e; float dists[MAX_CLIP_VERTS]; int sides[MAX_CLIP_VERTS]; vec3 newv[2][MAX_CLIP_VERTS]; int newc[2]; int i, j; if (nump > MAX_CLIP_VERTS-2) interface::Error("ClipSkyPolygon: MAX_CLIP_VERTS"); if (stage == 6) { // fully clipped, so draw it AddSkyPolygon (nump, vecs); return; } front = back = false; for (i=0; i<nump ; i++) { d = vec3::dotProduct(vecs[i], sky_clip[stage]); 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_ON; dists[i] = d; } if (!front || !back) { // not clipped ClipSkyPolygon (nump, vecs, stage+1); return; } // clip it sides[i] = sides[0]; dists[i] = dists[0]; vecs[i] = vecs[0]; newc[0] = newc[1] = 0; for (i=0; i<nump ; i++) { const vec3 &v = vecs[i]; switch (sides[i]) { case SIDE_FRONT: newv[0][newc[0]] = v; newc[0]++; break; case SIDE_BACK: newv[1][newc[1]] = v; newc[1]++; break; case SIDE_ON: newv[0][newc[0]] = v; newc[0]++; newv[1][newc[1]] = v; newc[1]++; break; } if (sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || sides[i+1] == sides[i]) continue; d = dists[i] / (dists[i] - dists[i+1]); for (j=0 ; j<3 ; j++) { e = v[j] + d*(vecs[i + 1][j] - v[j]); newv[0][newc[0]][j] = e; newv[1][newc[1]][j] = e; } newc[0]++; newc[1]++; } // continue ClipSkyPolygon(newc[0], &newv[0][0], stage+1); ClipSkyPolygon(newc[1], &newv[1][0], stage+1); }
/* * ClipSkyPolygon */ static void ClipSkyPolygon( drawSurfaceSky_t *drawSurf, int nump, vec_t *vecs, int stage, int *visAxis ) { const float *norm; float *v; bool front, back; float d, e; float dists[MAX_CLIP_VERTS + 1]; int sides[MAX_CLIP_VERTS + 1]; vec3_t newv[2][MAX_CLIP_VERTS + 1]; int newc[2]; int i, j; if( nump > MAX_CLIP_VERTS ) { ri.Com_Error( ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS" ); return; } loc1: if( stage == 6 ) { // fully clipped, so draw it DrawSkyPolygon( drawSurf, nump, vecs, visAxis ); 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_ON; } dists[i] = d; } if( !front || !back ) { // not clipped stage++; goto loc1; } // 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_ON: VectorCopy( v, newv[0][newc[0]] ); newc[0]++; VectorCopy( v, newv[1][newc[1]] ); newc[1]++; break; } if( sides[i] == SIDE_ON || sides[i + 1] == SIDE_ON || 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 ClipSkyPolygon( drawSurf, newc[0], newv[0][0], stage + 1, visAxis ); ClipSkyPolygon( drawSurf, newc[1], newv[1][0], stage + 1, visAxis ); }
/* * ClipSkyPolygon */ static void ClipSkyPolygon(int nump, Vec3 vecs, int stage) { float *norm; float *v; qbool front, back; float d, e; float dists[MAX_CLIP_VERTS]; int sides[MAX_CLIP_VERTS]; Vec3 newv[2][MAX_CLIP_VERTS]; int newc[2]; int i, j; if(nump > MAX_CLIP_VERTS-2) ri.Error (ERR_DROP, "ClipSkyPolygon: MAX_CLIP_VERTS"); if(stage == 6){ /* fully clipped, so draw it */ AddSkyPolygon (nump, vecs); return; } front = back = qfalse; norm = sky_clip[stage]; for(i=0, v = vecs; i<nump; i++, v+=3){ d = dotv3 (v, norm); if(d > ON_EPSILON){ front = qtrue; sides[i] = SIDE_FRONT; }else if(d < -ON_EPSILON){ back = qtrue; sides[i] = SIDE_BACK; }else sides[i] = SIDE_ON; dists[i] = d; } if(!front || !back){ /* not clipped */ ClipSkyPolygon (nump, vecs, stage+1); return; } /* clip it */ sides[i] = sides[0]; dists[i] = dists[0]; copyv3 (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: copyv3 (v, newv[0][newc[0]]); newc[0]++; break; case SIDE_BACK: copyv3 (v, newv[1][newc[1]]); newc[1]++; break; case SIDE_ON: copyv3 (v, newv[0][newc[0]]); newc[0]++; copyv3 (v, newv[1][newc[1]]); newc[1]++; break; } if(sides[i] == SIDE_ON || sides[i+1] == SIDE_ON || 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 */ ClipSkyPolygon (newc[0], newv[0][0], stage+1); ClipSkyPolygon (newc[1], newv[1][0], stage+1); }