using Godot; namespace Rokojori { public class RDTexture: RenderingObject { public RDTexture( RDContext context, Rid rid ):base( context, rid ){} public static RDTexture Create( RDContext effect, RDTextureFormat format, RDTextureView view ) { return new RDTexture( effect, effect.renderingDevice.TextureCreate( format, view ) ); } public static RDTexture Color( RDContext context ) { var rid = context.sceneBuffers.GetColorLayer( (uint) context.view ); return new RDTexture( context, rid ); } public static RDTexture Depth( RDContext context ) { var rid = context.sceneBuffers.GetDepthLayer( (uint) context.view ); return new RDTexture( context, rid ); } public void SetData( byte[] data, int layer = 0 ) { var error = context.renderingDevice.TextureUpdate( rid, (uint) layer, data ); if ( error == Error.Ok ) { context.Verbose( "Data was set" ); return; } context.Error( error ); } public void SetData( Viewport viewport ) { SetData( viewport.GetTexture().GetImage() ); } public void SetData( Image image ) { var textureDataFormat = RDTextureFormats.ImageFormatToDataFormat( image.GetFormat() ); if ( textureDataFormat != format.Format ) { context.Error( "Incompatible image format:", textureDataFormat, " Expected:", format.Format ); return; } SetData( image.GetData() ); } public int numPixels => (int) ( format.Width * format.Height ); public int channelsPerPixel => RDTextureFormats.GetNumChannels( format.Format ); public RDTextureFormats.PixelChannelEncoding pixelChannelEncoding => RDTextureFormats.GetPixelChannelEncoding( format.Format ); public int bytesPerPixel => RDTextureFormats.NumBytesFor( pixelChannelEncoding ) * channelsPerPixel; public int GetNumBytes( int layer = 0 ) { var bytes = numPixels * bytesPerPixel; while ( layer > 0 ) { bytes /= 4; layer --; } return bytes; } public void SetData( Color color ) { var fmt = format.Format; var colorBytes = RDTextureFormats.ColorToBytes( color, fmt ); if ( colorBytes == null ) { context.Error( "Unsupported texture format" ); return; } context.Verbose( "ColorBytes:", colorBytes ); var bytes = new byte[ GetNumBytes() ]; context.Verbose( "NumPixels", numPixels, "BytesPerPixel", bytesPerPixel, "Num Bytes", GetNumBytes( 0 ) ); for ( int i = 0; i < bytes.Length; i+= colorBytes.Length ) { System.Array.Copy( colorBytes, 0, bytes, i, colorBytes.Length ); } context.Verbose( "First Byte", bytes[ 0 ], bytes[ 1 ], bytes[ 2 ], bytes[ 3 ] ); SetData( bytes ); } public byte[] GetData( int layer = 0) { return context.renderingDevice.TextureGetData( rid, (uint) layer ); } public int width => (int) format.Width; public int height => (int) format.Height; public RenderingDevice.DataFormat dataFormat => format.Format; public Image.Format imageFormat => RDTextureFormats.DataFormatToImageFormat( dataFormat ); public Image GetImage() { var fmt = format; var imgF = RDTextureFormats.DataFormatToImageFormat( format.Format ); var data = GetData(); var output = ""; for ( int i = 0; i < 20; i++ ) { if ( i != 0 ){ output += ", "; } output += data[ i ] + ""; } context.Verbose( "Converting:", fmt.Format, ">>", imgF, "output:", output ); return Image.CreateFromData( (int) fmt.Width, (int)fmt.Height, false, imgF, data ); } public Texture2D GetTexture2D() { return ImageTexture.CreateFromImage( GetImage() ); } public RDTextureFormat format { get { return context.renderingDevice.TextureGetFormat( rid ); } } public Vector2I size { get { var textureFormat = format; return new Vector2I( (int) textureFormat.Width, (int) textureFormat.Height ); } } public static RDTexture EnsureScreenSizeTexture( RDTexture texture, RDContext context, bool cleanUp = true ) { var size = context.internalSize; if ( texture == null || texture.size != size ) { if ( cleanUp && texture != null ) { context.Free( texture, "Old Screen Size Texture" ); } texture = Create( context, size ); } return texture; } public static RDTexture Create( RDContext context, RDTextureFormat format ) { var view = new RDTextureView(); var rid = context.renderingDevice.TextureCreate( format, view ); return new RDTexture( context, rid ); } public static RDTextureFormat DefaultFormat( int w, int h, RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Sfloat) { var format = new RDTextureFormat(); format.Width = (uint) w; format.Height = (uint) h; format.Format = dataFormat; format.UsageBits = RenderingDevice.TextureUsageBits.StorageBit | RenderingDevice.TextureUsageBits.SamplingBit | RenderingDevice.TextureUsageBits.CanCopyFromBit | RenderingDevice.TextureUsageBits.CanUpdateBit | RenderingDevice.TextureUsageBits.CanCopyToBit | RenderingDevice.TextureUsageBits.CpuReadBit ; return format; } public static RDTexture Create( RDContext context, Vector2I size, RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Sfloat ) { return Create( context, size.X, size.Y, dataFormat ); } public static RDTexture Create( RDContext context, int width, int height, RenderingDevice.DataFormat dataFormat = RenderingDevice.DataFormat.R16G16B16A16Sfloat, RenderingDevice.TextureUsageBits textureUsageBits = RDTextureFormats.Usage_Default ) { var view = new RDTextureView(); var format = RDTextureFormats.DefaultFormat( width, height, dataFormat ); format.UsageBits = textureUsageBits; context.Verbose( "Format:", format, "DataFormat", dataFormat); var rid = context.renderingDevice.TextureCreate( format, view ); return new RDTexture( context, rid ); } public static RDTexture CreateCopyFrom( RDContext context, SubViewport viewport ) { var dataFormat = RDTextureFormats.GetDataFormat( viewport ); var bytes = RDTextureFormats.GetNumBytes( viewport ); var image = viewport.GetTexture().GetImage(); var viewPortImageFormat = image.GetFormat(); var rdFormat = RDTextureFormats.ImageFormatToDataFormat( viewPortImageFormat ); var data = image.GetData(); RJLog.Log( "Data", data.Length, Lists.SubList( data, 0, 100 ) ); RJLog.Log( "Copying Texture From", viewport.Size, viewPortImageFormat, rdFormat, "Bytes", bytes ); var texture = Create( context, viewport.Size, dataFormat ); texture.SetData( data ); return texture; } } }