📄 gl_light.pas
字号:
light := 0;
dl := r_newrefdef.dlights;
for lnum := 0 to r_newrefdef.num_dlights - 1 do
begin
VectorSubtract(vec3_p(@currententity^.origin)^, dl^.origin, dist);
add := dl^.intensity - (VectorLength(dist));
add := add * (1 / 256);
if (add > 0) then
VectorMA(color, add, dl^.color, color);
Inc(dl);
end;
VectorScale(color, gl_modulate_^.value, color);
end;
(*
===============
R_AddDynamicLights
===============
*)
procedure R_AddDynamicLights(surf: msurface_p);
var
lnum,
sd,
td: Integer;
fdist,
frad,
fminlight: Single;
impact,
local: vec3_t;
s, t, i, smax,
tmax: Integer;
tex: mtexinfo_p;
dl: dlight_p;
pfBL: PSingleArray;
fsacc,
ftacc: Single;
begin
smax := (surf^.extents[0] shr 4) + 1;
tmax := (surf^.extents[1] shr 4) + 1;
tex := surf^.texinfo;
for lnum := 0 to r_newrefdef.num_dlights - 1 do
begin
if ((surf^.dlightbits and (1 shl lnum)) = 0) then
continue; // not lit by this light
dl := @dlight_arrp(r_newrefdef.dlights)^[lnum];
frad := dl^.intensity;
fdist := DotProduct(dl^.origin, surf^.plane^.normal) - surf^.plane^.dist;
frad := frad - fabs(fdist);
// rad is now the highest intensity on the plane
fminlight := DLIGHT_CUTOFF; // FIXME: make configurable?
if (frad < fminlight) then
continue;
fminlight := frad - fminlight;
for i := 0 to 2 do
begin
impact[i] := dl^.origin[i] - surf^.plane^.normal[i] * fdist;
end;
local[0] := trunc(DotProduct(impact, vec3_p(@tex^.vecs[0])^) + tex^.vecs[0][3] - surf^.texturemins[0]);
local[1] := trunc(DotProduct(impact, vec3_p(@tex^.vecs[1])^) + tex^.vecs[1][3] - surf^.texturemins[1]);
pfBL := @s_blocklights;
ftacc := 0;
for t := 0 to tmax - 1 do
begin
td := trunc(local[1] - ftacc);
if (td < 0) then
td := -td;
fsacc := 0;
for s := 0 to smax - 1 do
begin
sd := Q_ftol(local[0] - fsacc);
if (sd < 0) then
sd := -sd;
if (sd > td) then
fdist := sd + (td shr 1)
else
fdist := td + (sd shr 1);
if (fdist < fminlight) then
begin
pfBL[0] := pfBL[0] + (frad - fdist) * dl^.color[0];
pfBL[1] := pfBL[1] + (frad - fdist) * dl^.color[1];
pfBL[2] := pfBL[2] + (frad - fdist) * dl^.color[2];
end;
fsacc := fsacc + 16;
pfBL := Pointer(Cardinal(pfBL) + 3 * SizeOf(Single));
end;
ftacc := ftacc + 16;
end;
end;
end;
(*
** R_SetCacheState
*)
procedure R_SetCacheState(surf: msurface_p);
var
maps: integer;
begin
maps := 0;
while (maps < MAXLIGHTMAPS) and (surf^.styles[maps] <> 255) do
begin
surf^.cached_light[maps] := r_newrefdef.lightstyles[surf^.styles[maps]].white;
inc(maps);
end;
end;
(*
===============
R_BuildLightMap
Combine and scale multiple lightmaps into the floating format in blocklights
===============
*)
procedure R_BuildLightMap(surf: msurface_p; dest: PByteArray; stride: integer);
var
smax, tmax: integer;
r, g, b, a, max: integer;
i, j, size: integer;
lightmap: PByteArray;
scale: array[0..3] of Single;
nummaps: integer;
bl: PSingleArray;
style: lightstyle_p;
monolightmap: integer;
maps: integer;
t: Single;
label
Store;
begin
if (surf^.TexInfo^.Flags and (SURF_SKY or SURF_TRANS33 or SURF_TRANS66 or SURF_WARP)) <> 0 then
ri.Sys_Error(ERR_DROP, 'R_BuildLightMap called for non-lit surface');
smax := (surf^.extents[0] shr 4) + 1;
tmax := (surf^.extents[1] shr 4) + 1;
size := smax * tmax;
if (size > (sizeof(s_blocklights) shr 4)) then
ri.Sys_Error(ERR_DROP, 'Bad s_blocklights size');
// set to full bright if no light data
if (surf^.samples = nil) then
begin
for i := 0 to (size * 3) - 1 do
s_blocklights[i] := 255;
maps := 0;
while (maps < MAXLIGHTMAPS) and (surf^.styles[maps] <> 255) do
begin
style := @r_newrefdef.lightstyles[surf^.styles[maps]];
Inc(maps);
end;
goto store;
end;
// count the # of maps
nummaps := 0;
while (nummaps < MAXLIGHTMAPS) and (surf^.styles[nummaps] <> 255) do
Inc(nummaps);
lightmap := Pointer(surf^.samples);
// add all the lightmaps
if (nummaps = 1) then
begin
maps := 0;
while (maps < MAXLIGHTMAPS) and (surf^.styles[maps] <> 255) do
begin
bl := @s_blocklights;
for i := 0 to 2 do
scale[i] := gl_modulate_^.value * r_newrefdef.lightstyles[surf^.styles[maps]].rgb[i];
if (scale[0] = 1) and
(scale[1] = 1) and
(scale[2] = 1) then
begin
for i := 0 to size - 1 do
begin
bl[0] := lightmap[i * 3 + 0];
bl[1] := lightmap[i * 3 + 1];
bl[2] := lightmap[i * 3 + 2];
inc(PSingle(bl), 3);
end;
end
else
begin
for i := 0 to size - 1 do
begin
bl[0] := lightmap[i * 3 + 0] * scale[0];
bl[1] := lightmap[i * 3 + 1] * scale[1];
bl[2] := lightmap[i * 3 + 2] * scale[2];
inc(pSingle(bl), 3);
end;
end;
inc(pByte(lightmap), size * 3); // skip to next lightmap
Inc(maps);
end;
end
else
begin
memset(@s_blocklights, 0, sizeof(s_blocklights[0]) * size * 3);
maps := 0;
while (maps < MAXLIGHTMAPS) and (surf^.styles[maps] <> 255) do
begin
bl := @s_blocklights;
for i := 0 to 2 do
scale[i] := gl_modulate_^.value * r_newrefdef.lightstyles[surf^.styles[maps]].rgb[i];
if (scale[0] = 1) and
(scale[1] = 1) and
(scale[2] = 1) then
begin
for i := 0 to size - 1 do
begin
bl[0] := lightmap[i * 3 + 0];
bl[1] := lightmap[i * 3 + 1];
bl[2] := lightmap[i * 3 + 2];
inc(pSingle(bl), 3);
end;
end
else
begin
for i := 0 to size - 1 do
begin
bl[0] := lightmap[i * 3 + 0] * scale[0];
bl[1] := lightmap[i * 3 + 1] * scale[1];
bl[2] := lightmap[i * 3 + 2] * scale[2];
inc(pSingle(bl), 3);
end;
end;
inc(PByte(lightmap), size * 3); // skip to next lightmap
Inc(maps);
end;
end;
// add all the dynamic lights
if (surf^.dlightframe = r_framecount) then
R_AddDynamicLights(surf);
// put into texture format
Store: // Label
stride := stride - (smax shl 2);
bl := @s_blocklights;
monolightmap := Byte(gl_monolightmap^.string_[0]);
if (monolightmap = Byte('0')) then
begin
for i := 0 to tmax - 1 do
begin
for j := 0 to smax - 1 do
begin
r := Q_ftol(bl[0]);
g := Q_ftol(bl[1]);
b := Q_ftol(bl[2]);
// catch negative lights
if (r < 0) then
r := 0;
if (g < 0) then
g := 0;
if (b < 0) then
b := 0;
(*
** determine the brightest of the three color components
*)
if (r > g) then
max := r
else
max := g;
if (b > max) then
max := b;
(*
** alpha is ONLY used for the mono lightmap case. For this reason
** we set it to the brightest of the color components so that
** things don't get too dim.
*)
a := max;
(*
** rescale all the color components if the intensity of the greatest
** channel exceeds 1.0
*)
if (max > 255) then
begin
t := 255 / max;
r := Trunc(r * t);
g := Trunc(g * t);
b := Trunc(b * t);
a := Trunc(a * t);
end;
dest[0] := r;
dest[1] := g;
dest[2] := b;
dest[3] := a;
inc(pSingle(bl), 3);
inc(PByte(dest), 4); //dest :=dest + 4;
end;
inc(PByte(dest), stride); // dest :=dest + stride;
end
end
else
begin
for i := 0 to tmax - 1 do
begin
for j := 0 to smax - 1 do
begin
r := Q_ftol(bl[0]);
g := Q_ftol(bl[1]);
b := Q_ftol(bl[2]);
// catch negative lights
if (r < 0) then
r := 0;
if (g < 0) then
g := 0;
if (b < 0) then
b := 0;
(*/*
//** determine the brightest of the three color components
//*/*)
if (r > g) then
max := r
else
max := g;
if (b > max) then
max := b;
(*
** alpha is ONLY used for the mono lightmap case. For this reason
** we set it to the brightest of the color components so that
** things don't get too dim.
*)
a := max;
(*
** rescale all the color components if the intensity of the greatest
** channel exceeds 1.0
*)
if (max > 255) then
begin
t := 255 / max;
r := trunc(r * t);
g := trunc(g * t);
b := trunc(b * t);
a := trunc(a * t);
end;
(*
** So if we are doing alpha lightmaps we need to set the R, G, and B
** components to 0 and we need to set alpha to 1-alpha.
*)
case Char(monolightmap) of
'L',
'I':
begin
r := a;
g := 0;
b := 0;
end;
'C':
begin
// try faking colored lighting
a := Trunc(255 - ((r + g + b) / 3));
r := Trunc(r * (a / 255));
g := Trunc(g * (a / 255));
b := Trunc(b * (a / 255));
end;
else
//'A':
begin
r := 0;
g := 0;
b := 0;
a := 255 - a;
end;
end;
dest[0] := r;
dest[1] := g;
dest[2] := b;
dest[3] := a;
//bl :=bl + 3;
inc(PSingle(bl), 3);
inc(PByte(dest), 4); // dest :=dest + 4;
end;
end;
inc(PByte(dest), stride); // dest := dest + stride ;
end;
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -