Files
UnrealEngine/Engine/Shaders/Private/MediaShaders.usf
2025-05-18 13:04:45 +08:00

649 lines
23 KiB
HLSL

// Copyright Epic Games, Inc. All Rights Reserved.
/*=============================================================================
MediaShaders.usf: Shaders to convert various media decoder outputs to RGBA
=============================================================================*/
#include "Common.ush"
#include "ColorUtils.ush"
#include "GammaCorrectionCommon.ush"
#include "TonemapCommon.ush"
/* Vertex shader
=============================================================================*/
void MainVertexShader(
in float4 InPosition : ATTRIBUTE0,
in float2 InUV : ATTRIBUTE1,
out float4 OutPosition : SV_POSITION,
out float2 OutUV : TEXCOORD0)
{
OutPosition = InPosition;
OutUV = InUV;
}
/* Pixel shaders
=============================================================================*/
// shader to convert a AYUV texture to RGBA
void AYUVConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float4 AYUV = AYUVConvertUB.Texture.Sample(AYUVConvertUB.Sampler, InUV.xy);
OutColor.xyz = YuvToRgb(AYUV.zyx, AYUVConvertUB.ColorTransform, AYUVConvertUB.SrgbToLinear);
OutColor.w = AYUV.w;
}
// shader to convret a Windows Bitmap texture
void BMPConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
InUV.y = 1.0f - InUV.y;
float2 ScaledUV = InUV * BMPConvertUB.UVScale;
float4 RGB = BMPConvertUB.Texture.Sample(BMPConvertUB.Sampler, ScaledUV);
OutColor.xyz = (BMPConvertUB.SrgbToLinear == 1) ? sRGBToLinear(RGB.xyz) : RGB.xyz;
OutColor.w = RGB.w;
}
#define UE_Color_EEncoding_Linear 1u
#define UE_Color_EEncoding_sRGB 2u
#define UE_Color_EEncoding_ST2084 3u
#define UE_Color_EEncoding_Gamma22 4u
#define UE_Color_EEncoding_BT1886 5u
#define UE_Color_EEncoding_Gamma26 6u
#define UE_Color_EEncoding_Cineon 7u
#define UE_Color_EEncoding_REDLog 8u
#define UE_Color_EEncoding_REDLog3G10 9u
#define UE_Color_EEncoding_SLog1 10u
#define UE_Color_EEncoding_SLog2 11u
#define UE_Color_EEncoding_SLog3 12u
#define UE_Color_EEncoding_AlexaV3LogC 13u
#define UE_Color_EEncoding_CanonLog 14u
#define UE_Color_EEncoding_ProTune 15u
#define UE_Color_EEncoding_VLog 16u
#define ToneMapMethod_None 0u
#define ToneMapMethod_Hable 1u
#define ToneMapMethod_SimpleReinhard 2u
float3 ApplyColorProcessingRGB(float3 Color, float4x4 CSMtx, uint EOTF, uint ToneMapMethod = 0)
{
// Go linear
switch(EOTF)
{
case UE_Color_EEncoding_sRGB: Color = sRGBToLinear(Color); break;
case UE_Color_EEncoding_ST2084: Color = ST2084ToLinear(Color); break;
case UE_Color_EEncoding_SLog3: Color = SLog3ToLinear(Color); break;
default: break;
}
// Adjust colorspace
float4 Col4 = float4(Color, 1);
Color.x = dot(CSMtx[0], Col4);
Color.y = dot(CSMtx[1], Col4);
Color.z = dot(CSMtx[2], Col4);
switch(ToneMapMethod)
{
case ToneMapMethod_Hable: Color = HableToneMap(Color); break;
case ToneMapMethod_SimpleReinhard: Color = SimpleReinhardToneMap(Color); break;
default: break;
}
return Color;
}
float3 ApplyColorProcessing(float3 YUV, float4x4 YUVMtx, float4x4 CSMtx, uint EOTF, uint ToneMapMethod = 0)
{
float3 Color;
float4 YUV4 = float4(YUV, 1);
Color.x = dot(YUVMtx[0], YUV4);
Color.y = dot(YUVMtx[1], YUV4);
Color.z = dot(YUVMtx[2], YUV4);
// Make sure we safely stay above zero
Color = max(Color, 0.0f);
return ApplyColorProcessingRGB(Color, CSMtx, EOTF, ToneMapMethod);
}
// shader to convert a NV12 texture to RGBA (real NV12 texture - DX11)
void NV12ConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 ScaledUV = InUV * NV12ConvertUB.UVScale;
float3 YUV;
YUV.x = NV12ConvertUB.SRV_Y.Sample(NV12ConvertUB.SamplerB, ScaledUV).x;
YUV.yz = NV12ConvertUB.SRV_UV.Sample(NV12ConvertUB.SamplerP, ScaledUV).xy;
YUV.yz = NV12ConvertUB.SwapChroma != 0u ? YUV.zy : YUV.yz;
// Output with solid alpha
OutColor = float4(ApplyColorProcessing(YUV, NV12ConvertUB.ColorTransform, NV12ConvertUB.CSTransform, NV12ConvertUB.EOTF, NV12ConvertUB.ToneMapMethod), 1.0f);
}
// shader to convert a NV12 texture to RGBA (NV12 data, packed into a G8 texture; manually addressed)
void NV12ConvertAsBytesPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 ScaledUV = InUV * NV12ConvertAsBytesUB.UVScale;
float3 YUV;
YUV.x = NV12ConvertAsBytesUB.Texture.Sample(NV12ConvertAsBytesUB.SamplerB, ScaledUV).x;
ScaledUV.y *= 0.5f;
ScaledUV.y += 2.0f / 3.0f;
uint UVOffs = uint(InUV.x * NV12ConvertAsBytesUB.OutputWidth / 2.0f) * 2;
float UPos = (float(UVOffs * NV12ConvertAsBytesUB.UVScale.x) + 0.5f) / NV12ConvertAsBytesUB.OutputWidth;
float VPos = (float(UVOffs * NV12ConvertAsBytesUB.UVScale.x) + 1.5f) / NV12ConvertAsBytesUB.OutputWidth;
YUV.y = NV12ConvertAsBytesUB.Texture.Sample(NV12ConvertAsBytesUB.SamplerP, float2(UPos, ScaledUV.y)).x;
YUV.z = NV12ConvertAsBytesUB.Texture.Sample(NV12ConvertAsBytesUB.SamplerP, float2(VPos, ScaledUV.y)).x;
YUV.yz = NV12ConvertAsBytesUB.SwapChroma != 0u ? YUV.zy : YUV.yz;
OutColor = float4(ApplyColorProcessing(YUV, NV12ConvertAsBytesUB.ColorTransform, NV12ConvertAsBytesUB.CSTransform, NV12ConvertAsBytesUB.EOTF, NV12ConvertAsBytesUB.ToneMapMethod), 1.0f);
}
// shader to convert a NV21 texture to RGBA
void NV21ConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 ScaledUV = InUV * NV21ConvertUB.UVScale;
float3 YUV;
YUV.x = NV21ConvertUB.Texture.Sample(NV21ConvertUB.SamplerB, ScaledUV).x;
ScaledUV.y *= 0.5f;
ScaledUV.y += 2.0f / 3.0f;
uint UVOffs = uint(ScaledUV.x * NV21ConvertUB.OutputWidth / 2.0f) * 2;
float UPos = (float(UVOffs * NV21ConvertUB.UVScale.x) + 1.5f) / NV21ConvertUB.OutputWidth;
float VPos = (float(UVOffs * NV21ConvertUB.UVScale.x) + 0.5f) / NV21ConvertUB.OutputWidth;
YUV.y = NV21ConvertUB.Texture.Sample(NV21ConvertUB.SamplerP, float2(UPos, ScaledUV.y)).x;
YUV.z = NV21ConvertUB.Texture.Sample(NV21ConvertUB.SamplerP, float2(VPos, ScaledUV.y)).x;
OutColor.xyz = YuvToRgb(YUV, NV21ConvertUB.ColorTransform, NV21ConvertUB.SrgbToLinear);
OutColor.w = 1.0f;
}
// shader to convert an RGB texture
void RGBConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 ScaledUV = InUV * RGBConvertUB.UVScale;
float4 Color = RGBConvertUB.Texture.Sample(RGBConvertUB.Sampler, ScaledUV);
OutColor = float4(ApplyColorProcessingRGB(Color.xyz, RGBConvertUB.CSTransform, RGBConvertUB.EOTF, RGBConvertUB.ToneMapMethod),
dot(RGBConvertUB.CSTransform[3], Color));
}
static const float4 kYCoCgOffsets = float4(-0.50196078431373, -0.50196078431373, 0, 0);
// shader to convert an YCoCg texture (usually in DXT5 format - note: no alpha present; it is part of the encoding)
void YCoCgConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 ScaledUV = InUV * YCoCgConvertUB.UVScale;
float4 CoCgSY = YCoCgConvertUB.Texture.Sample(YCoCgConvertUB.Sampler, ScaledUV);
CoCgSY += kYCoCgOffsets;
float Scale = (CoCgSY.z * (255.0 / 8.0)) + 1.0;
float Co = CoCgSY.x / Scale;
float Cg = CoCgSY.y / Scale;
float Y = CoCgSY.w;
float3 Col = float3(Y + Co - Cg, Y + Cg, Y - Co - Cg);
OutColor = float4(ApplyColorProcessingRGB(Col, YCoCgConvertUB.CSTransform, YCoCgConvertUB.EOTF, YCoCgConvertUB.ToneMapMethod), 1.0f);
}
// shader to convert a luma (Y) and chroma (CbCr) texture to RGBA
void YCbCrConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float3 YUV;
YUV.x = YCbCrConvertUB.LumaTexture.Sample(YCbCrConvertUB.LumaSampler, InUV.xy).x;
YUV.yz = YCbCrConvertUB.CbCrTexture.Sample(YCbCrConvertUB.CbCrSampler, InUV.xy).xy;
OutColor.xyz = YuvToRgb(YUV, YCbCrConvertUB.ColorTransform, YCbCrConvertUB.SrgbToLinear);
OutColor.w = 1.0f;
}
// shader to convert a luma (Y) and chroma (CbCr) texture to RGBA using a full 4x4 matrix passed in
void YCbCrConvertPS_4x4Matrix(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float4 YUV;
YUV.x = YCbCrConvertUB.LumaTexture.Sample(YCbCrConvertUB.LumaSampler, InUV.xy).x;
YUV.yz = YCbCrConvertUB.CbCrTexture.Sample(YCbCrConvertUB.CbCrSampler, InUV.xy).xy;
YUV.w = 1.0;
float4 sRGB = mul(YCbCrConvertUB.ColorTransform, YUV);
if (YCbCrConvertUB.SrgbToLinear == 0)
{
OutColor = sRGB;
}
else
{
OutColor = float4(sRGBToLinear(sRGB.xyz), 1.0);
}
}
// shader to convert a UYVY texture to RGBA
void UYVYConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float4 UYVYB = UYVYConvertUB.Texture.Sample(UYVYConvertUB.SamplerB, float2(InUV.x, InUV.y));
float4 UYVYP = UYVYConvertUB.Texture.Sample(UYVYConvertUB.SamplerP, float2(InUV.x, InUV.y));
float Pos = 2.0f * InUV.x * UYVYConvertUB.Width;
float3 YUV;
YUV.x = (floor(Pos % 2.0f) == 0) ? UYVYP.y : UYVYP.w;
YUV.yz = UYVYB.zx;
OutColor.xyz = YuvToRgb(YUV, UYVYConvertUB.ColorTransform, UYVYConvertUB.SrgbToLinear);
OutColor.w = 1.0f;
}
// shader to convert YUV v216/2yuv/vuy2 (YUV 422) to RGB
/*
Input data os expected as RGBA16 data [representing the Cb:Y0:Cr:Y1 or Y0:Cb:Y1:Cr data for each pixel pair]
(data could represent 10, 12, 14 or 16 bits per component - storage is always 16-bit OR plain old 8-bit)
*/
void YUVv216ConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
// Read 422 data from source (1 input texel generates 2 output texels)
uint3 PosUV = uint3(InUV * float2(YUVv216ConvertUB.OutputDimX * 0.5, YUVv216ConvertUB.OutputDimY), 0u);
float4 InRaw = YUVv216ConvertUB.YUVTexture.Load(PosUV);
// Assemble YUV data from input
InRaw = (YUVv216ConvertUB.IsARGBFmt != 0u) ? InRaw.zyxw : InRaw; // PF_ARGB8 vs. PF_ABGR16 ordering
float4 CbY0CrY1 = (YUVv216ConvertUB.IsCbY0CrY1 != 0u) ? InRaw : InRaw.yxwz; // CbY0CrY1 vs. Y0CbY1Cr ordering
CbY0CrY1 = (YUVv216ConvertUB.SwapChroma != 0u) ? CbY0CrY1.zyxw : CbY0CrY1; // Cb/Cr swap
float3 YUV = (uint(InUV.x * YUVv216ConvertUB.OutputDimX) & 1u) ? CbY0CrY1.wxz : CbY0CrY1.yxz; // Decode to YCbCr for odd/even pixels
// Needed for UYVY to RGB
BRANCH
if (YUVv216ConvertUB.UseBilinearSampler != 0u)
{
float4 InSampled = YUVv216ConvertUB.YUVTexture.Sample(YUVv216ConvertUB.SamplerB, InUV);
InSampled = (YUVv216ConvertUB.IsARGBFmt != 0u) ? InSampled.zyxw : InSampled; // PF_ARGB8 vs. PF_ABGR16 ordering
float4 CbY0CrY1Sampled = (YUVv216ConvertUB.IsCbY0CrY1 != 0u) ? InSampled : InSampled.yxwz; // CbY0CrY1 vs. Y0CbY1Cr ordering
CbY0CrY1Sampled = (YUVv216ConvertUB.SwapChroma != 0u) ? CbY0CrY1Sampled.zyxw : CbY0CrY1Sampled; // Cb/Cr swap
float3 YUVSampled = (uint(InUV.x * YUVv216ConvertUB.OutputDimX) & 1u) ? CbY0CrY1Sampled.wxz : CbY0CrY1Sampled.yxz; // Decode to YCbCr for odd/even pixels
YUV.yz = YUVSampled.yz;
}
OutColor = float4(ApplyColorProcessing(YUV, YUVv216ConvertUB.ColorTransform, YUVv216ConvertUB.CSTransform, YUVv216ConvertUB.EOTF, YUVv216ConvertUB.ToneMapMethod), 1.0f);
}
// shader to convert YUV v210 to RGB
/*
Input data is expected as R10G10B10A2 data [representing the Cb:Y0:Cr:Y1 data for each pixel pair, A2 is discarded]
*/
void YUVv210ConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
uint PosX = InUV.x * YUVv210ConvertUB.OutputDimX;
uint PixelIndex = Mod(PosX, 6);
uint3 PosUV = uint3(4 * (PosX / 6), InUV.y * YUVv210ConvertUB.OutputDimY, 0u);
float3 In0 = YUVv210ConvertUB.YUVTexture.Load(PosUV, int2(0,0)).rgb; // Cb0, Y0, Cr0
float3 In1 = YUVv210ConvertUB.YUVTexture.Load(PosUV, int2(1,0)).rgb; // Y1, Cb1, Y2
float3 In2 = YUVv210ConvertUB.YUVTexture.Load(PosUV, int2(2,0)).rgb; // Cr1, Y3, Cb2
float3 In3 = YUVv210ConvertUB.YUVTexture.Load(PosUV, int2(3,0)).rgb; // Y4, Cr2, Y5
float3 YUV;
if (PixelIndex == 0)
{
YUV = In0.yxz;
}
else if (PixelIndex == 1)
{
YUV = float3(In1.x, In0.xz);
}
else if (PixelIndex == 2)
{
YUV = float3(In1.zy, In2.x);
}
else if (PixelIndex == 3)
{
YUV = float3(In2.y, In1.y, In2.x);
}
else if (PixelIndex == 4)
{
YUV = float3(In3.x, In2.z, In3.y);
}
else
{
YUV = float3(In3.z, In2.z, In3.y);
}
OutColor = float4(ApplyColorProcessing(YUV, YUVv210ConvertUB.ColorTransform, YUVv210ConvertUB.CSTransform, YUVv210ConvertUB.EOTF, YUVv210ConvertUB.ToneMapMethod), 1.0f);
}
// shader to convert YUV Y416 to RGB
void YUVY416ConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float4 AVYU = YUVY416ConvertUB.SRV_Y.Sample(YUVY416ConvertUB.BilinearClampedSamplerUV, InUV);
AVYU = (YUVY416ConvertUB.bIsARGBFmt != 0u) ? AVYU.zyxw : AVYU; // PF_ARGB8 vs. PF_ABGR16 ordering
OutColor = float4(ApplyColorProcessing(AVYU.yzw, YUVY416ConvertUB.ColorTransform, YUVY416ConvertUB.CSTransform, YUVY416ConvertUB.EOTF, YUVY416ConvertUB.ToneMapMethod), AVYU.x);
}
// shader to convert ARGB16 big endian to RGB
void ARGB16BigConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
uint4 InRaw = ARGB16BigConvertUB.Texture.Load(uint3(ARGB16BigConvertUB.OutputWidth * InUV.x, ARGB16BigConvertUB.OutputHeight * InUV.y, 0));
InRaw = (InRaw >> 8u) | ((InRaw & 0xff) << 8u);
float4 In = float4(InRaw) * (1.0 / 65535.0);
float3 Color = In.yzw;
OutColor = float4(ApplyColorProcessingRGB(Color, ARGB16BigConvertUB.CSTransform, ARGB16BigConvertUB.EOTF, ARGB16BigConvertUB.ToneMapMethod), In.x);
}
// shader to convert three Y, U, and V textures to RGBA
void YUVConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 ScaledUV = InUV * YUVConvertUB.UVScale;
float3 YUV;
YUV.x = YUVConvertUB.YTexture.Sample(YUVConvertUB.YSampler, ScaledUV).x;
YUV.y = YUVConvertUB.UTexture.Sample(YUVConvertUB.USampler, ScaledUV).x;
YUV.z = YUVConvertUB.VTexture.Sample(YUVConvertUB.VSampler, ScaledUV).x;
OutColor.xyz = YuvToRgb(YUV, YUVConvertUB.ColorTransform, YUVConvertUB.SrgbToLinear);
OutColor.w = 1.0f;
}
// shader to convert a YUY2 texture to RGBA
void YUY2ConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 ScaledUV = InUV * YUY2ConvertUB.UVScale;
float3 YUV;
YUV.yz = YUY2ConvertUB.Texture.Sample(YUY2ConvertUB.SamplerB, ScaledUV).yw;
float4 YUY2P = YUY2ConvertUB.Texture.Sample(YUY2ConvertUB.SamplerP, ScaledUV);
float Pos = InUV.x * YUY2ConvertUB.OutputWidth;
YUV.x = (floor(Pos % 2.0f) == 0) ? YUY2P.z : YUY2P.x;
OutColor.xyz = YuvToRgb(YUV, YUY2ConvertUB.ColorTransform, YUY2ConvertUB.SrgbToLinear);
OutColor.w = 1.0f;
}
// shader to convert a YVYU texture to RGBA
void YVYUConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float4 YVYUB = YVYUConvertUB.Texture.Sample(YVYUConvertUB.SamplerB, float2(InUV.x, InUV.y));
float4 YVYUP = YVYUConvertUB.Texture.Sample(YVYUConvertUB.SamplerP, float2(InUV.x, InUV.y));
float Pos = 2.0f * InUV.x * YVYUConvertUB.Width;
float3 YUV;
YUV.x = (floor(Pos % 2.0f) == 0) ? YVYUP.z : YVYUP.x;
YUV.yz = YVYUB.wy;
OutColor.xyz = YuvToRgb(YUV, YVYUConvertUB.ColorTransform, YVYUConvertUB.SrgbToLinear);
OutColor.w = 1.0f;
}
// shader to convert a P010 texture to RGBA (real P010 texture - DX11)
void P010ConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 ScaledUV = InUV * P010ConvertUB.UVScale;
float3 YUV;
YUV.x = P010ConvertUB.SRV_Y.Sample(P010ConvertUB.SamplerB, ScaledUV).x;
YUV.yz = P010ConvertUB.SRV_UV.Sample(P010ConvertUB.SamplerP, ScaledUV).xy;
OutColor = float4(ApplyColorProcessing(YUV, P010ConvertUB.ColorTransform, P010ConvertUB.CSTransform, P010ConvertUB.EOTF, P010ConvertUB.ToneMapMethod), 1.0f);
}
// shader to convert a P010 texture to RGBA (P010 data, packed into a G16 texture; manually addressed)
void P010ConvertAsUINT16sPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 ScaledUV = InUV * P010ConvertAsUINT16sUB.UVScale;
float3 YUV;
YUV.x = P010ConvertAsUINT16sUB.Texture.Sample(P010ConvertAsUINT16sUB.SamplerB, ScaledUV).x;
ScaledUV.y *= 0.5f;
ScaledUV.y += 2.0f / 3.0f;
uint UVOffs = uint(InUV.x * P010ConvertAsUINT16sUB.OutputWidth / 2.0f) * 2;
float UPos = (float(UVOffs * P010ConvertAsUINT16sUB.UVScale.x) + 0.5f) / P010ConvertAsUINT16sUB.OutputWidth;
float VPos = (float(UVOffs * P010ConvertAsUINT16sUB.UVScale.x) + 1.5f) / P010ConvertAsUINT16sUB.OutputWidth;
YUV.y = P010ConvertAsUINT16sUB.Texture.Sample(P010ConvertAsUINT16sUB.SamplerP, float2(UPos, ScaledUV.y)).x;
YUV.z = P010ConvertAsUINT16sUB.Texture.Sample(P010ConvertAsUINT16sUB.SamplerP, float2(VPos, ScaledUV.y)).x;
OutColor = float4(ApplyColorProcessing(YUV, P010ConvertAsUINT16sUB.ColorTransform, P010ConvertAsUINT16sUB.CSTransform, P010ConvertAsUINT16sUB.EOTF, P010ConvertAsUINT16sUB.ToneMapMethod), 1.0f);
}
// shader to convert P010 data stored as 3 pane RGB_2101010 to RGBA
void P010_2101010ConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
// ES does not allow reuse of the sampler for >1 textures (the shader is unused with that API, though)
#if COMPILER_GLSL_ES3_1==0
// Adjust incoming UVs for Y / UV read
float2 ScaledUV_Y = InUV * P010_2101010ConvertUB.UVScaleY;
float2 ScaledUV_UV = InUV * P010_2101010ConvertUB.UVScaleUV;
// Find out which component of the read pixel we will need for Y and UV respectively
int2 Xint = int2(InUV.x * P010_2101010ConvertUB.OutputWidthY, InUV.x * P010_2101010ConvertUB.OutputWidthUV);
int2 Xlow = Xint % 3;
float3 SelY = (Xlow.x == 0) ? float3(1,0,0) : ((Xlow.x == 1) ? float3(0,1,0) : float3(0,0,1));
float3 SelUV = (Xlow.y == 0) ? float3(1,0,0) : ((Xlow.y == 1) ? float3(0,1,0) : float3(0,0,1));
// Build YUV input value from the 3 textures
float3 YUV;
YUV.x = dot(P010_2101010ConvertUB.SRV_Y.Sample(P010_2101010ConvertUB.SamplerP, ScaledUV_Y).xyz, SelY);
YUV.y = dot(P010_2101010ConvertUB.SRV_U.Sample(P010_2101010ConvertUB.SamplerP, ScaledUV_UV).xyz, SelUV);
YUV.z = dot(P010_2101010ConvertUB.SRV_V.Sample(P010_2101010ConvertUB.SamplerP, ScaledUV_UV).xyz, SelUV);
OutColor = float4(ApplyColorProcessing(YUV, P010_2101010ConvertUB.ColorTransform, P010_2101010ConvertUB.CSTransform, P010_2101010ConvertUB.EOTF, P010_2101010ConvertUB.ToneMapMethod), 1.0f);
#else
OutColor = float4(1,0,1,1);
#endif // COMPILER_GLSL_ES3_1
}
// shader to convert RGB to Y component of YUV
void RGB8toY8ConvertPS(float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float OutColor : SV_Target0)
{
float3 RGB = RGB8toY8ConvertUB.Texture.Sample(RGB8toY8ConvertUB.SamplerP, float2(InUV.x, InUV.y)).rgb;
float3 TempRGB = RGB;
if (RGB8toY8ConvertUB.LinearToSrgb == 1)
{
TempRGB = LinearToSrgb(RGB);
}
// transform rgb to single y/u/v component
float TColor = dot(RGB8toY8ConvertUB.ColorTransform.xyz, TempRGB) + RGB8toY8ConvertUB.ColorTransform.w;
OutColor = clamp(TColor, 0.0f, 1.0f);
}
TextureExternal InExternalTexture;
// shader to read from TextureExternal source
void ReadTextureExternalPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 UV = float2(dot(InUV, ReadTextureExternalUB.ScaleRotation.xy), dot(InUV, ReadTextureExternalUB.ScaleRotation.zw)) + ReadTextureExternalUB.Offset;
float4 RGBOut = TextureExternalSample(InExternalTexture, ReadTextureExternalUB.SamplerP, UV);
OutColor = float4(sRGBToLinear(RGBOut.xyz), 1.0);
}
/* Media Capture Pixel shaders
=============================================================================*/
Texture2D InputTexture;
SamplerState InputSampler;
float4x4 ColorTransform;
uint DoLinearToSrgb;
float OnePixelDeltaX;
float PaddingScale;
float InputPixelOffsetX;
// shader to convert from RGB to 8 bits UYVY
void RGB8toUYVY8ConvertPS(
noperspective float4 UVAndScreenPos : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 UV = UVAndScreenPos.xy;
float3 RGB0 = InputTexture.Sample(InputSampler, float2(UV.x + 0.5f * OnePixelDeltaX, UV.y)).rgb;
float3 RGB1 = InputTexture.Sample(InputSampler, float2(UV.x + 1.5f * OnePixelDeltaX, UV.y)).rgb;
float3 YUV0 = RgbToYuv(RGB0, ColorTransform, DoLinearToSrgb);
float3 YUV1 = RgbToYuv(RGB1, ColorTransform, DoLinearToSrgb);
OutColor.xyzw = float4(YUV0.z, YUV0.x, YUV0.y, YUV1.x);
}
// shader to convert from RGB to YUV v210
void RGB10toYUVv210ConvertPS(
noperspective float4 UVAndScreenPos : TEXCOORD0,
out uint4 OutColor : SV_Target0)
{
float2 UV = UVAndScreenPos.xy;
float X = (UV.x * PaddingScale) - OnePixelDeltaX * 2.5f;
float3 RGB0 = InputTexture.Sample(InputSampler, float2(X, UV.y)).rgb;
float3 RGB1 = InputTexture.Sample(InputSampler, float2(X + OnePixelDeltaX, UV.y)).rgb;
float3 RGB2 = InputTexture.Sample(InputSampler, float2(X + OnePixelDeltaX * 2.0f, UV.y)).rgb;
float3 RGB3 = InputTexture.Sample(InputSampler, float2(X + OnePixelDeltaX * 3.0f, UV.y)).rgb;
float3 RGB4 = InputTexture.Sample(InputSampler, float2(X + OnePixelDeltaX * 4.0f, UV.y)).rgb;
float3 RGB5 = InputTexture.Sample(InputSampler, float2(X + OnePixelDeltaX * 5.0f, UV.y)).rgb;
uint3 YUV0 = RgbToYuv(RGB0, ColorTransform, DoLinearToSrgb) * 1023;
uint3 YUV1 = RgbToYuv(RGB1, ColorTransform, DoLinearToSrgb) * 1023;
uint3 YUV2 = RgbToYuv(RGB2, ColorTransform, DoLinearToSrgb) * 1023;
uint3 YUV3 = RgbToYuv(RGB3, ColorTransform, DoLinearToSrgb) * 1023;
uint3 YUV4 = RgbToYuv(RGB4, ColorTransform, DoLinearToSrgb) * 1023;
uint3 YUV5 = RgbToYuv(RGB5, ColorTransform, DoLinearToSrgb) * 1023;
uint W0 = (YUV0.z << 20) | (YUV0.x << 10) | YUV0.y;
uint W1 = (YUV2.x << 20) | (YUV2.y << 10) | YUV1.x;
uint W2 = (YUV4.y << 20) | (YUV3.x << 10) | YUV2.z;
uint W3 = (YUV5.x << 20) | (YUV4.z << 10) | YUV4.x;
OutColor.xyzw = uint4(W0, W1, W2, W3);
}
// Shader to convert from Android's VYU to RGBA
void VYUConvertPS(
float4 InPosition : SV_POSITION,
float2 InUV : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 ScaledUV = InUV * VYUConvertUB.UVScale;
float3 YUV = VYUConvertUB.Texture.Sample(VYUConvertUB.Sampler, ScaledUV).gbr;
// Output with solid alpha
OutColor = float4(ApplyColorProcessing(YUV, VYUConvertUB.ColorTransform, VYUConvertUB.CSTransform, VYUConvertUB.EOTF, VYUConvertUB.ToneMapMethod), 1.0f);
}
// Following defines must reflect values in EMediaCaptureConversionOperation in MediaOutput
#define INVERT_ALPHA 3
#define SET_ALPHA_ONE 4
// Shader to swizzle rgba textures, set alpha to 1 or invert alpha
void SwizzleRgbPS(
noperspective float4 UVAndScreenPos : TEXCOORD0,
out float4 OutColor : SV_Target0)
{
float2 UV = UVAndScreenPos.xy;
float4 Color = InputTexture.Sample(InputSampler, UV);
#if CONVERSION_OP == INVERT_ALPHA
OutColor.rgba = float4(Color.rgb, 1 - Color.a);
#elif CONVERSION_OP == SET_ALPHA_ONE
OutColor.rgba = float4(Color.rgb, 1.0f);
#else
OutColor.rgba = Color.rgba;
#endif
}