/// <summary> /// Function to read the textures for the font. /// </summary> /// <param name="filePath">The path to the font file.</param> /// <param name="fontInfo">The information about the font.</param> /// <returns>A list of textures.</returns> private IReadOnlyList <GorgonTexture2D> ReadTextures(string filePath, BmFontInfo fontInfo) { var textures = new GorgonTexture2D[fontInfo.FontTextures.Length]; var directory = new DirectoryInfo(Path.GetDirectoryName(filePath).FormatDirectory(Path.DirectorySeparatorChar)); Debug.Assert(directory.Exists, "Font directory should exist, but does not."); for (int i = 0; i < fontInfo.FontTextures.Length; ++i) { var fileInfo = new FileInfo(directory.FullName.FormatDirectory(Path.DirectorySeparatorChar) + fontInfo.FontTextures[i].FormatFileName()); if (!fileInfo.Exists) { throw new FileNotFoundException(string.Format(Resources.GORGFX_ERR_FONT_TEXTURE_FILE_NOT_FOUND, fileInfo.FullName)); } IGorgonImageCodec codec = GetImageCodec(fileInfo.Extension); using (IGorgonImage image = codec.LoadFromFile(fileInfo.FullName)) { image.ToTexture2D(Factory.Graphics, new GorgonTexture2DLoadOptions { Name = $"BmFont_Texture_{Guid.NewGuid():N}" }); } } return(textures); }
/// <summary> /// Function to clean up the renderer objects. /// </summary> private void CleanUpRenderer() { if (_renderer == null) { return; } if (_lastState != null) { _renderer.End2D(_lastState); _lastState = null; } if (_texture != null) { _texture.Dispose(); _texture = null; } if (_defaultTexture != null) { _defaultTexture.Dispose(); _defaultTexture = null; } if (_swapChain != null) { _swapChain.Dispose(); _swapChain = null; } _clipper = null; _graphics = null; }
/// <summary> /// Function to update the text on the label that allows previewing of the atlas. /// </summary> /// <param name="dataContext">The current data context.</param> private void UpdateLabelArrayText(ITextureAtlas dataContext) { if ((dataContext?.Atlas?.Textures == null) || (dataContext.Atlas.Textures.Count == 0)) { LabelArray.Text = Resources.GORTAG_TEXT_NO_ATLAS; return; } GorgonTexture2D texture = dataContext.Atlas.Textures[dataContext.PreviewTextureIndex].Texture; if ((dataContext.Atlas.Textures.Count == 1) && (texture.ArrayCount == 1)) { LabelArray.Text = string.Empty; return; } if (dataContext.Atlas.Textures.Count == 1) { LabelArray.Text = string.Format(Resources.GORTAG_TEXT_ARRAY_COUNT, dataContext.PreviewArrayIndex + 1, texture.ArrayCount); return; } if (texture.ArrayCount == 1) { LabelArray.Text = string.Format(Resources.GORTAG_TEXT_TEXTURE_COUNT, dataContext.PreviewTextureIndex + 1, dataContext.Atlas.Textures.Count); return; } LabelArray.Text = string.Format(Resources.GORTAG_TEXT_ARRAY_TEXTURE_COUNT, dataContext.PreviewArrayIndex + 1, texture.ArrayCount, dataContext.PreviewTextureIndex + 1, dataContext.Atlas.Textures.Count); }
/// <summary> /// Function to set up the renderer. /// </summary> /// <param name="renderer">Renderer to use.</param> public void SetupRenderer(Gorgon2D renderer) { if (DesignMode) { return; } try { Gorgon.ApplicationIdleLoopMethod = null; if (_renderer != renderer) { CleanUpRenderer(); } if (renderer == null) { return; } _renderer = renderer; _graphics = renderer.Graphics; if (_swapChain == null) { _swapChain = _graphics.Output.CreateSwapChain("ImageDisplay", new GorgonSwapChainSettings { Window = panelTextureDisplay, Format = BufferFormat.R8G8B8A8_UIntNormal }); } if (_lastState == null) { _lastState = renderer.Begin2D(); } if (_defaultTexture == null) { _defaultTexture = _graphics.Textures.CreateTexture <GorgonTexture2D>("DefaultPattern", Resources.Pattern); } if (_clipper == null) { InitializeClipper(null, RectangleF.Empty); } _region = new RectangleF(0, 0, 1, 1); _renderer.Target = _swapChain; Gorgon.ApplicationIdleLoopMethod = Idle; } finally { ValidateCommands(); } }
/// <summary> /// Function to read a keyframe from a chunk. /// </summary> /// <param name="chunk">Chunk to read from.</param> void IKeyFrame.FromChunk(GorgonChunkReader chunk) { Value = null; Time = chunk.ReadFloat(); bool hasTexture = chunk.ReadBoolean(); // Get the texture region we're using. TextureRegion = chunk.ReadRectangleF(); if (!hasTexture) { return; } // Get our texture name. _textureName = chunk.ReadString(); // Read in our texture information. _settings = new GorgonTexture2DSettings { ArrayCount = chunk.ReadInt32(), Format = chunk.Read <BufferFormat>(), Size = chunk.ReadSize(), IsTextureCube = chunk.ReadBoolean(), MipCount = chunk.ReadInt32(), Multisampling = new GorgonMultisampling(chunk.ReadInt32(), chunk.ReadInt32()), Usage = BufferUsage.Default, ShaderViewFormat = BufferFormat.Unknown }; // Defer load the texture. GetTexture(); }
/// <summary> /// Raises the <see cref="E:System.Windows.Forms.Form.Load" /> event. /// </summary> /// <param name="e">An <see cref="T:System.EventArgs" /> that contains the event data.</param> protected override void OnLoad(EventArgs e) { base.OnLoad(e); Cursor.Current = Cursors.WaitCursor; try { // Set up the graphics interface. _graphics = new GorgonGraphics(); // Create our 2D renderer to display the image. _2D = _graphics.Output.Create2DRenderer(this, 1280, 800); // Center the window on the screen. Screen currentMonitor = Screen.FromControl(this); Location = new Point(currentMonitor.WorkingArea.Left + (currentMonitor.WorkingArea.Width / 2 - Width / 2), currentMonitor.WorkingArea.Top + (currentMonitor.WorkingArea.Height / 2 - Height / 2)); // Load our base texture. _image = _graphics.Textures.FromMemory <GorgonTexture2D>("SourceTexture", Resources.SourceTexture, new GorgonCodecDDS()); // Load the custom codec. if (!LoadCodec()) { GorgonDialogs.ErrorBox(this, "Unable to load the useless image codec plug-in."); Gorgon.Quit(); return; } // Convert the image to our custom codec. ConvertImage(); // Set up our idle time processing. Gorgon.ApplicationIdleLoopMethod = () => { _2D.Clear(Color.White); // Draw to the window. Draw(); // Render with a vsync interval of 2 (typically 30 FPS). // We're not making an action game here. _2D.Render(2); return(true); }; } catch (Exception ex) { GorgonDialogs.ErrorBox(this, ex); Gorgon.Quit(); } finally { Cursor.Current = Cursors.Default; } }
/// <summary> /// Function called when the content has changed. /// </summary> public override void RefreshContent() { base.RefreshContent(); if (_content == null) { throw new InvalidCastException(string.Format(Resources.GORSPR_ERR_CONTENT_NOT_SPRITE, Content.Name)); } SetUpScrolling(); if (_anchorImage == null) { _anchorImage = ContentObject.Graphics.Textures.CreateTexture <GorgonTexture2D>("AnchorTexture", Resources.anchor_24x24); _anchorSprite = _content.Renderer.Renderables.CreateSprite("AnchorSprite", _anchorImage.Settings.Size, _anchorImage); _anchorSprite.Anchor = new Vector2(_anchorSprite.Size.X / 2.0f, _anchorSprite.Size.Y / 2.0f); _anchorSprite.SmoothingMode = SmoothingMode.Smooth; _anchorAnim = new AnchorColorAnim(); scrollHorizontal.Value = 0; scrollVertical.Value = 0; _clipper = new Clipper(_content.Renderer, panelSprite) { SelectorPattern = _content.BackgroundTexture, DefaultCursor = Cursors.Cross }; _halfScreen = (Point)(new Vector2(panelSprite.ClientSize.Width / 2.0f, panelSprite.ClientSize.Height / 2.0f)); CalculateSpritePosition(); } ValidateControls(); }
public void Test2DStagingFail() { GorgonTexture2D texture = null; try { texture = _framework.Graphics.Textures.CreateTexture("Test2D", new GorgonTexture2DSettings { Width = 256, Height = 256, ArrayCount = 1, Format = BufferFormat.R8G8B8A8, MipCount = 1, AllowUnorderedAccessViews = false, Usage = BufferUsage.Staging }); texture.GetShaderView(BufferFormat.R8G8B8A8_Int); } finally { if (texture != null) { texture.Dispose(); } } }
/// <summary> /// Function to render the thumbnail into the image passed in. /// </summary> /// <param name="image">The image to render the thumbnail into.</param> /// <param name="scale">The scale of the image.</param> private void RenderThumbnail(ref IGorgonImage image, float scale) { lock (_syncLock) { using (GorgonTexture2D texture = image.ToTexture2D(GraphicsContext.Graphics, new GorgonTexture2DLoadOptions { Usage = ResourceUsage.Immutable, IsTextureCube = false })) using (var rtv = GorgonRenderTarget2DView.CreateRenderTarget(GraphicsContext.Graphics, new GorgonTexture2DInfo { ArrayCount = 1, Binding = TextureBinding.ShaderResource, Format = BufferFormat.R8G8B8A8_UNorm, MipLevels = 1, Height = (int)(image.Height * scale), Width = (int)(image.Width * scale), Usage = ResourceUsage.Default })) { GorgonTexture2DView view = texture.GetShaderResourceView(mipCount: 1, arrayCount: 1); rtv.Clear(GorgonColor.BlackTransparent); GraphicsContext.Graphics.SetRenderTarget(rtv); GraphicsContext.Graphics.DrawTexture(view, new DX.Rectangle(0, 0, rtv.Width, rtv.Height), blendState: GorgonBlendState.Default, samplerState: GorgonSamplerState.Default); GraphicsContext.Graphics.SetRenderTarget(null); image?.Dispose(); image = rtv.Texture.ToImage(); } } }
/// <summary> /// Releases unmanaged and - optionally - managed resources. /// </summary> /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param> protected override void Dispose(bool disposing) { if (!_disposed) { if (disposing) { if (_logo != null) { _logo.Dispose(); } if (_2D != null) { _2D.Dispose(); } } } _container = null; _2D = null; _logo = null; _disposed = true; base.Dispose(disposing); }
/// <summary> /// Function to perform initialization on the content. /// </summary> /// <returns>A control to embed into the container interface.</returns> protected override ContentPanel OnInitialize() { _delta = Program.Settings.AnimateStartPageLogo ? Program.Settings.StartPageAnimationPulseRate.Abs() : 0; _container = new ContentPanel(this) { CaptionVisible = false }; _2D = Graphics.Output.Create2DRenderer(_container.PanelDisplay); // Create the logo for display. _logo = Graphics.Textures.FromMemory <GorgonTexture2D>("Logo", Resources.Gorgon_2_x_Logo_Blurry, new GorgonCodecDDS()); var textureCoordinates = new RectangleF(Vector2.Zero, _logo.ToTexel(new Vector2(_logo.Settings.Width, _logo.Settings.Height / 3))); // Set up coordinates for our blurred images. _blurStates = new[] { textureCoordinates, // No blur. new RectangleF(new Vector2(0, textureCoordinates.Height), textureCoordinates.Size), // Medium blur. new RectangleF(new Vector2(0, textureCoordinates.Height * 2), textureCoordinates.Size) // Max blur. }; _sourceState = _blurStates[2]; _destState = _blurStates[1]; return(_container); }
/// <summary> /// Function to load a texture from a file. /// </summary> /// <param name="graphics">The graphics interface that will own the texture.</param> /// <param name="filePath">The path to the file.</param> /// <param name="codec">The codec that is used to decode the the data in the stream.</param> /// <param name="options">[Optional] Options used to further define the texture.</param> /// <returns>A new <see cref="GorgonTexture2DReadWriteView"/></returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="graphics"/>, <paramref name="filePath"/>, or the <paramref name="codec"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="filePath"/> parameter is empty.</exception> /// <remarks> /// <para> /// This will load an <see cref="IGorgonImage"/> from a file on disk and put it into a <see cref="GorgonTexture2D"/> object and return a <see cref="GorgonTexture2DReadWriteView"/>. /// </para> /// <para> /// If specified, the <paramref name="options"/>parameter will define how Gorgon and shaders should handle the texture. The <see cref="GorgonTextureLoadOptions"/> type contains the following: /// <list type="bullet"> /// <item> /// <term>Binding</term> /// <description>When defined, will indicate the <see cref="TextureBinding"/> that defines how the texture will be bound to the graphics pipeline. If it is omitted, then the binding will be /// <see cref="TextureBinding.ShaderResource"/>.</description> /// </item> /// <item> /// <term>Usage</term> /// <description>When defined, will indicate the preferred usage for the texture. If it is omitted, then the usage will be set to <see cref="ResourceUsage.Default"/>.</description> /// </item> /// <item> /// <term>Multisample info</term> /// <description>When defined (i.e. not <b>null</b>), defines the multisampling to apply to the texture. If omitted, then the default is <see cref="GorgonMultisampleInfo.NoMultiSampling"/>.</description> /// </item> /// <item> /// <term>ConvertToPremultipliedAlpha</term> /// <description>Converts the image to premultiplied alpha before uploading the image data to the texture.</description> /// </item> /// </list> /// </para> /// <para> /// Since the <see cref="GorgonTexture2D"/> created by this method is linked to the <see cref="GorgonTexture2DReadWriteView"/> returned, disposal of either one will dispose of the other on your behalf. If /// the user created a <see cref="GorgonTexture2DReadWriteView"/> from the <see cref="GorgonTexture2D.GetShaderResourceView"/> method on the <see cref="GorgonTexture2D"/>, then it's assumed the user knows /// what they are doing and will handle the disposal of the texture and view on their own. /// </para> /// </remarks> public static GorgonTexture2DReadWriteView FromFile(GorgonGraphics graphics, string filePath, IGorgonImageCodec codec, GorgonTexture2DLoadOptions options = null) { if (graphics == null) { throw new ArgumentNullException(nameof(graphics)); } if (filePath == null) { throw new ArgumentNullException(nameof(filePath)); } if (string.IsNullOrWhiteSpace(filePath)) { throw new ArgumentEmptyException(nameof(filePath)); } if (codec == null) { throw new ArgumentNullException(nameof(codec)); } using (IGorgonImage image = codec.LoadFromFile(filePath)) { GorgonTexture2D texture = image.ToTexture2D(graphics, options); GorgonTexture2DReadWriteView view = texture.GetReadWriteView(); view.OwnsResource = true; return(view); } }
/// <summary> /// Function to build builds from the font information. /// </summary> /// <param name="textures">The list of textures loaded.</param> /// <param name="fontInfo">The font information to retrieve glyph data from.</param> /// <returns>A new list of glyphs.</returns> private IReadOnlyList <GorgonGlyph> GetGlyphs(IReadOnlyList <GorgonTexture2D> textures, BmFontInfo fontInfo) { var glyphs = new List <GorgonGlyph>(); foreach (char character in fontInfo.Characters) { int advance = fontInfo.CharacterAdvances[character]; // Build a glyph that is not linked to a texture if it's whitespace. if (char.IsWhiteSpace(character)) { glyphs.Add(CreateGlyph(character, advance)); continue; } int textureIndex = fontInfo.GlyphTextureIndices[character]; GorgonTexture2D texture = textures[textureIndex]; DX.Rectangle glyphRectangle = fontInfo.GlyphRects[character]; DX.Point offset = fontInfo.GlyphOffsets[character]; GorgonGlyph glyph = CreateGlyph(character, advance); glyph.Offset = offset; glyph.UpdateTexture(texture, glyphRectangle, DX.Rectangle.Empty, 0); glyphs.Add(glyph); } return(glyphs); }
/// <summary> /// Handles the Click event of the ButtonImagePath control. /// </summary> /// <param name="sender">The source of the event.</param> /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param> private void ButtonImagePath_Click(object sender, EventArgs e) { Cursor.Current = Cursors.WaitCursor; IGorgonImage image = null; var png = new GorgonCodecPng(); try { if (DialogOpenPng.ShowDialog(this) != DialogResult.OK) { return; } TextImagePath.Text = DialogOpenPng.FileName; _sourceTexture?.Texture?.Dispose(); _outputTexture?.Dispose(); _sourceTexture = null; _outputTexture = null; image = png.LoadFromFile(DialogOpenPng.FileName); _sourceTexture = image.ConvertToFormat(BufferFormat.R8G8B8A8_UNorm) .ToTexture2D(_graphics, new GorgonTexture2DLoadOptions { Name = Path.GetFileNameWithoutExtension(DialogOpenPng.FileName) }).GetShaderResourceView(); _outputTexture = new GorgonTexture2D(_graphics, new GorgonTexture2DInfo(_sourceTexture, "Output") { Format = BufferFormat.R8G8B8A8_Typeless, Binding = TextureBinding.ShaderResource | TextureBinding.ReadWriteView }); // Get an SRV for the output texture so we can render it later. _outputView = _outputTexture.GetShaderResourceView(BufferFormat.R8G8B8A8_UNorm); // Get a UAV for the output. _outputUav = _outputTexture.GetReadWriteView(BufferFormat.R32_UInt); // Process the newly loaded texture. _sobel.Process(_sourceTexture, _outputUav, TrackThickness.Value, TrackThreshold.Value / 100.0f); TrackThreshold.Enabled = TrackThickness.Enabled = true; } catch (Exception ex) { GorgonDialogs.ErrorBox(this, ex); TrackThreshold.Enabled = TrackThickness.Enabled = false; } finally { image?.Dispose(); Cursor.Current = Cursors.Default; } }
/// <summary> /// Funciton to generate random noise for the effect. /// </summary> private void GenerateRandomNoise() { int textureSize = 128; object parameter; if ((Parameters.TryGetValue("TextureSize", out parameter)) && (parameter != null)) { var size = (int)parameter; if (size > 16) { textureSize = size; } } using (var image = new GorgonImageData(new GorgonTexture2DSettings { Width = textureSize, Height = textureSize, Format = BufferFormat.R8_UIntNormal, Usage = BufferUsage.Default })) { unsafe { var dataPtr = (byte *)image.Buffers[0].Data.UnsafePointer; // Write perlin noise to the texture. for (int y = 0; y < textureSize; ++y) { for (int x = 0; x < textureSize; ++x) { float simplexNoise = GorgonRandom.SimplexNoise(new Vector2(x * (1.0f / _noiseFrequency), y * (1.0f / _noiseFrequency))); if (simplexNoise < -0.75f) { simplexNoise *= -1; } else { simplexNoise *= 0.95f; } if (simplexNoise < 0.125f) { simplexNoise = 0.0f; } *(dataPtr++) = (byte)(simplexNoise * 255.0f); } } } _randomTexture = Graphics.Textures.CreateTexture <GorgonTexture2D>("Effect.OldFilm.RandomTexture", image); } }
/// <summary> /// Edits the specified object's value using the editor style indicated by the <see cref="M:System.Drawing.Design.UITypeEditor.GetEditStyle" /> method. /// </summary> /// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext" /> that can be used to gain additional context information.</param> /// <param name="provider">An <see cref="T:System.IServiceProvider" /> that this editor can use to obtain services.</param> /// <param name="value">The object to edit.</param> /// <returns> /// The new value of the object. If the value of the object has not changed, this should return the same object it was passed. /// </returns> public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value) { var sprite = (GorgonSpriteContent)((ContentTypeDescriptor)context.Instance).Content; GorgonTexture2D currentTexture = sprite.Texture; string textureName = currentTexture != null ? currentTexture.Name : string.Empty; Dependency dependency = sprite.Dependencies.SingleOrDefault(item => string.Equals(item.Type, GorgonSpriteContent.TextureDependencyType)); using (var editorDialog = new EditorFileDialog { Text = Resources.GORSPR_DLG_SELECT_TEXTURE, Filename = textureName, StartDirectory = GorgonSpriteEditorPlugIn.Settings.LastTexturePath, FileView = FileViews.Large }) { editorDialog.FileTypes.Add(sprite.ImageEditor.ContentType); if ((editorDialog.ShowDialog() == DialogResult.Cancel) || (string.Equals(editorDialog.Filename, textureName, StringComparison.OrdinalIgnoreCase))) { // Resharper is just plain wrong here. EditValue can most certainly return NULL. // ReSharper disable once AssignNullToNotNullAttribute return(currentTexture); } GorgonTexture2D texture; // Read the new texture. using (Stream file = editorDialog.OpenFile()) { using (IImageEditorContent image = sprite.ImageEditor.ImportContent(editorDialog.Files[0], file)) { if (image.Image.Settings.ImageType != ImageType.Image2D) { throw new GorgonException(GorgonResult.CannotRead, Resources.GORSPR_ERR_2D_TEXTURE_ONLY); } texture = ContentObject.Graphics.Textures.CreateTexture <GorgonTexture2D>(editorDialog.Filename, image.Image); } } // Update the dependency list for this sprite. if (dependency != null) { if (sprite.Dependencies.Contains(dependency.EditorFile, dependency.Type)) { sprite.Dependencies.Remove(dependency.EditorFile, dependency.Type); } } sprite.Dependencies[editorDialog.Files[0], GorgonSpriteContent.TextureDependencyType] = new Dependency(editorDialog.Files[0], GorgonSpriteContent.TextureDependencyType); sprite.Dependencies.CacheDependencyObject(editorDialog.Files[0], GorgonSpriteContent.TextureDependencyType, texture); GorgonSpriteEditorPlugIn.Settings.LastTexturePath = Path.GetDirectoryName(editorDialog.Filename).FormatDirectory('/'); return(texture); } }
/// <summary> /// Function to clean up resources used by the effect. /// </summary> public void FreeResources() { if (_randomTexture == null) { return; } _randomTexture.Dispose(); _randomTexture = null; }
/// <summary> /// Function to create a new sprite object. /// </summary> /// <param name="name">Name of the sprite.</param> /// <param name="size">Size of the sprite.</param> /// <param name="texture">Texture to apply to the sprite.</param> /// <returns>A new sprite.</returns> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="name"/> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="System.ArgumentException">Thrown when the name parameter is an empty string.</exception> public GorgonSprite CreateSprite(string name, Vector2 size, GorgonTexture2D texture) { Vector2 texelSize = Vector2.Zero; if (texture != null) { texelSize = texture.ToTexel(size); } return(CreateSprite(name, size, texture, new RectangleF(Vector2.Zero, texelSize))); }
/// <summary> /// Function to draw a filled rectangle onto the current target. /// </summary> /// <param name="rectangle">Rectangle dimensions.</param> /// <param name="color">Color for the rectangle.</param> /// <param name="texture">Texture to apply to the rectangle.</param> /// <param name="textureRegion">Texture dimensions to use.</param> public void FilledRectangle(RectangleF rectangle, GorgonColor color, GorgonTexture2D texture, RectangleF textureRegion) { SetStates(_rect); _rect.IsFilled = true; _rect.Color = color; _rect.Texture = texture; _rect.TextureRegion = textureRegion; _rect.Rectangle = rectangle; _rect.LineThickness = new Vector2(1.0f); _rect.Draw(); }
/// <summary> /// Function to locate the associated texture codec and file for a sprite. /// </summary> /// <param name="fileSystem">The file system to evaluate.</param> /// <param name="localDir">The local directory for the sprite file.</param> /// <param name="renderer">The renderer used for resource look up.</param> /// <param name="textureName">The name of the texture.</param> /// <param name="codecs">The list of available image codecs to use when determining texture type.</param> /// <returns>A tuple containing the codec, the texture file, and a flag to indicate that the texture was previously loaded into memory.</returns> private static (IGorgonImageCodec codec, IGorgonVirtualFile file, bool alreadyLoaded) LocateTextureCodecAndFile( IGorgonFileSystem fileSystem, IGorgonVirtualDirectory localDir, Gorgon2D renderer, string textureName, IEnumerable <IGorgonImageCodec> codecs) { // First, attempt to locate the resource by its name. If it's already loaded, we should not load it again. GorgonTexture2D texture = renderer.Graphics .LocateResourcesByName <GorgonTexture2D>(textureName) .FirstOrDefault(); if (texture != null) { return(null, null, true); } IGorgonImageCodec codec; // We couldn't find the texture in our loaded resources, so try to locate it on the file system. // First, check the local directory. IEnumerable <IGorgonVirtualFile> files = fileSystem.FindFiles(localDir.FullPath, $"{textureName}.*", false); foreach (IGorgonVirtualFile file in files) { codec = FindTextureCodec(file, codecs); if (codec != null) { return(codec, file, false); } } // Check to see if the name has path information for the texture in the name. // The GorgonEditor from v2 does this. if (!textureName.Contains("/")) { // It is not. We cannot load the texture. return(null, null, false); } IGorgonVirtualFile textureFile = fileSystem.GetFile(textureName); if (textureFile == null) { return(null, null, false); } // Try to find a codec for the image file. codec = FindTextureCodec(textureFile, codecs); return(codec == null ? (null, null, false) : (codec, textureFile, false)); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonRenderTarget2DView" /> class. /// </summary> /// <param name="texture">The render target texture to bind.</param> /// <param name="format">The format of the render target view.</param> /// <param name="formatInfo">The format information.</param> /// <param name="mipSlice">The mip slice to use in the view.</param> /// <param name="arrayIndex">The first array index to use in the view.</param> /// <param name="arrayCount">The number of array indices to use in the view.</param> internal GorgonRenderTarget2DView(GorgonTexture2D texture, BufferFormat format, GorgonFormatInfo formatInfo, int mipSlice, int arrayIndex, int arrayCount) : base(texture, format, formatInfo) { Texture = texture; MipSlice = mipSlice; ArrayIndex = arrayIndex; ArrayCount = arrayCount; MipWidth = (Width >> MipSlice).Max(1); MipHeight = (Height >> MipSlice).Max(1); Bounds = new DX.Rectangle(0, 0, Width, Height); }
/// <summary> /// Function to load the associated sprite texture based on the project metadata. /// </summary> /// <param name="graphics">The graphics interface to use when looking up or creating the texture.</param> /// <param name="fileSystem">The file system containing the file to load.</param> /// <param name="metadata">The metadata for the project.</param> /// <param name="imagePath">The path to the image.</param> /// <param name="usage">The intended usage for the texture.</param> /// <param name="codecs">The list of available codecs.</param> /// <returns>A new texture containing the sprite texture data.</returns> private static GorgonTexture2D GetTexture(GorgonGraphics graphics, IGorgonFileSystem fileSystem, IProjectMetadata metadata, string imagePath, ResourceUsage usage, IReadOnlyDictionary <string, IGorgonImageCodec> codecs) { bool shouldConvertToPremultiplied = false; // First, check to see if this texture isn't already loaded into memory. GorgonTexture2D texture = graphics.LocateResourcesByName <GorgonTexture2D>(imagePath).FirstOrDefault(); if (texture != null) { return(texture); } if (!metadata.ProjectItems.TryGetValue(imagePath, out ProjectItemMetadata textureMetadata)) { return(null); } if (textureMetadata.Attributes.TryGetValue("PremultipliedAlpha", out string isPremultiplied)) { #pragma warning disable CA1806 // Do not ignore method results bool.TryParse(isPremultiplied, out shouldConvertToPremultiplied); #pragma warning restore CA1806 // Do not ignore method results } if ((!textureMetadata.Attributes.TryGetValue(CommonEditorConstants.ContentTypeAttr, out string contentType)) || (!string.Equals(contentType, CommonEditorContentTypes.ImageType, StringComparison.OrdinalIgnoreCase)) || (!textureMetadata.Attributes.TryGetValue("ImageCodec", out string imageCodecTypeName)) || (!codecs.TryGetValue(imageCodecTypeName, out IGorgonImageCodec codec))) { return(null); } IGorgonVirtualFile file = fileSystem.GetFile(imagePath); if (file == null) { return(null); } using (Stream fileStream = file.OpenStream()) { texture = GorgonTexture2D.FromStream(graphics, fileStream, codec, file.Size, new GorgonTexture2DLoadOptions { ConvertToPremultipliedAlpha = shouldConvertToPremultiplied, IsTextureCube = false, Name = file.FullPath, Binding = TextureBinding.ShaderResource, Usage = (((usage & ResourceUsage.None) == ResourceUsage.None) || ((usage & ResourceUsage.Staging) == ResourceUsage.Staging)) ? ResourceUsage.Default : usage }); } return(texture); }
/// <summary> /// Function to free any resources allocated by the effect. /// </summary> public void FreeResources() { _backgroundTarget = null; if (_displacementTarget == null) { return; } _displacementTarget.Dispose(); _displacementTarget = null; }
/// <summary>Function to create the texture for the view.</summary> /// <param name="graphics">The graphics interface used to create the texture.</param> /// <param name="imageData">The image data to create the texture from.</param> /// <param name="name">The name of the texture.</param> protected override void OnCreateTexture(GorgonGraphics graphics, IGorgonImage imageData, string name) { _texture = imageData.ToTexture2D(graphics, new GorgonTexture2DLoadOptions { Name = name, Binding = TextureBinding.ShaderResource, Usage = ResourceUsage.Immutable, IsTextureCube = false }); _textureView = _texture.GetShaderResourceView(); }
/// <summary> /// Function to create a new texture that is bindable to the GPU. /// </summary> /// <param name="graphics">The graphics interface to use when creating the target.</param> /// <param name="info">The information about the texture.</param> /// <param name="initialData">[Optional] Initial data used to populate the texture.</param> /// <returns>A new <see cref="GorgonTexture2DView"/>.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="graphics"/>, or <paramref name="info"/> parameter is <b>null</b>.</exception> /// <remarks> /// <para> /// This is a convenience method that will create a <see cref="GorgonTexture2D"/> and a <see cref="GorgonTexture2DView"/> as a single object that users can use to apply a texture as a shader /// resource. This helps simplify creation of a texture by executing some prerequisite steps on behalf of the user. /// </para> /// <para> /// Since the <see cref="GorgonTexture2D"/> created by this method is linked to the <see cref="GorgonTexture2DView"/> returned, disposal of either one will dispose of the other on your behalf. If /// the user created a <see cref="GorgonTexture2DView"/> from the <see cref="GorgonTexture2D.GetShaderResourceView"/> method on the <see cref="GorgonTexture2D"/>, then it's assumed the user knows /// what they are doing and will handle the disposal of the texture and view on their own. /// </para> /// <para> /// If an <paramref name="initialData"/> image is provided, and the width/height/depth is not the same as the values in the <paramref name="info"/> parameter, then the image data will be cropped to /// match the values in the <paramref name="info"/> parameter. Things like array count, and mip levels will still be taken from the <paramref name="initialData"/> image parameter. /// </para> /// </remarks> /// <seealso cref="GorgonTexture2D"/> public static GorgonTexture2DView CreateTexture(GorgonGraphics graphics, IGorgonTexture2DInfo info, IGorgonImage initialData = null) { if (graphics == null) { throw new ArgumentNullException(nameof(graphics)); } if (info == null) { throw new ArgumentNullException(nameof(info)); } if (initialData != null) { if ((initialData.Width < info.Width) || (initialData.Height < info.Height)) { initialData.Expand(info.Width, info.Height, 1); } if ((initialData.Width > info.Width) || (initialData.Height > info.Height)) { initialData.Crop(new DX.Rectangle(0, 0, info.Width, info.Height), 1); } } var newInfo = new GorgonTexture2DInfo(info) { Usage = info.Usage == ResourceUsage.Staging ? ResourceUsage.Default : info.Usage, Binding = (info.Binding & TextureBinding.ShaderResource) != TextureBinding.ShaderResource ? (info.Binding | TextureBinding.ShaderResource) : info.Binding }; GorgonTexture2D texture = initialData == null ? new GorgonTexture2D(graphics, newInfo) : initialData.ToTexture2D(graphics, new GorgonTexture2DLoadOptions { Usage = newInfo.Usage, Binding = newInfo.Binding, MultisampleInfo = newInfo.MultisampleInfo, Name = newInfo.Name, IsTextureCube = newInfo.IsCubeMap }); GorgonTexture2DView result = texture.GetShaderResourceView(); result.OwnsResource = true; return(result); }
/// <summary> /// Function to load the texture information. /// </summary> /// <param name="reader">The reader containing the texture information.</param> /// <param name="overrideTexture">The texture to assign to the sprite instead of the texture associated with the name stored in the file.</param> /// <param name="textureOffset">The texture transform offset.</param> /// <param name="textureScale">The texture transform scale.</param> /// <param name="textureArrayIndex">The texture array index.</param> /// <returns>The texture attached to the sprite.</returns> private GorgonTexture2DView LoadTexture(GorgonBinaryReader reader, GorgonTexture2DView overrideTexture, out DX.Vector2 textureOffset, out DX.Vector2 textureScale, out int textureArrayIndex) { // Write out as much info about the texture as we can so we can look it up based on these values when loading. string textureName = reader.ReadString(); textureOffset = DX.Vector2.Zero; textureScale = DX.Vector2.One; textureArrayIndex = 0; if (string.IsNullOrWhiteSpace(textureName)) { return(null); } reader.ReadValue(out textureOffset); reader.ReadValue(out textureScale); reader.ReadValue(out textureArrayIndex); reader.ReadValue(out int textureWidth); reader.ReadValue(out int textureHeight); reader.ReadValue(out BufferFormat textureFormat); reader.ReadValue(out int textureArrayCount); reader.ReadValue(out int textureMipCount); GorgonTexture2D texture = null; // Locate the texture resource. if (overrideTexture == null) { texture = Renderer.Graphics.LocateResourcesByName <GorgonTexture2D>(textureName) .FirstOrDefault(item => item.Width == textureWidth && item.Height == textureHeight && item.Format == textureFormat && item.ArrayCount == textureArrayCount && item.MipLevels == textureMipCount); if (texture == null) { textureOffset = DX.Vector2.Zero; textureScale = DX.Vector2.One; textureArrayIndex = 0; return(null); } } reader.ReadValue(out int viewArrayIndex); reader.ReadValue(out int viewArrayCount); reader.ReadValue(out int viewMipSlice); reader.ReadValue(out int viewMipCount); reader.ReadValue(out BufferFormat viewFormat); return(overrideTexture ?? texture.GetShaderResourceView(viewFormat, viewMipSlice, viewMipCount, viewArrayIndex, viewArrayCount)); }
/// <summary> /// Function to rent a render target from the factory. /// </summary> /// <param name="targetInfo">The information about the render target to retrieve.</param> /// <param name="name">A unique user defined name for a new render target.</param> /// <param name="clearOnRetrieve">[Optional] <b>true</b> to clear the render target when retrieved, or <b>false</b> to leave the contents as-is.</param> /// <returns>The requested render target.</returns> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="targetInfo"/>, or the <paramref name="name"/> parameter is <b>null</b>.</exception> /// <exception cref="ArgumentException">Thrown when the <paramref name="name"/> parameter is empty.</exception> /// <remarks> /// <para> /// All calls to this method should be paired with a call to the <see cref="Return"/> method. Failure to do so may result in a leak. /// </para> /// <para> /// The optional <paramref name="clearOnRetrieve"/> parameter, if set to <b>true</b>,, will clear the contents of a render target that is being reused /// prior to returning it. In some cases this is not ideal, so setting it to <b>false</b> will preserve the contents. New render targets will always /// be cleared. /// </para> /// <note type="caution"> /// <para> /// For performance reasons, any exceptions thrown from this method will only be thrown when Gorgon is compiled as DEBUG. /// </para> /// </note> /// </remarks> public GorgonRenderTarget2DView Rent(IGorgonTexture2DInfo targetInfo, string name, bool clearOnRetrieve = true) { name.ValidateString(nameof(name)); targetInfo.ValidateObject(nameof(targetInfo)); ExpireTargets(); // Ensure the information is valid. GorgonTexture2DInfo newInfo = _textureInfoAllocator.Allocate(); newInfo.Copy(name, targetInfo); newInfo.Binding = targetInfo.Binding | TextureBinding.RenderTarget | TextureBinding.ShaderResource; newInfo.Usage = ResourceUsage.Default; for (int i = 0; i < _renderTargets.Count; ++i) { GorgonRenderTarget2DView rtv = _renderTargets[i]; GorgonTexture2D target = _renderTargets[i].Texture; if ((!_rented.Contains(rtv)) && (target.Width == newInfo.Width) && (target.Height == newInfo.Height) && (target.MipLevels == newInfo.MipLevels) && (target.ArrayCount == newInfo.ArrayCount) && (target.Format == newInfo.Format) && (target.Binding == newInfo.Binding) && (target.MultisampleInfo.Equals(newInfo.MultisampleInfo)) && (newInfo.IsCubeMap == target.IsCubeMap) && (string.Equals(newInfo.Name, rtv.Texture.Name, StringComparison.OrdinalIgnoreCase))) { if (clearOnRetrieve) { rtv.Clear(GorgonColor.BlackTransparent); } _renderTargets.Remove(rtv); _expiryTime.Remove(rtv); _rented.Add(rtv); return(rtv); } } if (_renderTargets.Count == 0) { _expiryTimer.Reset(); } var newRtv = GorgonRenderTarget2DView.CreateRenderTarget(_graphics, newInfo); // Cache a default shader resource view (the texture holds the cache, we hold a separate one so we can clean it up later). _srvs.Add(newRtv.GetShaderResourceView()); newRtv.OwnerFactory = this; _rented.Add(newRtv); newRtv.Clear(GorgonColor.BlackTransparent); return(newRtv); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonTexture2DReadWriteView"/> class. /// </summary> /// <param name="texture">The texture to view.</param> /// <param name="format">The format for the view.</param> /// <param name="formatInfo">Information about the format.</param> /// <param name="firstMipLevel">The first mip level to view.</param> /// <param name="arrayIndex">The first array index to view.</param> /// <param name="arrayCount">The number of array indices to view.</param> /// <exception cref="ArgumentNullException">Thrown when the <paramref name="texture"/>, or the <paramref name="formatInfo"/> parameter is <b>null</b>.</exception> internal GorgonTexture2DReadWriteView(GorgonTexture2D texture, BufferFormat format, GorgonFormatInfo formatInfo, int firstMipLevel, int arrayIndex, int arrayCount) : base(texture) { FormatInformation = formatInfo ?? throw new ArgumentNullException(nameof(formatInfo)); Format = format; Texture = texture; Bounds = new DX.Rectangle(0, 0, Width, Height); MipSlice = firstMipLevel; ArrayIndex = arrayIndex; ArrayCount = arrayCount; }
/// <summary> /// Function to create a new sprite object. /// </summary> /// <param name="name">Name of the sprite.</param> /// <param name="size">Size of the sprite.</param> /// <param name="texture">Texture to apply to the sprite.</param> /// <param name="textureRegion">Region of the texture to map to the sprite.</param> /// <returns>A new sprite.</returns> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="name"/> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="System.ArgumentException">Thrown when the name parameter is an empty string.</exception> public GorgonSprite CreateSprite(string name, Vector2 size, GorgonTexture2D texture, RectangleF textureRegion) { if (texture == null) { return(CreateSprite(name, size, Color.White)); } return(CreateSprite(name, new GorgonSpriteSettings { Color = Color.White, Size = size, InitialScale = new Vector2(1.0f), Texture = texture, TextureRegion = textureRegion })); }
public void Test2ViewsSameShaderStage() { GorgonTexture2D texture = null; _framework.CreateTestScene(Shaders, Shaders, true); try { using (var data = new GorgonImageData(new GorgonTexture2DSettings { Width = 256, Height = 256, ArrayCount = 1, Format = BufferFormat.R8G8B8A8, MipCount = 1, ShaderViewFormat = BufferFormat.R8G8B8A8_Int, AllowUnorderedAccessViews = false, Usage = BufferUsage.Default })) { for (int i = 0; i < 5000; i++) { data.Buffers[0].Data.Position = ((GorgonRandom.RandomInt32(0, 256) * data.Buffers[0].PitchInformation.RowPitch) + GorgonRandom.RandomInt32(0, 256) * 4); data.Buffers[0].Data.Write((int)((GorgonRandom.RandomSingle() * 2.0f - 1.0f) * (Int32.MaxValue - 2))); } texture = _framework.Graphics.Textures.CreateTexture <GorgonTexture2D>("Test2D", data); } GorgonTextureShaderView view = texture.GetShaderView(BufferFormat.R8G8B8A8_UIntNormal); _framework.Graphics.Shaders.PixelShader.Resources[0] = texture; _framework.Graphics.Shaders.PixelShader.Resources[1] = view; Assert.IsTrue(_framework.Run() == DialogResult.Yes); } finally { if (texture != null) { texture.Dispose(); } } }