2024-09-05 16:43:17 +02:00
#if UNITY_EDITOR_OSX | | UNITY_STANDALONE_OSX | | UNITY_IOS | | UNITY_TVOS | | UNITY_VISIONOS
#define UNITY_PLATFORM_SUPPORTS_YPCBCR
#endif
#if UNITY_EDITOR | | UNITY_STANDALONE_OSX | | UNITY_STANDALONE_WIN | | UNITY_WSA_10_0 | | UNITY_IOS | | UNITY_TVOS | | UNITY_VISIONOS | | UNITY_ANDROID | | ( UNITY_WEBGL & & UNITY_2017_2_OR_NEWER )
#define UNITY_PLATFORM_SUPPORTS_LINEAR
#endif
using System.Collections ;
using System.Collections.Generic ;
using UnityEngine ;
using UnityEngine.Rendering ;
//-----------------------------------------------------------------------------
// Copyright 2015-2024 RenderHeads Ltd. All rights reserved.
//-----------------------------------------------------------------------------
namespace RenderHeads.Media.AVProVideo
{
#if AVPRO_FEATURE_VIDEORESOLVE
[System.Serializable]
public class VideoResolve : ITextureProducer
{
[SerializeField] VideoResolveOptions _options = VideoResolveOptions . Create ( ) ;
[SerializeField] RenderTexture _targetRenderTexture = null ;
[SerializeField] ScaleMode _targetRenderTextureScale = ScaleMode . ScaleToFit ;
void SetSource ( ITextureProducer textureSource )
{
//_commandBuffer.IssuePluginEvent(blahCallback, 0);
//Graphics.ExecuteCommandBuffer(_commandBuffer);
}
// ITextureProducer implementation
/// <inheritdoc/>
public int GetTextureCount ( ) { return 1 ; }
/// <inheritdoc/>
public Texture GetTexture ( int index = 0 ) { return _texture ; }
/// <inheritdoc/>
public int GetTextureFrameCount ( ) { return _textureSource . GetTextureFrameCount ( ) ; }
/// <inheritdoc/>
public bool SupportsTextureFrameCount ( ) { return _textureSource . SupportsTextureFrameCount ( ) ; }
/// <inheritdoc/>
public long GetTextureTimeStamp ( ) { return _textureSource . GetTextureTimeStamp ( ) ; }
/// <inheritdoc/>
public bool RequiresVerticalFlip ( ) { return false ; }
/// <inheritdoc/>
public StereoPacking GetTextureStereoPacking ( ) { return StereoPacking . None ; }
/// <inheritdoc/>
public TransparencyMode GetTextureTransparency ( ) { return TransparencyMode . Transparent ; }
/// <inheritdoc/>
public AlphaPacking GetTextureAlphaPacking ( ) { return AlphaPacking . None ; }
/// <inheritdoc/>
public Matrix4x4 GetYpCbCrTransform ( ) { return Matrix4x4 . identity ; }
private ITextureProducer _textureSource ;
private Texture _texture ;
private CommandBuffer _commandBuffer ;
}
#endif
public struct LazyShaderProperty
{
public LazyShaderProperty ( string name )
{
_name = name ;
_id = 0 ;
}
public string Name { get { return _name ; } }
public int Id { get { if ( _id = = 0 ) { _id = Shader . PropertyToID ( _name ) ; } return _id ; } }
private string _name ;
private int _id ;
}
/// <summary>Helper class for everything related to setting up materials for rendering/resolving videos</summary>
public class VideoRender
{
public const string Shader_IMGUI = "AVProVideo/Internal/IMGUI/Texture Transparent" ;
public const string Shader_Resolve = "AVProVideo/Internal/Resolve" ;
public const string Shader_ResolveOES = "AVProVideo/Internal/ResolveOES" ;
public const string Shader_Preview = "AVProVideo/Internal/Preview" ;
#if UNITY_PLATFORM_SUPPORTS_YPCBCR
public const string Keyword_UseYpCbCr = "USE_YPCBCR" ;
#endif
public const string Keyword_AlphaPackTopBottom = "ALPHAPACK_TOP_BOTTOM" ;
public const string Keyword_AlphaPackLeftRight = "ALPHAPACK_LEFT_RIGHT" ;
public const string Keyword_AlphaPackNone = "ALPHAPACK_NONE" ;
public const string Keyword_StereoTopBottom = "STEREO_TOP_BOTTOM" ;
public const string Keyword_StereoLeftRight = "STEREO_LEFT_RIGHT" ;
public const string Keyword_StereoCustomUV = "STEREO_CUSTOM_UV" ;
2025-02-21 10:21:19 +01:00
public const string Keyword_StereoTwoTextures = "STEREO_TWO_TEXTURES" ;
2024-09-05 16:43:17 +02:00
public const string Keyword_StereoNone = "MONOSCOPIC" ;
public const string Keyword_StereoDebug = "STEREO_DEBUG" ;
public const string Keyword_LayoutEquirect180 = "LAYOUT_EQUIRECT180" ;
public const string Keyword_LayoutNone = "LAYOUT_NONE" ;
public const string Keyword_ForceEyeNone = "FORCEEYE_NONE" ;
public const string Keyword_ForceEyeLeft = "FORCEEYE_LEFT" ;
public const string Keyword_ForceEyeRight = "FORCEEYE_RIGHT" ;
public const string Keyword_ApplyGamma = "APPLY_GAMMA" ;
public static readonly LazyShaderProperty PropChromaTex = new LazyShaderProperty ( "_ChromaTex" ) ;
2025-02-21 10:21:19 +01:00
// Default right-eye texture shader properties
public static readonly LazyShaderProperty PropMainTex_R = new LazyShaderProperty ( "_MainTex_R" ) ;
public static readonly LazyShaderProperty PropChromaTex_R = new LazyShaderProperty ( "_ChromaTex_R" ) ;
2024-09-05 16:43:17 +02:00
#if UNITY_PLATFORM_SUPPORTS_YPCBCR
public static readonly LazyShaderProperty PropYpCbCrTransform = new LazyShaderProperty ( "_YpCbCrTransform" ) ;
public static readonly LazyShaderProperty PropUseYpCbCr = new LazyShaderProperty ( "_UseYpCbCr" ) ;
#endif
public static readonly LazyShaderProperty PropVertScale = new LazyShaderProperty ( "_VertScale" ) ;
public static readonly LazyShaderProperty PropApplyGamma = new LazyShaderProperty ( "_ApplyGamma" ) ;
public static readonly LazyShaderProperty PropStereo = new LazyShaderProperty ( "Stereo" ) ;
public static readonly LazyShaderProperty PropAlphaPack = new LazyShaderProperty ( "AlphaPack" ) ;
public static readonly LazyShaderProperty PropLayout = new LazyShaderProperty ( "Layout" ) ;
public static readonly LazyShaderProperty PropViewMatrix = new LazyShaderProperty ( "_ViewMatrix" ) ;
public static readonly LazyShaderProperty PropTextureMatrix = new LazyShaderProperty ( "_MainTex_Xfrm" ) ;
public static string Keyword_UseHSBC = "USE_HSBC" ;
public static readonly LazyShaderProperty PropHue = new LazyShaderProperty ( "_Hue" ) ;
public static readonly LazyShaderProperty PropSaturation = new LazyShaderProperty ( "_Saturation" ) ;
public static readonly LazyShaderProperty PropContrast = new LazyShaderProperty ( "_Contrast" ) ;
public static readonly LazyShaderProperty PropBrightness = new LazyShaderProperty ( "_Brightness" ) ;
public static readonly LazyShaderProperty PropInvGamma = new LazyShaderProperty ( "_InvGamma" ) ;
public static Material CreateResolveMaterial ( bool usingAndroidOES )
{
return new Material ( Shader . Find ( usingAndroidOES ? VideoRender . Shader_ResolveOES : VideoRender . Shader_Resolve ) ) ;
}
public static Material CreateIMGUIMaterial ( )
{
return new Material ( Shader . Find ( VideoRender . Shader_Preview ) ) ;
}
public static void SetupLayoutMaterial ( Material material , VideoMapping mapping )
{
switch ( mapping )
{
default :
material . DisableKeyword ( Keyword_LayoutEquirect180 ) ;
material . EnableKeyword ( Keyword_LayoutNone ) ;
break ;
// Only EquiRectangular180 currently does anything in the shader
case VideoMapping . EquiRectangular180 :
material . DisableKeyword ( Keyword_LayoutNone ) ;
material . EnableKeyword ( Keyword_LayoutEquirect180 ) ;
break ;
}
}
public static void SetupStereoEyeModeMaterial ( Material material , StereoEye mode )
{
switch ( mode )
{
case StereoEye . Both :
material . DisableKeyword ( Keyword_ForceEyeLeft ) ;
material . DisableKeyword ( Keyword_ForceEyeRight ) ;
material . EnableKeyword ( Keyword_ForceEyeNone ) ;
break ;
case StereoEye . Left :
material . DisableKeyword ( Keyword_ForceEyeNone ) ;
material . DisableKeyword ( Keyword_ForceEyeRight ) ;
material . EnableKeyword ( Keyword_ForceEyeLeft ) ;
break ;
case StereoEye . Right :
material . DisableKeyword ( Keyword_ForceEyeNone ) ;
material . DisableKeyword ( Keyword_ForceEyeLeft ) ;
material . EnableKeyword ( Keyword_ForceEyeRight ) ;
break ;
}
}
public static void SetupStereoMaterial ( Material material , StereoPacking packing )
{
switch ( packing )
{
case StereoPacking . None :
material . DisableKeyword ( Keyword_StereoTopBottom ) ;
material . DisableKeyword ( Keyword_StereoLeftRight ) ;
material . DisableKeyword ( Keyword_StereoCustomUV ) ;
material . DisableKeyword ( Keyword_StereoTwoTextures ) ;
material . EnableKeyword ( Keyword_StereoNone ) ;
break ;
case StereoPacking . TopBottom :
material . DisableKeyword ( Keyword_StereoNone ) ;
material . DisableKeyword ( Keyword_StereoLeftRight ) ;
material . DisableKeyword ( Keyword_StereoCustomUV ) ;
material . DisableKeyword ( Keyword_StereoTwoTextures ) ;
material . EnableKeyword ( Keyword_StereoTopBottom ) ;
break ;
case StereoPacking . LeftRight :
material . DisableKeyword ( Keyword_StereoNone ) ;
material . DisableKeyword ( Keyword_StereoTopBottom ) ;
material . DisableKeyword ( Keyword_StereoTwoTextures ) ;
material . DisableKeyword ( Keyword_StereoCustomUV ) ;
material . EnableKeyword ( Keyword_StereoLeftRight ) ;
break ;
case StereoPacking . CustomUV :
material . DisableKeyword ( Keyword_StereoNone ) ;
material . DisableKeyword ( Keyword_StereoTopBottom ) ;
material . DisableKeyword ( Keyword_StereoLeftRight ) ;
material . DisableKeyword ( Keyword_StereoTwoTextures ) ;
material . EnableKeyword ( Keyword_StereoCustomUV ) ;
break ;
case StereoPacking . TwoTextures :
material . DisableKeyword ( Keyword_StereoNone ) ;
material . DisableKeyword ( Keyword_StereoTopBottom ) ;
material . DisableKeyword ( Keyword_StereoLeftRight ) ;
material . DisableKeyword ( Keyword_StereoCustomUV ) ;
material . EnableKeyword ( Keyword_StereoTwoTextures ) ;
break ;
}
}
public static void SetupGlobalDebugStereoTinting ( bool enabled )
{
if ( enabled )
{
Shader . EnableKeyword ( Keyword_StereoDebug ) ;
}
else
{
Shader . DisableKeyword ( Keyword_StereoDebug ) ;
}
}
public static void SetupAlphaPackedMaterial ( Material material , AlphaPacking packing )
{
switch ( packing )
{
case AlphaPacking . None :
material . DisableKeyword ( Keyword_AlphaPackTopBottom ) ;
material . DisableKeyword ( Keyword_AlphaPackLeftRight ) ;
material . EnableKeyword ( Keyword_AlphaPackNone ) ;
break ;
case AlphaPacking . TopBottom :
material . DisableKeyword ( Keyword_AlphaPackNone ) ;
material . DisableKeyword ( Keyword_AlphaPackLeftRight ) ;
material . EnableKeyword ( Keyword_AlphaPackTopBottom ) ;
break ;
case AlphaPacking . LeftRight :
material . DisableKeyword ( Keyword_AlphaPackNone ) ;
material . DisableKeyword ( Keyword_AlphaPackTopBottom ) ;
material . EnableKeyword ( Keyword_AlphaPackLeftRight ) ;
break ;
}
}
public static void SetupGammaMaterial ( Material material , bool playerSupportsLinear )
{
#if UNITY_PLATFORM_SUPPORTS_LINEAR
if ( QualitySettings . activeColorSpace = = ColorSpace . Linear & & ! playerSupportsLinear )
{
material . EnableKeyword ( Keyword_ApplyGamma ) ;
}
else
{
material . DisableKeyword ( Keyword_ApplyGamma ) ;
}
#endif
}
public static void SetupTextureMatrix ( Material material , float [ ] transform )
{
if ( material = = null )
return ;
if ( transform = = null | | transform . Length ! = 6 )
transform = new float [ 6 ] { 1.0f , 0.0f , 0.0f , 1.0f , 0.0f , 0.0f } ;
Vector4 v0 = new Vector4 ( transform [ 0 ] , transform [ 1 ] , 0 , 0 ) ;
Vector4 v1 = new Vector4 ( transform [ 2 ] , transform [ 3 ] , 0 , 0 ) ;
Vector4 v2 = new Vector4 ( 0 , 0 , 1 , 0 ) ;
Vector4 v3 = new Vector4 ( transform [ 4 ] , transform [ 5 ] , 0 , 1 ) ;
material . SetMatrix ( PropTextureMatrix . Id , new Matrix4x4 ( v0 , v1 , v2 , v3 ) ) ;
}
public static void SetupTextureMatrix ( Material material , Matrix4x4 transform )
{
if ( material = = null )
return ;
material . SetMatrix ( PropTextureMatrix . Id , transform ) ;
}
#if UNITY_PLATFORM_SUPPORTS_YPCBCR
public static void SetupYpCbCrMaterial ( Material material , bool enable , Matrix4x4 transform , Texture texture )
{
if ( material . HasProperty ( VideoRender . PropUseYpCbCr . Id ) )
{
if ( enable )
{
material . EnableKeyword ( VideoRender . Keyword_UseYpCbCr ) ;
material . SetMatrix ( VideoRender . PropYpCbCrTransform . Id , transform ) ;
material . SetTexture ( VideoRender . PropChromaTex . Id , texture ) ;
}
else
{
material . DisableKeyword ( VideoRender . Keyword_UseYpCbCr ) ;
}
}
}
#endif
public static void SetupVerticalFlipMaterial ( Material material , bool flip )
{
material . SetFloat ( VideoRender . PropVertScale . Id , flip ? - 1f : 1f ) ;
}
public static Texture GetTexture ( MediaPlayer mediaPlayer , int textureIndex )
{
Texture result = null ;
if ( mediaPlayer ! = null )
{
if ( mediaPlayer . UseResampler & & mediaPlayer . FrameResampler ! = null & & mediaPlayer . FrameResampler . OutputTexture ! = null )
{
if ( mediaPlayer . FrameResampler . OutputTexture . Length > textureIndex )
{
result = mediaPlayer . FrameResampler . OutputTexture [ textureIndex ] ;
}
}
else if ( mediaPlayer . TextureProducer ! = null )
{
if ( mediaPlayer . TextureProducer . GetTextureCount ( ) > textureIndex )
{
result = mediaPlayer . TextureProducer . GetTexture ( textureIndex ) ;
}
}
}
return result ;
}
public static void SetupMaterialForMedia ( Material material , MediaPlayer mediaPlayer , int texturePropId = - 1 , Texture fallbackTexture = null , bool forceFallbackTexture = false )
{
Debug . Assert ( material ! = null ) ;
if ( mediaPlayer ! = null )
{
Texture mainTexture = GetTexture ( mediaPlayer , 0 ) ;
Matrix4x4 textureTransform = Matrix4x4 . identity ;
2025-02-21 10:21:19 +01:00
bool isUsingYCbCr = mediaPlayer . IsUsingYCbCr ( ) ;
Texture yCbCrTexture = isUsingYCbCr ? GetTexture ( mediaPlayer , 1 ) : null ;
2024-09-05 16:43:17 +02:00
Matrix4x4 yCbCrTransform = Matrix4x4 . identity ;
2025-02-21 10:21:19 +01:00
2024-09-05 16:43:17 +02:00
StereoPacking stereoPacking = StereoPacking . None ;
AlphaPacking alphaPacking = AlphaPacking . None ;
bool flipY = false ;
bool isLinear = false ;
if ( texturePropId ! = - 1 )
{
if ( mainTexture = = null | | forceFallbackTexture )
{
mainTexture = fallbackTexture ;
}
material . SetTexture ( texturePropId , mainTexture ) ;
}
ITextureProducer textureProducer = mediaPlayer . TextureProducer ;
if ( textureProducer ! = null )
{
flipY = textureProducer . RequiresVerticalFlip ( ) ;
2025-02-21 10:21:19 +01:00
if ( isUsingYCbCr )
{
yCbCrTransform = textureProducer . GetYpCbCrTransform ( ) ;
}
2024-09-05 16:43:17 +02:00
stereoPacking = textureProducer . GetTextureStereoPacking ( ) ;
alphaPacking = textureProducer . GetTextureAlphaPacking ( ) ;
textureTransform = textureProducer . GetTextureMatrix ( ) ;
}
if ( mediaPlayer . Info ! = null )
{
isLinear = mediaPlayer . Info . PlayerSupportsLinearColorSpace ( ) ;
}
SetupMaterial ( material , flipY , isLinear , yCbCrTransform , yCbCrTexture , textureTransform , mediaPlayer . VideoLayoutMapping , stereoPacking , alphaPacking ) ;
2025-02-21 10:21:19 +01:00
if ( stereoPacking = = StereoPacking . TwoTextures )
{
#if UNITY_PLATFORM_SUPPORTS_YPCBCR
if ( isUsingYCbCr )
{
material . SetTexture ( PropMainTex_R . Id , GetTexture ( mediaPlayer , 2 ) ) ;
material . SetTexture ( PropChromaTex_R . Id , GetTexture ( mediaPlayer , 3 ) ) ;
}
else
#endif
{
material . SetTexture ( PropMainTex_R . Id , GetTexture ( mediaPlayer , 1 ) ) ;
}
}
2024-09-05 16:43:17 +02:00
}
else
{
if ( texturePropId ! = - 1 )
{
material . SetTexture ( texturePropId , fallbackTexture ) ;
}
SetupMaterial ( material , false , true , Matrix4x4 . identity , null , Matrix4x4 . identity ) ;
}
}
internal static void SetupMaterial (
Material material ,
bool flipVertically ,
bool playerSupportsLinear ,
Matrix4x4 ycbcrTransform ,
Texture ycbcrTexture ,
Matrix4x4 textureTransform ,
VideoMapping mapping = VideoMapping . Normal ,
StereoPacking stereoPacking = StereoPacking . None ,
AlphaPacking alphaPacking = AlphaPacking . None )
{
SetupVerticalFlipMaterial ( material , flipVertically ) ;
// Apply changes for layout
if ( material . HasProperty ( VideoRender . PropLayout . Id ) )
{
VideoRender . SetupLayoutMaterial ( material , mapping ) ;
}
// Apply changes for stereo videos
if ( material . HasProperty ( VideoRender . PropStereo . Id ) )
{
VideoRender . SetupStereoMaterial ( material , stereoPacking ) ;
}
// Apply changes for alpha videos
if ( material . HasProperty ( VideoRender . PropAlphaPack . Id ) )
{
VideoRender . SetupAlphaPackedMaterial ( material , alphaPacking ) ;
}
// Apply gamma correction
#if UNITY_PLATFORM_SUPPORTS_LINEAR
if ( material . HasProperty ( VideoRender . PropApplyGamma . Id ) )
{
VideoRender . SetupGammaMaterial ( material , playerSupportsLinear ) ;
}
#endif
// Adjust for cropping/orientation (when the decoder decodes in blocks that overrun the video frame size, it pads), OES only as we apply this lower down for none-OES
VideoRender . SetupTextureMatrix ( material , textureTransform ) ;
#if UNITY_PLATFORM_SUPPORTS_YPCBCR
VideoRender . SetupYpCbCrMaterial ( material , ycbcrTexture ! = null , ycbcrTransform , ycbcrTexture ) ;
#endif
}
[System.Flags]
public enum ResolveFlags : int
{
Mipmaps = 1 < < 0 ,
PackedAlpha = 1 < < 1 ,
StereoLeft = 1 < < 2 ,
StereoRight = 1 < < 3 ,
ColorspaceSRGB = 1 < < 4 ,
}
public static void SetupResolveMaterial ( Material material , VideoResolveOptions options )
{
if ( options . IsColourAdjust ( ) )
{
material . EnableKeyword ( VideoRender . Keyword_UseHSBC ) ;
material . SetFloat ( VideoRender . PropHue . Id , options . hue ) ;
material . SetFloat ( VideoRender . PropSaturation . Id , options . saturation ) ;
material . SetFloat ( VideoRender . PropBrightness . Id , options . brightness ) ;
material . SetFloat ( VideoRender . PropContrast . Id , options . contrast ) ;
material . SetFloat ( VideoRender . PropInvGamma . Id , 1f / options . gamma ) ;
}
else
{
material . DisableKeyword ( VideoRender . Keyword_UseHSBC ) ;
}
material . color = options . tint ;
}
public static RenderTexture ResolveVideoToRenderTexture ( Material resolveMaterial , RenderTexture targetTexture , ITextureProducer texture , ResolveFlags flags , ScaleMode scaleMode = ScaleMode . StretchToFill )
{
int targetWidth = texture . GetTexture ( 0 ) . width ;
int targetHeight = texture . GetTexture ( 0 ) . height ;
StereoEye eyeMode = StereoEye . Both ;
if ( ( ( flags & ResolveFlags . StereoLeft ) = = ResolveFlags . StereoLeft ) & &
( ( flags & ResolveFlags . StereoRight ) ! = ResolveFlags . StereoRight ) )
{
eyeMode = StereoEye . Left ;
}
else if ( ( ( flags & ResolveFlags . StereoLeft ) ! = ResolveFlags . StereoLeft ) & &
( ( flags & ResolveFlags . StereoRight ) = = ResolveFlags . StereoRight ) )
{
eyeMode = StereoEye . Right ;
}
// RJT NOTE: No longer passing in PAR as combined with larger videos (e.g. 8K+) it can lead to textures >16K which most platforms don't support
// - Instead, the PAR is accounted for during drawing (which is more efficient too)
// - https://github.com/RenderHeads/UnityPlugin-AVProVideo/issues/1297
float pixelAspectRatio = 1.0f ; // texture.GetTexturePixelAspectRatio();
GetResolveTextureSize (
texture . GetTextureAlphaPacking ( ) ,
texture . GetTextureStereoPacking ( ) ,
eyeMode ,
pixelAspectRatio ,
texture . GetTextureMatrix ( ) ,
ref targetWidth ,
ref targetHeight ) ;
if ( targetTexture )
{
bool sizeChanged = ( targetTexture . width ! = targetWidth ) | | ( targetTexture . height ! = targetHeight ) ;
if ( sizeChanged )
{
RenderTexture . ReleaseTemporary ( targetTexture ) ;
targetTexture = null ;
}
}
if ( ! targetTexture )
{
2025-02-21 10:21:19 +01:00
GetCompatibleRenderTextureFormatOptions options = GetCompatibleRenderTextureFormatOptions . ForResolve ;
if ( texture . GetTextureAlphaPacking ( ) ! = AlphaPacking . None )
{
options | = GetCompatibleRenderTextureFormatOptions . RequiresAlpha ;
}
RenderTextureFormat format = texture . GetCompatibleRenderTextureFormat ( options ) ;
2024-09-05 16:43:17 +02:00
RenderTextureReadWrite readWrite = ( ( flags & ResolveFlags . ColorspaceSRGB ) = = ResolveFlags . ColorspaceSRGB ) ? RenderTextureReadWrite . sRGB : RenderTextureReadWrite . Linear ;
2025-02-21 10:21:19 +01:00
targetTexture = RenderTexture . GetTemporary ( targetWidth , targetHeight , 0 , format , readWrite ) ;
2024-09-05 16:43:17 +02:00
}
// Set target mipmap generation support
{
bool requiresMipmap = ( flags & ResolveFlags . Mipmaps ) = = ResolveFlags . Mipmaps ;
bool requiresRecreate = ( targetTexture . IsCreated ( ) & & targetTexture . useMipMap ! = requiresMipmap ) ;
if ( requiresRecreate )
{
targetTexture . Release ( ) ;
}
if ( ! targetTexture . IsCreated ( ) )
{
targetTexture . useMipMap = targetTexture . autoGenerateMips = requiresMipmap ;
targetTexture . Create ( ) ;
}
}
// Render resolve blit
// TODO: combine these two paths into a single material blit
{
bool prevSRGB = GL . sRGBWrite ;
GL . sRGBWrite = targetTexture . sRGB ;
RenderTexture prev = RenderTexture . active ;
if ( scaleMode = = ScaleMode . StretchToFill )
{
Graphics . Blit ( texture . GetTexture ( 0 ) , targetTexture , resolveMaterial ) ;
}
else
{
RenderTexture . active = targetTexture ;
bool partialAreaRender = ( scaleMode = = ScaleMode . ScaleToFit ) ;
if ( partialAreaRender )
{
GL . Clear ( false , true , Color . black ) ;
}
VideoRender . DrawTexture ( new Rect ( 0f , 0f , targetTexture . width , targetTexture . height ) , texture . GetTexture ( 0 ) , scaleMode , texture . GetTextureAlphaPacking ( ) , texture . GetTexturePixelAspectRatio ( ) , resolveMaterial ) ;
}
RenderTexture . active = prev ;
GL . sRGBWrite = prevSRGB ;
}
return targetTexture ;
}
public static void GetResolveTextureSize ( AlphaPacking alphaPacking , StereoPacking stereoPacking , StereoEye eyeMode , float pixelAspectRatio , Matrix4x4 textureXfrm , ref int width , ref int height )
{
Vector4 size = new Vector4 ( width , height , 0 , 0 ) ;
size = textureXfrm * size ;
width = ( int ) Mathf . Abs ( size . x ) ;
height = ( int ) Mathf . Abs ( size . y ) ;
switch ( alphaPacking )
{
case AlphaPacking . LeftRight :
width / = 2 ;
break ;
case AlphaPacking . TopBottom :
height / = 2 ;
break ;
}
if ( eyeMode ! = StereoEye . Both )
{
switch ( stereoPacking )
{
case StereoPacking . LeftRight :
width / = 2 ;
break ;
case StereoPacking . TopBottom :
height / = 2 ;
break ;
}
}
if ( pixelAspectRatio > 0f )
{
if ( pixelAspectRatio > 1f )
{
width = Mathf . RoundToInt ( width * pixelAspectRatio ) ;
}
else if ( pixelAspectRatio < 1f )
{
height = Mathf . RoundToInt ( height / pixelAspectRatio ) ;
}
}
}
public static bool RequiresResolve ( ITextureProducer texture )
{
2025-02-21 10:21:19 +01:00
return texture . GetTextureAlphaPacking ( ) ! = AlphaPacking . None | |
texture . RequiresVerticalFlip ( ) | |
texture . GetTextureStereoPacking ( ) ! = StereoPacking . None | |
texture . GetTextureCount ( ) > 1 ;
2024-09-05 16:43:17 +02:00
}
public static void DrawTexture ( Rect destRect , Texture texture , ScaleMode scaleMode , AlphaPacking alphaPacking , float pixelAspectRatio , Material material )
{
if ( Event . current = = null | | Event . current . type = = EventType . Repaint )
{
int sourceWidth = texture . width ;
int sourceHeight = texture . height ;
Matrix4x4 textureXfrm = Matrix4x4 . identity ;
GetResolveTextureSize ( alphaPacking , StereoPacking . Unknown , StereoEye . Both , pixelAspectRatio , textureXfrm , ref sourceWidth , ref sourceHeight ) ;
float sourceRatio = ( float ) sourceWidth / ( float ) sourceHeight ;
Rect sourceRect = new Rect ( 0f , 0f , 1f , 1f ) ;
switch ( scaleMode )
{
case ScaleMode . ScaleAndCrop :
{
float destRatio = destRect . width / destRect . height ;
if ( destRatio > sourceRatio )
{
float adjust = sourceRatio / destRatio ;
sourceRect = new Rect ( 0f , ( 1f - adjust ) * 0.5f , 1f , adjust ) ;
}
else
{
float adjust = destRatio / sourceRatio ;
sourceRect = new Rect ( 0.5f - adjust * 0.5f , 0f , adjust , 1f ) ;
}
}
break ;
case ScaleMode . ScaleToFit :
{
float destRatio = destRect . width / destRect . height ;
if ( destRatio > sourceRatio )
{
float adjust = sourceRatio / destRatio ;
destRect = new Rect ( destRect . xMin + destRect . width * ( 1f - adjust ) * 0.5f , destRect . yMin , adjust * destRect . width , destRect . height ) ;
}
else
{
float adjust = destRatio / sourceRatio ;
destRect = new Rect ( destRect . xMin , destRect . yMin + destRect . height * ( 1f - adjust ) * 0.5f , destRect . width , adjust * destRect . height ) ;
}
}
break ;
case ScaleMode . StretchToFill :
break ;
}
GL . PushMatrix ( ) ;
if ( RenderTexture . active = = null )
{
//GL.LoadPixelMatrix();
GL . LoadPixelMatrix ( 0f , Screen . width , Screen . height , 0f ) ;
}
else
{
GL . LoadPixelMatrix ( 0f , RenderTexture . active . width , RenderTexture . active . height , 0f ) ;
}
Graphics . DrawTexture ( destRect , texture , sourceRect , 0 , 0 , 0 , 0 , GUI . color , material ) ;
GL . PopMatrix ( ) ;
}
}
}
}