// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only

/*!

\title Optimizing 2D Assets
\page quick3d-asset-conditioning-2d-assets howto

Optimizing the images used by Texture components in your scene can substantially
improve both the startup and runtime performance of your application, as well as
the visual quality in certain situations.

\section1 Motivation

Unoptimized images can hurt the performance of your application in several ways:

\list
\li A large image takes more memory bandwidth when being traversed as a texture.
\li PNG and JPG compressed images must be decompressed before they can be sent to the graphics
    system.
\li Poorly sized images degrade performance and quality on startup
\li Sending uncompressed images to the graphics system takes longer, and they take up more graphics
    memory when there.
\endlist

Additionally, choosing an appropriate size for your images and \l {Using MipMaps}{using mipmaps}
can prevent aliasing issues if your image is going to be shown substantially smaller at some points.

\target image-dimensions
\section1 Reducing Image Dimensions

\note Make your image small, but with dimensions that are power of two.

The first thing you need to do is resize your image to be \e {almost} as small as possible. Smaller
images can be loaded faster by the graphics system as they need less bandwidth and memory. Think
about the largest size that your image will ever be seen at, and resize your image down to that
size. If your texture will be tiling at about 32 pixels per repetition, don't save it at 1024×1024.

However, note that both the horizontal and vertical dimensions of your image
must be POT(power of two) to be stored on the GPU. Most of modern GPUs support
NPOT(non-power of two) textures but many investigations show that using NPOT
textures hurts about 30% of the performance. If you need to use NPOT textures,
we recommend to make the dimensions multiple of 4. It might help your GPU to use
its memory and cache efficiently and finally increase performance.

\note If you are \l {Using MipMaps}{using mipmaps}, there are further constraints on image
dimensions.

\section1 Using MipMaps

\note Use mipmaps when your image may be seen smaller than the original size, including portions
in perspective.

Enabling mipmaps creates many smaller copies of the image at an additional 1/3 memory usage. Each
mipmap dimension is halved from the one preceding it, and is downsized in image editing tool with
good image resampling. The result speeds up rendering, decreases the time that the GPU
uses for texture lookup, and also reduces aliasing artifacts such as moiré effects or
\l {quick3d-asset-conditioning-anti-aliasing#texture-aliasing}{texture subsampling}.

To provide mipmaps at build time, the texture needs to be in a container format like KTX, as
standard image formats do not have the capability of storing mipmaps.

It is possible to generate mipmaps at runtime by setting the property Texture::generateMipmaps
to \c true.

\note Mipmaps require specific image dimensions to work correctly at all levels, depending on which
encoding is used.

\section2 MipMaps and Image Dimensions

If the original image dimensions are represented by \c width, \c height, and \c depth,
the number of mipmap levels will be \c {1 + floor(log2(max(width, height, depth)))}
and each levels' dimensions will be \c {max(1, width_prev >> 1)}, \c {max(1, height_prev >> 1)},
and \c {max(1, depth_prev >> 1)}.

\section1 Saving Alpha Channels

Most of the time when dealing with images with semi-transparent regions, it is easier to use
image editing tool's transparent layers when editing such images. If you choose a compressed
encoding that supports alpha, the transparent regions of your scene are properly used for the
alpha information.

However, in certain cases you need to control the RGB values of fully transparent pixels.
Specifically, you can see visual artifacts if:

\list
\li Any portion of your image will ever be seen at a size larger than saved.
\li You have fully transparent pixels in your image next to rather opaque pixels.
\endlist

In this case, the texture interpolation between a fully-transparent pixel and its neighboring
somewhat-opaque pixel blends the RGB values between the two. If you use the image editing tool's
transparent layers, the RGB values for certain transparent pixels are saved as white, and you
will thus see white fringing at the edges of your transparent regions.

For such cases, instead of creating a semi-transparent layer in your image editing tool, create a
layer with no transparency at all, setting the RGB value for every pixel you care about. Then, save
the alpha information in a fourth channel.

*/
