⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gl_rsurf.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 3 页
字号:
{$ALIGN ON}{$MINENUMSIZE 4}
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): GL_RSURF.C: surface-related refresh code                          }
{                                                                            }
{ Initial conversion by : YgriK (Igor Karpov) - glYgriK@hotbox.ru            }
{ Initial conversion on : 16-Jan-2002                                        }
{                                                                            }
{ This File contains part of convertion of Quake2 source to ObjectPascal.    }
{ More information about this project can be found at:                       }
{ http://www.sulaco.co.za/quake2/                                            }
{                                                                            }
{ Copyright (C) 1997-2001 Id Software, Inc.                                  }
{                                                                            }
{ This program is free software; you can redistribute it and/or              }
{ modify it under the terms of the GNU General Public License                }
{ as published by the Free Software Foundation; either version 2             }
{ of the License, or (at your option) any later version.                     }
{                                                                            }
{ This program is distributed in the hope that it will be useful,            }
{ but WITHOUT ANY WARRANTY; without even the implied warranty of             }
{ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                       }
{                                                                            }
{ See the GNU General Public License for more details.                       }
{                                                                            }
{----------------------------------------------------------------------------}
// 28.06.2003 Juha: Proofreaded
// GL_RSURF.C: surface-related refresh code

unit gl_rsurf;

interface

uses
  q_shared,
  ref,
  qfiles,
  gl_local,
  OpenGL,
  qgl_win,
  gl_model_h,
  gl_rmain;

procedure R_DrawAlphaSurfaces;
procedure R_DrawBrushModel(e: entity_p);
procedure R_DrawWorld;
procedure R_MarkLeaves;

procedure GL_BuildPolygonFromSurface(fa: msurface_p);
procedure GL_CreateSurfaceLightmap(surf: msurface_p);
procedure GL_BeginBuildingLightmaps(m: model_p);
procedure GL_EndBuildingLightmaps;

var
  c_visible_lightmaps: Integer;
  c_visible_textures: Integer;


implementation

uses
  q_shwin,
  SysUtils,
  CPas,
  DelphiTypes,
  qgl_h,
  gl_light,
  gl_model,
  gl_warp,
  gl_image;

var
  modelorg: vec3_t; // relative to viewpoint
  r_alpha_surfaces: msurface_p;

const
  DYNAMIC_LIGHT_WIDTH = 128;
  DYNAMIC_LIGHT_HEIGHT = 128;

  LIGHTMAP_BYTES = 4;

  BLOCK_WIDTH = 128;
  BLOCK_HEIGHT = 128;

  MAX_LIGHTMAPS = 128;

  GL_LIGHTMAP_FORMAT = GL_RGBA;

type
  gllightmapstate_t = record
    internal_format: integer;
    current_lightmap_texture: integer;

    lightmap_surfaces: array[0..MAX_LIGHTMAPS - 1] of msurface_p;

    allocated: array[0..BLOCK_WIDTH - 1] of integer;

    // the lightmap texture data needs to be kept in
    // main memory so texsubimage can update properly
    lightmap_buffer: array[0..4 * BLOCK_WIDTH * BLOCK_HEIGHT - 1] of byte;
  end;

var
  gl_lms: gllightmapstate_t;


procedure LM_InitBlock; forward;
procedure LM_UploadBlock(dynamic_: qboolean); forward;
function LM_AllocBlock(w, h: integer; var x, y: integer): qboolean; forward;


{*
=============================================================

 BRUSH MODELS

=============================================================
*}

{*
===============
R_TextureAnimation

Returns the proper texture for a given time and base texture
===============
*}
function R_TextureAnimation(tex: mtexinfo_p): image_p;
var
  c: integer;
begin
  if (tex.next = nil) then
  begin
    Result := tex.image;
    Exit;
  end;

  c := currententity.frame mod tex.numframes;
  while (c <> 0) do
  begin
    tex := tex.next;
    Dec(c);
  end;

  Result := tex.image;
end; //function

(*
/*
=================
WaterWarpPolyVerts

Mangles the x and y coordinates in a copy of the poly
so that any drawing routine can be water warped
=================
*/
glpoly_t *WaterWarpPolyVerts (glpoly_t *p)
{
 int		i;
 float	*v, *nv;
 static byte	buffer[1024];
 glpoly_t *out;

 out = (glpoly_t * )buffer;

 out->numverts = p->numverts;
 v = p->verts[0];
 nv = out->verts[0];
 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE, nv+=VERTEXSIZE)
 {
  nv[0] = v[0] + 4*sin(v[1]*0.05+r_newrefdef.time)*sin(v[2]*0.05+r_newrefdef.time);
  nv[1] = v[1] + 4*sin(v[0]*0.05+r_newrefdef.time)*sin(v[2]*0.05+r_newrefdef.time);

  nv[2] = v[2];
  nv[3] = v[3];
  nv[4] = v[4];
  nv[5] = v[5];
  nv[6] = v[6];
 }

 return out;
}

/*
================
DrawGLWaterPoly

Warp the vertex coordinates
================
*/
void DrawGLWaterPoly (glpoly_t *p)
{
 int		i;
 float	*v;

 p = WaterWarpPolyVerts (p);
 qglBegin (GL_TRIANGLE_FAN);
 v = p->verts[0];
 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
 {
  qglTexCoord2f (v[3], v[4]);
  qglVertex3fv (v);
 }
 qglEnd ();
}
void DrawGLWaterPolyLightmap (glpoly_t *p)
{
 int		i;
 float	*v;

 p = WaterWarpPolyVerts (p);
 qglBegin (GL_TRIANGLE_FAN);
 v = p->verts[0];
 for (i=0 ; i<p->numverts ; i++, v+= VERTEXSIZE)
 {
  qglTexCoord2f (v[5], v[6]);
  qglVertex3fv (v);
 }
 qglEnd ();
}
*)

{*
================
DrawGLPoly
================
*}
procedure DrawGLPoly(p: glpoly_p);
var
  i: integer;
  v: PSingle;
begin
  qglBegin(GL_POLYGON);

  i := 0;
  v := @p^.verts[0];
  while (i < p^.NumVerts) do
  begin
    qglTexCoord2f(PSingleArray(v)^[3], PSingleArray(v)^[4]);
    qglVertex3fv(PGLFloat(v));
    Inc(i);
    Inc(v, VERTEXSIZE);
  end;
  qglEnd();
end;

//============
//PGM
{*
================
DrawGLFlowingPoly -- version of DrawGLPoly that handles scrolling texture
================
*}
procedure DrawGLFlowingPoly(fa: msurface_p);
var
  i: integer;
  v: PSingle;
  p: glpoly_p;
  scroll: Single;
begin
  p := fa.polys;

  scroll := -64 * ((r_newrefdef.time / 40.0) - Trunc(r_newrefdef.time / 40.0));
  if (scroll = 0.0) then
    scroll := -64.0;

  qglBegin(GL_POLYGON);
  v := @p.verts[0];
  i := 0;
  while (i < p^.NumVerts) do
  begin
    qglTexCoord2f((PSingleArray(v)^[3] + scroll), PSingleArray(v)^[4]);
    qglVertex3fv(PGLfloat(v));
    Inc(v, VERTEXSIZE);
    Inc(i);
  end;
  qglEnd();
end;

//PGM
//============

{*
** R_DrawTriangleOutlines
*}

procedure R_DrawTriangleOutlines;
var
  i, j: integer;
  p: glpoly_p;
  surf: msurface_p;
begin
  if (gl_showtris.value = 0) then
    Exit;

  qglDisable(GL_TEXTURE_2D);
  qglDisable(GL_DEPTH_TEST);
  qglColor4f(1, 1, 1, 1);

  for i := 0 to MAX_LIGHTMAPS - 1 do
  begin
    surf := gl_lms.lightmap_surfaces[i];
    while (surf <> nil) do
    begin
      p := surf.polys;
      while (p <> nil) do
      begin
        for j := 2 to p.numverts - 1 do
        begin
          qglBegin(GL_LINE_STRIP);
          qglVertex3fv(@p.verts[0]);
          qglVertex3fv(@p.verts[j - 1]);
          qglVertex3fv(@p.verts[j]);
          qglVertex3fv(@p.verts[0]);
          qglEnd();
        end;
        p := p^.chain;
      end;
      surf := surf^.lightmapchain;
    end;
  end;

  qglEnable(GL_DEPTH_TEST);
  qglEnable(GL_TEXTURE_2D);
end; //procedure

{*
** DrawGLPolyChain
*}

procedure DrawGLPolyChain(p: glpoly_p; soffset, toffset: Single);
var
  v: PSingle;
  j: integer;
begin
  if (soffset = 0) and (toffset = 0) then
  begin
    while (p <> nil) do
    begin
      qglBegin(GL_POLYGON);
      v := @p^.verts[0];
      j := 0;
      while (j < p^.NumVerts) do
      begin
        qglTexCoord2f(PSingleArray(v)^[5], PSingleArray(v)^[6]);
        qglVertex3fv(PGLfloat(v));
        Inc(j);
        Inc(v, VERTEXSIZE);
      end;
      qglEnd();
      p := p^.Chain;
    end;
  end
  else
  begin
    while (p <> nil) do
    begin
      qglBegin(GL_POLYGON);
      v := @p.verts[0];
      j := 0;
      while (j < p^.NumVerts) do
      begin
        qglTexCoord2f(PSingleArray(v)^[5] - soffset, PSingleArray(v)^[6] - toffset);
        qglVertex3fv(PGLfloat(v));
        Inc(j);
        Inc(v, VERTEXSIZE);
      end;
      qglEnd();
      p := p^.Chain;
    end;
  end;
end;

{*
** R_BlendLightMaps
**
** This routine takes all the given light mapped surfaces in the world and
** blends them into the framebuffer.
*}

procedure R_BlendLightmaps;
var
  i, smax, tmax: integer;
  surf,
    newdrawsurf,
    drawsurf: msurface_p;
  base: PByte;
begin
  newdrawsurf := nil;

  // don't bother if we're set to fullbright
  if (r_fullbright.value <> 0) then
    Exit;
  if (r_worldmodel.lightdata = nil) then
    Exit;

  // don't bother writing Z
  qglDepthMask(False);

  {*
  ** set the appropriate blending mode unless we're only looking at the
  ** lightmaps.
  *}
  if (gl_lightmap.value = 0) then
  begin
    qglEnable(GL_BLEND);

    if (gl_saturatelighting.value <> 0) then
      qglBlendFunc(GL_ONE, GL_ONE)
    else
    begin
      if (gl_monolightmap.string_[0] <> '0') then
      begin
        case UpCase(gl_monolightmap.string_[0]) of
          'I': qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
          'L': qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
          //'A':  <- Juha: This falls to default section as well.
        else
          qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        end;
      end
      else
        qglBlendFunc(GL_ZERO, GL_SRC_COLOR);
    end; //else
  end; //if

  if (currentmodel = r_worldmodel) then
    c_visible_lightmaps := 0;

  {*
  ** render static lightmaps first
  *}
  for i := 1 to MAX_LIGHTMAPS - 1 do
    if (gl_lms.lightmap_surfaces[i] <> nil) then
    begin
      if (currentmodel = r_worldmodel) then
        Inc(c_visible_lightmaps);
      GL_Bind(gl_state.lightmap_textures + i);

      surf := gl_lms.lightmap_surfaces[i];
      while (surf <> nil) do
      begin
        if (surf.polys <> nil) then
          DrawGLPolyChain(surf.polys, 0, 0);
        surf := surf^.LightMapChain;
      end;
    end;

  {*
  ** render dynamic lightmaps
  *}
  if (gl_dynamic.value <> 0) then
  begin
    LM_InitBlock();

    GL_Bind(gl_state.lightmap_textures + 0);

    if (currentmodel = r_worldmodel) then
      Inc(c_visible_lightmaps);

    newdrawsurf := gl_lms.lightmap_surfaces[0];

    surf := gl_lms.lightmap_surfaces[0];
    while (surf <> nil) do
    begin
      smax := (surf.extents[0] shr 4) + 1;
      tmax := (surf.extents[1] shr 4) + 1;

      if (LM_AllocBlock(smax, tmax, surf.dlight_s, surf.dlight_t)) then
      begin
        base := @gl_lms.lightmap_buffer;
        Inc(base, (surf.dlight_t * BLOCK_WIDTH + surf.dlight_s) * LIGHTMAP_BYTES);

        R_BuildLightMap(surf, PByteArray(base), BLOCK_WIDTH * LIGHTMAP_BYTES);
      end
      else
      begin
             // upload what we have so far
        LM_UploadBlock(true);

             // draw all surfaces that use this lightmap
        drawsurf := newdrawsurf;
        while (drawsurf <> surf) do
        begin
          if (drawsurf.polys <> nil) then
            DrawGLPolyChain(drawsurf.polys,
              (drawsurf.light_s - drawsurf.dlight_s) * (1.0 / 128.0),
              (drawsurf.light_t - drawsurf.dlight_t) * (1.0 / 128.0));
          drawsurf := drawsurf^.lightmapchain;
        end;

        newdrawsurf := drawsurf;

             // clear the block
        LM_InitBlock();

             // try uploading the block now
        if (not LM_AllocBlock(smax, tmax, surf.dlight_s, surf.dlight_t)) then
          ri.Sys_Error(ERR_FATAL, 'Consecutive calls to LM_AllocBlock(%d,%d) failed (dynamic)'#10, [smax, tmax]);

        base := @gl_lms.lightmap_buffer;
        Inc(base, (surf.dlight_t * BLOCK_WIDTH + surf.dlight_s) * LIGHTMAP_BYTES);

        R_BuildLightMap(surf, PByteArray(base), BLOCK_WIDTH * LIGHTMAP_BYTES);
      end;
      surf := surf^.lightmapchain;
    end;

    {*
    ** draw remainder of dynamic lightmaps that haven't been uploaded yet
    *}
    if (newdrawsurf <> nil) then
      LM_UploadBlock(true);

    surf := newdrawsurf;
    while (surf <> nil) do
    begin
      if (surf.polys <> nil) then
        DrawGLPolyChain(surf.polys,
          (surf.light_s - surf.dlight_s) * (1.0 / 128.0),
          (surf.light_t - surf.dlight_t) * (1.0 / 128.0));
      surf := surf^.lightmapchain;
    end;
  end; //if

  {*
  ** restore state
  *}
  qglDisable(GL_BLEND);
  qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  qglDepthMask(True);
end; //procedure

{*
================
R_RenderBrushPoly
================
*}
procedure R_RenderBrushPoly(fa: msurface_p);
var
  maps,
    smax, tmax: integer;
  image: image_p;
  is_dynamic: qboolean;
  temp: array[0..34 * 34 - 1] of Cardinal;
label
  _dynamic;
begin
  is_dynamic := false;

  Inc(c_brush_polys);

  image := R_TextureAnimation(fa.texinfo);

  if ((fa.flags and SURF_DRAWTURB) <> 0) then
  begin
    GL_Bind(image^.texnum);

    // warp texture, no lightmaps
    GL_TexEnv(GL_MODULATE);
    qglColor4f(gl_state.inverse_intensity,
      gl_state.inverse_intensity,
      gl_state.inverse_intensity,
      1.0);
    EmitWaterPolys(fa);
    GL_TexEnv(GL_REPLACE);

    Exit;
  end
  else
  begin
    GL_Bind(image^.texnum);

    GL_TexEnv(GL_REPLACE);
  end;

//======
//PGM
  if (fa.texinfo.flags and SURF_FLOWING) <> 0 then
    DrawGLFlowingPoly(fa)
  else
    DrawGLPoly(fa^.polys);
//PGM
//======

  {*
  ** check for lightmap modification
  *}
  maps := 0;
  while (maps < MAXLIGHTMAPS) and (fa^.styles[maps] <> 255) do
  begin
    if (r_newrefdef.lightstyles[fa^.styles[maps]].white <> fa^.cached_light[maps]) then
      goto _dynamic;
    Inc(maps);
  end;

  // dynamic this frame or dynamic previously
  if (fa^.dlightframe = r_framecount) then
  begin

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -