bmh/FlightSimulation/Plugins/CesiumForUnreal_5.4/Source/CesiumRuntime/Private/CesiumTextureUtility.h
2025-02-07 22:52:32 +08:00

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