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

📄 gl_image.pas

📁 delphi编的不错的贪吃蛇
💻 PAS
📖 第 1 页 / 共 4 页
字号:

Fill background pixels so mipmapping doesn't have haloes
=================
*}
type
  floodfill_t = record
    x, y: SmallInt;
  end;

// must be a power of 2
const
  FLOODFILL_FIFO_SIZE = $1000;
  FLOODFILL_FIFO_MASK = (FLOODFILL_FIFO_SIZE - 1);

procedure R_FloodFillSkin(skin: PByte; skinwidth, skinheight: integer);
var
  fillcolor: Byte; // assume this is the pixel to fill
  fifo: array[0..FLOODFILL_FIFO_SIZE - 1] of floodfill_t;
  inpt, outpt: Integer;
  filledcolor: Integer;
  x, y, i, fdc: Integer;
  pos: PByte;

  procedure FLOODFILL_STEP(off, dx, dy: Integer);
  begin
    if (PByteArray(pos)^[off] = fillcolor) then
    begin
      PByteArray(pos)[off] := 255;
      fifo[inpt].x := x + (dx);
      fifo[inpt].y := y + (dy);
      inpt := (inpt + 1) and FLOODFILL_FIFO_MASK;
    end
    else
      if (PByteArray(pos)^[off] <> 255) then
        fdc := PByteArray(pos)^[off];
  end;

begin
  fillcolor := skin^; // assume this is the pixel to fill
  inpt := 0;
  outpt := 0;
  filledcolor := -1;

  if (filledcolor = -1) then
  begin
    filledcolor := 0;
    // attempt to find opaque black
    for i := 1 to 256 - 1 do
      if (d_8to24table[i] = (255 shl 0)) then // alpha 1.0
      begin
        filledcolor := i;
        break;
      end;
  end;

  // can't fill to filled color or to transparent color (used as visited marker)
  if ((fillcolor = filledcolor) or (fillcolor = 255)) then
  begin
    //printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
    Exit;
  end;

  fifo[inpt].x := 0;
  fifo[inpt].y := 0;
  inpt := (inpt + 1) and FLOODFILL_FIFO_MASK;

  while (outpt <> inpt) do
  begin
    x := fifo[outpt].x;
    y := fifo[outpt].y;
    fdc := filledcolor;
    pos := @PByteArray(skin)^[x + skinwidth * y];

    outpt := (outpt + 1) and FLOODFILL_FIFO_MASK;

    if (x > 0) then
      FLOODFILL_STEP(-1, -1, 0);
    if (x < skinwidth - 1) then
      FLOODFILL_STEP(1, 1, 0);
    if (y > 0) then
      FLOODFILL_STEP(-skinwidth, 0, -1);
    if (y < skinheight - 1) then
      FLOODFILL_STEP(skinwidth, 0, 1);
    PByteArray(skin)^[x + skinwidth * y] := fdc;
  end;
end;

//=======================================================

{*
================
GL_ResampleTexture
================
*}
procedure GL_ResampleTexture(in_: PCardinal; inwidth, inheight: integer; out_: PCardinal; outwidth, outheight: integer);
var
  i, j: Integer;
  inrow, inrow2: PCardinal;
  frac, fracstep: Cardinal;
  p1, p2: array[0..1024 - 1] of Cardinal;
  pix1, pix2, pix3, pix4: PByteArray;
  tmp: PByteArray; // <- Added by Juha to ease some wicked pointer calculations.
begin
  fracstep := (inwidth * $10000) div outwidth;

  frac := fracstep shr 2;
  for i := 0 to outwidth - 1 do
  begin
    p1[i] := 4 * (frac shr 16);
    frac := frac + fracstep;
  end;
  frac := 3 * (fracstep shr 2);
  for i := 0 to outwidth - 1 do
  begin
    p2[i] := 4 * (frac shr 16);
    frac := frac + fracstep;
  end;

  for i := 0 to outheight - 1 do
  begin
    inrow := Pointer(Cardinal(in_) + (inwidth * Trunc((i + 0.25) * inheight / outheight)) * sizeof(Cardinal));
    inrow2 := Pointer(Cardinal(in_) + (inwidth * Trunc((i + 0.75) * inheight / outheight)) * sizeof(Cardinal));
    frac := fracstep shr 1;
    for j := 0 to outwidth - 1 do
    begin
      pix1 := Pointer(Cardinal(inrow) + p1[j]);
      pix2 := Pointer(Cardinal(inrow) + p2[j]);
      pix3 := Pointer(Cardinal(inrow2) + p1[j]);
      pix4 := Pointer(Cardinal(inrow2) + p2[j]);
      tmp := Pointer(Cardinal(out_) + j * sizeof(Cardinal));
      tmp[0] := (pix1[0] + pix2[0] + pix3[0] + pix4[0]) shr 2;
      tmp[1] := (pix1[1] + pix2[1] + pix3[1] + pix4[1]) shr 2;
      tmp[2] := (pix1[2] + pix2[2] + pix3[2] + pix4[2]) shr 2;
      tmp[3] := (pix1[3] + pix2[3] + pix3[3] + pix4[3]) shr 2;
    end;
    Inc(out_, outwidth);
  end;
end;

{*
================
GL_LightScaleTexture

Scale up the pixel values in a texture to increase the
lighting range
================
*}
procedure GL_LightScaleTexture(in_: PCardinal; inwidth, inheight: integer; only_gamma: qboolean);
var
  i, c: Integer;
  p: PByte;
begin
  if (only_gamma) then
  begin
    p := PByte(in_);
    c := inwidth * inheight;
    for i := 0 to c - 1 do
    begin
      PByteArray(p)^[0] := gammatable[PByteArray(p)^[0]];
      PByteArray(p)^[1] := gammatable[PByteArray(p)^[1]];
      PByteArray(p)^[2] := gammatable[PByteArray(p)^[2]];
      Inc(p, 4);
    end;
  end
  else
  begin
    p := PByte(in_);
    c := inwidth * inheight;
    for i := 0 to c - 1 do
    begin
      PByteArray(p)^[0] := gammatable[intensitytable[PByteArray(p)^[0]]];
      PByteArray(p)^[1] := gammatable[intensitytable[PByteArray(p)^[1]]];
      PByteArray(p)^[2] := gammatable[intensitytable[PByteArray(p)^[2]]];
      Inc(p, 4);
    end;
  end;
end;

{*
================
GL_MipMap

Operates in place, quartering the size of the texture
================
*}
procedure GL_MipMap(in_: PByteArray; width, height: integer);
var
  i, j: integer;
  out_: PByteArray;
begin
  width := width shl 2;
  height := height shr 1;
  out_ := in_;
  for i := 0 to height - 1 do
  begin
    j := 0;
    while (j < width) do
    begin
      out_[0] := (in_[0] + in_[4] + in_[width + 0] + in_[width + 4]) shr 2;
      out_[1] := (in_[1] + in_[5] + in_[width + 1] + in_[width + 5]) shr 2;
      out_[2] := (in_[2] + in_[6] + in_[width + 2] + in_[width + 6]) shr 2;
      out_[3] := (in_[3] + in_[7] + in_[width + 3] + in_[width + 7]) shr 2;
      Inc(j, 8);
      out_ := Pointer(Cardinal(out_) + 4);
      in_ := Pointer(Cardinal(in_) + 8);
    end;
    in_ := Pointer(Cardinal(in_) + width);
  end;
end;

{*
===============
GL_Upload32

Returns has_alpha
===============
*}
procedure GL_BuildPalettedTexture(paletted_texture: PByte; scaled: PByte; scaled_width, scaled_height: integer);
var
  i: integer;
  r, g, b, c: Cardinal;
begin
  for i := 0 to scaled_width * scaled_height - 1 do
  begin
    r := (PByteArray(scaled)^[0] shr 3) and 31;
    g := (PByteArray(scaled)^[1] shr 2) and 63;
    b := (PByteArray(scaled)^[2] shr 3) and 31;

    c := r or (g shl 5) or (b shl 11);

    PByteArray(paletted_texture)[i] := gl_state.d_16to8table[c];

    Inc(scaled, 4);
  end;
end;

var
  upload_width, upload_height: integer;
  uploaded_paletted: qboolean;

function GL_Upload32(data: PCardinal; width, height: integer; mipmap: qboolean): qboolean;
var
  scaled: array[0..256 * 256 - 1] of Cardinal;
  paletted_texture: array[0..256 * 256 - 1] of byte;
  samples,
  scaled_width, scaled_height,
  miplevel: integer;
  i, c: Integer;
  scan: PByte;
  comp: Integer;
label
  done;
begin
  uploaded_paletted := false;

  scaled_width := 1;
  while (scaled_width < width) do
    scaled_width := scaled_width shl 1;
  if (gl_round_down^.value <> 0) and (scaled_width > width) and (mipmap) then
    scaled_width := scaled_width shr 1;
  scaled_height := 1;
  while (scaled_height < height) do
    scaled_height := scaled_height shl 1;
  if (gl_round_down^.value <> 0) and (scaled_height > height) and (mipmap) then
    scaled_height := scaled_height shr 1;

  // let people sample down the world textures for speed
  if (mipmap) then
  begin
    scaled_width := scaled_width shr Trunc(gl_picmip^.Value);
    scaled_height := scaled_height shr Trunc(gl_picmip^.value);
  end;

  // don't ever bother with >256 textures
  if (scaled_width > 256) then
    scaled_width := 256;
  if (scaled_height > 256) then
    scaled_height := 256;

  if (scaled_width < 1) then
    scaled_width := 1;
  if (scaled_height < 1) then
    scaled_height := 1;

  upload_width := scaled_width;
  upload_height := scaled_height;

  if (scaled_width * scaled_height > sizeof(scaled) / 4) then
    ri.Sys_Error(ERR_DROP, 'GL_Upload32: too big');

  // scan the texture for any non-255 alpha
  c := width * height;
  scan := Pointer(Cardinal(data) + 3);
  samples := gl_solid_format;
  for i := 0 to c - 1 do
  begin
    if (scan^ <> 255) then
    begin
      samples := gl_alpha_format;
      break;
    end;
    Inc(scan, 4);
  end;

  if (samples = gl_solid_format) then
    comp := gl_tex_solid_format
  else
    if (samples = gl_alpha_format) then
      comp := gl_tex_alpha_format
    else
    begin
      ri.Con_Printf(PRINT_ALL,
        'Unknown number of texture components %i'#10,
        samples);
      comp := samples;
    end;

{*
  if (mipmap)
          gluBuild2DMipmaps (GL_TEXTURE_2D, samples, width, height, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  else if (scaled_width == width && scaled_height == height)
          qglTexImage2D (GL_TEXTURE_2D, 0, comp, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, trans);
  else
  )
          gluScaleImage (GL_RGBA, width, height, GL_UNSIGNED_BYTE, trans,
                  scaled_width, scaled_height, GL_UNSIGNED_BYTE, scaled);
          qglTexImage2D (GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, scaled);
  )
*}

  if (scaled_width = width) and (scaled_height = height) then
  begin
    if (not mipmap) then
    begin
      if (Assigned(qglColorTableEXT) and (gl_ext_palettedtexture.value <> 0) and (samples = gl_solid_format)) then
      begin
        uploaded_paletted := true;
        GL_BuildPalettedTexture(@paletted_texture, PByte(data), scaled_width, scaled_height);
        qglTexImage2D(GL_TEXTURE_2D,
          0,
          GL_COLOR_INDEX8_EXT,
          scaled_width,
          scaled_height,
          0,
          GL_COLOR_INDEX,
          GL_UNSIGNED_BYTE,
          @paletted_texture);
      end
      else
        qglTexImage2D(GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
      goto done;
    end;
    memcpy(@scaled, data, width * height * 4);
  end
  else
    GL_ResampleTexture(data, width, height, @scaled, scaled_width, scaled_height);

  GL_LightScaleTexture(@scaled, scaled_width, scaled_height, not mipmap);

  if (Assigned(qglColorTableEXT) and (gl_ext_palettedtexture.Value <> 0) and (samples = gl_solid_format)) then
  begin
    uploaded_paletted := true;
    GL_BuildPalettedTexture(@paletted_texture, @scaled, scaled_width, scaled_height);
    qglTexImage2D(GL_TEXTURE_2D,
      0,
      GL_COLOR_INDEX8_EXT,
      scaled_width,
      scaled_height,
      0,
      GL_COLOR_INDEX,
      GL_UNSIGNED_BYTE,
      @paletted_texture);
  end
  else
    qglTexImage2D(GL_TEXTURE_2D, 0, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, @scaled);

  if (mipmap) then
  begin
    miplevel := 0;
    while (scaled_width > 1) or (scaled_height > 1) do
    begin
      GL_MipMap(@scaled, scaled_width, scaled_height);
      scaled_width := scaled_width shr 1;
      scaled_height := scaled_height shr 1;
      if (scaled_width < 1) then
        scaled_width := 1;
      if (scaled_height < 1) then
        scaled_height := 1;
      Inc(miplevel);
      if (Assigned(qglColorTableEXT) and (gl_ext_palettedtexture.Value <> 0) and (samples = gl_solid_format)) then
      begin
        uploaded_paletted := true;
        GL_BuildPalettedTexture(@paletted_texture, @scaled, scaled_width, scaled_height);
        qglTexImage2D(GL_TEXTURE_2D,
          miplevel,
          GL_COLOR_INDEX8_EXT,
          scaled_width,
          scaled_height,
          0,
          GL_COLOR_INDEX,
          GL_UNSIGNED_BYTE,
          @paletted_texture);
      end
      else
        qglTexImage2D(GL_TEXTURE_2D, miplevel, comp, scaled_width, scaled_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, @scaled);
    end;
  end;
  done: ;

  if (mipmap) then
  begin
    qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_min);
    qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max)
  end
  else
  begin
    qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gl_filter_max);
    qglTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gl_filter_max);
  end;

  Result := (samples = gl_alpha_format);
end;

{*
===============
GL_Upload8

Returns has_alpha
===============
*}
(*
static qboolean IsPowerOf2( int value )
{
 int i = 1;

 while ( 1 )
 {
  if ( value == i )
   return true;
  if ( i > value )

⌨️ 快捷键说明

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