//----------------------------------------------------------------------- //----------------------------------------------------------------------- // file="CollisionTexture.cs" // Project: StgSharp // AuthorGroup: Nitload Space // Copyright (c) Nitload Space. All rights reserved. // // Permission is hereby granted, free of charge, to any person // obtaining a copy of this software and associated documentation // files (the “Software”), to deal in the Software without restriction, // including without limitation the rights to use, copy, modify, merge, // publish, distribute, sublicense, and/or sell copies of the Software, // and to permit persons to whom the Software is furnished to do so, // subject to the following conditions: // // The above copyright notice and // this permission notice shall be included in all copies // or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED “AS IS”, // WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, // ARISING FROM, OUT OF OR IN CONNECTION WITH // THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // //----------------------------------------------------------------------- //----------------------------------------------------------------------- using StgSharp.Data; using StgSharp.Geometries; using StgSharp.Graphics; using StgSharp.Graphics.GL; using StgSharp.Logic; using StgSharp.Math; using System; using System.Buffers; using System.Collections.Generic; using System.Linq; using System.Resources; using System.Text; using System.Threading.Tasks; namespace StgSharp.Stg { public class CollisionTextureInput : BlueprintPipelineArgs { #pragma warning disable CS8618 public CollisionTextureInput() #pragma warning restore CS8618 { } public new List Value { get; set; } } public class OneDimensionalCollisionTexture2D : glRenderStream { private const string inputName = "InstanceBufferList"; private const string outputName = "CollisionTextureOutput"; private FrameBuffer fbo; ShaderProgram generatingShader; VertexArray vao; VertexBuffer vbo; ElementBuffer ebo; public OneDimensionalCollisionTexture2D(RenderStreamConstructArgs args) : base(args) { throw new InvalidOperationException( $"Collision TextureGL unit cannot share context with other render stream or set as mainstream of a form,{($"and cannot be inited by {typeof(RenderStreamConstructArgs).Name} as well.")}" ); } #pragma warning disable CS8618 public OneDimensionalCollisionTexture2D(Radius angleStride, string name) : #pragma warning restore CS8618 base(new RenderStreamConstructArgs { Height = 1, Width = (int)((new Radius(Scaler.Pi)) / angleStride), UnitCubeSize = (1, 1, 1), Name = name }) { InternalInit(); } protected override string[] InputPortsName => [ inputName, ]; protected override string[] OutputPortsName => [ outputName, ]; protected override void Deinit() { throw new NotImplementedException(); } protected override void Init() { generatingShader = CreateShaderProgram(); Shader vertexShader = CreateShaderSegment(ShaderType.Vertex, 1); Shader fragmentShader = CreateShaderSegment(ShaderType.Fragment, 1); vertexShader.Compile(0, InternalIO.CollisionTextureVertexShader); fragmentShader.Compile(0, InternalIO.CollisionTextureFragmentShader); vertexShader.AttachTo(0, generatingShader); fragmentShader.AttachTo(0, generatingShader); generatingShader.Link(); generatingShader.Use(); vbo = CreateVertexBuffer(3); vao = CreateVertexArray(1); ebo = CreateElementBuffer(1); fbo = CreateFrameBuffer(1); RenderBuffer rbo = CreateRenderBuffer(1); glFunc.SetRenderBufferStorage( RenderBufferInternalFormat.Depth24_Stencil8, this.Size); t = CreateTexture(1); t.Bind2D(0); glFunc.TextureImage2d(Texture2DTarget.Texture2D, 0, (int)ImageChannel.WithAlphaChannel, (uint)Width, (uint)Height, (int)ImageChannel.WithAlphaChannel, ImageChannelLayout.Byte, glHandle.ZeroHandle); t.Set2dWrapProperty(Wrap.Repeat, Wrap.Repeat); t.Set2dFilterProperty(Filter.Nearest, Filter.Nearest); glFunc.FrameBufferTexture2d(FrameBufferTarget.All, glAttachment.Color(0), Texture2DTarget.Texture2D, t[0], 0); glFunc.CombineFrameBufferRenderBuffer(fbo[0], rbo[0]); textureOutput = new float[this.Width]; } TextureGL t; float[] textureOutput; protected override void Main( in Dictionary input, in Dictionary output) { if (input == null) { throw new InvalidOperationException($"Unknown operation lead to null ref of {nameof(input)}"); } if (input[inputName].Args is not CollisionTextureInput inpipeline || inpipeline.Value == null || inpipeline.Value.Count == 0) { throw new InvalidOperationException(); } List bufferList = inpipeline.Value; fbo.Bind(0); glFunc.ClearColor(0, 0, 0, 1); glFunc.Clear(MaskBufferBit.DEPTH|MaskBufferBit.COLOR); generatingShader.Use(); vao.Bind(0); foreach (IInstancingBuffer item in bufferList) { IGeometry g = item.TypicalShape; if (!(g is PlainGeometry)) { throw new InvalidOperationException("The current particle buffer contains non-planar geometry,"); } ebo.Bind(0); ebo.SetValue(0,g.VertexIndices,BufferUsage.StreamDraw); vbo.WriteVectorData(0,item.CoordAndRotationSpan,BufferUsage.StreamDraw); VertexArray.SetVertexAttribute(1,3,TypeCode.Single,false, 4 * sizeof(float), 0); VertexArray.SetVertexAttribute(2,1, TypeCode.Single,false,4*sizeof(float), 3 * sizeof(float)); vbo.WriteScalerData(2, item.ScalingSpan, BufferUsage.StreamDraw); VertexArray.SetVertexAttribute(3, 1, TypeCode.Single, false, sizeof(float), 0); vbo.WriteVectorData(1,g.VertexStream,BufferUsage.StreamDraw); VertexArray.SetVertexAttribute(0,3,TypeCode.Single,false,4*sizeof(float),0); glFunc.DrawElementsInstanced(GeometryType.TRIANGLES,(uint)g.VertexIndices.Length / 3, TypeCode.UInt32,IntPtr.Zero,(uint)item.ScalingSpan.Length); } t.Bind2D(0); glFunc.GetTextureImage(Texture2DTarget.Texture2D,0,ImageChannel.SingleColor,ImageChannelLayout.Float,ref textureOutput); VertexArray.BindNull(); } protected override void ProcessInput() { throw new NotImplementedException(); } } }