📄 gl_light.pas
字号:
{----------------------------------------------------------------------------}
{ }
{ 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 + -