203 lines
7.5 KiB
C++
203 lines
7.5 KiB
C++
// Copyright 2020-2024 CesiumGS, Inc. and Contributors
|
|
|
|
#pragma once
|
|
|
|
#include "CesiumAsync/SharedAssetDepot.h"
|
|
#include "CesiumGltf/Model.h"
|
|
#include "CesiumGltf/Texture.h"
|
|
#include "CesiumMetadataValueType.h"
|
|
#include "CesiumTextureResource.h"
|
|
#include "Engine/Texture.h"
|
|
#include "Engine/Texture2D.h"
|
|
#include "Engine/TextureDefines.h"
|
|
#include "RHI.h"
|
|
#include "Runtime/Launch/Resources/Version.h"
|
|
#include "Templates/UniquePtr.h"
|
|
#include <CesiumUtility/IntrusivePointer.h>
|
|
#include <CesiumUtility/ReferenceCounted.h>
|
|
|
|
namespace CesiumGltf {
|
|
struct ImageAsset;
|
|
struct Texture;
|
|
} // namespace CesiumGltf
|
|
|
|
namespace CesiumTextureUtility {
|
|
|
|
// A slightly roundabout way to a hold a UTexture2D.
|
|
//
|
|
// We can't let Unreal's garbage collector be exclusively responsible for the
|
|
// lifetime of our textures because it doesn't run often enough (and not at all
|
|
// in the Editor). And we also need shared ownership of UTexture2Ds when a tile
|
|
// is "upsampled" from its parent for raster overlays. So this class allows us
|
|
// to control the lifetime of a UTexture2D via reference counting.
|
|
//
|
|
// Yes, this means we're controlling the lifetime of a garbage collected
|
|
// `UTexture2D` object via reference counting.
|
|
//
|
|
// Instances of this class are created whenever we create a UTexture2D. A
|
|
// pointer to the instance is held in `LoadedTextureResult` as well as in a
|
|
// private extension added to the glTF `Texture` from which the UTexture2D was
|
|
// created.
|
|
struct ReferenceCountedUnrealTexture
|
|
: CesiumUtility::ReferenceCountedThreadSafe<ReferenceCountedUnrealTexture> {
|
|
ReferenceCountedUnrealTexture() noexcept;
|
|
~ReferenceCountedUnrealTexture() noexcept;
|
|
|
|
// The texture game object, once it's created.
|
|
TObjectPtr<UTexture2D> getUnrealTexture() const;
|
|
void setUnrealTexture(const TObjectPtr<UTexture2D>& p);
|
|
|
|
// The renderer / RHI FTextureResource holding the pixel data.
|
|
const FCesiumTextureResourceUniquePtr& getTextureResource() const;
|
|
FCesiumTextureResourceUniquePtr& getTextureResource();
|
|
void setTextureResource(FCesiumTextureResourceUniquePtr&& p);
|
|
|
|
private:
|
|
TObjectPtr<UTexture2D> _pUnrealTexture;
|
|
FCesiumTextureResourceUniquePtr _pTextureResource;
|
|
};
|
|
|
|
/**
|
|
* @brief Half-loaded Unreal texture with info on how to finish loading the
|
|
* texture on the game thread and render thread.
|
|
*/
|
|
struct LoadedTextureResult {
|
|
TextureAddress addressX;
|
|
TextureAddress addressY;
|
|
TextureFilter filter;
|
|
TextureGroup group;
|
|
bool sRGB{true};
|
|
|
|
// The index of the `CesiumGltf::Texture` instance with the glTF. Or -1 if
|
|
// this result wasn't created from a texture in a glTF.
|
|
int64_t textureIndex = -1;
|
|
|
|
// The UTexture2D that has already been created, if any.
|
|
CesiumUtility::IntrusivePointer<ReferenceCountedUnrealTexture> pTexture;
|
|
};
|
|
|
|
/**
|
|
* Does the asynchronous part of renderer resource preparation for a `Texture`
|
|
* in a glTF. Should be called in a worker thread.
|
|
*
|
|
* The `cesium.pixelData` will be removed from the image associated with the
|
|
* texture so that it can be passed to Unreal's renderer thread without copying
|
|
* it.
|
|
*
|
|
* @param model The glTF Model for which to load this texture.
|
|
* @param texture The glTF Texture to load. This parameter is non-const because
|
|
* a private extension will be added to this `Texture` in order to track the
|
|
* associated Unreal texture.
|
|
* @param sRGB True if the texture should be treated as sRGB; false if it should
|
|
* be treated as linear.
|
|
* {@link CesiumGltf::Model::images}, and all pointers must be initialized to
|
|
* nullptr before the first call to `loadTextureFromModelAnyThreadPart` during
|
|
* the glTF load process.
|
|
*/
|
|
TUniquePtr<LoadedTextureResult> loadTextureFromModelAnyThreadPart(
|
|
CesiumGltf::Model& model,
|
|
CesiumGltf::Texture& texture,
|
|
bool sRGB);
|
|
|
|
/**
|
|
* Does the asynchronous part of renderer resource preparation for a glTF
|
|
* `Image` with the given `Sampler` settings.
|
|
*
|
|
* The `cesium.pixelData` will be removed from the image so that it can be
|
|
* passed to Unreal's renderer thread without copying it.
|
|
*
|
|
* @param image The glTF image for each to create a texture.
|
|
* @param sampler The sampler settings to use with the texture.
|
|
* @param sRGB True if the texture should be treated as sRGB; false if it should
|
|
* be treated as linear.
|
|
*/
|
|
TUniquePtr<LoadedTextureResult> loadTextureFromImageAndSamplerAnyThreadPart(
|
|
CesiumGltf::ImageAsset& image,
|
|
const CesiumGltf::Sampler& sampler,
|
|
bool sRGB);
|
|
|
|
/**
|
|
* @brief Does the asynchronous part of renderer resource preparation for
|
|
* a texture.The given image _must_ be prepared before calling this method by
|
|
* calling {@link ExtensionImageAssetUnreal::getOrCreate} and then waiting
|
|
* for {@link ExtensionImageAssetUnreal::getFuture} to resolve. This method
|
|
* should be called in a background thread.
|
|
*
|
|
* @param image The image.
|
|
* @param addressX The X addressing mode.
|
|
* @param addressY The Y addressing mode.
|
|
* @param filter The sampler filtering to use for this texture.
|
|
* @param useMipMapsIfAvailable true to use this image's mipmaps for sampling,
|
|
* if they exist; false to ignore any mipmaps that might be present.
|
|
* @param group The texture group of this texture.
|
|
* @param sRGB Whether this texture uses a sRGB color space.
|
|
* @param overridePixelFormat The explicit pixel format to use. If std::nullopt,
|
|
* the pixel format is inferred from the image.
|
|
* @return The loaded texture.
|
|
*/
|
|
TUniquePtr<LoadedTextureResult> loadTextureAnyThreadPart(
|
|
CesiumGltf::ImageAsset& image,
|
|
TextureAddress addressX,
|
|
TextureAddress addressY,
|
|
TextureFilter filter,
|
|
bool useMipMapsIfAvailable,
|
|
TextureGroup group,
|
|
bool sRGB,
|
|
std::optional<EPixelFormat> overridePixelFormat);
|
|
|
|
/**
|
|
* @brief Does the main-thread part of render resource preparation for this
|
|
* image and queues up any required render-thread tasks to finish preparing the
|
|
* image.
|
|
*
|
|
* @param model The model with which this texture is associated. This is used to
|
|
* store a pointer to the created texture in an extension on the glTF texture so
|
|
* that it can be reused later.
|
|
* @param pHalfLoadedTexture The half-loaded renderer texture.
|
|
* @return The Unreal texture result.
|
|
*/
|
|
CesiumUtility::IntrusivePointer<ReferenceCountedUnrealTexture>
|
|
loadTextureGameThreadPart(
|
|
CesiumGltf::Model& model,
|
|
LoadedTextureResult* pHalfLoadedTexture);
|
|
|
|
/**
|
|
* @brief Does the main-thread part of render resource preparation for this
|
|
* image and queues up any required render-thread tasks to finish preparing the
|
|
* image.
|
|
*
|
|
* @param pHalfLoadedTexture The half-loaded renderer texture.
|
|
* @return The Unreal texture result.
|
|
*/
|
|
CesiumUtility::IntrusivePointer<ReferenceCountedUnrealTexture>
|
|
loadTextureGameThreadPart(LoadedTextureResult* pHalfLoadedTexture);
|
|
|
|
/**
|
|
* @brief Convert a glTF {@link CesiumGltf::Sampler::WrapS} value to an Unreal
|
|
* `TextureAddress` value.
|
|
*
|
|
* @param wrapS The glTF wrapS value.
|
|
* @returns The Unreal equivalent, or `TextureAddress::TA_Wrap` if the glTF
|
|
* value is unknown or invalid.
|
|
*/
|
|
TextureAddress convertGltfWrapSToUnreal(int32_t wrapS);
|
|
|
|
/**
|
|
* @brief Convert a glTF {@link CesiumGltf::Sampler::WrapT} value to an Unreal
|
|
* `TextureAddress` value.
|
|
*
|
|
* @param wrapT The glTF wrapT value.
|
|
* @returns The Unreal equivalent, or `TextureAddress::TA_Wrap` if the glTF
|
|
* value is unknown or invalid.
|
|
*/
|
|
TextureAddress convertGltfWrapTToUnreal(int32_t wrapT);
|
|
|
|
std::optional<EPixelFormat> getPixelFormatForImageAsset(
|
|
const CesiumGltf::ImageAsset& imageCesium,
|
|
const std::optional<EPixelFormat> overridePixelFormat);
|
|
|
|
std::optional<ReferenceCountedUnrealTexture>
|
|
getUnrealTextureFromGltfTexture(const CesiumGltf::Texture& texture);
|
|
|
|
} // namespace CesiumTextureUtility
|