649 lines
23 KiB
HLSL
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
|
|
}
|
|
|
|
|