📄 r_surf.pas
字号:
// PLEASE, don't modify this file
// 50% complete
{----------------------------------------------------------------------------}
{ }
{ File(s): r_surf.c: surface-related refresh code }
{ }
{ Initial conversion by : YgriK (Igor Karpov) - glYgriK@hotbox.ru }
{ Initial conversion on : 04-Feb-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 : }
{ Updated by : }
{ }
{----------------------------------------------------------------------------}
{ * Still dependent (to compile correctly) on: }
{ x) }
{ }
{----------------------------------------------------------------------------}
{ * TODO: }
{ 1) Do more tests }
{ }
{----------------------------------------------------------------------------}
// r_surf.c: surface-related refresh code
unit r_surf;
interface
uses
q_shared,
r_model,
r_local;
procedure D_FlushCaches;
procedure R_SurfacePatch;
procedure R_InitCaches;
function R_TextureAnimation(tex: mtexinfo_p): image_p;
procedure R_DrawSurface;
function D_CacheSurface(surface: msurface_p; miplevel: Integer): surfcache_p;
var
r_drawsurf: drawsurf_t;
sc_size: Integer;
sc_rover: surfcache_p;
sc_base: surfcache_p;
implementation
uses
r_bsp_c,
r_light,
r_main,
r_misc,
ref,
SysUtils;
procedure R_DrawSurfaceBlock8_mip0; forward;
procedure R_DrawSurfaceBlock8_mip1; forward;
procedure R_DrawSurfaceBlock8_mip2; forward;
procedure R_DrawSurfaceBlock8_mip3; forward;
var
surfmiptable: array[0..3]
of procedure = (
R_DrawSurfaceBlock8_mip0,
R_DrawSurfaceBlock8_mip1,
R_DrawSurfaceBlock8_mip2,
R_DrawSurfaceBlock8_mip3
);
//*****************************************
// CodeFusion: Has been commented because
// it's not used in pure delphi version.
//*****************************************
// sourcesstep : Integer;
// lightdelta : Integer;
// lightdeltastep : Integer;
//*****************************************
var
lightleft: Integer;
blocksize: Integer;
sourcetstep: Integer;
lightright: Integer;
lightleftstep: Integer;
lightrightstep: Integer;
blockdivshift: Integer;
blockdivmask: Cardinal;
prowdestbase: Pointer;
pbasesource: PByte;
surfrowbytes: Integer; // used by ASM files
r_lightptr: PCardinal;
r_stepback: Integer;
r_lightwidth: Integer;
r_numhblocks: Integer;
r_numvblocks: Integer;
r_source: PByte;
r_sourcemax: PByte;
//extern unsigned blocklights[1024]; // allow some very large lightmaps
surfscale: Single;
r_cache_thrash: qboolean; // set if surface cache is thrashing
(*
===============
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;
(*
===============
R_DrawSurface
===============
*)
procedure R_DrawSurface;
var
basetptr: PByte;
smax, tmax: Integer;
twidth, u: Integer;
soffset: Integer;
basetoffset: Integer;
texwidth: Integer;
horzblockstep: Integer;
pcolumndest: PByte;
pblockdrawer: procedure;
mt: image_p;
begin
surfrowbytes := r_drawsurf.rowbytes;
mt := r_drawsurf.image;
r_source := mt^.pixels[r_drawsurf.surfmip];
// the fractional light values should range from 0 to (VID_GRADES - 1) << 16
// from a source range of 0 - 255
texwidth := mt^.width shr r_drawsurf.surfmip;
blocksize := 16 shr r_drawsurf.surfmip;
blockdivshift := 4 - r_drawsurf.surfmip;
blockdivmask := (1 shl blockdivshift) - 1;
r_lightwidth := _SAR(r_drawsurf.surf^.extents[0], 4) + 1;
r_numhblocks := r_drawsurf.surfwidth shr blockdivshift;
r_numvblocks := r_drawsurf.surfheight shr blockdivshift;
//==============================
pblockdrawer := surfmiptable[r_drawsurf.surfmip];
// TODO: only needs to be set when there is a display settings change
horzblockstep := blocksize;
smax := mt^.width shr r_drawsurf.surfmip;
twidth := texwidth;
tmax := mt^.height shr r_drawsurf.surfmip;
sourcetstep := texwidth;
r_stepback := tmax * twidth;
r_sourcemax := PByte(Integer(r_source) + (tmax * smax));
soffset := r_drawsurf.surf^.texturemins[0];
basetoffset := r_drawsurf.surf^.texturemins[1];
// << 16 components are to guarantee positive values for %
soffset := (_SAR(soffset, r_drawsurf.surfmip) + _SAR(smax, 16)) mod smax;
basetptr := @PByteArray(r_source)^[(((_SAR(basetoffset, r_drawsurf.surfmip) + _SAR(tmax, 16)) mod tmax) * twidth)];
pcolumndest := r_drawsurf.surfdat;
for u := 0 to r_numhblocks - 1 do
begin
r_lightptr := PCardinal(Integer(@blocklights) + (u * SizeOf(Cardinal)));
prowdestbase := pcolumndest;
pbasesource := PByte(Integer(basetptr) + soffset);
pblockdrawer;
soffset := soffset + blocksize;
if (soffset >= smax) then
soffset := 0;
Inc(Integer(pcolumndest), horzblockstep);
end;
end;
//=============================================================================
{$IFNDEF id386}
(*
================
R_DrawSurfaceBlock8_mip0
================
*)
procedure R_DrawSurfaceBlock8_mip0;
var
v, i, b: Integer;
lightstep: Integer;
lighttemp: Integer;
light: Integer;
pix: Byte;
psource: PByte;
prowdest: PByte;
begin
psource := pbasesource;
prowdest := prowdestbase;
for V := 0 to r_numvblocks - 1 do
begin
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft := r_lightptr^;
lightright := PCardinal(Integer(r_lightptr) + SizeOf(Cardinal))^;
Inc(Integer(r_lightptr), r_lightwidth * SizeOf(Cardinal));
lightleftstep := _SAR(Integer(r_lightptr^) - lightleft, 4);
lightrightstep := _SAR(Integer(PCardinal(Integer(r_lightptr) + SizeOf(Cardinal))^) - lightright, 4);
for i := 0 to 15 do
begin
lighttemp := lightleft - lightright;
lightstep := _SAR(lighttemp, 4);
light := lightright;
for b := 15 downto 0 do
begin
pix := PByteArray(psource)^[b];
PByteArray(prowdest)^[b] := PByteArray(vid.colormap)^[(light and $FF00) + pix];
Inc(light, lightstep);
end;
Inc(Integer(psource), sourcetstep);
Inc(lightright, lightrightstep);
Inc(lightleft, lightleftstep);
Inc(Integer(prowdest), surfrowbytes);
end;
if (Integer(psource) >= Integer(r_sourcemax)) then
Dec(Integer(psource), r_stepback);
end;
end;
(*
================
R_DrawSurfaceBlock8_mip1
================
*)
procedure R_DrawSurfaceBlock8_mip1;
var
v, i, b: Integer;
lightstep: Integer;
lighttemp: Integer;
light: Integer;
pix: Byte;
psource: PByte;
prowdest: PByte;
begin
psource := pbasesource;
prowdest := prowdestbase;
for V := 0 to r_numvblocks - 1 do
begin
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft := r_lightptr^;
lightright := PCardinal(Integer(r_lightptr) + SizeOf(Cardinal))^;
Inc(Integer(r_lightptr), r_lightwidth * SizeOf(Cardinal));
lightleftstep := _SAR(Integer(r_lightptr^) - lightleft, 3);
lightrightstep := _SAR(Integer(PCardinal(Integer(r_lightptr) + SizeOf(Cardinal))^) - lightright, 3);
for i := 0 to 7 do
begin
lighttemp := lightleft - lightright;
lightstep := _SAR(lighttemp, 3);
light := lightright;
for b := 7 downto 0 do
begin
pix := PByteArray(psource)^[b];
PByteArray(prowdest)^[b] := PByteArray(vid.colormap)^[(light and $FF00) + pix];
Inc(light, lightstep);
end;
Inc(Integer(psource), sourcetstep);
Inc(lightright, lightrightstep);
Inc(lightleft, lightleftstep);
Inc(Integer(prowdest), surfrowbytes);
end;
if (Integer(psource) >= Integer(r_sourcemax)) then
Dec(Integer(psource), r_stepback);
end;
end;
(*
================
R_DrawSurfaceBlock8_mip2
================
*)
procedure R_DrawSurfaceBlock8_mip2;
var
v, i, b: Integer;
lightstep: Integer;
lighttemp: Integer;
light: Integer;
pix: Byte;
psource: PByte;
prowdest: PByte;
begin
psource := pbasesource;
prowdest := prowdestbase;
for V := 0 to r_numvblocks - 1 do
begin
// FIXME: make these locals?
// FIXME: use delta rather than both right and left, like ASM?
lightleft := r_lightptr^;
lightright := PCardinal(Integer(r_lightptr) + SizeOf(Cardinal))^;
Inc(Integer(r_lightptr), r_lightwidth * SizeOf(Cardinal));
lightleftstep := _SAR(Integer(r_lightptr^) - lightleft, 2);
lightrightstep := _SAR(Integer(PCardinal(Integer(r_lightptr) + SizeOf(Cardinal))^) - lightright, 2);
for i := 0 to 3 do
begin
lighttemp := lightleft - lightright;
lightstep := _SAR(lighttemp, 2);
light := lightright;
for b := 3 downto 0 do
begin
pix := PByteArray(psource)^[b];
PByteArray(prowdest)^[b] := PByteArray(vid.colormap)^[(light and $FF00) + pix];
Inc(light, lightstep);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -