EM_Task/UnrealEd/Private/Texture2DPreview.cpp
Boshuang Zhao 5144a49c9b add
2026-02-13 16:18:33 +08:00

164 lines
8.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
/*==============================================================================
Texture2DPreview.h: Implementation for previewing 2D Textures and normal maps.
==============================================================================*/
#include "Texture2DPreview.h"
#include "Shader.h"
#include "GlobalShader.h"
#include "SimpleElementShaders.h"
#include "ShaderParameterUtils.h"
#include "PipelineStateCache.h"
#include "TextureResource.h"
#include "RenderCore.h"
#include "VirtualTexturing.h"
#include "Engine/Texture2DArray.h"
/*------------------------------------------------------------------------------
Batched element shaders for previewing 2d textures.
------------------------------------------------------------------------------*/
/**
* Simple pixel shader for previewing 2d textures at a specified mip level
*/
namespace
{
class FTexture2DPreviewVirtualTexture: SHADER_PERMUTATION_BOOL("SAMPLE_VIRTUAL_TEXTURE");
class FTexture2DPreviewTexture2DArray: SHADER_PERMUTATION_BOOL("TEXTURE_ARRAY");
} // namespace
class FSimpleElementTexture2DPreviewPS: public FGlobalShader
{
DECLARE_SHADER_TYPE(FSimpleElementTexture2DPreviewPS, Global);
public:
using FPermutationDomain = TShaderPermutationDomain<FTexture2DPreviewVirtualTexture, FTexture2DPreviewTexture2DArray>;
FSimpleElementTexture2DPreviewPS(const ShaderMetaType::CompiledShaderInitializerType& Initializer): FGlobalShader(Initializer)
{
InTexture.Bind(Initializer.ParameterMap, TEXT("InTexture"), SPF_Mandatory);
InTextureSampler.Bind(Initializer.ParameterMap, TEXT("InTextureSampler"));
InPageTableTexture0.Bind(Initializer.ParameterMap, TEXT("InPageTableTexture0"));
InPageTableTexture1.Bind(Initializer.ParameterMap, TEXT("InPageTableTexture1"));
VTPackedPageTableUniform.Bind(Initializer.ParameterMap, TEXT("VTPackedPageTableUniform"));
VTPackedUniform.Bind(Initializer.ParameterMap, TEXT("VTPackedUniform"));
TextureComponentReplicate.Bind(Initializer.ParameterMap, TEXT("TextureComponentReplicate"));
TextureComponentReplicateAlpha.Bind(Initializer.ParameterMap, TEXT("TextureComponentReplicateAlpha"));
ColorWeights.Bind(Initializer.ParameterMap, TEXT("ColorWeights"));
PackedParameters.Bind(Initializer.ParameterMap, TEXT("PackedParams"));
NumSlices.Bind(Initializer.ParameterMap, TEXT("NumSlices"));
}
FSimpleElementTexture2DPreviewPS() {}
/** Should the shader be cached? Always. */
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
FPermutationDomain PermutationVector(Parameters.PermutationId);
if (IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5) == false)
{
return false;
}
return IsFeatureLevelSupported(Parameters.Platform, ERHIFeatureLevel::SM5) && !IsConsolePlatform(Parameters.Platform);
}
void SetParameters(FRHICommandList& RHICmdList, const FTexture* TextureValue, const FMatrix& ColorWeightsValue, float GammaValue, float MipLevel, float LayerIndex, bool bIsNormalMap, bool bIsSingleVTPhysicalSpace, bool bIsVirtualTexture, bool bIsTextureArray)
{
FRHIPixelShader* ShaderRHI = RHICmdList.GetBoundPixelShader();
if (bIsVirtualTexture)
{
FVirtualTexture2DResource* VirtualTextureValue = (FVirtualTexture2DResource*)TextureValue;
IAllocatedVirtualTexture* AllocatedVT = VirtualTextureValue->AcquireAllocatedVT();
FRHIShaderResourceView* PhysicalView = AllocatedVT->GetPhysicalTextureSRV((uint32)LayerIndex, TextureValue->bSRGB);
SetSRVParameter(RHICmdList, ShaderRHI, InTexture, PhysicalView);
SetSamplerParameter(RHICmdList, ShaderRHI, InTextureSampler, VirtualTextureValue->SamplerStateRHI);
SetTextureParameter(RHICmdList, ShaderRHI, InPageTableTexture0, AllocatedVT->GetPageTableTexture(0u));
if (AllocatedVT->GetNumPageTableTextures() > 1u)
{
SetTextureParameter(RHICmdList, ShaderRHI, InPageTableTexture1, AllocatedVT->GetPageTableTexture(1u));
}
else
{
SetTextureParameter(RHICmdList, ShaderRHI, InPageTableTexture1, GBlackTexture->TextureRHI);
}
FUintVector4 PageTableUniform[2];
FUintVector4 Uniform;
AllocatedVT->GetPackedPageTableUniform(PageTableUniform);
AllocatedVT->GetPackedUniform(&Uniform, (uint32)LayerIndex);
SetShaderValueArray(RHICmdList, ShaderRHI, VTPackedPageTableUniform, PageTableUniform, UE_ARRAY_COUNT(PageTableUniform));
SetShaderValue(RHICmdList, ShaderRHI, VTPackedUniform, Uniform);
}
else
{
SetTextureParameter(RHICmdList, ShaderRHI, InPageTableTexture0, GBlackTexture->TextureRHI);
SetTextureParameter(RHICmdList, ShaderRHI, InPageTableTexture1, GBlackTexture->TextureRHI);
SetTextureParameter(RHICmdList, ShaderRHI, InTexture, InTextureSampler, TextureValue);
}
SetShaderValue(RHICmdList, ShaderRHI, ColorWeights, ColorWeightsValue);
FVector4 PackedParametersValue(GammaValue, MipLevel, bIsNormalMap ? 1.0 : -1.0f, bIsSingleVTPhysicalSpace ? 0 : LayerIndex);
SetShaderValue(RHICmdList, ShaderRHI, PackedParameters, PackedParametersValue);
// Store slice count for texture array
if (bIsTextureArray)
{
const float NumSlicesData = TextureValue ? TextureValue->GetSizeZ() : 1;
SetShaderValue(RHICmdList, ShaderRHI, NumSlices, NumSlicesData);
}
SetShaderValue(RHICmdList, ShaderRHI, TextureComponentReplicate, (TextureValue && TextureValue->bGreyScaleFormat) ? FLinearColor(1, 0, 0, 0) : FLinearColor(0, 0, 0, 0));
SetShaderValue(RHICmdList, ShaderRHI, TextureComponentReplicateAlpha, (TextureValue && TextureValue->bGreyScaleFormat) ? FLinearColor(1, 0, 0, 0) : FLinearColor(0, 0, 0, 1));
}
private:
LAYOUT_FIELD(FShaderResourceParameter, InTexture); // if VT, this used as the physical texture
LAYOUT_FIELD(FShaderResourceParameter, InTextureSampler); // if VT, this is the physical sampler
LAYOUT_FIELD(FShaderResourceParameter, InPageTableTexture0);
LAYOUT_FIELD(FShaderResourceParameter, InPageTableTexture1);
LAYOUT_FIELD(FShaderParameter, VTPackedPageTableUniform);
LAYOUT_FIELD(FShaderParameter, VTPackedUniform);
LAYOUT_FIELD(FShaderParameter, TextureComponentReplicate);
LAYOUT_FIELD(FShaderParameter, TextureComponentReplicateAlpha);
LAYOUT_FIELD(FShaderParameter, ColorWeights);
LAYOUT_FIELD(FShaderParameter, PackedParameters);
LAYOUT_FIELD(FShaderParameter, NumSlices);
};
IMPLEMENT_GLOBAL_SHADER(FSimpleElementTexture2DPreviewPS, "/Engine/Private/SimpleElementTexture2DPreviewPixelShader.usf", "Main", SF_Pixel);
/** Binds vertex and pixel shaders for this element */
void FBatchedElementTexture2DPreviewParameters::BindShaders(
FRHICommandList& RHICmdList,
FGraphicsPipelineStateInitializer& GraphicsPSOInit,
ERHIFeatureLevel::Type InFeatureLevel,
const FMatrix& InTransform,
const float InGamma,
const FMatrix& ColorWeights,
const FTexture* Texture)
{
TShaderMapRef<FSimpleElementVS> VertexShader(GetGlobalShaderMap(InFeatureLevel));
FSimpleElementTexture2DPreviewPS::FPermutationDomain PermutationVector;
PermutationVector.Set<FTexture2DPreviewVirtualTexture>(bIsVirtualTexture);
PermutationVector.Set<FTexture2DPreviewTexture2DArray>(bIsTextureArray);
TShaderMapRef<FSimpleElementTexture2DPreviewPS> PixelShader(GetGlobalShaderMap(InFeatureLevel), PermutationVector);
GraphicsPSOInit.BoundShaderState.VertexDeclarationRHI = GSimpleElementVertexDeclaration.VertexDeclarationRHI;
GraphicsPSOInit.BoundShaderState.VertexShaderRHI = VertexShader.GetVertexShader();
GraphicsPSOInit.BoundShaderState.PixelShaderRHI = PixelShader.GetPixelShader();
GraphicsPSOInit.PrimitiveType = PT_TriangleList;
if (bIsSingleChannelFormat)
{
GraphicsPSOInit.BlendState = TStaticBlendState<>::GetRHI();
}
SetGraphicsPipelineState(RHICmdList, GraphicsPSOInit, EApplyRendertargetOption::ForceApply);
VertexShader->SetParameters(RHICmdList, InTransform);
PixelShader->SetParameters(RHICmdList, Texture, ColorWeights, InGamma, MipLevel, LayerIndex, bIsNormalMap, bIsSingleVTPhysicalSpace, bIsVirtualTexture, bIsTextureArray);
}