diff --git a/port-source/kam_remake/src/common/KM_Defaults.pas b/port-source/kam_remake/src/common/KM_Defaults.pas index a7e5b7c..1b24562 100644 --- a/port-source/kam_remake/src/common/KM_Defaults.pas +++ b/port-source/kam_remake/src/common/KM_Defaults.pas @@ -175,7 +175,6 @@ var SHOW_UNITS_IN_HOUSE :Boolean = False; //Should we hide units when they are in house ? IGNORE_MOUSE_SCROLLING :Boolean = False; //Ignore mouse scrolling SKIP_RENDER :Boolean = False; //Skip all the rendering in favor of faster logic - DO_NOT_SKIP_LOAD_TILESET:Boolean = False; //Do not skip load tileset even if SKIP_RENDER is set SKIP_SOUND :Boolean = False; //Skip all the sounds in favor of faster logic SKIP_LOADING_CURSOR :Boolean = False; //Skip loading and setting cursor SKIP_SETTINGS_SAVE :Boolean = False; //Skip save main/game settings into the ini file @@ -217,11 +216,9 @@ var SHOW_WALK_CONNECT :Boolean = False; //Show floodfill areas of interconnected areas SHOW_GROUP_MEMBERS_POS :Boolean = False; //Show group members position TEST_VIEW_CLIP_INSET :Boolean = False; //Renders smaller area to see if everything gets clipped well - OUTLINE_ALL_SPRITES :Boolean = False; //Render outline around every sprite SHOW_ATTACK_RADIUS :Boolean = False; //Render towers/archers attack radius DISPLAY_SOUNDS :Boolean = False; //Display sounds on map RENDER_3D :Boolean = False; //Experimental 3D render - LINEAR_FILTER_SPRITES :Boolean = False; //To check pixel sampling alignment issues (bouncing) at 100% zoom HOUSE_BUILDING_STEP :Single = 0; WATER_LIGHT_MULTIPLIER :Single = DEFAULT_WATER_LIGHT_MULTIPLIER; //Terrain light multiplier OVERLAY_NAVMESH :Boolean = False; //Show navmesh diff --git a/port-source/kam_remake/src/res/KM_ResSprites.pas b/port-source/kam_remake/src/res/KM_ResSprites.pas index de13ba9..2e8c30b 100644 --- a/port-source/kam_remake/src/res/KM_ResSprites.pas +++ b/port-source/kam_remake/src/res/KM_ResSprites.pas @@ -46,11 +46,9 @@ type fTemp: Boolean; fPad: Byte; // Padding between sprites to avoid neighbour edge visibility - {$IFNDEF NO_OGL} procedure SetGFXData(aTexID: Cardinal; aSpriteInfo: TKMBinItem; aAtlasType: TKMSpriteAtlasType); - procedure PrepareAtlases(aSpriteInfo: TBinArray; aMode: TKMSpriteAtlasType; aTexType: TKMTexFormat; var aBaseRAM, aColorRAM, aTexCount: Cardinal; + procedure PrepareAtlases(aSpriteInfo: TBinArray; aMode: TKMSpriteAtlasType; aTexType: TKMTexFormat; aFillGFXData: Boolean = True; aOnCheckTerminated: TBooleanFuncSimple = nil); - {$ENDIF} protected fRT: TRXType; fRXData: TRXData; @@ -62,9 +60,9 @@ type procedure ReadRXZHeader(aStream: TStream; out aFormat: TKMRXXFormat); procedure CollectSpriteFilesToOverloadInFolder(const aFolder: string; aFileList: TStringList); {$IFNDEF NO_OGL} - procedure MakeGFX_BinPacking(aTexType: TKMTexFormat; aIDList: TList; var aBaseRAM, aColorRAM, aTexCount: Cardinal; + procedure MakeGFX_BinPacking(aTexType: TKMTexFormat; aIDList: TList; aFillGFXData: Boolean = True; aOnCheckTerminated: TBooleanFuncSimple = nil; aMaxAtlasSize: Integer = -1); overload; - procedure MakeGFX_BinPacking(aTexType: TKMTexFormat; aStartingIndex: Integer; var aBaseRAM, aColorRAM, aTexCount: Cardinal; + procedure MakeGFX_BinPacking(aTexType: TKMTexFormat; aStartingIndex: Integer; aFillGFXData: Boolean = True; aOnCheckTerminated: TBooleanFuncSimple = nil); overload; procedure MakeGFXInternal(aAlphaShadows: Boolean; aIDList: TList; aFillGFXData: Boolean; aOnCheckTerminated: TBooleanFuncSimple; aMaxAtlasSize: Integer); @@ -112,11 +110,6 @@ type function IsEmpty: Boolean; - procedure ExportAllSpritesFromRXData(const aFolder: string); - procedure ExportFullImageData(const aFolder: string; aIndex: Integer); - procedure ExportImage(const aFile: string; aIndex: Integer); - procedure ExportMask(const aFile: string; aIndex: Integer); - procedure ClearGameResGenTemp; procedure GenerateTexturesFromLoadedRXZ; @@ -206,8 +199,6 @@ type function LoadSprites(aRT: TRXType; aAlphaShadows: Boolean): Boolean; function LoadRXASprites(aRT: TRXType): Boolean; function LoadRXASpritesAndGenTextures(aRT: TRXType): Boolean; - procedure ExportToPNG(aRT: TRXType); - property AlphaShadows: Boolean read fAlphaShadows; property FileName[aRX: TRXType]: string read GetRXFileName; @@ -251,18 +242,15 @@ uses {$ENDIF} KromUtils, KM_SoftShadows, KM_Resource, KM_ResUnits, - {$IFNDEF NO_OGL} KM_Render, - {$ENDIF} TypInfo, KM_Log, KM_CommonClasses, - KM_FileIO, KaMResourceInput, KaMGeneratedTerrainBridge, + KaMResourceInput, KaMGeneratedTerrainBridge, KM_CommonUtils, KM_Utils, KM_Points, KM_GameSettings; const MAX_GAME_ATLAS_SIZE = 2048; //Max atlas size for KaM. No need for bigger atlases - LOG_EXTRA_GFX: Boolean = False; OVERLOAD_SKIP_MASK = 'skip'; var @@ -272,9 +260,7 @@ var function GetMaxAtlasSize: Integer; begin Result := MAX_GAME_ATLAS_SIZE; - {$IFNDEF NO_OGL} Result := Min(Result, TKMRender.MaxTextureSize); - {$ENDIF} end; @@ -295,7 +281,6 @@ end; //This is a crude solution to allow Campaigns to delete sprites they add procedure TKMSpritePack.DeleteSpriteTexture(aIndex: Integer); begin - {$IFNDEF NO_OGL} if gGFXData[fRT, aIndex].Tex.TexID <> 0 then TKMRender.DeleteTexture(gGFXData[fRT, aIndex].Tex.TexID); if gGFXData[fRT, aIndex].Alt.TexID <> 0 then @@ -303,7 +288,6 @@ begin gGFXData[fRT, aIndex].Tex.TexID := 0; gGFXData[fRT, aIndex].Alt.TexID := 0; - {$ENDIF} end; @@ -804,11 +788,6 @@ var decompressionStream: TDecompressionStream; rxxFormat: TKMRXXFormat; begin - case fRT of - rxTiles: if SKIP_RENDER and not DO_NOT_SKIP_LOAD_TILESET then Exit; - else if SKIP_RENDER then Exit; - end; - ReadRXZHeader(aStream, rxxFormat); // Not sure what to do yet, silently "fail" for now @@ -877,11 +856,6 @@ var {$ENDIF} begin {$IFNDEF NO_OGL} - case fRT of - rxTiles: if SKIP_RENDER and not DO_NOT_SKIP_LOAD_TILESET then Exit; - else if SKIP_RENDER then Exit; - end; - ReadRXZHeader(aStream, rxxFormat); // Not sure what to do yet, silently "fail" for now @@ -1018,7 +992,6 @@ procedure TKMSpritePack.OverloadGeneratedFromFolder(aAlphaShadows: Boolean; cons var idList: TList; begin - if SKIP_RENDER then Exit; if not DirectoryExists(aFolder) then Exit; {$IFDEF WDC} @@ -1113,7 +1086,6 @@ procedure TKMSpritePack.OverloadRXDataFromFolder(const aFolder: string; aOnProgr end; {$ENDIF} begin - if SKIP_RENDER then Exit; if not DirectoryExists(aFolder) then Exit; {$IFDEF WDC} @@ -1123,132 +1095,6 @@ begin end; -// Export RX to Bitmaps without need to have GraphicsEditor, also this way we preserve image indexes -procedure TKMSpritePack.ExportAllSpritesFromRXData(const aFolder: string); -var - I: Integer; -begin - ForceDirectories(aFolder); - - for I := 1 to fRXData.Count do - if not TThread.CheckTerminated then - ExportFullImageData(aFolder, I); -end; - - -procedure TKMSpritePack.ExportFullImageData(const aFolder: string; aIndex: Integer); -var - s: string; -begin - if fRXData.Flag[aIndex] <> 1 then Exit; - - ExportImage(aFolder + Format('%d_%.4d.png', [Ord(fRT)+1, aIndex]), aIndex); - - if fRXData.HasMask[aIndex] then - ExportMask(aFolder + Format('%d_%.4da.png', [Ord(fRT)+1, aIndex]), aIndex); - - // Pivot - s := IntToStr(fRXData.Pivot[aIndex].x) + sLineBreak + IntToStr(fRXData.Pivot[aIndex].y) + sLineBreak; - - //SizeNoShadow is used only for Units - if fRT = rxUnits then - s := s + IntToStr(fRXData.SizeNoShadow[aIndex].Left) + sLineBreak + - IntToStr(fRXData.SizeNoShadow[aIndex].Top) + sLineBreak + - IntToStr(fRXData.SizeNoShadow[aIndex].Right) + sLineBreak + - IntToStr(fRXData.SizeNoShadow[aIndex].Bottom) + sLineBreak; - - WriteTextUtf8(s, aFolder + Format('%d_%.4d.txt', [Ord(fRT)+1, aIndex])); -end; - - -procedure TKMSpritePack.ExportImage(const aFile: string; aIndex: Integer); -var - I, K: Integer; - M: Byte; - treatMask: Boolean; - pngWidth, pngHeight: Word; - pngData: TKMCardinalArray; -begin - pngWidth := fRXData.Size[aIndex].X; - pngHeight := fRXData.Size[aIndex].Y; - - SetLength(pngData, pngWidth * pngHeight); - - //Export RGB values - for I := 0 to pngHeight - 1 do - for K := 0 to pngWidth - 1 do - begin - treatMask := fRXData.HasMask[aIndex] and (fRXData.Mask[aIndex, I*pngWidth + K] > 0); - if (fRT = rxHouses) - and ((aIndex < 680) - or (aIndex = 1657) - or (aIndex = 1659) - or (aIndex = 1681) - or (aIndex = 1683) - or (aIndex > 2050)) then - treatMask := False; - - if treatMask then - begin - M := fRXData.Mask[aIndex, I*pngWidth + K]; - - //Replace background with corresponding brightness of Red - if fRXData.RGBA[aIndex, I*pngWidth + K] = FLAG_COLOR_DARK then - //Brightness < 0.5, mix with black - pngData[I*pngWidth + K] := M - else - //Brightness > 0.5, mix with white - pngData[I*pngWidth + K] := $FF + (255 - M) * $010100; - end - else - pngData[I*pngWidth + K] := fRXData.RGBA[aIndex, I*pngWidth + K] and $FFFFFF; - - pngData[I*pngWidth + K] := pngData[I*pngWidth + K] or (fRXData.RGBA[aIndex, I*pngWidth + K] and $FF000000); - end; - - //Mark pivot location with a dot -// K := pngWidth + fRXData.Pivot[aIndex].x; -// I := pngHeight + fRXData.Pivot[aIndex].y; -// if InRange(I, 0, pngHeight-1) and InRange(K, 0, pngWidth-1) then -// pngData[I*pngWidth + K] := $FFFF00FF; - - SaveToPng(pngWidth, pngHeight, pngData, aFile); -end; - - -procedure TKMSpritePack.ExportMask(const aFile: string; aIndex: Integer); -var - I, K: Integer; - pngWidth, pngHeight: Word; - pngData: TKMCardinalArray; - maskColor: Cardinal; -begin - pngWidth := fRXData.Size[aIndex].X; - pngHeight := fRXData.Size[aIndex].Y; - - SetLength(pngData, pngWidth * pngHeight); - - //Export Mask - if fRXData.HasMask[aIndex] then - begin - for I := 0 to pngHeight - 1 do - for K := 0 to pngWidth - 1 do - begin - if fRT = rxHouses then - begin - maskColor := fRXData.Mask[aIndex, I * pngWidth + K]; - if maskColor <> 0 then - maskColor := GetGreyColor(maskColor) or $FF000000; - end else - maskColor := (Byte(fRXData.Mask[aIndex, I * pngWidth + K] > 0) * $FFFFFF) or $FF000000; - pngData[I * pngWidth + K] := maskColor; - end; - - SaveToPng(pngWidth, pngHeight, pngData, aFile); - end; -end; - - function TKMSpritePack.GetAverageSpriteColors(aCount: Integer): TKMColor3bArray; var I, L, M: Integer; @@ -1315,11 +1161,8 @@ end; procedure TKMSpritePack.MakeGFXInternal(aAlphaShadows: Boolean; aIDList: TList; aFillGFXData: Boolean; aOnCheckTerminated: TBooleanFuncSimple; aMaxAtlasSize: Integer); var - I, K: Integer; texType: TKMTexFormat; - baseRAM, idealRAM, colorRAM, texCount: Cardinal; begin - if SKIP_RENDER then Exit; if fRXData.Count = 0 then Exit; if aAlphaShadows and (fRT in [rxTrees,rxHouses,rxUnits,rxGui,rxTiles]) or not aAlphaShadows and (fRT = rxGuiMain) then @@ -1327,24 +1170,9 @@ begin else texType := tfRGB5A1; - MakeGFX_BinPacking(texType, aIDList, baseRAM, colorRAM, texCount, aFillGFXData, aOnCheckTerminated, aMaxAtlasSize); - - if LOG_EXTRA_GFX then - begin - idealRAM := 0; - for K := 0 to aIDList.Count - 1 do - begin - I := aIDList[K]; - if fRXData.Flag[I] <> 0 then - Inc(idealRAM, fRXData.Size[I].X * fRXData.Size[I].Y * TEX_FORMAT_SIZE[texType]); - end; - - gLog.AddTime(IntToStr(texCount) + ' Textures created'); - gLog.AddNoTime(Format('%d/%d', [baseRAM div 1024, idealRAM div 1024]) + - ' Kbytes allocated/ideal for ' + RX_INFO[fRT].FileName + ' GFX when using Packing'); - gLog.AddNoTime(IntToStr(colorRAM div 1024) + ' KBytes for team colors'); - end; + MakeGFX_BinPacking(texType, aIDList, aFillGFXData, aOnCheckTerminated, aMaxAtlasSize); end; +{$ENDIF} @@ -1377,7 +1205,8 @@ begin end; -procedure TKMSpritePack.MakeGFX_BinPacking(aTexType: TKMTexFormat; aStartingIndex: Integer; var aBaseRAM, aColorRAM, aTexCount: Cardinal; +{$IFNDEF NO_OGL} +procedure TKMSpritePack.MakeGFX_BinPacking(aTexType: TKMTexFormat; aStartingIndex: Integer; aFillGFXData: Boolean = True; aOnCheckTerminated: TBooleanFuncSimple = nil); var I: Integer; @@ -1388,14 +1217,15 @@ begin for I := aStartingIndex to fRXData.Count do idList.Add(I); - MakeGFX_BinPacking(aTexType, idList, aBaseRAM, aColorRAM, aTexCount, aFillGFXData, aOnCheckTerminated); + MakeGFX_BinPacking(aTexType, idList, aFillGFXData, aOnCheckTerminated); finally idList.Free; end; end; +{$ENDIF} -procedure TKMSpritePack.PrepareAtlases(aSpriteInfo: TBinArray; aMode: TKMSpriteAtlasType; aTexType: TKMTexFormat; var aBaseRAM, aColorRAM, aTexCount: Cardinal; +procedure TKMSpritePack.PrepareAtlases(aSpriteInfo: TBinArray; aMode: TKMSpriteAtlasType; aTexType: TKMTexFormat; aFillGFXData: Boolean = True; aOnCheckTerminated: TBooleanFuncSimple = nil); var I, K, L, M: Integer; @@ -1403,7 +1233,6 @@ var texID: Cardinal; ID: Integer; atlasData: TKMCardinalArray; - texFilter: TKMFilterType; begin // gLog.AddTime('Length(aSpriteInfo) = ' + IntToStr(Length(aSpriteInfo))); //Prepare atlases @@ -1458,23 +1287,12 @@ begin if (L = fRXData.Size[ID].Y - 1) then atlasData[Pixel + aSpriteInfo[I].Width] := atlasData[Pixel]; end; - //Sprite outline - if OUTLINE_ALL_SPRITES and ( - (L = 0) or (M = 0) - or (L = fRXData.Size[ID].Y - 1) - or (M = fRXData.Size[ID].X - 1)) then - atlasData[Pixel] := $FF0000FF; end; end; if aFillGFXData then begin - //Generate texture once - texFilter := ftNearest; - if LINEAR_FILTER_SPRITES and (fRT in [rxTrees, rxHouses, rxUnits]) then - texFilter := ftLinear; - - texID := TKMRender.GenTexture(aSpriteInfo[I].Width, aSpriteInfo[I].Height, @atlasData[0], aTexType, texFilter, texFilter); + texID := TKMRender.GenTexture(aSpriteInfo[I].Width, aSpriteInfo[I].Height, @atlasData[0], aTexType, ftNearest, ftNearest); //Now that we know texture IDs we can fill GFXData structure SetGFXData(texID, aSpriteInfo[I], aMode); @@ -1488,19 +1306,13 @@ begin fAtlases[aMode, I].Data := atlasData; end; - if aMode = saBase then - Inc(aBaseRAM, aSpriteInfo[I].Width * aSpriteInfo[I].Height * TEX_FORMAT_SIZE[aTexType]) - else - Inc(aColorRAM, aSpriteInfo[I].Width * aSpriteInfo[I].Height * TEX_FORMAT_SIZE[aTexType]); - - Inc(aTexCount); - end; end; // This algorithm is planned to take advantage of more efficient 2D bin packing -procedure TKMSpritePack.MakeGFX_BinPacking(aTexType: TKMTexFormat; aIDList: TList; var aBaseRAM, aColorRAM, aTexCount: Cardinal; +{$IFNDEF NO_OGL} +procedure TKMSpritePack.MakeGFX_BinPacking(aTexType: TKMTexFormat; aIDList: TList; aFillGFXData: Boolean = True; aOnCheckTerminated: TBooleanFuncSimple = nil; aMaxAtlasSize: Integer = -1); function CheckTerminated: Boolean; begin @@ -1513,8 +1325,6 @@ var spriteInfo: TBinArray; atlasSize, allTilesAtlasSize, maxAtlasSize: Integer; begin - aBaseRAM := 0; - aColorRAM := 0; //Prepare base atlases SetLength(spriteSizes, aIDList.Count);// fRXData.Count - aStartingIndex + 1); K := 0; @@ -1555,7 +1365,7 @@ begin SetLength(fAtlases[saBase], Length(spriteInfo)); - PrepareAtlases(spriteInfo, saBase, aTexType, aBaseRAM, aColorRAM, aTexCount, aFillGFXData, aOnCheckTerminated); + PrepareAtlases(spriteInfo, saBase, aTexType, aFillGFXData, aOnCheckTerminated); if CheckTerminated then Exit; @@ -1579,7 +1389,7 @@ begin BinPack(spriteSizes, atlasSize, fPad, spriteInfo); if CheckTerminated then Exit; SetLength(fAtlases[saMask], Length(spriteInfo)); - PrepareAtlases(spriteInfo, saMask, tfAlpha8, aBaseRAM, aColorRAM, aTexCount, aFillGFXData, aOnCheckTerminated); + PrepareAtlases(spriteInfo, saMask, tfAlpha8, aFillGFXData, aOnCheckTerminated); end; {$ENDIF} @@ -1598,31 +1408,22 @@ end; // Texture generating task can be done only by main thread, as OpenGL does not work with multiple threads // Note: this could be from the loader thread by using `Synchronise` procedure procedure TKMSpritePack.GenerateTexturesFromLoadedRXZ; -{$IFNDEF NO_OGL} var I: Integer; SAT: TKMSpriteAtlasType; texID: Cardinal; - texFilter: TKMFilterType; -{$ENDIF} begin - {$IFNDEF NO_OGL} for SAT := Low(fAtlases) to High(fAtlases) do for I := Low(fAtlases[SAT]) to High(fAtlases[SAT]) do begin with fAtlases[SAT,I] do begin - texFilter := ftNearest; - if LINEAR_FILTER_SPRITES and (fRT in [rxTrees, rxHouses, rxUnits]) then - texFilter := ftLinear; - - texID := TKMRender.GenTexture(Container.Width, Container.Height, @Data[0], TexType, texFilter, texFilter); + texID := TKMRender.GenTexture(Container.Width, Container.Height, @Data[0], TexType, ftNearest, ftNearest); //Now that we know texture IDs we can fill GFXData structure SetGFXData(texID, Container, SAT); end; end; - {$ENDIF} end; @@ -2352,16 +2153,6 @@ begin end; -procedure TKMResSprites.ExportToPNG(aRT: TRXType); -begin - if LoadSprites(aRT, False) then - begin - fSprites[aRT].ExportAllSpritesFromRXData(ExeDir + 'Export' + PathDelim + RX_INFO[aRT].FileName + '.rx' + PathDelim); - ClearTemp; - end; -end; - - constructor TKMGameResourceWorker.Create(aOwner: TKMResSprites; aSerial: QWord; aRT: TRXType; aAlphaShadows, aInputIsRXA: Boolean; aInput: TStream); begin inherited Create(True);