Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / Фейслифтинг Quake II

Фейслифтинг Quake II

Страницы: 1 2 3 Следующая »
ChebПостоялецwww24 июля 200716:42#0
Короче, удивляюсь, почему никто раньше не заметил.
Скины монстров и вообще многие текстуры в Квейке 2 были созданы ещё *до* появления 3d ускорителей. И, соответственно, размеры у них в подавляющем большинстве - *не* кратны степени двойки. А Квака 2 создавалась во времена, когда ни один ускоритель не поддерживал текстуры больше 256*256. И угадайте, что квейк делает когда грузит скин, например, размером 309х160 ?.. Прааально, он его безбожно уродует, упрессовывая в 256х128.

Ну, исходники уже тыщу лет доступны под GNU GPL, лезем в них и снимаем идиотское ограничение, попутно привинчивая фильтр lanczos для резайсинга:

http://www.chebmaster.com/q2facelift/index_ru.html

Глюк с лайтмапами благополучно исправлен, см. мой последний пост.
Новый вариант - пор той жессылке :)

Правка: 11 мар. 2018 20:34

chiaroscuroПостоялецwww24 июля 200717:45#1
Какой стек нафиг???

Как ты сделал ресэмплинг? Наверное, у тебя с выделением памяти проблема. В Ку2 есть выделитель памяти -- Z_Malloc/Z_Free, есть еще и Hunk. Вот ими и пользуйся.

Кстати, раз уж выкладываешь бинарники, будь добр выложить и код.

CyberManiacПостоялецwww24 июля 200718:05#2
Скоко видел исходников кваки, но ни один запустить не смог. Не было ресурсов токо код.
ChebПостоялецwww24 июля 200718:17#3
Память выделяется в виде глобальной переменной под максимальный размер текстуры (была локальная переменная под максимальный размер текстуры).

Ничего не выделяю. Может, что-то выделяет пристёгнутая мной библиотека VampyreImaging - но и то вряд ли, она ресэмплит из уже выделенного (где-то раньше, в процедуре загрузки картинки) куска  прямо в эту глобальную переменную. У Дельфи собственный диспетчер памяти, и dll берёт память напрямую у WinApi.

Падать начало когда увеличил размер этого массива (тогда ещё - локальной переменной). Вывод?.. Слишком малый лимит стека. Расчитывалось-то на машины с 8..32 мегабайтами памяти.

>Наверное, у тебя с выделением памяти проблема.
С новой Dll точно так же падал и DelphiQuake пока я не залез в свойства проекта и не увеличил там максимальный размер стера раз в восемь.

ChebПостоялецwww24 июля 200718:34#4
Сорцы (2 мегабайта):

http://chebmaster.ru/_share/_001/_003/q_fclift_src/q_fclift_src.tgz

- там до кучи и весь Ку2, и вся Vampyre. Проекты под Turbo Delphi.

Я изменял только /ref_gl/gl_image.pas, и только две процедуры в ней.

Было

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 (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;

ChebПостоялецwww24 июля 200718:35#5
Стало
const
  MAX_TW = 1024;
  MAX_TH = 512;

var
  scaled: array[0..MAX_TH * MAX_TW - 1] of Cardinal;
  paletted_texture: array[0..MAX_TH * MAX_TW - 1] of byte;


function GL_Upload32(data: PCardinal; width, height: integer; mipmap: qboolean): qboolean;
var
  samples,
  scaled_width, scaled_height,
  miplevel: integer;
  i, c: Integer;
  scan: PByte;
  comp: Integer;
label
  done;
begin
  uploaded_paletted := false;

  scaled_width := 16;
  while (scaled_width < width*1.2) and (scaled_width <> width) do
    scaled_width := scaled_width shl 1;
  if width = 256 then scaled_width:=256;

  scaled_height := 16;
  while (scaled_height < height *1.2) and (scaled_height <> height) do
    scaled_height := scaled_height shl 1;

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

  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 (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;

Было

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;


Стало

procedure GL_ResampleTexture(in_: PCardinal; inwidth, inheight: integer; out_: PCardinal; outwidth, outheight: integer);
var
  i1, i2: TImageData;
begin
  i1.width:=inwidth;
  i1.height:=inheight;
  i1.format:=ifA8R8G8B8;
  i1.Size:=inwidth * inheight * 4;
  i1.bits:=in_;

  i2.width:=outwidth;
  i2.height:=outheight;
  i2.format:=ifA8R8G8B8;
  i2.Size:=outwidth * outheight * 4;
  i2.bits:=out_;

  StretchResample(
    i1, 0, 0, inwidth, inheight,
    i2, 0, 0, outwidth, outheight,
    sfLanczos, true);
end;

chiaroscuroПостоялецwww24 июля 200721:22#6
Весь Quake2 на паскале? Круто =)

Запусти в отладчике. Если еще этого не сделал. :)
Скачиваю, сейчас гляну, как оно падает.

chiaroscuroПостоялецwww24 июля 200721:35#7
Не могу скачать -- FireFox молча отказывается.
ChebПостоялецwww24 июля 200721:44#8
>Весь Quake2 на паскале? Круто =)
А то.
Но начинатель этого проекта, увы, погиб в автокатастрофе. ДельфиКу2 при запуске выводит, что посвящён его памяти.

Кстати, доопёр, откуда чёрные полигоны. Если в уровень воткнут удаляемый источник света (кристалл там взрывающийся, или ещё что), то все полигоны, которые он освещает, освещаются только им. Где-то не прокатывает сложение.

>Запусти в отладчике. Если еще этого не сделал. :)
Ась?.. А что такое отладчик?..
Если серьёзно, всю жизнь использую debug writes, никогда отладчиками не пользовался. К тому же я сейчас под Виндовс набегами, разучился уже ей пользоваться - всё время на Линуксе сижу.

По идее, для разрешения всех проблем достаточно, чтобы кто-то владеющий Си, перекомпилировал в ней quake2.exe, в несколько раз подняв лимиты стека и кучи. Я уверен, этого будет достаточно.

ChebПостоялецwww24 июля 200721:47#9
>Не могу скачать -- FireFox молча отказывается.
???? :(
Может, антивирус шалит?
Или я в тот момент компьютер перезагружал.
SepticПостоялецwww25 июля 20079:48#10
Я тоже как-то давно разбирался с сорцами кваки. Изменил метод вывода частиц, теперь вместо обычных gl_points там текстурированные квады. Вот, если кому интересно:
http://www.gamedev.ru/download/?id=5787
Причем самое интересное, что в коде было почти все необходимое для этого, но многое было закомментировано. Текстура частиц там тоже была, но однобитная, я переделал ее в серошкальную. Интересно, что эта текстура (кругляшки) применялась движком в качестве дефолтной (т.е. когда оригинал не найден), а не по своему прямому назначению.
YgriKПостоялецwww25 июля 200710:05#11
Cheb
Абалдеть - дело Jan Horn всеже живет.
Он долго и упорно начинал этот проект и прикладывал максимум сил, чтобы он развивался.
Светлая ему память.
6 June 2002 18:30
g-contПостоялецwww25 июля 200715:31#12
>>По идее, для разрешения всех проблем достаточно, чтобы кто-то владеющий Си, перекомпилировал в ней quake2.exe, в несколько раз подняв лимиты стека и кучи. Я уверен, этого будет достаточно.
Да не надо там ничего поднимать, просто буффер под картинку увеличить в 2 раза и все.
ИМХО, проблемы со стеком - чисто паскалевская особенность.
ChebПостоялецwww25 июля 200716:37#13
Сейчас попробовал ещё скачать длл - мой собственный сервер начал гнать какую-то пургу.
Похоже, длл файлы не любит.
Запаковал всё в архив:
http://host-17-99.imsys.net/_share/_001/_003/q2_facelifted.zip
ChebПостоялецwww25 июля 200716:43#14
>Да не надо там ничего поднимать, просто буффер под картинку увеличить в 2 раза и все.
Какой именно? И где он задаётся?
Напоминаю, что проблема с падением прямо при запуске присутствовала и в дельфи-версии екзешника, и решилась именно увеличением пределов стека/кучи в свойствах проекта - это параметры для линкера, сколько я знаю.
Поправьте если ошибаюсь, в Ку2 собственный диспетчер памяти и у него очень небольшой лимит.

Объём стека, насколько мне известно - это свойство, записываемое прямо в заголовке exe файла, поскольку под стек системе нужно резервировать непрерывный и линейный кусок виртуального адресного пространства, чтобы ненароком не выделить в нём страницу под кучу. Соответственно, стек не может вырасти больше, чем на определённую величину.

>Я тоже как-то давно разбирался с сорцами кваки.
Вот собраться бы, да свести свои усилия воедино...
У меня где-то и VC и сишные исходники Ку2 лежат - но сколько сил нужно, чтобы всё это откопать, установить и снова построить - просто руки опускаются.

Страницы: 1 2 3 Следующая »

/ Форум / Программирование игр / Графика

2001—2018 © GameDev.ru — Разработка игр