/// <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(); }
private void ControllerDraw(Controller3D mc, ulong unused) { System.Diagnostics.Debug.WriteLine("Draw"); GLMatrixCalcUniformBlock mcub = (GLMatrixCalcUniformBlock)items.UB("MCUB"); mcub.SetFull(gl3dcontroller.MatrixCalc); rObjects.Render(glwfc.RenderState, gl3dcontroller.MatrixCalc, false); GLStatics.Check(); //GLStatics.Flush(); var t1 = ts1.GetCounter(); var t2 = ts2.GetCounter(); System.Diagnostics.Debug.WriteLine($"Time Taken {t2 - t1} ns"); var t = sync.ClientWait(ClientWaitSyncFlags.SyncFlushCommandsBit, 100000000); System.Diagnostics.Debug.WriteLine($"Sync {t}"); sync.Dispose(); var azel = gl3dcontroller.PosCamera.EyePosition.AzEl(gl3dcontroller.PosCamera.LookAt, true); this.Text = "Looking at " + gl3dcontroller.MatrixCalc.LookAt + " from " + gl3dcontroller.MatrixCalc.EyePosition + " cdir " + gl3dcontroller.PosCamera.CameraDirection + " azel " + azel + " zoom " + gl3dcontroller.PosCamera.ZoomFactor + " dist " + gl3dcontroller.MatrixCalc.EyeDistance + " FOV " + gl3dcontroller.MatrixCalc.FovDeg; }
// Find at point, return found and z point public GalacticMapObject FindPOI(Point loc, GLRenderState state, Size viewportsize, out float z) { z = 0; if (!objectshader.Enable) { return(null); } var geo = findshader.GetShader <GLPLGeoShaderFindTriangles>(OpenTK.Graphics.OpenGL4.ShaderType.GeometryShader); geo.SetScreenCoords(loc, viewportsize); GLStatics.Check(); rifind.Execute(findshader, state); // execute. Geoshader discards geometry by not outputting anything var res = geo.GetResult(); if (res != null) { // for (int i = 0; i < res.Length; i++) System.Diagnostics.Debug.WriteLine(i + " = " + res[i]); z = res[0].Z; int instance = (int)res[0].Y; // tbd wrong! not a one to one mapping return(galmap.RenderableMapObjects[indextoentry[instance]]); //TBD } return(null); }
/// <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(); }
/// <summary> /// Create or update texture using this pixel format - special. Used for depth or stencil buffers /// See <href>https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml</href> /// </summary> /// <param name="width">Width of texture</param> /// <param name="height">Height of texture</param> /// <param name="pixelinternalformat">Pixel internal format</param> /// <param name="pixelformat">Pixel format</param> /// <param name="pixeltype">Pixel type</param> public void CreateOrUpdateTexturePixelFormat(int width, int height, PixelInternalFormat pixelinternalformat, PixelFormat pixelformat, PixelType pixeltype) // make with a pixel format.. { if (Id < 0 || Width != width || Height != height) // if not there, or changed, we can't just replace it, size is fixed. Delete it { if (Id >= 0) { Dispose(); } InternalFormat = 0; // PixelInternalFormat does not fit within this, so zero it Width = width; Height = height; MipMapLevels = 1; GL.CreateTextures(TextureTarget.Texture2D, 1, out int id); GLStatics.RegisterAllocation(typeof(GLTexture2D)); GLStatics.Check(); Id = id; GL.BindTexture(TextureTarget.Texture2D, Id); GL.TexImage2D(TextureTarget.Texture2D, 0, pixelinternalformat, width, height, 0, pixelformat, pixeltype, (IntPtr)0); // we don't actually load data in, so its a null ptr. GLStatics.Check(); } }
/// <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); }
/// <summary> /// Create of update the texture with a new size and format /// You can call as many times to create textures. Only creates one if required /// Rgba8 is the normal one to pick /// </summary> /// <param name="width">Width of texture</param> /// <param name="depth">Number of levels of texture</param> /// <param name="internalformat">Internal format, see InternalFormat in Texture base class</param>/// /// <param name="wantedmipmaplevels">Mip map levels wanted in texture</param> public void CreateOrUpdateTexture(int width, int depth, SizedInternalFormat internalformat, int wantedmipmaplevels = 1) { if (Id < 0 || Width != width || Depth != depth || wantedmipmaplevels != MipMapLevels) { if (Id >= 0) { Dispose(); } InternalFormat = internalformat; Width = width; Height = 1; Depth = depth; MipMapLevels = wantedmipmaplevels; GL.CreateTextures(TextureTarget.Texture1DArray, 1, out int id); GLStatics.RegisterAllocation(typeof(GLTexture2DArray)); GLStatics.Check(); Id = id; GL.TextureStorage2D(Id, wantedmipmaplevels, InternalFormat, Width, Height); SetMinMagFilter(); GLStatics.Check(); } }
private void ControllerDraw(Controller3D mc, ulong unused) { System.Diagnostics.Debug.WriteLine("Draw"); GLMatrixCalcUniformBlock mcub = (GLMatrixCalcUniformBlock)items.UB("MCUB"); mcub.SetFull(gl3dcontroller.MatrixCalc); rObjects.Render(glwfc.RenderState, gl3dcontroller.MatrixCalc, true); GLStatics.Check(); GLStatics.Flush(); var t1 = ts1.GetCounter(); var t2 = ts2.GetCounter(); System.Diagnostics.Debug.WriteLine($"Time Taken {t2-t1} ns"); GLMemoryBarrier.All(); Vector3[] values3 = varyingbuffer.ReadVector3sPacked(0, 8); // varyings seem to ignore the vec3->vec4 packed thingy.. System.Diagnostics.Debug.Assert(values3[1] == new Vector3(shape[1].X, shape[1].Y, shape[1].Z)); System.Diagnostics.Debug.Assert(values3[3] == new Vector3(shape[3].X, shape[3].Y, shape[3].Z)); var azel = gl3dcontroller.PosCamera.EyePosition.AzEl(gl3dcontroller.PosCamera.LookAt, true); this.Text = "Looking at " + gl3dcontroller.MatrixCalc.LookAt + " from " + gl3dcontroller.MatrixCalc.EyePosition + " cdir " + gl3dcontroller.PosCamera.CameraDirection + " azel " + azel + " zoom " + gl3dcontroller.PosCamera.ZoomFactor + " dist " + gl3dcontroller.MatrixCalc.EyeDistance + " FOV " + gl3dcontroller.MatrixCalc.FovDeg; }
/// <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); } }
/// <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(); }
/// <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(); }
/// <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); }
/// <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; }
// ///<summary> Read from bound Read Frame buffer target in this pixel format and type. Bufsize indicates amount of space needed for byte array </summary> public void ReadPixels(ReadBufferMode src, int x0, int y0, int x1, int y1, PixelFormat format, PixelType type, int bufsize) { GL.ReadBuffer(src); byte[] array = new byte[bufsize]; GL.ReadnPixels(x0, y0, x1, y1, format, type, array.Length, array); GLStatics.Check(); }
/// <summary> Constructor, create a time query</summary> public GLOperationQueryTimeStamp() { this.Id = GL.GenQuery(); System.Diagnostics.Debug.Assert(Id != 0); GLStatics.RegisterAllocation(typeof(GLOperationQueryTimeStamp)); GLStatics.Check(); }
/// <summary> Skip pointer forward </summary> public void Skip(int p) { System.Diagnostics.Debug.Assert(mapmode != MapMode.None); CurrentPtr += p; CurrentPos += p; System.Diagnostics.Debug.Assert(CurrentPos <= Length); GLStatics.Check(); }
///<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(); }
///<summary> Attach a 2D texture to frame buffer on colourtarget and mipmaplevel, to a specific layer </summary> public void AttachColorLayered(GLTexture2DArray tex, int colourtarget = 0, int mipmaplevel = 0, int layer = 0) // not tested.. page 401 { ColorTarget = colourtarget; Width = tex.Width; Height = tex.Height; GL.NamedFramebufferTextureLayer(Id, FramebufferAttachment.ColorAttachment0 + ColorTarget, tex.Id, mipmaplevel, layer); GLStatics.Check(); }
///<summary> Attach a 2D texture to frame buffer on colourtarget and mipmaplevel </summary> public void AttachColor(GLTexture2D tex, int colourtarget = 0, int mipmaplevel = 0) { ColorTarget = colourtarget; Width = tex.Width; Height = tex.Height; GL.NamedFramebufferTexture(Id, FramebufferAttachment.ColorAttachment0 + ColorTarget, tex.Id, mipmaplevel); GLStatics.Check(); }
/// <summary> Get binary. Must have linked with wantbinary </summary> public byte[] GetBinary(out BinaryFormat binformat) { GL.GetProgram(Id, (GetProgramParameterName)0x8741, out int len); byte[] array = new byte[len]; GL.GetProgramBinary(Id, len, out int binlen, out binformat, array); GLStatics.Check(); return(array); }
/// <summary> Add a pipeline shader of shadertype </summary> public void Add(IGLPipelineComponentShader pipelineshader, ShaderType shadertype) { System.Diagnostics.Debug.Assert(!shaders.ContainsKey(shadertype)); shaders[shadertype] = pipelineshader; pipelineshader.References++; GL.UseProgramStages(pipelineid, convmask[shadertype], pipelineshader.Id); GLStatics.Check(); }
/// <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); }
/// <summary> Allocate a non multisampled buffer of width and height, and bind to target Renderbuffer </summary> public void Allocate(RenderbufferStorage storage, int width, int height) { Width = width; Height = height; GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, Id); GL.NamedRenderbufferStorage(Id, storage, Width, Height); GLStatics.Check(); }
///<summary> Changes GL target for rendering to this frame buffer, sets viewport, clears to colourback </summary> public void BindColor(OpenTK.Graphics.Color4 colourback) { GL.NamedFramebufferDrawBuffer(Id, DrawBufferMode.ColorAttachment0 + ColorTarget); // attach the FB to draw buffer target GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, Id); // bind the FB to the system GL.Viewport(new System.Drawing.Rectangle(0, 0, Width, Height)); // set the viewport GL.ClearColor(colourback); GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit); // clear the FB GLStatics.Check(); }
/// <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); }
///<summary> Unbinds from query buffer</summary> static public void UnbindQuery() { if (querybindindex != -1) { GL.BindBuffer(BufferTarget.QueryBuffer, 0); // 0 is the unbind value GLStatics.Check(); querybindindex = -1; } }
/// <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); }
/// <summary> Get the sync status of the fence. </summary> /// <param name="paraname">Get SyncCondition, SyncStatus, SyncFlags or ObjectType. Default is to get sync status</param> /// <returns>Returns an array of sync properties. Dependent on fence type</returns> public int[] Get(SyncParameterName paraname = SyncParameterName.SyncStatus) { int[] array = new int[20]; GL.GetSync(Id, paraname, array.Length, out int len, array); GLStatics.Check(); int[] res = new int[len]; Array.Copy(array, res, len); return(res); }
/// <summary> Allocate a multisample buffer of width, height, and samples depth, and bind to target Renderbuffer </summary> public void AllocateMultisample(RenderbufferStorage storage, int width, int height, int samples) { Width = width; Height = height; Samples = samples; GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, Id); GL.NamedRenderbufferStorageMultisample(Id, Samples, storage, Width, Height); GLStatics.Check(); }
/// <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; }