📄 gl_rsurf.c
字号:
// recurse down the children, front side first
R_RecursiveWorldNode (node->children[side]);
// draw stuff
for ( c = node->numsurfaces, surf = r_worldmodel->surfaces + node->firstsurface; c ; c--, surf++)
{
if (surf->visframe != r_framecount)
continue;
if ( (surf->flags & SURF_PLANEBACK) != sidebit )
continue; // wrong side
if (surf->texinfo->flags & SURF_SKY)
{ // just adds to visible sky bounds
R_AddSkySurface (surf);
}
else if (surf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
{ // add to the translucent chain
surf->texturechain = r_alpha_surfaces;
r_alpha_surfaces = surf;
}
else
{
if ( qglMTexCoord2fSGIS && !( surf->flags & SURF_DRAWTURB ) )
{
GL_RenderLightmappedPoly( surf );
}
else
{
// the polygon is visible, so add it to the texture
// sorted chain
// FIXME: this is a hack for animation
image = R_TextureAnimation (surf->texinfo);
surf->texturechain = image->texturechain;
image->texturechain = surf;
}
}
}
// recurse down the back side
R_RecursiveWorldNode (node->children[!side]);
/*
for ( ; c ; c--, surf++)
{
if (surf->visframe != r_framecount)
continue;
if ( (surf->flags & SURF_PLANEBACK) != sidebit )
continue; // wrong side
if (surf->texinfo->flags & SURF_SKY)
{ // just adds to visible sky bounds
R_AddSkySurface (surf);
}
else if (surf->texinfo->flags & (SURF_TRANS33|SURF_TRANS66))
{ // add to the translucent chain
// surf->texturechain = alpha_surfaces;
// alpha_surfaces = surf;
}
else
{
if ( qglMTexCoord2fSGIS && !( surf->flags & SURF_DRAWTURB ) )
{
GL_RenderLightmappedPoly( surf );
}
else
{
// the polygon is visible, so add it to the texture
// sorted chain
// FIXME: this is a hack for animation
image = R_TextureAnimation (surf->texinfo);
surf->texturechain = image->texturechain;
image->texturechain = surf;
}
}
}
*/
}
/*
=============
R_DrawWorld
=============
*/
void R_DrawWorld (void)
{
entity_t ent;
if (!r_drawworld->value)
return;
if ( r_newrefdef.rdflags & RDF_NOWORLDMODEL )
return;
currentmodel = r_worldmodel;
VectorCopy (r_newrefdef.vieworg, modelorg);
// auto cycle the world frame for texture animation
memset (&ent, 0, sizeof(ent));
ent.frame = (int)(r_newrefdef.time*2);
currententity = &ent;
gl_state.currenttextures[0] = gl_state.currenttextures[1] = -1;
qglColor3f (1,1,1);
memset (gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces));
R_ClearSkyBox ();
if ( qglMTexCoord2fSGIS )
{
GL_EnableMultitexture( true );
GL_SelectTexture( GL_TEXTURE0);
GL_TexEnv( GL_REPLACE );
GL_SelectTexture( GL_TEXTURE1);
if ( gl_lightmap->value )
GL_TexEnv( GL_REPLACE );
else
GL_TexEnv( GL_MODULATE );
R_RecursiveWorldNode (r_worldmodel->nodes);
GL_EnableMultitexture( false );
}
else
{
R_RecursiveWorldNode (r_worldmodel->nodes);
}
/*
** theoretically nothing should happen in the next two functions
** if multitexture is enabled
*/
DrawTextureChains ();
R_BlendLightmaps ();
R_DrawSkyBox ();
R_DrawTriangleOutlines ();
}
/*
===============
R_MarkLeaves
Mark the leaves and nodes that are in the PVS for the current
cluster
===============
*/
void R_MarkLeaves (void)
{
byte *vis;
byte fatvis[MAX_MAP_LEAFS/8];
mnode_t *node;
int i, c;
mleaf_t *leaf;
int cluster;
if (r_oldviewcluster == r_viewcluster && r_oldviewcluster2 == r_viewcluster2 && !r_novis->value && r_viewcluster != -1)
return;
// development aid to let you run around and see exactly where
// the pvs ends
if (gl_lockpvs->value)
return;
r_visframecount++;
r_oldviewcluster = r_viewcluster;
r_oldviewcluster2 = r_viewcluster2;
if (r_novis->value || r_viewcluster == -1 || !r_worldmodel->vis)
{
// mark everything
for (i=0 ; i<r_worldmodel->numleafs ; i++)
r_worldmodel->leafs[i].visframe = r_visframecount;
for (i=0 ; i<r_worldmodel->numnodes ; i++)
r_worldmodel->nodes[i].visframe = r_visframecount;
return;
}
vis = Mod_ClusterPVS (r_viewcluster, r_worldmodel);
// may have to combine two clusters because of solid water boundaries
if (r_viewcluster2 != r_viewcluster)
{
memcpy (fatvis, vis, (r_worldmodel->numleafs+7)/8);
vis = Mod_ClusterPVS (r_viewcluster2, r_worldmodel);
c = (r_worldmodel->numleafs+31)/32;
for (i=0 ; i<c ; i++)
((int *)fatvis)[i] |= ((int *)vis)[i];
vis = fatvis;
}
for (i=0,leaf=r_worldmodel->leafs ; i<r_worldmodel->numleafs ; i++, leaf++)
{
cluster = leaf->cluster;
if (cluster == -1)
continue;
if (vis[cluster>>3] & (1<<(cluster&7)))
{
node = (mnode_t *)leaf;
do
{
if (node->visframe == r_visframecount)
break;
node->visframe = r_visframecount;
node = node->parent;
} while (node);
}
}
#if 0
for (i=0 ; i<r_worldmodel->vis->numclusters ; i++)
{
if (vis[i>>3] & (1<<(i&7)))
{
node = (mnode_t *)&r_worldmodel->leafs[i]; // FIXME: cluster
do
{
if (node->visframe == r_visframecount)
break;
node->visframe = r_visframecount;
node = node->parent;
} while (node);
}
}
#endif
}
/*
=============================================================================
LIGHTMAP ALLOCATION
=============================================================================
*/
static void LM_InitBlock( void )
{
memset( gl_lms.allocated, 0, sizeof( gl_lms.allocated ) );
}
static void LM_UploadBlock( qboolean dynamic )
{
int texture;
int height = 0;
if ( dynamic )
{
texture = 0;
}
else
{
texture = gl_lms.current_lightmap_texture;
}
GL_Bind( gl_state.lightmap_textures + texture );
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if ( dynamic )
{
int i;
for ( i = 0; i < BLOCK_WIDTH; i++ )
{
if ( gl_lms.allocated[i] > height )
height = gl_lms.allocated[i];
}
qglTexSubImage2D( GL_TEXTURE_2D,
0,
0, 0,
BLOCK_WIDTH, height,
GL_LIGHTMAP_FORMAT,
GL_UNSIGNED_BYTE,
gl_lms.lightmap_buffer );
}
else
{
qglTexImage2D( GL_TEXTURE_2D,
0,
gl_lms.internal_format,
BLOCK_WIDTH, BLOCK_HEIGHT,
0,
GL_LIGHTMAP_FORMAT,
GL_UNSIGNED_BYTE,
gl_lms.lightmap_buffer );
if ( ++gl_lms.current_lightmap_texture == MAX_LIGHTMAPS )
ri.Sys_Error( ERR_DROP, "LM_UploadBlock() - MAX_LIGHTMAPS exceeded\n" );
}
}
// returns a texture number and the position inside it
static qboolean LM_AllocBlock (int w, int h, int *x, int *y)
{
int i, j;
int best, best2;
best = BLOCK_HEIGHT;
for (i=0 ; i<BLOCK_WIDTH-w ; i++)
{
best2 = 0;
for (j=0 ; j<w ; j++)
{
if (gl_lms.allocated[i+j] >= best)
break;
if (gl_lms.allocated[i+j] > best2)
best2 = gl_lms.allocated[i+j];
}
if (j == w)
{ // this is a valid spot
*x = i;
*y = best = best2;
}
}
if (best + h > BLOCK_HEIGHT)
return false;
for (i=0 ; i<w ; i++)
gl_lms.allocated[*x + i] = best + h;
return true;
}
/*
================
GL_BuildPolygonFromSurface
================
*/
void GL_BuildPolygonFromSurface(msurface_t *fa)
{
int i, lindex, lnumverts;
medge_t *pedges, *r_pedge;
int vertpage;
float *vec;
float s, t;
glpoly_t *poly;
vec3_t total;
// reconstruct the polygon
pedges = currentmodel->edges;
lnumverts = fa->numedges;
vertpage = 0;
VectorClear (total);
//
// draw texture
//
poly = Hunk_Alloc (sizeof(glpoly_t) + (lnumverts-4) * VERTEXSIZE*sizeof(float));
poly->next = fa->polys;
poly->flags = fa->flags;
fa->polys = poly;
poly->numverts = lnumverts;
for (i=0 ; i<lnumverts ; i++)
{
lindex = currentmodel->surfedges[fa->firstedge + i];
if (lindex > 0)
{
r_pedge = &pedges[lindex];
vec = currentmodel->vertexes[r_pedge->v[0]].position;
}
else
{
r_pedge = &pedges[-lindex];
vec = currentmodel->vertexes[r_pedge->v[1]].position;
}
s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s /= fa->texinfo->image->width;
t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t /= fa->texinfo->image->height;
VectorAdd (total, vec, total);
VectorCopy (vec, poly->verts[i]);
poly->verts[i][3] = s;
poly->verts[i][4] = t;
//
// lightmap texture coordinates
//
s = DotProduct (vec, fa->texinfo->vecs[0]) + fa->texinfo->vecs[0][3];
s -= fa->texturemins[0];
s += fa->light_s*16;
s += 8;
s /= BLOCK_WIDTH*16; //fa->texinfo->texture->width;
t = DotProduct (vec, fa->texinfo->vecs[1]) + fa->texinfo->vecs[1][3];
t -= fa->texturemins[1];
t += fa->light_t*16;
t += 8;
t /= BLOCK_HEIGHT*16; //fa->texinfo->texture->height;
poly->verts[i][5] = s;
poly->verts[i][6] = t;
}
poly->numverts = lnumverts;
}
/*
========================
GL_CreateSurfaceLightmap
========================
*/
void GL_CreateSurfaceLightmap (msurface_t *surf)
{
int smax, tmax;
byte *base;
if (surf->flags & (SURF_DRAWSKY|SURF_DRAWTURB))
return;
smax = (surf->extents[0]>>4)+1;
tmax = (surf->extents[1]>>4)+1;
if ( !LM_AllocBlock( smax, tmax, &surf->light_s, &surf->light_t ) )
{
LM_UploadBlock( false );
LM_InitBlock();
if ( !LM_AllocBlock( smax, tmax, &surf->light_s, &surf->light_t ) )
{
ri.Sys_Error( ERR_FATAL, "Consecutive calls to LM_AllocBlock(%d,%d) failed\n", smax, tmax );
}
}
surf->lightmaptexturenum = gl_lms.current_lightmap_texture;
base = gl_lms.lightmap_buffer;
base += (surf->light_t * BLOCK_WIDTH + surf->light_s) * LIGHTMAP_BYTES;
R_SetCacheState( surf );
R_BuildLightMap (surf, base, BLOCK_WIDTH*LIGHTMAP_BYTES);
}
/*
==================
GL_BeginBuildingLightmaps
==================
*/
void GL_BeginBuildingLightmaps (model_t *m)
{
static lightstyle_t lightstyles[MAX_LIGHTSTYLES];
int i;
unsigned dummy[128*128];
memset( gl_lms.allocated, 0, sizeof(gl_lms.allocated) );
r_framecount = 1; // no dlightcache
GL_EnableMultitexture( true );
GL_SelectTexture( GL_TEXTURE1);
/*
** setup the base lightstyles so the lightmaps won't have to be regenerated
** the first time they're seen
*/
for (i=0 ; i<MAX_LIGHTSTYLES ; i++)
{
lightstyles[i].rgb[0] = 1;
lightstyles[i].rgb[1] = 1;
lightstyles[i].rgb[2] = 1;
lightstyles[i].white = 3;
}
r_newrefdef.lightstyles = lightstyles;
if (!gl_state.lightmap_textures)
{
gl_state.lightmap_textures = TEXNUM_LIGHTMAPS;
// gl_state.lightmap_textures = gl_state.texture_extension_number;
// gl_state.texture_extension_number = gl_state.lightmap_textures + MAX_LIGHTMAPS;
}
gl_lms.current_lightmap_texture = 1;
/*
** if mono lightmaps are enabled and we want to use alpha
** blending (a,1-a) then we're likely running on a 3DLabs
** Permedia2. In a perfect world we'd use a GL_ALPHA lightmap
** in order to conserve space and maximize bandwidth, however
** this isn't a perfect world.
**
** So we have to use alpha lightmaps, but stored in GL_RGBA format,
** which means we only get 1/16th the color resolution we should when
** using alpha lightmaps. If we find another board that supports
** only alpha lightmaps but that can at least support the GL_ALPHA
** format then we should change this code to use real alpha maps.
*/
if ( toupper( gl_monolightmap->string[0] ) == 'A' )
{
gl_lms.internal_format = gl_tex_alpha_format;
}
/*
** try to do hacked colored lighting with a blended texture
*/
else if ( toupper( gl_monolightmap->string[0] ) == 'C' )
{
gl_lms.internal_format = gl_tex_alpha_format;
}
else if ( toupper( gl_monolightmap->string[0] ) == 'I' )
{
gl_lms.internal_format = GL_INTENSITY8;
}
else if ( toupper( gl_monolightmap->string[0] ) == 'L' )
{
gl_lms.internal_format = GL_LUMINANCE8;
}
else
{
gl_lms.internal_format = gl_tex_solid_format;
}
/*
** initialize the dynamic lightmap texture
*/
GL_Bind( gl_state.lightmap_textures + 0 );
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
qglTexImage2D( GL_TEXTURE_2D,
0,
gl_lms.internal_format,
BLOCK_WIDTH, BLOCK_HEIGHT,
0,
GL_LIGHTMAP_FORMAT,
GL_UNSIGNED_BYTE,
dummy );
}
/*
=======================
GL_EndBuildingLightmaps
=======================
*/
void GL_EndBuildingLightmaps (void)
{
LM_UploadBlock( false );
GL_EnableMultitexture( false );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -