예제 #1
0
 /// <summary>
 /// 2D Arrays or 3D from the bound read framebuffer (from sx/sy) into this texture at x/y -2D Array or 3D
 /// See <href>https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexSubImage3D.xhtml</href>
 /// </summary>
 /// <param name="miplevel">Mip Level to store data into</param>
 /// <param name="xoffset">Left offset to store in the texture</param>
 /// <param name="yoffset">Bottom offset to store in the texture</param>
 /// <param name="zoffset">Depth offset to store in the texture</param>
 /// <param name="x">Left corner to copy</param>
 /// <param name="y">Bottom corner to copy</param>
 /// <param name="width">Width to copy</param>
 /// <param name="height">Height to copy</param>
 public void CopyFromReadFrameBuffer2da3d(int miplevel, int xoffset, int yoffset, int zoffset, int x, int y, int width, int height)
 {
     System.Diagnostics.Debug.Assert(this is GLTexture2DArray || this is GLTexture3D);
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");
     GL.CopyTextureSubImage3D(Id, miplevel, xoffset, yoffset, zoffset, x, y, width, height);
     GLStatics.Check();
 }
예제 #2
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="name">Name of bitmap collection</param>
        /// <param name="rlist">Render list to draw into</param>
        /// <param name="bitmapsize">Bit map size</param>
        /// <param name="mipmaplevels">Mip map levels</param>
        /// <param name="textureformat">Texture format of bitmaps</param>
        /// <param name="cullface">True to cull face</param>
        /// <param name="depthtest">True to depth test</param>
        /// <param name="maxpergroup">Maximum number of bitmaps per group</param>
        /// <param name="yfixed">Set true to fix Y co-ord externally</param>
        public GLBitmaps(string name, GLRenderProgramSortedList rlist, Size bitmapsize, int mipmaplevels = 3,
                         OpenTK.Graphics.OpenGL4.SizedInternalFormat textureformat = OpenTK.Graphics.OpenGL4.SizedInternalFormat.Rgba8,
                         bool cullface = true, bool depthtest = true, int maxpergroup = int.MaxValue, bool yfixed = false)
        {
            this.name    = name;
            this.context = GLStatics.GetContext();

            int maxdepthpertexture = GL4Statics.GetMaxTextureDepth();   // limits the number of textures per 2darray
            int max = Math.Min(maxdepthpertexture, maxpergroup);        //note RI uses a VertexArray to load the matrix in, so not limited by that (max size of uniform buffer)

            matrixbuffers = new GLSetOfMatrixBufferWithGenerations(items, max);

            matrixbuffers.AddedNewGroup += AddedNewGroup;       // hook up call back to say i've made a group

            renderlist      = rlist;
            this.bitmapsize = bitmapsize;

            shader = new GLShaderPipeline(new GLPLVertexShaderMatrixQuadTexture(yfixed), new GLPLFragmentShaderTexture2DIndexed(0, alphablend: true));
            items.Add(shader);

            renderstate                    = GLRenderState.Quads();
            renderstate.CullFace           = cullface;
            renderstate.DepthTest          = depthtest;
            renderstate.ClipDistanceEnable = 1;  // we are going to cull primitives which are deleted

            texmipmaplevels    = mipmaplevels;
            this.textureformat = textureformat;
        }
예제 #3
0
 /// <summary>
 /// 1D Textures from the bound read framebuffer (from x/y) into this texture at xoffset
 /// See <href>https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyTexSubImage2D.xhtml</href>
 /// </summary>
 /// <param name="miplevel">Mip Level to store data into</param>
 /// <param name="xoffset">Left offset to store in the texture</param>
 /// <param name="x">Left corner to copy</param>
 /// <param name="y">Bottom corner to copy</param>
 /// <param name="width">Width to copy</param>
 public void CopyFromReadFrameBuffer1d(int miplevel, int xoffset, int x, int y, int width)
 {
     System.Diagnostics.Debug.Assert(this is GLTexture1D);
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");
     GL.CopyTextureSubImage1D(Id, miplevel, xoffset, x, y, width);
     GLStatics.Check();
 }
예제 #4
0
 /// <summary>Zero the buffer from this position and length</summary>
 public void Zero(int pos, int length)
 {
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");     // safety
     System.Diagnostics.Debug.Assert(Length != 0 && pos >= 0 && length <= Length && pos + length <= Length);
     GL.ClearNamedBufferSubData(Id, PixelInternalFormat.R32ui, (IntPtr)pos, length, PixelFormat.RedInteger, PixelType.UnsignedInt, (IntPtr)0);
     GLStatics.Check();
 }
예제 #5
0
        /// <summary>
        /// Set the sampler mode (GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_MIRRORED_REPEAT, GL_REPEAT, or GL_MIRROR_CLAMP_TO_EDGE) (Use OpenTK names)
        /// </summary>
        /// <param name="s">Texture wrap width</param>
        public void SetSamplerMode(TextureWrapMode s)
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");
            int st = (int)s;

            GL.TextureParameterI(Id, TextureParameterName.TextureWrapS, ref st);
        }
예제 #6
0
        /// <summary>
        /// Fill vertex buffer with vector4's, and write an indirect to indirectbuffer N
        /// </summary>
        /// <param name="vertices">Array of vertices to store</param>
        /// <param name="sourceoffset">Start position in array</param>
        /// <param name="sourcelength">Length of store</param>
        /// <param name="indirectbuffer">Which indirect buffer to store indexes into</param>
        /// <param name="vertexcount">If greater or equal to zero, use this count for indirects, else user source length</param>
        /// <param name="vertexbaseindex">Vertex base index for indirect</param>
        /// <param name="ic">Instance count for indirect</param>
        /// <param name="baseinstance">If greater or equal to zero, use this, else estimate the base instance number based on vertex position. </param>
        /// <returns>True if filled</returns>
        public bool Fill(Vector4[] vertices, int sourceoffset, int sourcelength,
                         int indirectbuffer,
                         int vertexcount     = -1,
                         int vertexbaseindex = 0,
                         int ic           = 1,
                         int baseinstance = -1)                     // baseinstance, <0 use CurrentPos on vertex buffer to estimate instance number, else use this
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");
            CreateIndirect(indirectbuffer);

            if (EnoughSpaceVertex(sourcelength, indirectbuffer))
            {
                Vertex.Fill(vertices, sourceoffset, sourcelength);          // creates a position
                //Vertex.Fill(vertices);          // creates a position
                //    System.Diagnostics.Debug.WriteLine($"Vertex buf {Vertex.Positions.Last()} size {vertices.Length * GLBuffer.Vec4size}");
                vertexcount  = vertexcount >= 0 ? vertexcount : sourcelength;
                baseinstance = baseinstance >= 0 ? baseinstance : (Vertex.Positions.Last() / GLBuffer.Vec4size);

                int pos = Indirects[indirectbuffer].Positions.Count * GLBuffer.WriteIndirectArrayStride;
                Indirects[indirectbuffer].AddPosition(pos);
                Indirects[indirectbuffer].StartWrite(pos, GLBuffer.WriteIndirectArrayStride);
                Indirects[indirectbuffer].WriteIndirectArray(vertexcount, ic, vertexbaseindex, baseinstance);
                Indirects[indirectbuffer].StopReadWrite();
                return(true);
            }
            else
            {
                return(false);
            }
        }
예제 #7
0
 /// <summary> Stop a read or write sequence, release buffer back to use </summary>
 public void StopReadWrite()
 {
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");     // safety
     GL.UnmapNamedBuffer(Id);
     mapmode = MapMode.None;
     GLStatics.Check();
 }
예제 #8
0
        /// <summary>
        /// Add a bitmap to the collection.
        /// </summary>
        /// <param name="tag">Tag for this bitmap, may be null</param>
        /// <param name="bmp">Bitmap</param>
        /// <param name="bmpmipmaplevels">The bitmap mip map levels</param>
        /// <param name="worldpos">Position of bitmap in world</param>
        /// <param name="size">Size to draw bitmap in world.</param>
        /// <param name="rotationradians">Rotation of bitmap (ignored if rotates below are on)</param>
        /// <param name="rotatetoviewer">True to rotate to viewer in azimuth</param>
        /// <param name="rotateelevation">True to rotate to viewer in elevation</param>
        /// <param name="alphafadescalar">Alpha Fade scalar on distance</param>
        /// <param name="alphafadepos">Alpha fade distance. Negative for fade in, positive for fade out </param>
        /// <param name="ownbitmap"></param>
        /// <param name="visible">True if visible on start</param>
        /// <returns></returns>
        // add a bitmap, indicate if owned by class or you.  Gives back group no, position in group, total in group
        public virtual Tuple <int, int, int> Add(object tag,
                                                 Bitmap bmp,
                                                 int bmpmipmaplevels,
                                                 Vector3 worldpos,
                                                 Vector3 size,
                                                 Vector3 rotationradians,
                                                 bool rotatetoviewer   = false, bool rotateelevation = false,
                                                 float alphafadescalar = 0,
                                                 float alphafadepos    = 0,
                                                 bool ownbitmap        = false,
                                                 bool visible          = true
                                                 )
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Bitmaps detected context incorrect");

            Matrix4 mat = GLPLVertexShaderMatrixQuadTexture.CreateMatrix(worldpos, size, rotationradians, rotatetoviewer, rotateelevation, alphafadescalar, alphafadepos, 0, visible);

            var gpc = matrixbuffers.Add(tag, ownbitmap ? bmp : null, mat);     // group, pos, total in group

            //  System.Diagnostics.Debug.WriteLine("Make bitmap {0} {1} {2} at {3}", gpc.Item1, gpc.Item2, gpc.Item3 , worldpos);

            grouptextureslist[gpc.Item1].LoadBitmap(bmp, gpc.Item2, false, bmpmipmaplevels); // texture does not own them, we may do
            grouprenderlist[gpc.Item1].InstanceCount = gpc.Item3;                            // update instance count to items in group
            return(gpc);
        }
예제 #9
0
 ///<summary>Create an empty buffer of this standard, default is std130. Standard defines the layout of members of the buffer. See OpenGL</summary>
 public GLBuffer(bool std430 = false) : base(std430)
 {
     GL.CreateBuffers(1, out int id);     // this actually makes the buffer, GenBuffer does not - just gets a name
     GLStatics.RegisterAllocation(typeof(GLBuffer));
     GLStatics.Check();
     Id      = id;
     context = GLStatics.GetContext();
 }
예제 #10
0
        /// <summary> Set Min Mag filter to linear </summary>
        public void SetMinMagLinear()
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");
            var textureFilter = (int)All.Linear;

            GL.TextureParameterI(Id, TextureParameterName.TextureMinFilter, ref textureFilter);
            GL.TextureParameterI(Id, TextureParameterName.TextureMagFilter, ref textureFilter);
        }
예제 #11
0
        /// <summary>
        /// Copy to another buffer. Other buffer must be Allocated to the size otherpos+length
        /// </summary>
        /// <param name="other">Other buffer</param>
        /// <param name="startpos">Start posiiton in buffer</param>
        /// <param name="otherpos">Position to store it in other buffer</param>
        /// <param name="length">Copy length</param>
        /// <param name="hint"></param>
        public void CopyTo(GLBuffer other, int startpos, int otherpos, int length, BufferUsageHint hint = BufferUsageHint.StaticDraw) // newlength can be zero, meaning discard and go back to start
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");                                  // safety
            int ourend   = startpos + length;
            int otherend = otherpos + length;

            System.Diagnostics.Debug.Assert(Length >= ourend && other.Length >= otherend);
            GL.CopyNamedBufferSubData(Id, other.Id, (IntPtr)startpos, (IntPtr)otherpos, length);
        }
예제 #12
0
        /// <summary>
        /// Construct a control display
        /// </summary>
        /// <param name="items">Items to store GL data to</param>
        /// <param name="win">GLWindowControl to hook to</param>
        /// <param name="mc">Matrix Calc to use</param>
        /// <param name="depthtest">Enable depth test</param>
        /// <param name="startz">Start Z for nearest top level window</param>
        /// <param name="deltaz">Delta Z between each top level window</param>
        /// <param name="arbbufferid">ARB buffer to use for texture bindless storage</param>
        public GLControlDisplay(GLItemsList items, GLWindowControl win, GLMatrixCalc mc,
                                bool depthtest  = true,             // do depth testing or not
                                float startz    = 0.001f,           // z for the deepest window (only will apply if depth testing
                                float deltaz    = 0.001f,           // delta betwwen them
                                int arbbufferid = 10
                                ) : base("displaycontrol", new Rectangle(0, 0, mc.ScreenCoordMax.Width, mc.ScreenCoordMax.Height))
        {
            glwin      = win;
            MatrixCalc = mc;
            context    = GLStatics.GetContext();

            this.items = items;

            vertexes = items.NewBuffer();

            vertexarray = items.NewVertexArray();
            vertexes.Bind(vertexarray, 0, 0, vertexesperentry * sizeof(float));                            // bind to 0, from 0, 2xfloats. Must bind after vertexarray is made as its bound during construction

            vertexarray.Attribute(0, 0, vertexesperentry, OpenTK.Graphics.OpenGL4.VertexAttribType.Float); // bind 0 on attr 0, 2 components per vertex

            GLRenderState rc = GLRenderState.Tri();

            rc.PrimitiveRestart = 0xff;
            rc.DepthTest        = depthtest;

            this.startz = startz;
            this.deltaz = deltaz;

            ri = new GLRenderableItem(PrimitiveType.TriangleStrip, rc, 0, vertexarray); // create a renderable item
            ri.CreateRectangleElementIndexByte(items.NewBuffer(), 255 / 5);             // note this limits top level controls number to 255/5.
            ri.DrawCount = 0;                                                           // nothing to draw at this point

            shader = new GLShaderPipeline(new GLPLVertexShaderScreenTexture(), new GLPLFragmentShaderBindlessTexture(arbbufferid, true, discardiftransparent: true));
            items.Add(shader);

            textures = new Dictionary <GLBaseControl, GLTexture2D>();
            size     = new Dictionary <GLBaseControl, Size>();
            visible  = new Dictionary <GLBaseControl, bool>();

            texturebinds = items.NewBindlessTextureHandleBlock(arbbufferid);

            glwin.MouseMove        += Gc_MouseMove;
            glwin.MouseClick       += Gc_MouseClick;
            glwin.MouseDoubleClick += Gc_MouseDoubleClick;
            glwin.MouseDown        += Gc_MouseDown;
            glwin.MouseUp          += Gc_MouseUp;
            glwin.MouseEnter       += Gc_MouseEnter;
            glwin.MouseLeave       += Gc_MouseLeave;
            glwin.MouseWheel       += Gc_MouseWheel;
            glwin.KeyDown          += Gc_KeyDown;
            glwin.KeyUp            += Gc_KeyUp;
            glwin.KeyPress         += Gc_KeyPress;
            glwin.Resize           += Gc_Resize;
            glwin.Paint            += Gc_Paint;

            suspendLayoutCount = 0;
        }
예제 #13
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="items">Item list to store buffers into</param>
 /// <param name="vertsize">Size of vertex buffer</param>
 /// <param name="indirectsize">Size of indirect buffer</param>
 /// <param name="std430">Std430 layout</param>
 /// <param name="bufferusagehint">Buffer usage hint</param>
 public GLVertexBufferIndirect(GLItemsList items, int vertsize, int indirectsize, bool std430 = false, BufferUsageHint bufferusagehint = BufferUsageHint.StaticDraw)
 {
     this.items        = items;
     this.indirectsize = indirectsize;
     this.bufferusage  = bufferusagehint;
     this.context      = GLStatics.GetContext();
     Vertex            = new GLBuffer(vertsize, std430, bufferusagehint);
     items.Add(Vertex);
 }
예제 #14
0
        /// <summary>
        /// Set Min Mag filter on texture
        /// </summary>
        /// <param name="minfilter">Min filter (default LinearMipmapLinear)</param>
        /// <param name="maxfilter">Max filter (default Linear)</param>
        public void SetMinMagFilter(All minfilter = All.LinearMipmapLinear, All maxfilter = All.Linear)
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");
            var textureMinFilter = (int)minfilter;

            GL.TextureParameterI(Id, TextureParameterName.TextureMinFilter, ref textureMinFilter);
            var textureMagFilter = (int)maxfilter;

            GL.TextureParameterI(Id, TextureParameterName.TextureMagFilter, ref textureMagFilter);
        }
예제 #15
0
 /// <summary>Call to ensure this texture has an ARB texture ID</summary>
 public long AcquireArbId()
 {
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");
     if (arbid == -1)
     {
         arbid = OpenTK.Graphics.OpenGL.GL.Arb.GetTextureHandle(Id);
         OpenTK.Graphics.OpenGL.GL.Arb.MakeTextureHandleResident(arbid);     // can't do this twice!
     }
     return(arbid);
 }
예제 #16
0
 /// <summary>Bind buffer to vertext array at this bindingindex, with the start position stride and divisor</summary>
 public void Bind(GLVertexArray va, int bindingindex, int start, int stride, int divisor = 0) // set buffer binding to a VA
 {
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect"); // safety
     System.Diagnostics.Debug.Assert(mapmode == MapMode.None);                                // catch unmap missing. Since binding to VA can be done before buffer is full, then don't check BufferSize
     va.Bind();
     GL.BindVertexBuffer(bindingindex, Id, (IntPtr)start, stride);                            // this buffer to binding index
     GL.VertexBindingDivisor(bindingindex, divisor);
     GLStatics.Check();
     //System.Diagnostics.Debug.WriteLine("BUFBIND " + bindingindex + " To B" + Id + " pos " + start + " stride " + stride + " divisor " + divisor);
 }
예제 #17
0
        /// <summary>
        /// From any type of ImageTarget into this - All types
        /// See <href>https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glCopyImageSubData.xhtml</href>
        /// </summary>
        /// <param name="srcid">Texture or Renderbuffer source</param>
        /// <param name="srcTarget">Source image type</param>
        /// <param name="srcmiplevel">Mipmap level to copy from</param>
        /// <param name="sx">Source X</param>
        /// <param name="sy">Source Y</param>
        /// <param name="sz">Source Z level</param>
        /// <param name="dmiplevel">Destination mip level</param>
        /// <param name="dx">Destination X</param>
        /// <param name="dy">Destination Y</param>
        /// <param name="dz">Destination Z (0 for 2D/1D</param>
        /// <param name="width">Destination Width</param>
        /// <param name="height">Destination Height</param>
        public void CopyFrom(int srcid, ImageTarget srcTarget, int srcmiplevel, int sx, int sy, int sz, int dmiplevel, int dx, int dy, int dz, int width, int height)
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");
            // not sure, according to spec, the dest target may just need to be a texture type..
            ImageTarget it = this is GLTexture2D ? ImageTarget.Texture2D : this is GLTexture2DArray ? ImageTarget.Texture2DArray : this is GLTexture1D ? ImageTarget.Texture1D : ImageTarget.Texture3D;

            GL.CopyImageSubData(srcid, srcTarget, srcmiplevel, sx, sy, sz,
                                Id, it, dmiplevel, dx, dy, dz, width, height, 1);
            GLStatics.Check();
        }
예제 #18
0
 /// <summary>Bind buffer to parameter binding point</summary>
 public void BindParameter()
 {
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect"); // safety
     System.Diagnostics.Debug.Assert(mapmode == MapMode.None && Length > 0);                  // catch unmap missing or nothing in buffer
     // if (parameterbindindex != Id) // removed for testing
     {
         GL.BindBuffer((BufferTarget)0x80ee, Id);        // fudge due to ID not being there in 3.3.2
         GLStatics.Check();
         parameterbindindex = Id;
     }
 }
예제 #19
0
 ///<summary> Bind to query buffer</summary>
 public void BindQuery()
 {
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect"); // safety
     System.Diagnostics.Debug.Assert(mapmode == MapMode.None && Length > 0);                  // catch unmap missing or nothing in buffer
     if (querybindindex != Id)
     {
         GL.BindBuffer(BufferTarget.QueryBuffer, Id);
         GLStatics.Check();
         querybindindex = Id;
     }
 }
예제 #20
0
 /// <summary>Bind buffer to indirect binding point</summary>
 public void BindIndirect()
 {
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect"); // safety
     System.Diagnostics.Debug.Assert(mapmode == MapMode.None && Length > 0);                  // catch unmap missing or nothing in buffer
     //if (indirectbindindex != Id) // removed for testing
     {
         GL.BindBuffer(BufferTarget.DrawIndirectBuffer, Id);
         GLStatics.Check();
         indirectbindindex = Id;
     }
 }
예제 #21
0
 ///<summary>Allocate or reallocate buffer size. Call first to set buffer size. Allow for alignment in your size</summary>
 public void AllocateBytes(int bytessize, BufferUsageHint hint = BufferUsageHint.StaticDraw)
 {
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect"); // safety
     if (bytessize > 0)                                                                       // can call twice - get fresh buffer each time
     {
         Length = bytessize;
         GL.NamedBufferData(Id, Length, (IntPtr)0, hint);                                          // set buffer size
         var err = GL.GetError();
         System.Diagnostics.Debug.Assert(err == ErrorCode.NoError, $"GL NamedBuffer error {err}"); // check for any errors, always.
         ResetPositions();
     }
 }
예제 #22
0
        /// <summary>
        /// Clear part of an image
        /// See <href>https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glClearTexSubImage.xhtml</href>
        /// </summary>
        /// <param name="level">Level to clear</param>
        /// <param name="x">Left edge</param>
        /// <param name="y">Lower edge</param>
        /// <param name="z">Front of region</param>
        /// <param name="width">Width to clear</param>
        /// <param name="height">Height to clear</param>
        /// <param name="depth">Depth to clear</param>
        /// <param name="red">Red value, 0-1</param>
        /// <param name="green">Green value, 0-1</param>
        /// <param name="blue">Blue value, 0-1</param>
        /// <param name="alpha">Alpha value, 0-1</param>
        public void ClearSubImage(int level, int x, int y, int z, int width, int height, int depth, float red, float green, float blue, float alpha)
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");

            int    size = Marshal.SizeOf <float>() * 4;
            IntPtr pnt  = Marshal.AllocHGlobal(size);

            float[] a = new float[] { red, green, blue, alpha };
            Marshal.Copy(a, 0, pnt, a.Length);
            GL.ClearTexSubImage(Id, level, x, y, z, width, height, depth, PixelFormat.Rgba, PixelType.Float, pnt);
            Marshal.FreeHGlobal(pnt);
            GLStatics.Check();
        }
예제 #23
0
        /// <summary>
        /// Clear image to this color
        /// </summary>
        /// <param name="level">Level to clear</param>
        /// <param name="red">Red value, 0-1</param>
        /// <param name="green">Green value, 0-1</param>
        /// <param name="blue">Blue value, 0-1</param>
        /// <param name="alpha">Alpha value, 0-1</param>
        public void ClearImage(int level, float red, float green, float blue, float alpha)  // confirmed
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");
            int size = Marshal.SizeOf <float>() * 4;

            IntPtr pnt = Marshal.AllocHGlobal(size);

            float[] a = new float[] { red, green, blue, alpha };
            Marshal.Copy(a, 0, pnt, a.Length);
            GL.ClearTexImage(Id, level, PixelFormat.Rgba, PixelType.Float, pnt);
            Marshal.FreeHGlobal(pnt);
            GLStatics.Check();
        }
예제 #24
0
 /// <summary>
 /// Bind buffer to the specific transform feedback buffer object at binding index
 /// See <href>https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTransformFeedbackBufferBase.xhtml</href>
 /// </summary>
 /// <param name="bindingindex">Index of binding point within xfb</param>
 /// <param name="xfb">Name of the transformation feeback buffer object. 0 means default transform</param>
 /// <param name="offset">Offset into buffer if size != -1</param>
 /// <param name="size">Buffer area allocated. If size == -1, all of buffer</param>
 public void BindTransformFeedback(int bindingindex, int xfb = 0, int offset = 0, int size = -1)
 {
     System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect"); // safety
     System.Diagnostics.Debug.Assert(mapmode == MapMode.None && Length > 0);                  // catch unmap missing or nothing in buffer
     if (size == -1)
     {
         GL.TransformFeedbackBufferBase(xfb, bindingindex, Id);
     }
     else
     {
         GL.TransformFeedbackBufferRange(xfb, bindingindex, Id, (IntPtr)offset, size);
     }
     GLStatics.Check();
 }
예제 #25
0
        ///<summary> Begin a write. Select position and size. (datasize=0=all buffer).
        /// Buffer access mask decides what to keep about the range, default is to wipe the mapped area. Use 0 in bam not to do this. Trap for young players here</summary>
        public void StartWrite(int fillpos, int datasize = 0, BufferAccessMask bufferaccessmask = BufferAccessMask.MapInvalidateRangeBit)
        {
            if (datasize == 0)
            {
                datasize = Length - fillpos;
            }

            System.Diagnostics.Debug.Assert(mapmode == MapMode.None && fillpos >= 0 && fillpos + datasize <= Length); // catch double maps
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");                  // safety

            CurrentPtr = GL.MapNamedBufferRange(Id, (IntPtr)fillpos, datasize, BufferAccessMask.MapWriteBit | bufferaccessmask);

            CurrentPos = fillpos;
            mapmode    = MapMode.Write;
            GLStatics.Check();
        }
예제 #26
0
        /// <summary>
        /// Start read on definable area
        /// </summary>
        public void StartRead(int fillpos, int datasize = 0)        // read the buffer (datasize=0=all buffer)
        {
            if (datasize == 0)
            {
                datasize = Length - fillpos;
            }

            System.Diagnostics.Debug.Assert(mapmode == MapMode.None && fillpos >= 0 && fillpos + datasize <= Length); // catch double maps
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");                  // safety

            CurrentPtr = GL.MapNamedBufferRange(Id, (IntPtr)fillpos, datasize, BufferAccessMask.MapReadBit);

            CurrentPos = fillpos;
            mapmode    = MapMode.Read;
            GLStatics.Check();
        }
예제 #27
0
        /// <summary>
        /// Resize the buffer. Note this results in a new GL Buffer, so any VertexArrays will need remaking. Also note the Positions are maintained, you may want to delete those manually.
        /// </summary>
        public void Resize(int newlength, BufferUsageHint hint = BufferUsageHint.StaticDraw)         // newlength can be zero, meaning discard and go back to start
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect"); // safety
            if (Length != newlength)
            {
                GL.CreateBuffers(1, out int newid);
                if (newlength > 0)
                {
                    GL.NamedBufferData(newid, newlength, (IntPtr)0, hint);                                    // set buffer size
                    var err = GL.GetError();
                    System.Diagnostics.Debug.Assert(err == ErrorCode.NoError, $"GL NamedBuffer error {err}"); // check for any errors, always.
                    if (Length > 0)                                                                           // if previous buffer had data
                    {
                        GL.CopyNamedBufferSubData(Id, newid, (IntPtr)0, (IntPtr)0, Math.Min(Length, newlength));
                    }
                }

                GL.DeleteBuffer(Id);        // delete old buffer

                Id     = newid;             // swap to new
                Length = newlength;
            }
        }
예제 #28
0
        /// <summary>Dispose of texture, will free bitmaps if owned</summary>
        public void Dispose()           // you can double dispose.
        {
            System.Diagnostics.Debug.Assert(context == GLStatics.GetContext(), "Context incorrect");
            if (Id >= 0)
            {
                if (arbid != -1)                                                       // if its been arb'd, de-arb it
                {
                    OpenTK.Graphics.OpenGL.GL.Arb.MakeTextureHandleNonResident(arbid); // can't do this twice!
                    arbid = -1;
                }

                GL.DeleteTexture(Id);
                GLStatics.RegisterDeallocation(GetType());
                Id = -2;    // -2 means made, then destroyed

                if (BitMaps != null)
                {
                    for (int i = 0; i < BitMaps.Length; i++)
                    {
                        if (OwnBitMaps[i] && BitMaps[i] != null)     // we may have empty spaces in the bitmap list
                        {
                            BitMaps[i].Dispose();
                        }
                    }

                    BitMaps    = null;
                    OwnBitMaps = null;
                }
            }
            else
            {
                if (Id == -2)                                                                                                         // goes -1 -> ID -> -2, never uses stays as -1
                {
                    System.Diagnostics.Trace.WriteLine($"OFC Warning - double disposing of a texture block in {GetType().FullName}"); // only an warning due to the fact you can create and not use
                }
            }
        }
예제 #29
0
        /// <summary>
        /// Make a GL Control and attach to control.
        /// </summary>
        /// <param name="attachcontrol">Control to attach the GL Control to</param>
        /// <param name="mode">TK graphics mode</param>
        public GLWinFormControl(Control attachcontrol, OpenTK.Graphics.GraphicsMode mode = null)
        {
            if (mode == null)
            {
                mode = OpenTK.Graphics.GraphicsMode.Default;
            }

            glControl = new GLControlKeyOverride(mode);

            glControl.MakeCurrent();        // make sure GLControl is current context selected, in case operating with multiples

            glControl.Dock            = DockStyle.Fill;
            glControl.BackColor       = System.Drawing.Color.Black;
            glControl.Name            = "glControl";
            glControl.TabIndex        = 0;
            glControl.VSync           = true;
            glControl.PreviewKeyDown += Gl_PreviewKeyDown;

            attachcontrol.Controls.Add(glControl);

            glControl.MouseDown        += Gc_MouseDown;
            glControl.MouseUp          += Gc_MouseUp;
            glControl.MouseMove        += Gc_MouseMove;
            glControl.MouseEnter       += Gc_MouseEnter;
            glControl.MouseLeave       += Gc_MouseLeave;
            glControl.MouseClick       += Gc_MouseClick;
            glControl.MouseDoubleClick += Gc_MouseDoubleClick;
            glControl.MouseWheel       += Gc_MouseWheel;
            glControl.KeyDown          += Gc_KeyDown;
            glControl.KeyUp            += Gc_KeyUp;
            glControl.KeyPress         += Gc_KeyPress;
            glControl.Resize           += Gc_Resize;
            glControl.Paint            += GlControl_Paint;
            context = GLStatics.GetContext();
            System.Diagnostics.Debug.WriteLine($"GL Context {context} created");
            gltime.Start();
        }
        /// <summary>
        /// Creator of this draw set
        /// </summary>
        /// <param name="textures"> number of 2D textures to allow maximum (limited by GL)</param>
        /// <param name="estimateditemspergroup">Estimated objects per group, this adds on vertext buffer space to allow for mat4 alignment. Smaller means more allowance.</param>
        /// <param name="mingroups">Minimum groups to have</param>
        /// <param name="objectbuffer">Object buffer to use</param>
        /// <param name="objectvertexes">Number of object vertexes</param>
        /// <param name="objrc">The object render state control</param>
        /// <param name="objpt">The object draw primitive type</param>
        /// <param name="texturesize">The size of the label</param>
        /// <param name="textrc">The text render state</param>
        /// <param name="textureformat">The texture format for the text</param>
        /// <param name="debuglimittexture">For debug, set this to limit maximum number of entries. 0 = off</param>
        /// <returns></returns>
        public Tuple <GLRenderableItem, GLRenderableItem> Create(
            int textures,
            int estimateditemspergroup,
            int mingroups,
            GLBuffer objectbuffer, int objectvertexes, GLRenderState objrc, PrimitiveType objpt,
            Size texturesize, GLRenderState textrc, SizedInternalFormat textureformat,
            int debuglimittexture = 0)
        {
            this.objectvertexescount = objectvertexes;
            this.context             = GLStatics.GetContext();

            // Limit number of 2d textures in a single 2d array
            int maxtextper2darray = GL4Statics.GetMaxTextureDepth();

            if (debuglimittexture > 0)
            {
                maxtextper2darray = debuglimittexture;
            }

            // set up number of textmaps bound
            int maxtexturesbound = GL4Statics.GetMaxFragmentTextures();
            int textmaps         = Math.Min(textures, maxtexturesbound);

            // which then give us the number of stars we can do
            int objectcount = textmaps * maxtextper2darray;
            int groupcount  = objectcount / estimateditemspergroup;

            groupcount = Math.Max(mingroups, groupcount);               // min groups

            // System.Diagnostics.Debug.WriteLine($"GLObjectWithLabels oc {objectcount} gc {groupcount}");

            // estimate maximum vert buffer needed, allowing for extra due to the need to align the mat4
            int vertbufsize = objectcount * (GLBuffer.Vec4size + GLBuffer.Mat4size) + // for a vec4 + mat4 per object
                              groupcount * GLBuffer.Mat4size;                         // and for groupcount Mat4 fragmentation per group

            // create the vertex indirect buffer
            dataindirectbuffer = new GLVertexBufferIndirect(items, vertbufsize, GLBuffer.WriteIndirectArrayStride * groupcount, true, BufferUsageHint.DynamicDraw);

            // objects
            ObjectRenderer = GLRenderableItem.CreateVector4Vector4(items, objpt, objrc,
                                                                   objectbuffer, 0, 0,           // binding 0 is shapebuf, offset 0, no draw count yet
                                                                   dataindirectbuffer.Vertex, 0, // binding 1 is vertex's world positions, offset 0
                                                                   null, 0, 1);                  // no ic, second divisor 1
            ObjectRenderer.BaseIndexOffset      = 0;                                             // offset in bytes where commands are stored
            ObjectRenderer.MultiDrawCountStride = GLBuffer.WriteIndirectArrayStride;

            // text

            this.textures = new GLTexture2DArray[textmaps];

            for (int i = 0; i < this.textures.Length; i++)
            {
                int n = Math.Min(objectcount, maxtextper2darray);
                this.textures[i] = new GLTexture2DArray(texturesize.Width, texturesize.Height, n, textureformat, 1);
                items.Add(this.textures[i]);
                objectcount -= maxtextper2darray;
            }

            TextRenderer = GLRenderableItem.CreateMatrix4(items, PrimitiveType.Quads, textrc,
                                                          dataindirectbuffer.Vertex, 0, 0,           //attach buffer with matrices, no draw count
                                                          new GLRenderDataTexture(this.textures, 0), // binding 0 assign to our texture 2d
                                                          0, 1);                                     //no ic, and matrix divide so 1 matrix per vertex set
            TextRenderer.BaseIndexOffset      = 0;                                                   // offset in bytes where commands are stored
            TextRenderer.MultiDrawCountStride = GLBuffer.WriteIndirectArrayStride;


            return(new Tuple <GLRenderableItem, GLRenderableItem>(ObjectRenderer, TextRenderer));
        }