Перейти к содержанию
Fire Monkey от А до Я
  • 0

Чудовищный баг с альфа-каналом и StyleBook'ом


HoShiMin

Вопрос

Есть моделька человека, собранная из TPlane'ов, на голове - шлем, на шлем накладывается текстура с прозрачными пикселями. Модельку можно вращать. Если подключить StyleBook, то голова перестаёт прорисовываться сквозь прозрачные пиксели при вращении.

 

Запустили приложение, голова прорисована:

9fe0b565f3.png

 

Поворачиваем - голова мгновенно "стирается":

E2pkl78UaepEmY.png

 

Отключаем StyleBook - крутим модельку, всё хорошо:

V2Veq0VSKWXymv.png

 

 

Как исправить рендеринг сквозь прозрачные пиксели?

 

P.S.: Если в StyleBook'e поставить галочку на UseStyleManager, то снова всё отрисовывается нормально, но использовать StyleManager очень неудобно.

 

 

Код текстурирования

// Скопировать часть битмапа в другой битмап:
procedure CopyBitmapToBitmap(
                              const SrcBitmap    : FMX.Graphics.TBitmap; // Из какого битмапа копируем
                              const DestBitmap   : FMX.Graphics.TBitmap; // В какой битмап копируем
                              const SrcRect      : TRectF;               // Какой прямоугольник
                              const DstRect      : TRectF;               // В какой прямоугольник
                              ScaleCoeff         : Single  = 1.0;        // Коэффициент масштабирования (DstRect * ScaleCoeff)
                              Opacity            : Single  = 1.0;        // Коэффициент прозрачности накладываемого изображения
                              FlushBeforeDrawing : Boolean = True;       // Очищать ли предыдущее содержимое
                              Interpolate        : Boolean = False       // Интерполировать ли при масштабировании
                             );
 
  function Max(const A, B: Single): Single; inline;
  begin
    if A > B then Result := A else Result := B;
  end;
 
begin
  if FlushBeforeDrawing then DestBitmap.Clear($00000000);
  DestBitmap.SetSize(Round(Max(DstRect.Left, DstRect.Right) * ScaleCoeff), Round(Max(DstRect.Top, DstRect.Bottom) * ScaleCoeff));
 
  DestBitmap.Canvas.BeginScene;
  DestBitmap.Canvas.DrawBitmap(
                                SrcBitmap,
                                SrcRect,
                                RectF(
                                       DstRect.Left,
                                       DstRect.Top,
                                       DstRect.Left + ((DstRect.Right - DstRect.Left) * ScaleCoeff),
                                       DstRect.Top  + ((DstRect.Bottom - DstRect.Top) * ScaleCoeff)
                                      ),
                                Opacity,
                                not Interpolate
                               );
  DestBitmap.Canvas.EndScene;
end;
 
 
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 
 
procedure TMainForm.DrawSkin(FileStream: TMemoryStream);
type
  TTextureInfo  = array of Integer;      // OffsetX, OffsetY, Width, Height
  TCubeTexture  = array of TTextureInfo; // Front, Back, Left, Right, Top, Bottom
  TSurfaceArray = array of ^TPlane;
 
// Индексы элементов в массивах:
const
  iOffsetX = 0;
  iOffsetY = 1;
  iWidth   = 2;
  iHeight  = 3;
 
  iFront  = 0;
  iBack   = 1;
  iLeft   = 2;
  iRight  = 3;
  iTop    = 4;
  iBottom = 5;
 
  iHead     = 0;
  iTorso    = 1;
  iLeftArm  = 2;
  iRightArm = 3;
  iLeftLeg  = 4;
  iRightLeg = 5;
  iHelmet   = 6;
 
const
  HeadTexture : TCubeTexture = [// X  Y  W  H
                                 [8 , 8, 8, 8], // Front
                                 [24, 8, 8, 8], // Back
                                 [0 , 8, 8, 8], // Left
                                 [16, 8, 8, 8], // Right
                                 [8 , 0, 8, 8], // Top
                                 [16, 0, 8, 8]  // Bottom
                                ];
 
  ... { здесь пропущен список координат для каждой текстуры из битмапа } ...  
 
const
  ScaleCoeff: Single = 16.0;
 
var
  Bitmap: FMX.Graphics.TBitmap;
 
  // Список поверхностей каждой части модели:
  HeadPlanes     : TSurfaceArray;
  TorsoPlanes    : TSurfaceArray;
  LeftArmPlanes  : TSurfaceArray;
  RightArmPlanes : TSurfaceArray;
  LeftLegPlanes  : TSurfaceArray;
  RightLegPlanes : TSurfaceArray;
  HelmetPlanes   : TSurfaceArray;
 
  // Список частей модели:
  ModelParts: array of ^TSurfaceArray;
 
  // Список текстур каждой части модели:
  ObjectTextures: array of ^TCubeTexture;
 
  // I - счётчик по частям модели, J - счётчик по поверхностям:
  I, J: LongWord;
 
begin
  // Загружаем битмап из PNG-файла:
  Bitmap := FMX.Graphics.TBitmap.Create;
  Bitmap.LoadFromStream(FileStream);
 
  // Составляем массив из групп текстур для каждой части модели:
  ObjectTextures := [@HeadTexture, @TorsoTexture, @LeftArmTexture, @RightArmTexture, @LeftLegTexture, @RightLegTexture, @HelmetTexture];
 
  // Составляем список поверхностей:
  HeadPlanes     := [@HeadFront    , @HeadBack    , @HeadLeft    , @HeadRight    , @HeadTop    , @HeadBottom    ];
  TorsoPlanes    := [@TorsoFront   , @TorsoBack   , @TorsoLeft   , @TorsoRight   , @TorsoTop   , @TorsoBottom   ];
  LeftArmPlanes  := [@LeftArmFront , @LeftArmBack , @LeftArmLeft , @LeftArmRight , @LeftArmTop , @LeftArmBottom ];
  RightArmPlanes := [@RightArmFront, @RightArmBack, @RightArmLeft, @RightArmRight, @RightArmTop, @RightArmBottom];
  LeftLegPlanes  := [@LeftLegFront , @LeftLegBack , @LeftLegLeft , @LeftLegRight , @LeftLegTop , @LeftLegBottom ];
  RightLegPlanes := [@RightLegFront, @RightLegBack, @RightLegLeft, @RightLegRight, @RightLegTop, @RightLegBottom];
  HelmetPlanes   := [@HelmetFront  , @HelmetBack  , @HelmetLeft  , @HelmetRight  , @HelmetTop  , @HelmetBottom  ];
 
  // Составляем список частей модели:
  ModelParts := [@HeadPlanes, @TorsoPlanes, @LeftArmPlanes, @RightArmPlanes, @LeftLegPlanes, @RightLegPlanes, @HelmetPlanes];
 
  // Проходимся по каждой части модели (голова, корпус, ...):
  for I := 0 to High(ModelParts) do
  begin
    // Проходимся по каждой поверхности модели:
    for J := 0 to High(ModelParts[I]^) do
    begin
      // Рисуем текстуру на каждой поверхности:
      with (ModelParts[I]^)[J]^ do
      begin
        CopyBitmapToBitmap(
                            Bitmap,
                            TTextureMaterialSource(MaterialSource).Texture,
                            RectF(
                                   (ObjectTextures[I]^)[J][iOffsetX],
                                   (ObjectTextures[I]^)[J][iOffsetY],
                                   (ObjectTextures[I]^)[J][iOffsetX] + (ObjectTextures[I]^)[J][iWidth],
                                   (ObjectTextures[I]^)[J][iOffsetY] + (ObjectTextures[I]^)[J][iHeight]
                                  ),
                            RectF(0, 0, (ObjectTextures[I]^)[J][iWidth], (ObjectTextures[I]^)[J][iHeight]),
                            ScaleCoeff
                           );
 
        // Инвертируем текстуры для симметрии:
        if I in [iLeftArm, iLeftLeg] then
          TTextureMaterialSource(MaterialSource).Texture.FlipHorizontal;
 
      end;
    end;
  end;
 
  FreeAndNil(Bitmap);
end;
Ссылка на комментарий

Рекомендуемые сообщения

Ответов пока нет

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...