private void AddedNewGroup(int groupno, GLBuffer matrixbuffer) // callback due to new group added, we need a texture and a RI { var texture = new GLTexture2DArray(); items.Add(texture); texture.CreateOrUpdateTexture(bitmapsize.Width, bitmapsize.Height, matrixbuffers.Matricesperbuffer, textureformat, texmipmaplevels); grouptextureslist.Add(texture); // need to keep these for later addition var rd = new RenderData(texture); var renderableItem = GLRenderableItem.CreateMatrix4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Quads, renderstate, matrixbuffer, 0, 4, rd, ic: 0); //drawcount=4 (4 vertexes made up by shader), ic will be set in Add. renderlist.Add(shader, name + ":" + groupno, renderableItem); grouprenderlist.Add(renderableItem); }
/// <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)); }
protected override void OnLoad(EventArgs e) { base.OnLoad(e); Closed += ShaderTest_Closed; gl3dcontroller = new Controller3D(); gl3dcontroller.PaintObjects = ControllerDraw; gl3dcontroller.MatrixCalc.PerspectiveNearZDistance = 1f; gl3dcontroller.MatrixCalc.PerspectiveFarZDistance = 1000f; gl3dcontroller.ZoomDistance = 20F; gl3dcontroller.Start(glwfc, new Vector3(0, 0, 0), new Vector3(110f, 0, 0f), 1F); glwfc.MouseClick += GLMouseClick; gl3dcontroller.KeyboardTravelSpeed = (ms, eyedist) => { return((float)ms / 40.0f); }; items.Add(new GLColorShaderWorld(), "COSW"); items.Add(new GLColorShaderObjectTranslation(), "COSOT"); #region coloured lines if (true) { GLRenderState lines = GLRenderState.Lines(1); rObjects.Add(items.Shader("COSW"), GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, lines, GLShapeObjectFactory.CreateLines(new Vector3(-100, -0, -100), new Vector3(-100, -0, 100), new Vector3(10, 0, 0), 21), new Color4[] { Color.Red, Color.Red, Color.DarkRed, Color.DarkRed }) ); rObjects.Add(items.Shader("COSW"), GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, lines, GLShapeObjectFactory.CreateLines(new Vector3(-100, -0, -100), new Vector3(100, -0, -100), new Vector3(0, 0, 10), 21), new Color4[] { Color.Red, Color.Red, Color.DarkRed, Color.DarkRed })); } #endregion #region Coloured triangles if (true) { GLRenderState rc = GLRenderState.Tri(); rc.CullFace = false; rObjects.Add(items.Shader("COSOT"), "scopen", GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Triangles, rc, GLCubeObjectFactory.CreateSolidCubeFromTriangles(5f), new Color4[] { Color4.Red, Color4.Green, Color4.Blue, Color4.White, Color4.Cyan, Color4.Orange }, new GLRenderDataTranslationRotation(new Vector3(10, 0, 20)) )); } #endregion var sunvertex = new GLPLVertexShaderModelCoordWorldAutoscale(new Color[] { Color.FromArgb(255, 220, 220, 10), Color.FromArgb(255, 0, 0, 0) }); items.Add(sunvertex); var sunshader = new GLShaderPipeline(sunvertex, new GLPLStarSurfaceFragmentShader()); items.Add(sunshader); var shapebuf = new GLBuffer(); items.Add(shapebuf); var shape = GLSphereObjectFactory.CreateSphereFromTriangles(1, 0.5f); shapebuf.AllocateFill(shape); GLStorageBlock block = new GLStorageBlock(20); findshader = items.NewShaderPipeline(null, sunvertex, null, null, new GLPLGeoShaderFindTriangles(block, 16), null, null, null); int texunitspergroup = 16; // opengl minimum texture units per frag shader //var textshader = new GLShaderPipeline(new GLPLVertexShaderQuadTextureWithMatrixTranslation(), new GLPLFragmentShaderTexture2DIndexedMulti(0,0,true, texunitspergroup)); var textshader = new TextShader(texunitspergroup); items.Add(textshader); Font fnt = new Font("MS sans serif", 16f); if (true) { int maxstars = 1000; // this is an aspriation, depends on fragmentation of the system dataindirectbuffer = new GLVertexBufferIndirect(items, maxstars * (GLBuffer.Vec4size + GLBuffer.Mat4size), GLBuffer.WriteIndirectArrayStride * 100, true); var textarray = new GLTexture2DArray(128, 32, maxstars, SizedInternalFormat.Rgba8); int SectorSize = 10; { Vector3 pos = new Vector3(-20, 0, -15); Vector4[] array = new Vector4[10]; Random rnd = new Random(23); for (int i = 0; i < array.Length; i++) { array[i] = new Vector4(pos.X + rnd.Next(SectorSize), pos.Y + rnd.Next(SectorSize), pos.Z + rnd.Next(SectorSize), 0); } dataindirectbuffer.Fill(array, 0, array.Length, 0, shape.Length, 0, array.Length, -1); Matrix4[] matrix = new Matrix4[array.Length]; for (int i = 0; i < array.Length; i++) { int imgpos = textarray.DepthIndex; textarray.DrawText("A" + i, fnt, Color.White, Color.Blue, -1); var mat = GLPLVertexShaderMatrixQuadTexture.CreateMatrix(new Vector3(array[i].X, array[i].Y + 0.6f, array[i].Z), new Vector3(1, 0, 0.2f), new Vector3(-90F.Radians(), 0, 0), imagepos: imgpos); matrix[i] = mat; } dataindirectbuffer.Vertex.AlignMat4(); // instancing counts in mat4 sizes (mat4 0 @0, mat4 1 @ 64 etc) so align to it dataindirectbuffer.Fill(matrix, 0, matrix.Length, 1, 4, 0, array.Length, -1); } if (true) { Vector3 pos = new Vector3(-20, 0, 0); Vector4[] array = new Vector4[5]; Random rnd = new Random(23); for (int i = 0; i < array.Length; i++) { array[i] = new Vector4(pos.X + rnd.Next(SectorSize), pos.Y + rnd.Next(SectorSize), pos.Z + rnd.Next(SectorSize), 0); } dataindirectbuffer.Fill(array, 0, array.Length, 0, shape.Length, 0, array.Length, -1); } if (true) { Vector3 pos = new Vector3(-20, 0, 15); Vector4[] array = new Vector4[10]; Random rnd = new Random(23); for (int i = 0; i < array.Length; i++) { array[i] = new Vector4(pos.X + rnd.Next(SectorSize), pos.Y + rnd.Next(SectorSize), pos.Z + rnd.Next(SectorSize), 0); } dataindirectbuffer.Fill(array, 0, array.Length, 0, shape.Length, 0, array.Length, -1); Matrix4[] matrix = new Matrix4[array.Length]; for (int i = 0; i < array.Length; i++) { int imgpos = textarray.DepthIndex; textarray.DrawText("C" + i, fnt, Color.White, Color.Red, -1); var mat = GLPLVertexShaderMatrixQuadTexture.CreateMatrix(new Vector3(array[i].X, array[i].Y + 0.6f, array[i].Z), new Vector3(1, 0, 0.2f), new Vector3(-90F.Radians(), 0, 0), imagepos: imgpos); matrix[i] = mat; } dataindirectbuffer.Vertex.AlignMat4(); // instancing countis in mat4 sizes (mat4 0 @0, mat4 1 @ 64 etc) so align to it dataindirectbuffer.Fill(matrix, 0, matrix.Length, 1, 4, 0, array.Length, -1); } int[] indirectints0 = dataindirectbuffer.Indirects[0].ReadInts(0, 12); int[] indirectints1 = dataindirectbuffer.Indirects[1].ReadInts(0, 4); float[] worldpos = dataindirectbuffer.Vertex.ReadFloats(0, 3 * 2 * 4); if (true) { GLRenderState rt = GLRenderState.Tri(); // render is triangles, with no depth test so we always appear rt.DepthTest = true; rt.DepthClamp = true; var renderer = GLRenderableItem.CreateVector4Vector4(items, PrimitiveType.Triangles, rt, shapebuf, 0, 0, // binding 0 is shapebuf, offset 0, no draw count dataindirectbuffer.Vertex, 0, // binding 1 is vertex's world positions, offset 0 null, 0, 1); // no ic, second divisor 1 renderer.IndirectBuffer = dataindirectbuffer.Indirects[0]; renderer.BaseIndexOffset = 0; // offset in bytes where commands are stored renderer.DrawCount = 3; renderer.MultiDrawCountStride = GLBuffer.WriteIndirectArrayStride; rObjects.Add(sunshader, "sunshader", renderer); } if (true) { var rc = GLRenderState.Quads(); rc.CullFace = true; rc.DepthTest = true; rc.ClipDistanceEnable = 1; // we are going to cull primitives which are deleted var renderer = GLRenderableItem.CreateMatrix4(items, PrimitiveType.Quads, rc, dataindirectbuffer.Vertex, 0, 0, //attach buffer with matrices, no draw count new GLRenderDataTexture(textarray, 0), 0, 1); //no ic, and matrix divide so 1 matrix per vertex set renderer.IndirectBuffer = dataindirectbuffer.Indirects[1]; renderer.BaseIndexOffset = 0; // offset in bytes where commands are stored renderer.DrawCount = 2; renderer.MultiDrawCountStride = GLBuffer.WriteIndirectArrayStride; rObjects.Add(textshader, "textshader", renderer); } } if (true) { GLRenderState starrc = GLRenderState.Tri(); // render is triangles, with no depth test so we always appear starrc.DepthTest = true; starrc.DepthClamp = true; var textrc = GLRenderState.Quads(); textrc.DepthTest = true; textrc.ClipDistanceEnable = 1; // we are going to cull primitives which are deleted sl = new GLObjectsWithLabels(); var ris = sl.Create(texunitspergroup, 50, 50, shapebuf, shape.Length, starrc, PrimitiveType.Triangles, new Size(128, 32), textrc, SizedInternalFormat.Rgba8, 3); rObjects.Add(sunshader, "SLsunshade", ris.Item1); rObjects.Add(textshader, "SLtextshade", ris.Item2); items.Add(sl); int SectorSize = 10; { Vector3 pos = new Vector3(0, 0, -15); Vector4[] array = new Vector4[10]; string[] text = new string[array.Length]; Random rnd = new Random(31); for (int i = 0; i < array.Length; i++) { array[i] = new Vector4(pos.X + rnd.Next(SectorSize), pos.Y + rnd.Next(SectorSize), pos.Z + rnd.Next(SectorSize), 0); text[i] = "A.r" + i; } var mats = GLPLVertexShaderMatrixQuadTexture.CreateMatrices(array, new Vector3(0, 0.6f, 0), new Vector3(2f, 0, 0.4f), new Vector3(-90F.Radians(), 0, 0), true, false); var bmps = GLOFC.Utils.BitMapHelpers.DrawTextIntoFixedSizeBitmaps(sl.LabelSize, text, fnt, System.Drawing.Text.TextRenderingHint.ClearTypeGridFit, Color.White, Color.DarkBlue, 0.5f); List <GLObjectsWithLabels.BlockRef> bref = new List <GLObjectsWithLabels.BlockRef>(); sl.Add(array, mats, bmps, bref); GLOFC.Utils.BitMapHelpers.Dispose(bmps); } { Vector3 pos = new Vector3(0, 0, 0); Vector4[] array = new Vector4[20]; string[] text = new string[array.Length]; Random rnd = new Random(31); for (int i = 0; i < array.Length; i++) { array[i] = new Vector4(pos.X + rnd.Next(SectorSize), pos.Y + rnd.Next(SectorSize), pos.Z + rnd.Next(SectorSize), 0); text[i] = "B." + i; } List <GLObjectsWithLabels.BlockRef> bref = new List <GLObjectsWithLabels.BlockRef>(); sl.Add(array, text, fnt, Color.White, Color.DarkBlue, new Vector3(2f, 0, 0.4f), new Vector3(-90F.Radians(), 0, 0), true, false, null, 0.5f, new Vector3(0, 0.6f, 0), bref); } { Vector3 pos = new Vector3(0, 0, 15); Vector4[] array = new Vector4[10]; string[] text = new string[array.Length]; Random rnd = new Random(31); for (int i = 0; i < array.Length; i++) { array[i] = new Vector4(pos.X + rnd.Next(SectorSize), pos.Y + rnd.Next(SectorSize), pos.Z + rnd.Next(SectorSize), 0); text[i] = "C." + i; } List <GLObjectsWithLabels.BlockRef> bref = new List <GLObjectsWithLabels.BlockRef>(); sl.Add(array, text, fnt, Color.White, Color.DarkBlue, new Vector3(2f, 0, 0.4f), new Vector3(-90F.Radians(), 0, 0), true, false, null, 0.5f, new Vector3(0, 0.6f, 0), bref); } System.Diagnostics.Debug.WriteLine($"Sets {sl.Blocks} Removed {sl.BlocksRemoved}"); } // Sets of.. if (true) { GLRenderState starrc = GLRenderState.Tri(); // render is triangles, with no depth test so we always appear starrc.DepthTest = true; starrc.DepthClamp = true; var textrc = GLRenderState.Quads(); textrc.DepthTest = true; textrc.ClipDistanceEnable = 1; // we are going to cull primitives which are deleted slset = new GLSetOfObjectsWithLabels("SLSet", rObjects, true ? 4 : texunitspergroup, 50, 10, sunshader, shapebuf, shape.Length, starrc, PrimitiveType.Triangles, textshader, new Size(128, 32), textrc, SizedInternalFormat.Rgba8, 3); items.Add(slset); int SectorSize = 10; { Vector3 pos = new Vector3(20, 0, -15); Vector4[] array = new Vector4[10]; string[] text = new string[array.Length]; Random rnd = new Random(31); for (int i = 0; i < array.Length; i++) { array[i] = new Vector4(pos.X + rnd.Next(SectorSize), pos.Y + rnd.Next(SectorSize), pos.Z + rnd.Next(SectorSize), 0); text[i] = "S.A.r" + i; } var mats = GLPLVertexShaderMatrixQuadTexture.CreateMatrices(array, new Vector3(0, 0.6f, 0), new Vector3(2f, 0, 0.4f), new Vector3(-90F.Radians(), 0, 0), true, false); var bmps = GLOFC.Utils.BitMapHelpers.DrawTextIntoFixedSizeBitmaps(slset.LabelSize, text, fnt, System.Drawing.Text.TextRenderingHint.ClearTypeGridFit, Color.White, Color.DarkBlue, 0.5f); slset.Add("GA", text, array, mats, bmps); GLOFC.Utils.BitMapHelpers.Dispose(bmps); } { Vector3 pos = new Vector3(20, 0, 0); Vector4[] array = new Vector4[10]; string[] text = new string[array.Length]; Random rnd = new Random(31); for (int i = 0; i < array.Length; i++) { array[i] = new Vector4(pos.X + rnd.Next(SectorSize), pos.Y + rnd.Next(SectorSize), pos.Z + rnd.Next(SectorSize), 0); text[i] = "S.B." + i; } var mats = GLPLVertexShaderMatrixQuadTexture.CreateMatrices(array, new Vector3(0, 0.6f, 0), new Vector3(2f, 0, 0.4f), new Vector3(-90F.Radians(), 0, 0), true, false); var bmps = GLOFC.Utils.BitMapHelpers.DrawTextIntoFixedSizeBitmaps(slset.LabelSize, text, fnt, System.Drawing.Text.TextRenderingHint.ClearTypeGridFit, Color.White, Color.DarkBlue, 0.5f); slset.Add("GB", text, array, mats, bmps); GLOFC.Utils.BitMapHelpers.Dispose(bmps); } { Vector3 pos = new Vector3(20, 0, 15); Vector4[] array = new Vector4[10]; string[] text = new string[array.Length]; Random rnd = new Random(31); for (int i = 0; i < array.Length; i++) { array[i] = new Vector4(pos.X + rnd.Next(SectorSize), pos.Y + rnd.Next(SectorSize), pos.Z + rnd.Next(SectorSize), 0); text[i] = "S.C." + i; } var mats = GLPLVertexShaderMatrixQuadTexture.CreateMatrices(array, new Vector3(0, 0.6f, 0), new Vector3(2f, 0, 0.4f), new Vector3(-90F.Radians(), 0, 0), true, false); var bmps = GLOFC.Utils.BitMapHelpers.DrawTextIntoFixedSizeBitmaps(slset.LabelSize, text, fnt, System.Drawing.Text.TextRenderingHint.ClearTypeGridFit, Color.White, Color.DarkBlue, 0.5f); slset.Add("GC", text, array, mats, bmps); GLOFC.Utils.BitMapHelpers.Dispose(bmps); } } #region Matrix Calc Uniform items.Add(new GLMatrixCalcUniformBlock(), "MCUB"); // def binding of 0 #endregion }