📄 gl_rsurf.pas
字号:
Exit;
end; //if
// node is just a decision point, so go down the apropriate sides
// find which side of the node we are on
plane := node^.plane;
case plane^._type of
PLANE_X: dot := modelorg[0] - plane.dist;
PLANE_Y: dot := modelorg[1] - plane.dist;
PLANE_Z: dot := modelorg[2] - plane.dist;
else
dot := DotProduct(modelorg, plane^.normal) - plane^.dist;
end;
if (dot >= 0) then
begin
side := 0;
sidebit := 0;
end
else
begin
side := 1;
sidebit := SURF_PLANEBACK;
end;
// recurse down the children, front side first
R_RecursiveWorldNode(node^.children[side]);
// draw stuff
c := node^.numsurfaces;
surf := @r_worldmodel^.surfaces^[node^.firstsurface];
while (c <> 0) do
begin
if (surf.visframe <> r_framecount) then
goto Continue_;
if ((surf^.flags and SURF_PLANEBACK) <> sidebit) then
goto Continue_; // wrong side
if (surf^.texinfo^.flags and SURF_SKY) <> 0 then
begin
// just adds to visible sky bounds
R_AddSkySurface(surf);
end
else
if (surf^.texinfo^.flags and (SURF_TRANS33 or SURF_TRANS66) <> 0) then
begin
// add to the translucent chain
surf^.texturechain := r_alpha_surfaces;
r_alpha_surfaces := surf;
end
else
begin
if (Assigned(qglMTexCoord2fSGIS) and ((surf^.flags and SURF_DRAWTURB) = 0)) then
GL_RenderLightmappedPoly(surf)
else
begin
// 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;
end;
end;
Continue_:
Dec(c);
Inc(surf);
end;
// recurse down the back side
if side = 0 then
notside_ := 1
else
notside_ := 0;
R_RecursiveWorldNode(node.children[notside_]);
(*Id Software /*
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;
}
}
}
*/*)
end; //procedure
{*
=============
R_DrawWorld
=============
*}
procedure R_DrawWorld; //for gl_rmain
var
ent: entity_t;
begin
if (r_drawworld_.value = 0) then
Exit;
if (r_newrefdef.rdflags and RDF_NOWORLDMODEL) <> 0 then
Exit;
currentmodel := r_worldmodel;
VectorCopy(vec3_t(r_newrefdef.vieworg), modelorg);
// auto cycle the world frame for texture animation
memset(@ent, 0, sizeof(ent));
ent.frame := Trunc(r_newrefdef.time * 2);
currententity := @ent;
gl_state.currenttextures[0] := -1;
gl_state.currenttextures[1] := -1;
qglColor3f(1, 1, 1);
memset(@gl_lms.lightmap_surfaces, 0, sizeof(gl_lms.lightmap_surfaces));
R_ClearSkyBox();
if Assigned(qglMTexCoord2fSGIS) then
begin
GL_EnableMultitexture(true);
GL_SelectTexture(GL_TEXTURE0);
GL_TexEnv(GL_REPLACE);
GL_SelectTexture(GL_TEXTURE1);
if (gl_lightmap.value <> 0) then
GL_TexEnv(GL_REPLACE)
else
GL_TexEnv(GL_MODULATE);
R_RecursiveWorldNode(r_worldmodel^.nodes);
GL_EnableMultitexture(false);
end
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();
end; //procedure
{*
===============
R_MarkLeaves
Mark the leaves and nodes that are in the PVS for the current
cluster
===============
*}
procedure R_MarkLeaves; //for gl_rmain
var
vis: PByte;
fatvis: array[0..MAX_MAP_LEAFS div 8 - 1] of byte;
node: mnode_p;
i, c,
cluster: integer;
leaf: mleaf_p;
label
continue_;
begin
if (r_oldviewcluster = r_viewcluster) and (r_oldviewcluster2 = r_viewcluster2) and
(r_novis.value = 0) and (r_viewcluster <> -1) then
Exit;
// development aid to let you run around and see exactly where
// the pvs ends
if (gl_lockpvs^.value <> 0) then
Exit;
Inc(r_visframecount);
r_oldviewcluster := r_viewcluster;
r_oldviewcluster2 := r_viewcluster2;
if (r_novis^.value <> 0) or (r_viewcluster = -1) or (r_worldmodel.vis = nil) then
begin
// mark everything
for i := 0 to r_worldmodel.numleafs - 1 do
mLeaf_arrp(r_worldmodel.leafs)[i].visframe := r_visframecount;
for i := 0 to r_worldmodel.numnodes - 1 do
mNode_arrp(r_worldmodel.nodes)[i].visframe := r_visframecount;
Exit;
end;
vis := Mod_ClusterPVS(r_viewcluster, r_worldmodel);
// may have to combine two clusters because of solid water boundaries
if (r_viewcluster2 <> r_viewcluster) then
begin
memcpy(@fatvis, vis, (r_worldmodel.numleafs + 7) div 8);
vis := Mod_ClusterPVS(r_viewcluster2, r_worldmodel);
c := (r_worldmodel.numleafs + 31) div 32;
for i := 0 to c - 1 do
PIntegerArray(@fatvis)^[i] := PIntegerArray(@fatvis)^[i] or PIntegerArray(vis)^[i];
vis := @fatvis;
end;
leaf := r_worldmodel^.leafs;
for i := 0 to r_worldmodel^.numleafs - 1 do
begin
cluster := leaf^.cluster;
if (cluster = -1) then
goto continue_;
if (PByteArray(vis)^[cluster shr 3] and (1 shl (cluster and 7))) <> 0 then
begin
node := mnode_p(leaf);
repeat
if (node.visframe = r_visframecount) then
Break;
node.visframe := r_visframecount;
node := node.parent;
until node = nil;
end;
continue_:
Inc(leaf);
end;
(*
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);
}
}
*)
end; //procedure
{*
=============================================================================
LIGHTMAP ALLOCATION
=============================================================================
*}
procedure {static} LM_InitBlock;
begin
FillChar(gl_lms.allocated, sizeof(gl_lms.allocated), 0);
end; //procedure
procedure {static} LM_UploadBlock(dynamic_: qboolean);
var
texture, i,
height: integer;
begin
height := 0;
if dynamic_ then
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_ then
begin
for i := 0 to BLOCK_WIDTH - 1 do
if (gl_lms.allocated[i] > height) then
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);
end
else
begin
qglTexImage2D(GL_TEXTURE_2D,
0,
gl_lms.internal_format,
BLOCK_WIDTH, BLOCK_HEIGHT,
0,
GL_LIGHTMAP_FORMAT,
GL_UNSIGNED_BYTE,
@gl_lms.lightmap_buffer);
Inc(gl_lms.current_lightmap_texture);
if (gl_lms.current_lightmap_texture = MAX_LIGHTMAPS) then
ri.Sys_Error(ERR_DROP, 'LM_UploadBlock() - MAX_LIGHTMAPS exceeded'#10, []);
end;
end; //procedure
// returns a texture number and the position inside it
function {static} LM_AllocBlock(w, h: integer; var x, y: integer): qboolean;
var
i, j,
best, best2: integer;
begin
best := BLOCK_HEIGHT;
for i := 0 to BLOCK_WIDTH - w - 1 do
begin
best2 := 0;
j := 0;
while (j < w) do
begin
if (gl_lms.allocated[i + j] >= best) then
Break;
if (gl_lms.allocated[i + j] > best2) then
best2 := gl_lms.allocated[i + j];
inc(j);
end;
if (j = w) then
begin
// this is a valid spot
x := i;
best := best2;
y := best;
end;
end; //for
if (best + h > BLOCK_HEIGHT) then
begin
Result := false;
Exit;
end;
for i := 0 to w - 1 do
gl_lms.allocated[{*} x + i] := best + h;
Result := true;
end; //function
{*
================
GL_BuildPolygonFromSurface
================
*}
procedure GL_BuildPolygonFromSurface(fa: msurface_p);
var
i, lindex,
lnumverts,
vertpage: integer;
pedges,
r_pedge: medge_p;
vec: vec3_t;
s, t: Single;
poly: glpoly_p;
total: vec3_t;
begin
// reconstruct the polygon
pedges := medge_p(currentmodel^.edges);
lnumverts := fa^.numedges;
vertpage := 0;
VectorClear(total);
//
// draw texture
//
poly := Hunk_Alloc(sizeof(glpoly_t) + (lnumverts - 4) * VERTEXSIZE * sizeof(Single));
poly^.next := fa^.polys;
poly^.flags := fa^.flags;
fa^.polys := poly;
poly^.numverts := lnumverts;
for i := 0 to lnumverts - 1 do
begin
lindex := PIntegerArray(currentmodel^.surfedges)^[fa^.firstedge + i];
if (lindex > 0) then
begin
r_pedge := @mEdge_arrp(pedges)^[lindex];
vec := currentmodel^.vertexes[r_pedge^.v[0]].position;
end
else
begin
r_pedge := @mEdge_arrp(pedges)^[-lindex];
vec := currentmodel^.vertexes[r_pedge^.v[1]].position;
end;
s := DotProduct(vec, vec3_p(@fa^.texinfo^.vecs[0])^) + fa^.texinfo^.vecs[0][3];
s := s / fa^.texinfo^.image^.width;
t := DotProduct(vec, vec3_p(@fa^.texinfo^.vecs[1])^) + fa^.texinfo^.vecs[1][3];
t := t / fa^.texinfo^.image^.height;
VectorAdd(total, vec, total);
VectorCopy(vec, vec3_t(vec3_p(@poly^.verts[i])^));
poly.verts[i][3] := s;
poly.verts[i][4] := t;
//
// lightmap texture coordinates
//
s := DotProduct(vec, vec3_p(@fa^.texinfo^.vecs[0])^) + fa^.texinfo^.vecs[0][3];
s := s - fa^.texturemins[0];
s := s + fa^.light_s * 16;
s := s + 8;
s := s / (BLOCK_WIDTH * 16); //fa->texinfo->texture->width;
t := DotProduct(vec, vec3_p(@fa^.texinfo^.vecs[1])^) + fa^.texinfo^.vecs[1][3];
t := t - fa^.texturemins[1];
t := t + fa^.light_t * 16;
t := t + 8;
t := t / (BLOCK_HEIGHT * 16); //fa->texinfo->texture->height;
poly^.verts[i][5] := s;
poly^.verts[i][6] := t;
end; //for
poly^.numverts := lnumverts;
end; //procedure
{*
========================
GL_CreateSurfaceLightmap
========================
*}
procedure GL_CreateSurfaceLightmap(surf: msurface_p);
var
smax, tmax: integer;
base: PByte;
begin
if (surf.flags and (SURF_DRAWSKY or SURF_DRAWTURB) <> 0) then
Exit;
smax := (surf.extents[0] shr 4) + 1;
tmax := (surf.extents[1] shr 4) + 1;
if (not LM_AllocBlock(smax, tmax, surf^.light_s, surf^.light_t)) then
begin
LM_UploadBlock(false);
LM_InitBlock();
if (not LM_AllocBlock(smax, tmax, surf^.light_s, surf^.light_t)) then
ri.Sys_Error(ERR_FATAL, 'Consecutive calls to LM_AllocBlock(%d,%d) failed'#10, [smax, tmax]);
end;
surf^.lightmaptexturenum := gl_lms.current_lightmap_texture;
base := @gl_lms.lightmap_buffer;
Inc(base, (surf^.light_t * BLOCK_WIDTH + surf^.light_s) * LIGHTMAP_BYTES);
R_SetCacheState(surf);
R_BuildLightMap(surf, PByteArray(base), BLOCK_WIDTH * LIGHTMAP_BYTES);
end; //procedure
{*
==================
GL_BeginBuildingLightmaps
==================
*}
var
lightstyles: array[0..MAX_LIGHTSTYLES - 1] of lightstyle_t;
procedure GL_BeginBuildingLightmaps(m: model_p); //for gl_model
// static lightstyle_t lightstyles[MAX_LIGHTSTYLES];
var
i: integer;
dummy: array[0..128 * 128 - 1] of Cardinal;
begin
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 to MAX_LIGHTSTYLES - 1 do
begin
lightstyles[i].rgb[0] := 1;
lightstyles[i].rgb[1] := 1;
lightstyles[i].rgb[2] := 1;
lightstyles[i].white := 3;
end;
r_newrefdef.lightstyles := @lightstyles;
if (gl_state.lightmap_textures = 0) then
begin
gl_state.lightmap_textures := TEXNUM_LIGHTMAPS;
//idsoft gl_state.lightmap_textures = gl_state.texture_extension_number;
//idsoft gl_state.texture_extension_number = gl_state.lightmap_textures + MAX_LIGHTMAPS;
end;
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' )
if UpCase(gl_monolightmap.string_[0]) = 'A' then
begin
gl_lms.internal_format := gl_tex_alpha_format;
end
{*
** try to do hacked colored lighting with a blended texture
*}
else
if UpCase(gl_monolightmap.string_[0]) = 'C' then
gl_lms.internal_format := gl_tex_alpha_format
else
if UpCase(gl_monolightmap.string_[0]) = 'I' then
gl_lms.internal_format := GL_INTENSITY8
else
if UpCase(gl_monolightmap.string_[0]) = 'L' then
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);
end; //procedure
{*
=======================
GL_EndBuildingLightmaps
=======================
*}
procedure GL_EndBuildingLightmaps; //for gl_model
begin
LM_UploadBlock(false);
GL_EnableMultitexture(false);
end; //procedure
// End of file
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -