/// <summary> /// Initializes a new instance of the <see cref="WorldViewProjection"/> class. /// </summary> /// <param name="graphics">The graphics interface to use.</param> public Light(GorgonGraphics graphics) { _lightData[0].Attenuation = 6.0f; _lightData[0].LightColor = GorgonColor.White; _lightData[0].LightPosition = Vector3.Zero; _lightData[0].SpecularColor = GorgonColor.White; _lightData[0].SpecularPower = 512.0f; _buffer = graphics.Buffers.CreateConstantBuffer("LightBuffer", new GorgonConstantBufferSettings { SizeInBytes = LightData.Size * _lightData.Length, Usage = BufferUsage.Default }); _lightStore = new GorgonDataStream(_buffer.SizeInBytes); unsafe { DirectAccess.ZeroMemory(_lightStore.UnsafePointer, _buffer.SizeInBytes); var data = (LightData *)_lightStore.UnsafePointer; * data = _lightData[0]; } _buffer.Update(_lightStore); graphics.Shaders.PixelShader.ConstantBuffers[1] = _buffer; }
/// <summary> /// Function to flush the cache by rendering its contents. /// </summary> public void Flush() { GorgonVertexBufferBinding binding = _renderer.Graphics.Input.VertexBuffers[0]; // Apply the current projection/view matrix. if (_renderer.Camera.NeedsUpdate) { _renderer.Camera.Update(); } // Only advance the cache when we've got something to copy into the buffer. switch (binding.VertexBuffer.Settings.Usage) { case BufferUsage.Dynamic: // If we're not at the beginning of the cache, then // do a no overwrite lock. This will help performance. var flags = BufferLockFlags.Write | (_currentVertex > 0 ? BufferLockFlags.NoOverwrite : BufferLockFlags.Discard); using (GorgonDataStream stream = binding.VertexBuffer.Lock(flags, _renderer.Graphics)) { stream.Position = _currentVertex * Gorgon2DVertex.SizeInBytes; stream.WriteRange(_vertices, _currentVertex, _verticesWritten); binding.VertexBuffer.Unlock(); } break; default: binding.VertexBuffer.Update(_vertices, _currentVertex * Gorgon2DVertex.SizeInBytes, _renderer.Graphics); break; } // Draw the buffer data. switch (_renderer.Graphics.Input.PrimitiveType) { case PrimitiveType.PointList: case PrimitiveType.LineList: _renderer.Graphics.Output.Draw(_currentVertex, _verticesWritten); break; case PrimitiveType.TriangleList: if (_renderer.Graphics.Input.IndexBuffer == null) { _renderer.Graphics.Output.Draw(_currentVertex, _verticesWritten); } else { _renderer.Graphics.Output.DrawIndexed(_firstIndex, _vertexOffset, _indexCount); } break; } _currentVertex = _nextVertex; _firstIndex += _indexCount; _verticesWritten = 0; _indexCount = 0; NeedsFlush = false; }
public void DataStreamMarshalTest() { MyStruct[] items = new MyStruct[50]; for (int i = 0; i < items.Length; ++i) { items[i] = new MyStruct { MyInt = i, MyStr = "String #" + i + "\0" }; } using (GorgonDataStream stream = GorgonDataStream.MarshalArrayToStream(items)) { byte[] expected = Resources.DataStreamMarshalOut1; // Not sure how I can test the validity of the data? byte[] dataBlock = new byte[stream.Length]; stream.Read(dataBlock, 0, dataBlock.Length); Assert.IsTrue(expected.SequenceEqual(dataBlock)); } }
/// <summary> /// Function to read a font from memory. /// </summary> /// <param name="name">Name of the font object.</param> /// <param name="fontData">Byte array containing the font data.</param> /// <param name="missingTextureFunction">[Optional] A function that is called if a required user defined texture has not been loaded for the font.</param> /// <returns>The font in the array.</returns> /// <remarks> /// The fonts will not store user defined glyph textures, in order to facilitate the loading of the textures the users must either load the texture /// before loading the font or specify a callback method in the <paramref name="missingTextureFunction"/> parameter. This function will pass a name /// for the texture and will expect a texture to be returned. If NULL is returned, then an exception will be raised. /// <para>Fonts may only be created on the immediate context.</para></remarks> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="fontData"/> or the <paramref name="name"/> parameters are NULL.</exception> /// <exception cref="System.ArgumentException">Thrown if the name parameter is an empty string. /// <para>-or-</para> /// <para>Thrown if the font uses external textures.</para> /// <para>-or-</para> /// <para>Thrown if the fontData array is empty.</para> /// </exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown if the font cannot be read. /// <para>-or-</para> /// <para>Thrown if the graphics context is deferred.</para> /// </exception> public GorgonFont FromMemory(string name, byte[] fontData, Func <string, Size, GorgonTexture2D> missingTextureFunction = null) { using (var memoryStream = new GorgonDataStream(fontData)) { return(FromStream(name, memoryStream, missingTextureFunction)); } }
/// <summary> /// Function called when the effect is being initialized. /// </summary> /// <remarks> /// Use this method to set up the effect upon its creation. For example, this method could be used to create the required shaders for the effect. /// </remarks> protected override void OnInitialize() { base.OnInitialize(); _xOffsets = new Vector4[13]; _yOffsets = new Vector4[13]; _kernel = new float[13]; _blurBuffer = Graphics.ImmediateContext.Buffers.CreateConstantBuffer("Gorgon2DGaussianBlurEffect Constant Buffer", new GorgonConstantBufferSettings { SizeInBytes = DirectAccess.SizeOf <Vector4>() * _xOffsets.Length }); _blurStaticBuffer = Graphics.ImmediateContext.Buffers.CreateConstantBuffer("Gorgon2DGaussianBlurEffect Static Constant Buffer", new GorgonConstantBufferSettings { SizeInBytes = DirectAccess.SizeOf <Vector4>() * (_kernel.Length + 1) }); _blurKernelStream = new GorgonDataStream(_blurStaticBuffer.SizeInBytes); Passes[0].PixelShader = Graphics.ImmediateContext.Shaders.CreateShader <GorgonPixelShader>("Effect.PS.GaussBlur", "GorgonPixelShaderGaussBlur", "#GorgonInclude \"Gorgon2DShaders\""); UpdateKernel(); _blurSprite = Gorgon2D.Renderables.CreateSprite("Gorgon2DGaussianBlurEffect Sprite", new GorgonSpriteSettings { Size = BlurRenderTargetsSize }); _blurSprite.BlendingMode = BlendingMode.None; _blurSprite.SmoothingMode = SmoothingMode.Smooth; _blurSprite.TextureRegion = new RectangleF(0, 0, 1, 1); }
/// <summary> /// Function to update the buffer. /// </summary> /// <param name="stream">Stream containing the data used to update the buffer.</param> /// <param name="offset">Offset, in bytes, into the buffer to start writing at.</param> /// <param name="size">The number of bytes to write.</param> /// <param name="context">A graphics context to use when updating the buffer.</param> /// <remarks> /// Use the <paramref name="context" /> parameter to determine the context in which the buffer should be updated. This is necessary to use that context /// to update the buffer because 2 threads may not access the same resource at the same time. /// </remarks> protected override void OnUpdate(GorgonDataStream stream, int offset, int size, GorgonGraphics context) { GorgonDebug.AssertNull(stream, "stream"); #if DEBUG if (Settings.Usage != BufferUsage.Default) { throw new GorgonException(GorgonResult.AccessDenied, Resources.GORGFX_NOT_DEFAULT_USAGE); } #endif context.Context.UpdateSubresource( new DX.DataBox { DataPointer = stream.PositionPointer, RowPitch = size }, D3DResource, 0, new D3D11.ResourceRegion { Left = offset, Right = offset + size, Top = 0, Bottom = 1, Front = 0, Back = 1 }); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonTextureLockData"/> class. /// </summary> /// <param name="graphics">The graphics context that owns this lock.</param> /// <param name="texture">The texture that owns this lock.</param> /// <param name="cache">Lock cache that will contain this lock.</param> /// <param name="data">The data returned from the lock.</param> /// <param name="mipLevel">The mip level of the sub resource.</param> /// <param name="arrayIndex">Array index of the sub resource.</param> internal GorgonTextureLockData(GorgonGraphics graphics, GorgonTexture texture, GorgonTextureLockCache cache, DX.DataBox data, int mipLevel, int arrayIndex) : base(mipLevel, arrayIndex, 0) { Graphics = graphics; Texture = texture; _cache = cache; Width = Texture.Settings.Width; Height = Texture.Settings.Height; Depth = Texture.Settings.Depth; // Calculate the current size at the given mip level. for (int mip = 0; mip < mipLevel; ++mip) { if (Width > 1) { Width >>= 1; } if (Height > 1) { Height >>= 1; } if (Depth > 1) { Depth >>= 1; } } PitchInformation = new GorgonFormatPitch(data.RowPitch, data.SlicePitch); Data = new GorgonDataStream(data.DataPointer.ToPointer(), data.SlicePitch); }
/// <summary> /// Function to create a index buffer. /// </summary> /// <param name="name">The name of the buffer.</param> /// <param name="data">Data used to initialize the buffer.</param> /// <param name="usage">[Optional] Usage of the buffer.</param> /// <param name="is32Bit">[Optional] TRUE to indicate that we're using 32 bit indices, FALSE to use 16 bit indices </param> /// <typeparam name="T">Type of data in the array. Must be a value type.</typeparam> /// <returns>A new index buffer.</returns> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="name"/> is NULL (Nothing in VB.Net). /// <para>-or-</para> /// <para>Thrown when the <paramref name="data"/> parameter is NULL.</para> /// </exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the buffer could not be created.</exception> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="name"/> parameter is empty.</exception> /// <remarks>If creating an immutable index buffer, be sure to pre-populate it via the initialData parameter. /// <para>This method should only be called from an immediate graphics context, if it is called from a deferred context an exception will be thrown.</para> /// </remarks> public GorgonIndexBuffer CreateIndexBuffer <T>(string name, T[] data, BufferUsage usage = BufferUsage.Default, bool is32Bit = true) where T : struct { if (data == null) { throw new ArgumentNullException("data"); } if (data.Length == 0) { throw new ArgumentException(Resources.GORGFX_PARAMETER_MUST_NOT_BE_EMPTY, "data"); } int size = data.Length * DirectAccess.SizeOf <T>(); using (var dataStream = new GorgonDataStream(data)) { return(CreateIndexBuffer(name, new GorgonIndexBufferSettings { SizeInBytes = size, IsOutput = false, Usage = usage, Use32BitIndices = is32Bit }, dataStream)); } }
/// <summary> /// Function to update the buffer. /// </summary> /// <param name="stream">Stream containing the data used to update the buffer.</param> /// <param name="offset">Offset, in bytes, into the buffer to start writing at.</param> /// <param name="size">The number of bytes to write.</param> /// <param name="deferred">[Optional] The deferred context used to update the buffer.</param> /// <remarks>This method can only be used with buffers that have Default usage. Other buffer usages will thrown an exception. /// <para>Please note that constant buffers don't use the <paramref name="offset"/> and <paramref name="size"/> parameters.</para> /// <para>This method will respect the <see cref="GorgonLibrary.IO.GorgonDataStream.Position">Position</see> property of the data stream. /// This means that it will start reading from the stream at the current position. To read from the beginning of the stream, set the position /// to 0.</para> /// <para> /// If the <paramref name="deferred"/> parameter is NULL (Nothing in VB.Net), the immediate context will be used to update the buffer. If it is non-NULL, then it /// will use the specified deferred context. /// <para>If you are using a deferred context, it is necessary to use that context to update the buffer because 2 threads may not access the same resource at the same time. /// Passing a separate deferred context will alleviate that.</para> /// </para> /// </remarks> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the buffer usage is not set to default.</exception> public void Update(GorgonDataStream stream, int offset, int size, GorgonGraphics deferred = null) { if (deferred == null) { deferred = Graphics; } OnUpdate(stream, offset, size, deferred); }
/// <summary> /// Function to update the buffer. /// </summary> /// <param name="stream">Stream containing the data used to update the buffer.</param> /// <param name="offset">Offset, in bytes, into the buffer to start writing at.</param> /// <param name="size">The number of bytes to write.</param> /// <param name="context">A graphics context to use when updating the buffer.</param> /// <remarks> /// Use the <paramref name="context" /> parameter to determine the context in which the buffer should be updated. This is necessary to use that context /// to update the buffer because 2 threads may not access the same resource at the same time. /// </remarks> protected override void OnUpdate(GorgonDataStream stream, int offset, int size, GorgonGraphics context) { context.Context.UpdateSubresource( new DX.DataBox { DataPointer = stream.PositionPointer, RowPitch = 0, SlicePitch = 0 }, D3DResource); }
/// <summary> /// Initializes a new instance of the <see cref="GorgonImageBuffer" /> class. /// </summary> /// <param name="dataStart">The data start.</param> /// <param name="pitchInfo">The pitch info.</param> /// <param name="mipLevel">Mip map level.</param> /// <param name="arrayIndex">Array index.</param> /// <param name="sliceIndex">Slice index.</param> /// <param name="width">The width for the buffer.</param> /// <param name="height">The height for the buffer.</param> /// <param name="depth">The depth for the buffer.</param> /// <param name="format">Format of the buffer.</param> internal unsafe GorgonImageBuffer(void *dataStart, GorgonFormatPitch pitchInfo, int mipLevel, int arrayIndex, int sliceIndex, int width, int height, int depth, BufferFormat format) { Data = new GorgonDataStream(dataStart, pitchInfo.SlicePitch); PitchInformation = pitchInfo; MipLevel = mipLevel; ArrayIndex = arrayIndex; SliceIndex = sliceIndex; Width = width; Height = height; Depth = depth; Format = format; }
/// <summary> /// Function to create a structured buffer and initialize it with data. /// </summary> /// <param name="name">The name of the structured buffer.</param> /// <param name="value">Value to write to the buffer.</param> /// <param name="usage">Usage for the buffer.</param> /// <returns>A new structured buffer.</returns> /// <typeparam name="T">Type of data to write. Must be a value type.</typeparam> /// <remarks>This method should only be called from an immediate graphics context, if it is called from a deferred context an exception will be thrown.</remarks> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the buffer could not be created.</exception> public GorgonStructuredBuffer CreateStructuredBuffer <T>(string name, T value, BufferUsage usage) where T : struct { using (var stream = GorgonDataStream.ValueToStream(value)) { return(CreateStructuredBuffer(name, new GorgonStructuredBufferSettings { Usage = usage, SizeInBytes = DirectAccess.SizeOf <T>(), StructureSize = DirectAccess.SizeOf <T>() }, stream)); } }
public T FromMemory <T>(string name, string entryPoint, byte[] shaderData, IList <GorgonShaderMacro> macros = null, bool isDebug = false) #endif where T : GorgonShader { if (shaderData == null) { throw new ArgumentNullException("shaderData"); } using (var memoryStream = new GorgonDataStream(shaderData)) { return(FromStream <T>(name, entryPoint, memoryStream, shaderData.Length, macros, isDebug)); } }
/// <summary> /// Function used to initialize the buffer with data. /// </summary> /// <param name="data">Data to write.</param> /// <remarks>Passing NULL (Nothing in VB.Net) to the <paramref name="data"/> parameter should ignore the initialization and create the backing buffer as normal.</remarks> internal void Initialize(GorgonDataStream data) { Gorgon.Log.Print("Creating {0} Buffer '{1}'...", LoggingLevel.Verbose, BufferType, Name); CreateResources(data); // Update our statistics. switch (BufferType) { case BufferType.Constant: GorgonRenderStatistics.ConstantBufferCount++; GorgonRenderStatistics.ConstantBufferSize += D3DBuffer.Description.SizeInBytes; break; case BufferType.Index: GorgonRenderStatistics.IndexBufferCount++; GorgonRenderStatistics.IndexBufferSize += D3DBuffer.Description.SizeInBytes; break; case BufferType.Vertex: GorgonRenderStatistics.VertexBufferCount++; GorgonRenderStatistics.VertexBufferSize += D3DBuffer.Description.SizeInBytes; break; case BufferType.Structured: GorgonRenderStatistics.StructuredBufferCount++; GorgonRenderStatistics.StructuredBufferSize += D3DBuffer.Description.SizeInBytes; break; default: GorgonRenderStatistics.BufferCount++; GorgonRenderStatistics.BufferSize += D3DBuffer.Description.SizeInBytes; break; } if (IsRenderTarget) { GorgonRenderStatistics.RenderTargetCount++; GorgonRenderStatistics.RenderTargetSize += D3DBuffer.Description.SizeInBytes; } // Create any default shader views that are required. OnCreateDefaultShaderView(); if (IsRenderTarget) { OnCreateDefaultRenderTargetView(); } }
/// <summary> /// Initializes a new instance of the <see cref="Sphere" /> class. /// </summary> /// <param name="graphics">Graphics interface to use.</param> /// <param name="radius">Radius of the sphere</param> /// <param name="textureCoordinates">The texture coordinates to apply to the sphere.</param> /// <param name="angle">The angle of rotation, in degrees.</param> /// <param name="ringCount">Number of rings in the sphere.</param> /// <param name="segmentCount">Number of segments in the sphere.</param> public Sphere(GorgonGraphics graphics, float radius, RectangleF textureCoordinates, Vector3 angle, int ringCount = 8, int segmentCount = 16) { Quaternion orientation; // Calculate number of vertices and indices required for our sphere. PrimitiveType = PrimitiveType.TriangleList; VertexCount = (ringCount + 1) * (segmentCount + 1); IndexCount = 6 * ringCount * (segmentCount + 1); TriangleCount = IndexCount / 3; Quaternion.RotationYawPitchRoll(angle.Y.Radians(), angle.X.Radians(), angle.Z.Radians(), out orientation); Matrix.RotationQuaternion(ref orientation, out _orientation); unsafe { using (var vertexData = new GorgonDataStream(VertexCount * Vertex3D.Size)) using (var normalData = new GorgonDataStream(VertexCount * 2 * Vector4.SizeInBytes)) using (var indexData = new GorgonDataStream(IndexCount * DirectAccess.SizeOf <int>())) { GetVertices((Vertex3D *)vertexData.UnsafePointer, (int *)indexData.UnsafePointer, normalData.UnsafePointer, radius, textureCoordinates, ringCount, segmentCount); VertexBuffer = graphics.Buffers.CreateVertexBuffer("SphereVertexBuffer", new GorgonBufferSettings { Usage = BufferUsage.Immutable, SizeInBytes = (int)vertexData.Length }, vertexData); IndexBuffer = graphics.Buffers.CreateIndexBuffer("SphereIndexBuffer", new GorgonIndexBufferSettings { Usage = BufferUsage.Immutable, Use32BitIndices = true, SizeInBytes = (int)indexData.Length }, indexData); Normals = graphics.Buffers.CreateVertexBuffer("NormalsBuffer", new GorgonBufferSettings { Usage = BufferUsage.Immutable, SizeInBytes = (int)normalData.Length }, normalData); } } }
/// <summary> /// Function to read file meta data. /// </summary> /// <param name="stream">Stream used to read the metadata.</param> /// <returns> /// The image meta data as a <see cref="GorgonLibrary.Graphics.IImageSettings">IImageSettings</see> value. /// </returns> /// <exception cref="System.IO.IOException">Thrown when the <paramref name="stream"/> is write-only or if the stream cannot perform seek operations. /// <para>-or-</para> /// <para>Thrown if the file is corrupt or can't be read by the codec.</para> /// </exception> /// <exception cref="System.IO.EndOfStreamException">Thrown when an attempt to read beyond the end of the stream is made.</exception> public override IImageSettings GetMetaData(Stream stream) { long position = 0; int headerSize = DirectAccess.SizeOf <TGAHeader>(); if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead) { throw new IOException(Resources.GORGFX_STREAM_WRITE_ONLY); } if (!stream.CanSeek) { throw new IOException(Resources.GORGFX_STREAM_NO_SEEK); } if (stream.Length - stream.Position < sizeof(uint) + DirectAccess.SizeOf <TGAHeader>()) { throw new EndOfStreamException(Resources.GORGFX_STREAM_EOF); } try { position = stream.Position; TGAConversionFlags conversion; var gorgonDataStream = stream as GorgonDataStream; if (gorgonDataStream != null) { return(ReadHeader(gorgonDataStream, out conversion)); } using (var memoryStream = new GorgonDataStream(headerSize)) { memoryStream.ReadFromStream(stream, headerSize); memoryStream.Position = 0; return(ReadHeader(memoryStream, out conversion)); } } finally { stream.Position = position; } }
/// <summary> /// Function to update the buffer. /// </summary> /// <param name="stream">Stream containing the data used to update the buffer.</param> /// <param name="deferred">[Optional] A deferred context to use when updating the buffer.</param> /// <remarks>This method can only be used with buffers that have Default usage. Other buffer usages will thrown an exception. /// <para>This method will respect the <see cref="GorgonLibrary.IO.GorgonDataStream.Position">Position</see> property of the data stream. /// This means that it will start reading from the stream at the current position. To read from the beginning of the stream, set the position /// to 0.</para> /// <para> /// If the <paramref name="deferred"/> parameter is NULL (Nothing in VB.Net), the immediate context will be used to update the buffer. If it is non-NULL, then it /// will use the specified deferred context to clear the render target. /// <para>If you are using a deferred context, it is necessary to use that context to update the buffer because 2 threads may not access the same resource at the same time. /// Passing a separate deferred context will alleviate that.</para> /// </para> /// </remarks> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="stream"/> parameter is NULL (Nothing in VB.Net).</exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the buffer usage is not set to default.</exception> public void Update(GorgonDataStream stream, GorgonGraphics deferred = null) { GorgonDebug.AssertNull(stream, "stream"); #if DEBUG if (Settings.Usage != BufferUsage.Default) { throw new GorgonException(GorgonResult.AccessDenied, Resources.GORGFX_NOT_DEFAULT_USAGE); } #endif if (deferred == null) { deferred = Graphics; } OnUpdate(stream, 0, (int)(stream.Length - stream.Position), deferred); }
/// <summary> /// Function to create a generic buffer. /// </summary> /// <param name="name">Name of the buffer.</param> /// <param name="settings">The settings for the buffer.</param> /// <param name="stream">[Optional] Stream used to initialize the buffer.</param> /// <returns>A new generic buffer object.</returns> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="name"/> parameter is NULL (Nothing in VB.Net). /// <para>-or-</para> /// <para>Thrown when the <paramref name="settings"/> parameter is NULL.</para> /// </exception> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="name"/> parameter is empty.</exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the <see cref="GorgonLibrary.Graphics.GorgonBufferSettings.IsOutput">IsOutput</see> property is TRUE and has a usage that is not Default. /// <para>-or-</para> /// <para>Thrown when the <see cref="GorgonLibrary.Graphics.GorgonBufferSettings.SizeInBytes">SizeInBytes</see> property of the <paramref name="settings"/> parameter is less than 1.</para> /// <para>-or-</para> /// <para>Thrown when the usage is set to immutable and the <paramref name="stream"/> parameter is NULL (Nothing in VB.Net) or has no data.</para> /// </exception> /// <remarks>The generic buffer is intended to be used with the [RW]Buffer<> HLSL type. /// <para>Generic buffers are only available on video devices that are capable of SM4 or better.</para> /// <para>This method should only be called from an immediate graphics context, if it is called from a deferred context an exception will be thrown.</para> /// </remarks> public GorgonBuffer CreateBuffer(string name, GorgonBufferSettings settings, GorgonDataStream stream = null) { if (_graphics.IsDeferred) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_CANNOT_USE_DEFERRED_CONTEXT); } if (name == null) { throw new ArgumentNullException("name"); } if (settings == null) { throw new ArgumentNullException("settings"); } if (name.Length == 0) { throw new ArgumentException(Resources.GORGFX_PARAMETER_MUST_NOT_BE_EMPTY, "name"); } if ((settings.Usage == BufferUsage.Immutable) && ((stream == null) || (stream.Length == 0))) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_BUFFER_IMMUTABLE_REQUIRES_DATA); } if ((settings.Usage == BufferUsage.Dynamic) && (!settings.AllowShaderViews)) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_BUFFER_DYNAMIC_NEEDS_SHADER_VIEW); } // Validate our buffer settings. ValidateGenericBufferSettings(settings); var buffer = new GorgonBuffer(_graphics, name, settings); buffer.Initialize(stream); _graphics.AddTrackedObject(buffer); return(buffer); }
/// <summary> /// Function to retrieve the ranges available to a specific font. /// </summary> /// <param name="font">Font to look up.</param> /// <param name="hDc">Device context.</param> /// <returns>A list of ranges.</returns> public static IDictionary <string, GorgonRange> GetUnicodeRanges(Font font, IntPtr hDc) { Dictionary <string, GorgonRange> result; if (_ranges == null) { BuildUnicodeRangeList(); } uint size = GetFontUnicodeRanges(hDc, IntPtr.Zero); using (var stream = new GorgonDataStream((int)size)) { GetFontUnicodeRanges(hDc, stream.BasePointer); // Skip the first 12 bytes. stream.Read <Int64>(); stream.Read <Int32>(); var itemCount = stream.Read <int>(); result = new Dictionary <string, GorgonRange>(itemCount); for (int i = 0; i < itemCount; i++) { var min = stream.Read <ushort>(); var value = new GorgonRange(min, stream.Read <ushort>() + min - 1); var rangeName = (from unicodeRange in _ranges where unicodeRange.Value.Contains(value.Minimum) && unicodeRange.Value.Contains(value.Maximum) select unicodeRange).SingleOrDefault(); if ((!string.IsNullOrEmpty(rangeName.Key)) && (!result.ContainsKey(rangeName.Key))) { result.Add(rangeName.Key, rangeName.Value); } } } return(result); }
/// <summary> /// Function to load an image from a stream. /// </summary> /// <param name="stream">Stream containing the data to load.</param> /// <param name="size">Size of the data to read, in bytes.</param> /// <returns> /// The image data that was in the stream. /// </returns> protected internal override GorgonImageData LoadFromStream(GorgonDataStream stream, int size) { GorgonImageData imageData = null; TGAConversionFlags flags; if (DirectAccess.SizeOf <TGAHeader>() > size) { throw new EndOfStreamException(Resources.GORGFX_STREAM_EOF); } // Read the header information. IImageSettings settings = ReadHeader(stream, out flags); if (ArrayCount > 1) { settings.ArrayCount = ArrayCount; } try { // Create our image data structure. imageData = new GorgonImageData(settings); // Copy the data from the stream to the buffer. CopyImageData(stream, imageData, flags); } catch { // Clean up any memory allocated if we can't copy the image. if (imageData != null) { imageData.Dispose(); } throw; } return(imageData); }
public void BindStructBuffer() { _framework.CreateTestScene(_sbShaders, _sbShaders, false); using (var buffer = _framework.Graphics.Buffers.CreateStructuredBuffer("SB", new GorgonStructuredBufferSettings { SizeInBytes = 48, StructureSize = 12 })) { _bufferStream = new GorgonDataStream(48); _framework.Graphics.Shaders.VertexShader.Resources[0] = buffer; _framework.MaxTimeout = 10000; _framework.IdleFunc = () => { for (int i = 0; i < 4; i++) { var rnd = new Vector3(GorgonRandom.RandomSingle() * GorgonTiming.Delta, GorgonRandom.RandomSingle() * GorgonTiming.Delta, GorgonRandom.RandomSingle() * GorgonTiming.Delta); _bufferStream.Write(rnd); } _bufferStream.Position = 0; // ReSharper disable AccessToDisposedClosure buffer.Update(_bufferStream); // ReSharper restore AccessToDisposedClosure return(false); }; _framework.Run(); } }
/// <summary> /// Function to create a structured buffer and initialize it with data. /// </summary> /// <param name="name">The name of the structured buffer.</param> /// <param name="values">Values to write to the buffer.</param> /// <param name="usage">Usage for the buffer.</param> /// <returns>A new structured buffer.</returns> /// <typeparam name="T">Type of data to write. Must be a value type.</typeparam> /// <exception cref="System.ArgumentNullException">Thrown when the <paramref name="name"/> parameter is NULL (Nothing in VB.Net). /// <para>-or-</para> /// <para>Thrown when the <paramref name="values"/> parameter is NULL (Nothing in VB.Net).</para> /// </exception> /// <exception cref="System.ArgumentException">Thrown when the <paramref name="name"/> parameter is empty.</exception> /// <exception cref="GorgonLibrary.GorgonException">Thrown when the buffer could not be created.</exception> /// <remarks>This method should only be called from an immediate graphics context, if it is called from a deferred context an exception will be thrown.</remarks> public GorgonStructuredBuffer CreateStructuredBuffer <T>(string name, T[] values, BufferUsage usage) where T : struct { if (values == null) { throw new ArgumentNullException("values"); } if (values.Length == 0) { throw new ArgumentException(Resources.GORGFX_PARAMETER_MUST_NOT_BE_EMPTY, "values"); } using (var stream = new GorgonDataStream(values)) { return(CreateStructuredBuffer(name, new GorgonStructuredBufferSettings { Usage = usage, SizeInBytes = DirectAccess.SizeOf <T>() * values.Length, StructureSize = DirectAccess.SizeOf <T>() }, stream)); } }
/// <summary> /// Initializes a new instance of the <see cref="Plane"/> class. /// </summary> /// <param name="graphics">The graphics interface to use.</param> /// <param name="size">The width and height of the plane.</param> /// <param name="textureCoordinates">The texture coordinates to apply to the plane.</param> /// <param name="angle">The initial orientation, in degrees.</param> /// <param name="columns">The number of columns to subdivide by.</param> /// <param name="rows">The number of rows to subdivide by.</param> public Plane(GorgonGraphics graphics, Vector2 size, RectangleF textureCoordinates, Vector3 angle, int columns = 1, int rows = 1) { Quaternion orientation; PrimitiveType = PrimitiveType.TriangleStrip; VertexCount = (columns + 1) * (rows + 1); IndexCount = ((columns * rows) * 6) + (rows - 1); TriangleCount = (IndexCount - (rows - 1)) / 3; Quaternion.RotationYawPitchRoll(angle.Y.Radians(), angle.X.Radians(), angle.Z.Radians(), out orientation); Matrix.RotationQuaternion(ref orientation, out _orientation); unsafe { using (var vertexData = new GorgonDataStream(VertexCount * Vertex3D.Size)) using (var indexData = new GorgonDataStream(IndexCount * sizeof(int))) { GetVertices((Vertex3D *)vertexData.UnsafePointer, size, textureCoordinates, columns, rows); GetIndices((int *)indexData.UnsafePointer, columns, rows); CalculateTangents((Vertex3D *)vertexData.UnsafePointer, (int *)indexData.UnsafePointer); VertexBuffer = graphics.Buffers.CreateVertexBuffer("PlaneVB", new GorgonBufferSettings { Usage = BufferUsage.Immutable, SizeInBytes = (int)vertexData.Length }, vertexData); IndexBuffer = graphics.Buffers.CreateIndexBuffer("PlaneIB", new GorgonIndexBufferSettings { Usage = BufferUsage.Immutable, Use32BitIndices = true, SizeInBytes = (int)indexData.Length }, indexData); } } }
public void BindRawBuffer() { _framework.CreateTestScene(_rbShaders, _rbShaders, false); var values = new byte[256 * 256 * 4]; float angle = 0.0f; using (var buffer = _framework.Graphics.Buffers.CreateBuffer("RB", new GorgonBufferSettings { AllowRawViews = true, AllowShaderViews = true, DefaultShaderViewFormat = BufferFormat.R32_UInt, SizeInBytes = values.Length })) { _framework.Graphics.Shaders.PixelShader.Resources[0] = buffer; _framework.IdleFunc = () => { using (var stream = new GorgonDataStream(values)) { float rads = (angle * GorgonRandom.RandomSingle(8.0f, 32.0f) + 16.0f).Radians(); float x = 128 + GorgonRandom.RandomInt32(0, 5) + (rads * rads.Cos()); float y = 128 + GorgonRandom.RandomInt32(0, 5) + (rads * rads.Sin()); if (x > 255) { x = 255; } if (y > 255) { y = 255; } if (x < 0) { x = 0; } if (y < 0) { y = 0; } int pos = (((int)y * 1024) + ((int)x * 4)); for (int i = 0; i < pos - 50; i++) { values[i] = (byte)(values[i] * 0.95f); } values[pos] = 255; values[pos + 3] = values[pos + 2] = values[pos + 1] = (byte)GorgonRandom.RandomInt32(64, 128); angle += GorgonRandom.RandomSingle(1, 180) * GorgonTiming.Delta; if (angle > 360.0f) { angle = 0.0f; } buffer.Update(stream); return(false); } }; _framework.MaxTimeout = 15000; _framework.Run(); } }
/// <summary> /// Function to build the Icosphere. /// </summary> /// <param name="graphics">Graphics interface to use.</param> /// <param name="radius">Radius of the sphere.</param> /// <param name="tesselation">Tessellation factor for the sphere.</param> /// <param name="textureCoordinates">Texture coordinate offset and scale.</param> private void BuildSphere(GorgonGraphics graphics, float radius, int tesselation, RectangleF textureCoordinates) { GetBaseVertices(); List <int[]> indices = GetBaseIndices(); for (int i = 0; i < tesselation; ++i) { var subIndices = new List <int[]>(); foreach (int[] index in indices) { int index0 = GetMiddlePoint(index[0], index[1]); int index1 = GetMiddlePoint(index[1], index[2]); int index2 = GetMiddlePoint(index[2], index[0]); subIndices.Add(new [] { index[0], index0, index2 }); subIndices.Add(new[] { index[1], index1, index0 }); subIndices.Add(new[] { index[2], index2, index1 }); subIndices.Add(new[] { index0, index1, index2 }); } indices = subIndices; _cachedSplits.Clear(); } // Perform texture coordinate calculations and vertex/normal transformations. const float piRecip = 1.0f / (float)System.Math.PI; const float pi2Recip = 1.0f / (2.0f * (float)System.Math.PI); // Final list. var vertexList = new List <Vertex3D>(); var indexList = new List <int>(); for (int i = 0; i < _vertices.Count; ++i) { Vector3 position = _vertices[i]; Vector3 normal = position; Vector2 uv = Vector2.Zero; uv.X = (0.5f - position.X.ATan(position.Z) * pi2Recip) * textureCoordinates.Width + textureCoordinates.X; uv.Y = (0.5f - position.Y.ASin() * piRecip) * textureCoordinates.Height + textureCoordinates.Y; Vector3.Multiply(ref position, radius, out position); Vector3.TransformCoordinate(ref position, ref _orientation, out position); Vector3.TransformCoordinate(ref normal, ref _orientation, out normal); normal.Normalize(); vertexList.Add(new Vertex3D { Position = new Vector4(position, 1.0f), Normal = normal, UV = uv }); } foreach (int[] index in indices) { for (int j = 0; j < 3; ++j) { indexList.Add(index[j]); } } FixSeam(vertexList, indexList); unsafe { using (var vertexData = new GorgonDataStream(vertexList.ToArray())) using (var indexData = new GorgonDataStream(indexList.ToArray())) { VertexCount = vertexList.Count; IndexCount = indexList.Count; TriangleCount = IndexCount / 3; CalculateTangents((Vertex3D *)vertexData.UnsafePointer, (int *)indexData.UnsafePointer); VertexBuffer = graphics.Buffers.CreateVertexBuffer("IcoSphereVertexBuffer", new GorgonBufferSettings { SizeInBytes = (int)vertexData.Length, Usage = BufferUsage.Immutable }, vertexData); IndexBuffer = graphics.Buffers.CreateIndexBuffer("IcoSphereIndexbuffer", new GorgonIndexBufferSettings { Usage = BufferUsage.Immutable, Use32BitIndices = true, SizeInBytes = (int)indexData.Length }, indexData); } } }
/// <summary> /// Function to initialize the 2D renderer. /// </summary> private void Initialize() { // Add shader includes. if (!Graphics.Shaders.IncludeFiles.Contains("Gorgon2DShaders")) { Graphics.ImmediateContext.Shaders.IncludeFiles.Add("Gorgon2DShaders", Encoding.UTF8.GetString(Resources.BasicSprite)); } // Create shader states. PixelShader = new Gorgon2DPixelShaderState(this); VertexShader = new Gorgon2DVertexShaderState(this); // Create layout information so we can bind our vertices to the shader. DefaultLayout = Graphics.ImmediateContext.Input.CreateInputLayout("Gorgon2D Input Layout", typeof(Gorgon2DVertex), VertexShader.DefaultVertexShader); // Create pre-defined effects objects. Effects = new Gorgon2DEffects(this); int spriteVertexBufferSize = Gorgon2DVertex.SizeInBytes * _cache.CacheSize; int spriteIndexBufferSize = sizeof(int) * _cache.CacheSize * 6; // Set up our index buffer. using (var ibData = new GorgonDataStream(spriteIndexBufferSize)) { unsafe { ushort index = 0; var buffer = (int *)ibData.UnsafePointer; for (int i = 0; i < _cache.CacheSize; i++) { *(buffer++) = index; *(buffer++) = (index + 1); *(buffer++) = (index + 2); *(buffer++) = (index + 1); *(buffer++) = (index + 3); *(buffer++) = (index + 2); index += 4; } } DefaultIndexBuffer = Graphics.ImmediateContext.Buffers.CreateIndexBuffer("Gorgon2D Default Index Buffer", new GorgonIndexBufferSettings { IsOutput = false, SizeInBytes = (int)ibData.Length, Usage = BufferUsage.Immutable, Use32BitIndices = true }, ibData); } // Create our empty vertex buffer. _defaultVertexBuffer = new GorgonVertexBufferBinding( Graphics.ImmediateContext.Buffers.CreateVertexBuffer("Gorgon 2D Default Vertex Buffer", new GorgonBufferSettings { SizeInBytes = spriteVertexBufferSize, Usage = BufferUsage.Dynamic }), Gorgon2DVertex.SizeInBytes); // Set up the default render states. SetDefaultStates(); }
/// <summary> /// Initializes a new instance of the <see cref="Cube"/> class. /// </summary> /// <param name="graphics">The graphics interface.</param> /// <param name="size">The width, height and depth of the cube.</param> /// <param name="textureCoordinates">The texture coordinates for the faces of the cube.</param> /// <param name="angle">The initial orientation of the cube, in degrees.</param> /// <param name="columnsPerFace">The number of columns per face.</param> /// <param name="rowsPerFace">The number of rows per face.</param> public Cube(GorgonGraphics graphics, Vector3 size, RectangleF textureCoordinates, Vector3 angle, int columnsPerFace = 1, int rowsPerFace = 1) { PrimitiveType = PrimitiveType.TriangleList; Quaternion orientation; int faceVertexCount = (columnsPerFace + 1) * (rowsPerFace + 1); int faceIndexCount = (columnsPerFace * rowsPerFace) * 6; VertexCount = faceVertexCount * 6; IndexCount = faceIndexCount * 6; TriangleCount = IndexCount / 3; Quaternion.RotationYawPitchRoll(angle.Y.Radians(), angle.X.Radians(), angle.Z.Radians(), out orientation); Matrix.RotationQuaternion(ref orientation, out _orientation); unsafe { using ( GorgonDataStream vertexData = new GorgonDataStream(VertexCount * Vertex3D.Size), indexData = new GorgonDataStream(IndexCount * sizeof(int))) { var vertices = (Vertex3D *)vertexData.UnsafePointer; // Front. GetVertices(vertices, Vector3.UnitY, -Vector3.UnitZ, size, textureCoordinates, columnsPerFace, rowsPerFace); // Bottom. GetVertices(vertices + faceVertexCount, -Vector3.UnitZ, -Vector3.UnitY, size, textureCoordinates, columnsPerFace, rowsPerFace); // Back. GetVertices(vertices + (faceVertexCount * 2), Vector3.UnitY, Vector3.UnitZ, size, textureCoordinates, columnsPerFace, rowsPerFace); // Top. GetVertices(vertices + (faceVertexCount * 3), Vector3.UnitZ, Vector3.UnitY, size, textureCoordinates, columnsPerFace, rowsPerFace); // Left. GetVertices(vertices + (faceVertexCount * 4), Vector3.UnitY, -Vector3.UnitX, size, textureCoordinates, columnsPerFace, rowsPerFace); // Right GetVertices(vertices + (faceVertexCount * 5), Vector3.UnitY, Vector3.UnitX, size, textureCoordinates, columnsPerFace, rowsPerFace); var indices = (int *)indexData.UnsafePointer; GetIndices(indices, 0, columnsPerFace, rowsPerFace); GetIndices(indices + faceIndexCount, faceVertexCount, columnsPerFace, rowsPerFace); GetIndices(indices + (faceIndexCount * 2), faceVertexCount * 2, columnsPerFace, rowsPerFace); GetIndices(indices + (faceIndexCount * 3), faceVertexCount * 3, columnsPerFace, rowsPerFace); GetIndices(indices + (faceIndexCount * 4), faceVertexCount * 4, columnsPerFace, rowsPerFace); GetIndices(indices + (faceIndexCount * 5), faceVertexCount * 5, columnsPerFace, rowsPerFace); CalculateTangents(vertices, indices); VertexBuffer = graphics.Buffers.CreateVertexBuffer("CubeVB", new GorgonBufferSettings { Usage = BufferUsage.Immutable, SizeInBytes = (int)vertexData.Length }, vertexData); IndexBuffer = graphics.Buffers.CreateIndexBuffer("CubeIB", new GorgonIndexBufferSettings { Usage = BufferUsage.Immutable, Use32BitIndices = true, SizeInBytes = (int)indexData.Length }, indexData); } } }
/// <summary> /// Function to compress the files in a given directory. /// </summary> /// <param name="output">The output data stream.</param> /// <param name="directory">Directory containing the files to compress.</param> /// <param name="rootNode">Root node for the file allocation table.</param> private void CompressFiles(Stream output, GorgonFileSystemDirectory directory, XElement rootNode) { // If we have sub directories, then create those entries. foreach (var subDir in directory.Directories) { var dirNode = CreatePathNode(subDir); if (_token.IsCancellationRequested) { return; } CompressFiles(output, subDir, dirNode); if (_token.IsCancellationRequested) { return; } // Attach to the root. rootNode.Add(dirNode); } // Compress the files. foreach (var fileEntry in directory.Files) { // Load the file into a buffer for compression. long fileStart = output.Position; long fileSize; long compressedSize = 0; UpdateStatus(string.Format(Resources.GORPKW_SAVING_MSG, fileEntry.FullPath.Ellipses(45, true)), 0); if (_token.IsCancellationRequested) { return; } using (var sourceData = ScratchFileSystem.OpenStream(fileEntry, false)) { // Load the data into memory. using (var fileData = new GorgonDataStream((int)sourceData.Length)) { if (_token.IsCancellationRequested) { return; } sourceData.CopyTo(fileData); if (_token.IsCancellationRequested) { return; } fileSize = fileData.Length; fileData.Position = 0; using (var compressedData = new MemoryStream()) { if (_token.IsCancellationRequested) { return; } CompressData(fileData, compressedData); if (_token.IsCancellationRequested) { return; } compressedData.Position = 0; fileData.Position = 0; // Write the compressed data out to our blob file. if (compressedData.Length < fileSize) { if (_token.IsCancellationRequested) { return; } compressedData.CopyTo(output); if (_token.IsCancellationRequested) { return; } compressedSize = compressedData.Length; } else { if (_token.IsCancellationRequested) { return; } // We didn't compress anything, so just dump the file. fileData.CopyTo(output); if (_token.IsCancellationRequested) { return; } } } } } // Add to our directory. rootNode.Add(CreateFileNode(fileEntry, fileStart, fileSize, compressedSize)); } }
/// <summary> /// Function to write the file to the specified path. /// </summary> /// <param name="path">Path to the file.</param> /// <param name="token">Token used to cancel the task.</param> protected override void WriteFile(string path, CancellationToken token) { // Don't allow other threads in here. lock (_syncLock) { _token = token; _tempPath = ScratchFileSystem.WriteLocation + Path.GetFileName(Path.GetTempFileName()); // Calculate compression ratio. 9 is the max compression level for bzip 2. _compressionRatio = (int)System.Math.Round(Compression * 9.0f, 0, MidpointRounding.AwayFromZero); try { // Build file system. BuildFileSystem(); if (_token.IsCancellationRequested) { return; } // Turn off cancellation at this point. CanCancel(false); if (_token.IsCancellationRequested) { return; } // Write out our file. using (var outputFile = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read)) { // Combine the file system parts into a single packed file. using (var writer = new GorgonBinaryWriter(outputFile, true)) { // Write the file header. writer.Write("GORPACK1.SharpZip.BZ2"); // Copy FAT. using (var fatData = new GorgonDataStream(Encoding.UTF8.GetBytes(_fat.ToStringWithDeclaration()))) { using (var compressData = new MemoryStream()) { CompressData(fatData, compressData); compressData.Position = 0; writer.Write((int)compressData.Length); compressData.CopyTo(outputFile); } } } // Copy the file data. using (var fileData = File.Open(_tempPath, FileMode.Open, FileAccess.Read, FileShare.Read)) { fileData.CopyTo(outputFile); } } } finally { // Destroy the temp data file. File.Delete(_tempPath); } } }
/// <summary> /// Function to create the resources for the buffer. /// </summary> /// <param name="data">The initial data for the buffer.</param> private void CreateResources(GorgonDataStream data) { var desc = new D3D.BufferDescription { BindFlags = D3D.BindFlags.None, CpuAccessFlags = D3DCPUAccessFlags, OptionFlags = D3D.ResourceOptionFlags.None, SizeInBytes = Settings.SizeInBytes, StructureByteStride = Settings.StructureSize, Usage = D3DUsage }; // If this is a render target buffer, then ensure that we have a default resource. if ((IsRenderTarget) && (Settings.Usage != BufferUsage.Default)) { throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_RENDERTARGET_NEED_DEFAULT); } // Set up the buffer. If we're a staging buffer, then none of this stuff will // work because staging buffers can't be bound to the pipeline, so just skip it. if (Settings.Usage != BufferUsage.Staging) { switch (BufferType) { case BufferType.Constant: desc.BindFlags = D3D.BindFlags.ConstantBuffer; break; case BufferType.Index: desc.BindFlags = D3D.BindFlags.IndexBuffer; break; case BufferType.Vertex: desc.BindFlags = D3D.BindFlags.VertexBuffer; break; case BufferType.Structured: if (!IsRenderTarget) { desc.OptionFlags = D3D.ResourceOptionFlags.BufferStructured; } break; } // Update binding modifiers. if (Settings.AllowShaderViews) { desc.BindFlags |= D3D.BindFlags.ShaderResource; } if (Settings.AllowUnorderedAccessViews) { desc.BindFlags |= D3D.BindFlags.UnorderedAccess; } if (!IsRenderTarget) { if (Settings.AllowIndirectArguments) { desc.OptionFlags = D3D.ResourceOptionFlags.DrawIndirectArguments; } } else { desc.BindFlags |= D3D.BindFlags.RenderTarget; } if (Settings.IsOutput) { desc.BindFlags |= D3D.BindFlags.StreamOutput; } if (Settings.AllowRawViews) { desc.OptionFlags = D3D.ResourceOptionFlags.BufferAllowRawViews; } } // Create and initialize the buffer. if (data != null) { long position = data.Position; using (var dxStream = new DX.DataStream(data.BasePointer, data.Length - position, true, true)) { D3DResource = D3DBuffer = new D3D.Buffer(Graphics.D3DDevice, dxStream, desc); } } else { D3DResource = D3DBuffer = new D3D.Buffer(Graphics.D3DDevice, desc); } }