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

📄 gl_light.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 2 页
字号:
{----------------------------------------------------------------------------}
{                                                                            }
{ File(s): gl_light.c                                                        }
{                                                                            }
{ Initial conversion by : Lars Middendorf (lmid@gmx.de)                      }
{ Initial conversion on : 24-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.                       }
{                                                                            }
{----------------------------------------------------------------------------}
{ Updated on : 27/07/02                                                      }
{ Updated by : Fabrizio Rossini rossini.f@libero.it                          }
{ Updated on :08/08/02                                                       }
{ Updated by : Fabrizio Rossini rossini.f@libero.it                          }
{            Changed some type definitions to var and added some typecasting }
{      added definition of pSingleArray and corrected some pointer increment }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on:                               }
{                                                                            }
{----------------------------------------------------------------------------}
{ 28.06.2003 Juha: Proofreaded }
unit gl_light;

interface

uses
  DelphiTypes,
  SysUtils,
  OpenGL,
  q_shared,
  CPas,
  ref,
  qgl_h,
  gl_model_h,
  gl_local;

var
  r_dlightframecount: integer;
  s_blocklights: array[0..(34 * 34 * 3) - 1] of single;
  pointcolor: vec3_t;
  lightspot: vec3_t;
  lightplane: cplane_p; // used as shadow plane

const
  DLIGHT_CUTOFF = 64;

{
=============================================================================

DYNAMIC LIGHTS BLEND RENDERING

=============================================================================
}


procedure R_RenderDlight(light: dlight_p);
procedure R_RenderDlights;
procedure R_MarkLights(light: dlight_p; bit: integer; node: mnode_p);
procedure R_PushDlights;
function RecursiveLightPoint(node: mnode_p; const start, _end: vec3_t): integer;
procedure R_LightPoint(const p: vec3_t; var color: vec3_t);
procedure R_AddDynamicLights(surf: msurface_p);
procedure R_SetCacheState(surf: msurface_p);
procedure R_BuildLightMap(surf: msurface_p; dest: PByteArray; stride: integer);


implementation

uses
  QFiles,
  qgl_win,
  gl_rmain;

procedure R_RenderDlight(light: dlight_p);
var
  i, j: integer;
  a: single;
  v: vec3_t;
  rad: single;
begin
  rad := light^.intensity * 0.35;
  VectorSubtract(light^.origin, r_origin, v);

(*
 // FIXME?
        if VectorLength(v) < rad then
        begin
  // view is inside the dlight
  V_AddBlend(light.color[0],light.color[1],light.color[2],light.intensity * 0.0003, v_blend);
  exit;
        end;
*)
  qglBegin(GL_TRIANGLE_FAN);
  qglColor3f(light^.color[0] * 0.2, light^.color[1] * 0.2, light^.color[2] * 0.2);
  for i := 0 to 2 do
    v[i] := light^.origin[i] - vpn[i] * rad;
  qglVertex3fv(@v);
  qglColor3f(0, 0, 0);
  for i := 16 downto 0 do
  begin
    a := i / 16 * M_PI * 2;
    for j := 0 to 2 do
      v[j] := light^.origin[j] + vright[j] * cos(a) * rad
        + vup[j] * sin(a) * rad;
    qglVertex3fv(@v);
  end;
  qglEnd;

end;

procedure R_RenderDlights;
var
  i: Integer;
  l: dlight_p;
begin
  if (gl_flashblend^.value = 0) then
    exit;
  r_dlightframecount := r_framecount + 1; // because the count hasn't
                                          // advanced yet for this frame
  qglDepthMask(False);
  qglDisable(GL_TEXTURE_2D);
  qglShadeModel(GL_SMOOTH);
  qglEnable(GL_BLEND);
  qglBlendFunc(GL_ONE, GL_ONE);

  l := r_newrefdef.dlights;
  for i := 0 to (r_newrefdef.num_dlights - 1) do
  begin
    R_RenderDlight(l);
    inc(l);
  end;
  qglColor3f(1, 1, 1);
  qglDisable(GL_BLEND);
  qglEnable(GL_TEXTURE_2D);
  qglBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  qglDepthMask(True);
end;

(*
=============================================================================

DYNAMIC LIGHTS

=============================================================================
*)


(*
=============
R_MarkLights
=============
*)
procedure R_MarkLights(light: dlight_p; bit: integer; node: mnode_p);
var
  splitplane: cplane_p;
  dist: single;
  surf: msurface_p;
  i: integer;
begin
  if (node^.contents <> -1) then
    exit;
  splitplane := node^.plane;
  dist := DotProduct(light^.origin, splitplane^.normal) - splitplane^.dist;

  if (dist > light^.intensity - DLIGHT_CUTOFF) then
  begin
    R_MarkLights(light, bit, node^.children[0]);
    exit;
  end;
  if (dist < -light^.intensity + DLIGHT_CUTOFF) then
  begin
    R_MarkLights(light, bit, node^.children[1]);
    exit;
  end;
// mark the polygons
  surf := Pointer(Cardinal(r_worldmodel.surfaces) + node^.firstsurface * sizeof(mSurface_t));
  for i := 0 to node^.numsurfaces - 1 do
  begin
    if surf^.dlightframe <> r_dlightframecount then
    begin
      surf^.dlightbits := 0;
      surf^.dlightframe := r_dlightframecount;
    end;
    surf^.dlightbits := surf^.dlightbits or bit;
    inc(surf);
  end;

  R_MarkLights(light, bit, node^.children[0]);
  R_MarkLights(light, bit, node^.children[1]);
end;


(*
=============
R_PushDlights
=============
*)
procedure R_PushDlights;
var
  i: integer;
  l: dlight_p;
begin
  if (gl_flashblend^.value <> 0) then
    exit;

  r_dlightframecount := r_framecount + 1; // because the count hasn't
                                                //  advanced yet for this frame
  l := r_newrefdef.dlights;

  for i := 0 to r_newrefdef.num_dlights - 1 do
  begin
    R_MarkLights(l, 1 shl i, r_worldmodel^.nodes);
    inc(l);
  end;
end;

(*
=============================================================================

LIGHT SAMPLING

=============================================================================
*)

function RecursiveLightPoint(node: mnode_p; const start, _end: vec3_t): integer;
var
  front, back, frac: single;
  side: integer;
  plane: cplane_p;
  mid, scale: vec3_t;
  surf: msurface_p;
  s, t, ds, dt, i: integer;
  ii: Integer;
  tex: mtexinfo_p;
  lightmap: pByteArray;
  maps, r: integer;
  notside: Integer;
label
  continue_;
begin
  if (node^.contents <> -1) then
  begin
    result := -1; // didn't hit anything
    exit;
  end;
  // calculate mid point

  // FIXME: optimize for axial
  plane := node^.plane;
  front := DotProduct(start, plane^.normal) - plane^.dist;
  back := DotProduct(_end, plane^.normal) - plane^.dist;
  if front < 0 then
    side := 1
  else
    side := 0;


  // Juha: This translation looks a bit wicked, but should do the thing
  // if ( (back < 0) == side)
  if ((back < 0) and (side = 1)) or ((back >= 0) and (side = 0)) then
  begin
    result := RecursiveLightPoint(node^.children[side], start, _end);
    exit;
  end;

  frac := front / (front - back);
  mid[0] := start[0] + (_end[0] - start[0]) * frac;
  mid[1] := start[1] + (_end[1] - start[1]) * frac;
  mid[2] := start[2] + (_end[2] - start[2]) * frac;

// go down front side
  r := RecursiveLightPoint(node^.children[side], start, mid);
  if (r >= 0) then
  begin
    result := r; // hit something
    exit;
  end;

  if ((back < 0) and (side = 1)) or ((back >= 0) and (side = 0)) then
  begin
    result := -1; // didn't hit anything
    exit;
  end;

  // check for impact on this node
  //
  VectorCopy(mid, lightspot);
  lightplane := plane;

  surf := Pointer(Cardinal(r_worldmodel^.surfaces) + node^.firstsurface * sizeof(mSurface_t));
  for ii := 0 to node^.numsurfaces - 1 do
  begin
    if (surf^.flags and (SURF_DRAWTURB or SURF_DRAWSKY)) <> 0 then
      goto continue_; // no lightmaps

    tex := surf^.texinfo;

    s := trunc(DotProduct(mid, vec3_p(@tex^.vecs[0])^) + tex^.vecs[0][3]);
    t := trunc(DotProduct(mid, vec3_p(@tex^.vecs[1])^) + tex^.vecs[1][3]);

    if (s < surf^.texturemins[0]) or (t < surf^.texturemins[1]) then
      goto continue_;

    ds := s - surf^.texturemins[0];
    dt := t - surf^.texturemins[1];

    if (ds > surf^.extents[0]) or (dt > surf^.extents[1]) then
      goto continue_;

    if (surf^.samples = nil) then
    begin
      result := 0;
      exit;
    end;

    ds := ds shr 4;
    dt := dt shr 4;

    lightmap := PByteArray(surf^.samples);
    VectorCopy(vec3_origin, pointcolor);
    if lightmap<>nil then
    begin
      inc(PByte(lightmap), 3 * (dt * ((surf^.extents[0] shr 4) + 1) + ds));

      maps := 0;
      while (maps < MAXLIGHTMAPS) and (surf^.styles[maps] <> 255) do
      begin
        for i := 0 to 2 do
          scale[i] := gl_modulate_^.value * r_newrefdef.lightstyles[surf^.styles[maps]].rgb[i];

        pointcolor[0] := pointcolor[0] + lightmap[0] * scale[0] * (1.0 / 255);
        pointcolor[1] := pointcolor[1] + lightmap[1] * scale[1] * (1.0 / 255);
        pointcolor[2] := pointcolor[2] + lightmap[2] * scale[2] * (1.0 / 255);
        inc(PByte(lightmap), 3 * ((surf^.extents[0] shr 4) + 1) * ((surf.extents[1] shr 4) + 1));
        inc(maps);
      end;
    end;
    result := 1;
    exit;

    continue_:
    inc(surf);
  end;
  if side = 0 then
    notside := 1
  else
    notside := 0;
  result := RecursiveLightPoint(node^.children[notside], mid, _end);
end;


(*
===============
R_LightPoint
===============
*)
procedure R_LightPoint(const p: vec3_t; var color: vec3_t);
var
  _end: vec3_t;
  r: single;
  lnum: integer;
  dl: dlight_p;
  light: single;
  dist: vec3_t;
  add: single;
begin
  if (r_worldmodel^.lightdata = nil) then
  begin
    color[0] := 1;
    color[1] := 1;
    color[2] := 1;
    exit;
  end;

  _end[0] := p[0];
  _end[1] := p[1];
  _end[2] := p[2] - 2048;

  r := RecursiveLightPoint(r_worldmodel^.nodes, p, _end);

  if (r = -1) then
    VectorCopy(vec3_origin, color)
  else
    VectorCopy(pointcolor, color);

 //
 // add dynamic lights
 //

⌨️ 快捷键说明

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