public void Create(GLItemsList items, GLRenderProgramSortedList rObjects, float sunsize, GLStorageBlock findbufferresults) { sunvertex = new GLPLVertexShaderModelCoordWorldAutoscale(new Color[] { Color.FromArgb(255, 220, 220, 10), Color.FromArgb(255, 0, 0, 0) }, autoscale: 30, autoscalemin: 1, autoscalemax: 2, useeyedistance: false); sunshader = items.NewShaderPipeline(null, sunvertex, new GLPLStarSurfaceFragmentShader()); shapebuf = items.NewBuffer(false); var shape = GLSphereObjectFactory.CreateSphereFromTriangles(2, sunsize); shapebuf.AllocateFill(shape); GLRenderState starrc = GLRenderState.Tri(); // render is triangles, with no depth test so we always appear starrc.DepthTest = true; starrc.DepthClamp = true; var textrc = GLRenderState.Tri(); textrc.DepthTest = true; textrc.ClipDistanceEnable = 1; // we are going to cull primitives which are deleted int texunitspergroup = 16; textshader = items.NewShaderPipeline(null, new GLPLVertexShaderMatrixTriStripTexture(), new GLPLFragmentShaderTexture2DIndexMulti(0, 0, true, texunitspergroup)); slset = new GLSetOfObjectsWithLabels("SLSet", rObjects, texunitspergroup, 100, 10, sunshader, shapebuf, shape.Length, starrc, OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles, textshader, BitMapSize, textrc, SizedInternalFormat.Rgba8); items.Add(slset); var geofind = new GLPLGeoShaderFindTriangles(findbufferresults, 16); findshader = items.NewShaderPipeline(null, sunvertex, null, null, geofind, null, null, null); }
public void Create(GLItemsList items, GLRenderProgramSortedList rObjects, List <SystemClass> incomingsys, float bookmarksize, GLStorageBlock findbufferresults, bool depthtest) { if (ridisplay == null) { //var vert = new GLPLVertexScaleLookat(rotate: dorotate, rotateelevation: doelevation, commontransform: false, texcoords: true, // a look at vertex shader // // var vert = new GLPLVertexShaderWorldCoord(); var vert = new GLPLVertexScaleLookat(rotatetoviewer: dorotate, rotateelevation: doelevation, texcoords: true, generateworldpos: true, autoscale: 500, autoscalemin: 1f, autoscalemax: 20f); // below 500, 1f, above 500, scale up to 20x const int texbindingpoint = 1; var frag = new GLPLFragmentShaderTexture(texbindingpoint); // binding - simple texturer based on vs model coords objectshader = new GLShaderPipeline(vert, null, null, null, frag); items.Add(objectshader); var objtex = items.NewTexture2D("Bookmarktex", TestOpenTk.Properties.Resources.dotted2, OpenTK.Graphics.OpenGL4.SizedInternalFormat.Rgba8); objectshader.StartAction += (s, m) => { objtex.Bind(texbindingpoint); // bind tex array to, matching above }; bookmarkposbuf = items.NewBuffer(); // where we hold the vertexes for the suns, used by renderer and by finder GLRenderState rt = GLRenderState.Tri(); rt.DepthTest = depthtest; bookmarksize *= 10; // 0 is model pos, 1 is world pos by a buffer, 2 is tex co-ords ridisplay = GLRenderableItem.CreateVector4Vector4Vector2(items, OpenTK.Graphics.OpenGL4.PrimitiveType.TriangleStrip, rt, GLShapeObjectFactory.CreateQuadTriStrip(bookmarksize, bookmarksize), // quad2 4 vertexts as the model positions bookmarkposbuf, 0, // world positions come from here - not filled as yet GLShapeObjectFactory.TexTriStripQuad, ic: 0, seconddivisor: 1); rObjects.Add(objectshader, "bookmarks", ridisplay); var geofind = new GLPLGeoShaderFindTriangles(findbufferresults, 16);//, forwardfacing:false); findshader = items.NewShaderPipeline(null, vert, null, null, geofind, null, null, null); // hook to modelworldbuffer, at modelpos and worldpos. UpdateEnables will fill in instance count rifind = GLRenderableItem.CreateVector4Vector4Vector2(items, OpenTK.Graphics.OpenGL4.PrimitiveType.TriangleStrip, rt, GLShapeObjectFactory.CreateQuadTriStrip(bookmarksize, bookmarksize), // quad2 4 vertexts as the model positions bookmarkposbuf, 0, GLShapeObjectFactory.TexTriStripQuad, ic: 0, seconddivisor: 1); } bookmarkposbuf.AllocateFill(incomingsys.Select(x => new Vector4((float)x.X, (float)x.Y, (float)x.Z, 1)).ToArray()); ridisplay.InstanceCount = rifind.InstanceCount = incomingsys.Count; }
public void Start(GLItemsList items, GLRenderProgramSortedList rObjects, float bookmarksize, GLStorageBlock findbufferresults, bool depthtest) { var vert = new GLPLVertexScaleLookat(rotatetoviewer: dorotate, rotateelevation: doelevation, texcoords: true, generateworldpos: true, autoscale: 30, autoscalemin: 1f, autoscalemax: 30f); // above autoscale, 1f const int texbindingpoint = 1; var frag = new GLPLFragmentShaderTexture(texbindingpoint); // binding - simple texturer based on vs model coords objectshader = new GLShaderPipeline(vert, null, null, null, frag); items.Add(objectshader); var objtex = items.NewTexture2D("Bookmarktex", BaseUtils.Icons.IconSet.GetBitmap("GalMap.Bookmark"), OpenTK.Graphics.OpenGL4.SizedInternalFormat.Rgba8); objectshader.StartAction += (s, m) => { objtex.Bind(texbindingpoint); // bind tex array to, matching above }; bookmarkposbuf = items.NewBuffer(); // where we hold the vertexes for the suns, used by renderer and by finder GLRenderState rt = GLRenderState.Tri(); rt.DepthTest = depthtest; // 0 is model pos, 1 is world pos by a buffer, 2 is tex co-ords ridisplay = GLRenderableItem.CreateVector4Vector4Vector2(items, OpenTK.Graphics.OpenGL4.PrimitiveType.TriangleStrip, rt, GLShapeObjectFactory.CreateQuadTriStrip(bookmarksize, bookmarksize), // quad2 4 vertexts as the model positions bookmarkposbuf, 0, // world positions come from here - not filled as yet GLShapeObjectFactory.TexTriStripQuad, ic: 0, seconddivisor: 1); rObjects.Add(objectshader, "bookmarks", ridisplay); var geofind = new GLPLGeoShaderFindTriangles(findbufferresults, 16);//, forwardfacing:false); findshader = items.NewShaderPipeline(null, vert, null, null, geofind, null, null, null); // hook to modelworldbuffer, at modelpos and worldpos. UpdateEnables will fill in instance count rifind = GLRenderableItem.CreateVector4Vector4Vector2(items, OpenTK.Graphics.OpenGL4.PrimitiveType.TriangleStrip, rt, GLShapeObjectFactory.CreateQuadTriStrip(bookmarksize, bookmarksize), // quad2 4 vertexts as the model positions bookmarkposbuf, 0, GLShapeObjectFactory.TexTriStripQuad, ic: 0, seconddivisor: 1); }
private void IntCreatePath(GLItemsList items, GLRenderProgramSortedList rObjects, GLStorageBlock bufferfindresults) { HistoryEntry lastone = lastpos != -1 && lastpos < currentfilteredlist.Count ? currentfilteredlist[lastpos] : null; // see if lastpos is there, and store it if (TravelPathEndDateEnable || TravelPathStartDateEnable) { currentfilteredlist = unfilteredlist.Where(x => (!TravelPathStartDateEnable || x.EventTimeUTC >= TravelPathStartDate) && (!TravelPathEndDateEnable || x.EventTimeUTC <= TravelPathEndDate)).ToList(); if (currentfilteredlist.Count > MaxStars) { currentfilteredlist = currentfilteredlist.Skip(currentfilteredlist.Count - MaxStars).ToList(); } } else { if (unfilteredlist.Count > MaxStars) { currentfilteredlist = unfilteredlist.Skip(currentfilteredlist.Count - MaxStars).ToList(); } else { currentfilteredlist = unfilteredlist; } } // do date filter on currentfilteredlist lastpos = lastone == null ? -1 : currentfilteredlist.IndexOf(lastone); // may be -1, may have been removed var positionsv4 = currentfilteredlist.Select(x => new Vector4((float)x.System.X, (float)x.System.Y, (float)x.System.Z, 0)).ToArray(); var colours = currentfilteredlist.Select(x => x.JumpColor).ToArray(); float seglen = tapesize * 10; // a tape is a set of points (item1) and indexes to select them (item2), so we need an element index in the renderer to use. var tape = GLTapeObjectFactory.CreateTape(positionsv4, colours, tapesize, seglen, 0F.Radians(), margin: sunsize * 1.2f); if (ritape == null) // first time.. { // first the tape var tapetex = new GLTexture2D(Properties.Resources.chevron, internalformat: OpenTK.Graphics.OpenGL4.SizedInternalFormat.Rgba8); // tape image items.Add(tapetex); tapetex.SetSamplerMode(OpenTK.Graphics.OpenGL4.TextureWrapMode.Repeat, OpenTK.Graphics.OpenGL4.TextureWrapMode.Repeat); tapefrag = new GLPLFragmentShaderTextureTriStripColorReplace(1, Color.FromArgb(255, 206, 0, 0)); var vert = new GLPLVertexShaderWorldTextureTriStrip(); tapeshader = new GLShaderPipeline(vert, tapefrag); items.Add(tapeshader); GLRenderState rts = GLRenderState.Tri(tape.Item3, cullface: false); // set up a Tri strip, primitive restart value set from tape, no culling rts.DepthTest = depthtest; // no depth test so always appears // now the renderer, set up with the render control, tape as the points, and bind a RenderDataTexture so the texture gets binded each time ritape = GLRenderableItem.CreateVector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.TriangleStrip, rts, tape.Item1.ToArray(), new GLRenderDataTexture(tapetex)); tapepointbuf = items.LastBuffer(); // keep buffer for refill ritape.Visible = tape.Item1.Count > 0; // no items, set not visible, so it won't except over the BIND with nothing in the element buffer ritape.CreateElementIndex(items.NewBuffer(), tape.Item2.ToArray(), tape.Item3); // finally, we are using index to select vertexes, so create an index rObjects.Add(tapeshader, "travelpath-tape", ritape); // add render to object list // now the stars starposbuf = items.NewBuffer(); // where we hold the vertexes for the suns, used by renderer and by finder starposbuf.AllocateFill(positionsv4); //Vector4[] vectors = starposbuf.ReadVector4s(0, starposbuf.Length / 16); sunvertex = new GLPLVertexShaderModelCoordWorldAutoscale(new Color[] { Color.Yellow, Color.FromArgb(255, 230, 230, 1) }, autoscale: 30, autoscalemin: 1f, autoscalemax: 2f, useeyedistance: false); // below scale, 1f, above scale, scale up to x times (eyedist/scale) sunshader = new GLShaderPipeline(sunvertex, new GLPLStarSurfaceFragmentShader()); items.Add(sunshader); var shape = GLSphereObjectFactory.CreateSphereFromTriangles(2, sunsize); GLRenderState rt = GLRenderState.Tri(); // render is triangles, with no depth test so we always appear rt.DepthTest = depthtest; rt.DepthClamp = true; renderersun = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles, rt, shape, starposbuf, 0, null, currentfilteredlist.Count, 1); rObjects.Add(sunshader, "travelpath-suns", renderersun); // find compute var geofind = new GLPLGeoShaderFindTriangles(bufferfindresults, 16); findshader = items.NewShaderPipeline(null, sunvertex, null, null, geofind, null, null, null); rifind = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles, GLRenderState.Tri(), shape, starposbuf, ic: currentfilteredlist.Count, seconddivisor: 1); // Sun names, handled by textrenderer textrenderer = new GLBitmaps("bm-travelmap", rObjects, new Size(128, 40), depthtest: depthtest, cullface: false); items.Add(textrenderer); } else { tapepointbuf.AllocateFill(tape.Item1.ToArray()); // replace the points with a new one ritape.RenderState.PrimitiveRestart = GL4Statics.DrawElementsRestartValue(tape.Item3); // IMPORTANT missing bit Robert, must set the primitive restart value to the new tape size ritape.CreateElementIndex(ritape.ElementBuffer, tape.Item2.ToArray(), tape.Item3); // update the element buffer ritape.Visible = tape.Item1.Count > 0; starposbuf.AllocateFill(positionsv4); // and update the star position buffers so find and sun renderer works renderersun.InstanceCount = positionsv4.Length; // update the number of suns to draw. rifind.InstanceCount = positionsv4.Length; // update the find list } // name bitmaps HashSet <object> hashset = new HashSet <object>(currentfilteredlist); // so it can find it quickly textrenderer.CurrentGeneration++; // setup for next generation textrenderer.RemoveGeneration(textrenderer.CurrentGeneration - 1, hashset); // and remove all of the previous one which are not in hashset. Font fnt = new Font("Arial", 8.5F); using (StringFormat fmt = new StringFormat()) { fmt.Alignment = StringAlignment.Center; foreach (var isys in currentfilteredlist) { if (textrenderer.Exist(isys) == false) // if does not exist already, need a new label { textrenderer.Add(isys, isys.System.Name, fnt, Color.White, Color.Transparent, new Vector3((float)isys.System.X, (float)isys.System.Y - 5, (float)isys.System.Z), new Vector3(20, 0, 0), new Vector3(0, 0, 0), textformat: fmt, rotatetoviewer: true, rotateelevation: false, alphafadescalar: -200, alphafadepos: 300); } } } fnt.Dispose(); }
public void Start(GLWinFormControl glwfc) { this.glwfc = glwfc; matrixcalc = new GLMatrixCalc(); matrixcalc.PerspectiveNearZDistance = 1f; matrixcalc.PerspectiveFarZDistance = worldsize * 2; matrixcalc.InPerspectiveMode = true; matrixcalc.ResizeViewPort(this, glwfc.Size); items.Add(new GLMatrixCalcUniformBlock(), "MCUB"); // create a matrix uniform block displaycontrol = new GLControlDisplay(items, glwfc, matrixcalc); // hook form to the window - its the master, it takes its size from mc.ScreenCoordMax displaycontrol.Focusable = true; // we want to be able to focus and receive key presses. displaycontrol.Name = "displaycontrol"; displaycontrol.Font = new Font("Arial", 12); gl3dcontroller = new Controller3Dd(); gl3dcontroller.PaintObjects = ControllerDraw; gl3dcontroller.ZoomDistance = 20e6 * 1000 * mscaling; // zoom 1 is X km gl3dcontroller.PosCamera.ZoomMin = 0.001f; gl3dcontroller.PosCamera.ZoomMax = 300f; gl3dcontroller.PosCamera.ZoomScaling = 1.08f; gl3dcontroller.Start(matrixcalc, displaycontrol, new Vector3d(0, 0, 0), new Vector3d(135f, 0, 0f), 0.025F, registermouseui: false, registerkeyui: true); gl3dcontroller.KeyboardTravelSpeed = (ms, eyedist) => { double eyedistr = Math.Pow(eyedist, 1.0); float v = (float)Math.Max(eyedistr / 1200, 0); //System.Diagnostics.Debug.WriteLine("Speed " + eyedistr + " "+ v); return((float)ms * v); }; for (int i = 1; i <= 10; i++) { int v = i * i; double f = (gl3dcontroller.PosCamera.ZoomMax - gl3dcontroller.PosCamera.ZoomMin) * v / 100.0 + gl3dcontroller.PosCamera.ZoomMin; System.Diagnostics.Debug.WriteLine($"{i} {v} {f}"); } displaycontrol.Paint += (o, ts) => // subscribing after Controller start means we paint over the scene { // MCUB set up by Controller3DDraw which did the work first // System.Diagnostics.Debug.WriteLine("Controls Draw"); displaycontrol.Render(glwfc.RenderState, ts); }; displaycontrol.MouseClick += MouseClickOnMap; // grab mouse UI displaycontrol.MouseUp += MouseUpOnMap; displaycontrol.MouseDown += MouseDownOnMap; displaycontrol.MouseMove += MouseMoveOnMap; displaycontrol.MouseWheel += MouseWheelOnMap; double startspeed = 60 * 60 * 6; // in sec GLImage minus = new GLImage("timeplus1y", new Rectangle(0, 0, 32, 32), Properties.Resources.GoBackward); minus.MouseClick += (e1, m1) => { currentjd -= 365; }; displaycontrol.Add(minus); GLImage back = new GLImage("timeback", new Rectangle(40, 0, 32, 32), Properties.Resources.Backwards); back.MouseClick += (e1, m1) => { if (jdscaling > 0) { jdscaling /= 2; } else if (jdscaling < 0) { jdscaling *= 2; } else { jdscaling = -startspeed; } }; displaycontrol.Add(back); GLImage pause = new GLImage("timepause", new Rectangle(80, 0, 32, 32), Properties.Resources.Pause); pause.MouseClick += (e1, m1) => { jdscaling = 0; }; displaycontrol.Add(pause); GLImage fwd = new GLImage("timefwd", new Rectangle(120, 0, 32, 32), Properties.Resources.Forward); fwd.MouseClick += (e1, m1) => { if (jdscaling < 0) { jdscaling /= 2; } else if (jdscaling > 0) { jdscaling *= 2; } else { jdscaling = startspeed; } }; displaycontrol.Add(fwd); GLImage plus = new GLImage("timeplus1y", new Rectangle(160, 0, 32, 32), Properties.Resources.GoForward); plus.MouseClick += (e1, m1) => { currentjd += 365; }; displaycontrol.Add(plus); GLImage sysleft = new GLImage("sysleft", new Rectangle(200, 0, 32, 32), Properties.Resources.GoBackward); sysleft.MouseClick += (e1, m1) => { DisplayNode(-1); }; displaycontrol.Add(sysleft); mastersystem = new GLLabel("sysname", new Rectangle(230, 6, 70, 20), "All", Color.DarkOrange); mastersystem.TextAlign = ContentAlignment.MiddleCenter; displaycontrol.Add(mastersystem); GLImage sysright = new GLImage("sysright", new Rectangle(300, 0, 32, 32), Properties.Resources.GoForward); sysright.MouseClick += (e1, m1) => { DisplayNode(1); }; displaycontrol.Add(sysright); timedisplay = new GLLabel("state", new Rectangle(340, 6, 800, 20), "Label", Color.DarkOrange); displaycontrol.Add(timedisplay); datalabel = new GLLabel("datalabel", new Rectangle(0, 40, 400, 100), "", Color.DarkOrange); datalabel.TextAlign = ContentAlignment.TopLeft; displaycontrol.Add(datalabel); status = new GLLabel("Status", new Rectangle(0, 0, 2000, 24), "x"); status.Dock = DockingType.BottomLeft; status.ForeColor = Color.Orange; status.BackColor = Color.FromArgb(50, 50, 50, 50); displaycontrol.Add(status); rightclickmenubody = new GLContextMenu("RightClickMenuBody", new GLMenuItem("RCMInfo", "Information") { MouseClick = (s, e) => { } }, new GLMenuItem("RCMZoomIn", "Track") { MouseClick = (s, e) => { track = (int)rightclickmenubody.Tag; } }, new GLMenuItem("RCMZoomIn", "Track Central Body") { MouseClick = (s, e) => { int body = (int)rightclickmenubody.Tag; if (bodyinfo[body].parentindex >= 0) { track = bodyinfo[body].parentindex; } } }, new GLMenuItem("RCMZoomIn", "Zoom In") { }, new GLMenuItem("RCMUntrack", "Untrack") { MouseClick = (s1, e1) => { track = -1; } } ); rightclickmenubody.Opening += (ms, tag) => { ms["RCMUntrack"].Enabled = track != -1; }; rightclickmenuscreen = new GLContextMenu("RightClickMenuBody", new GLMenuItem("RCMSysDisplay", "System Display") { MouseClick = (s, e) => { } }, new GLMenuItem("RCMUntrack", "Untrack") { MouseClick = (s1, e1) => { track = -1; } } ); rightclickmenuscreen.Opening += (ms, tag) => { ms["RCMUntrack"].Enabled = track != -1; }; if (true) { var shader = new GLColorShaderWorld(); items.Add(shader); GLRenderState lines = GLRenderState.Lines(1); lines.DepthTest = false; int gridsize = (int)(worldsize * mscaling); int gridoffset = (int)(gridlines * mscaling); int nolines = gridsize / gridoffset * 2 + 1; Color gridcolour = Color.FromArgb(80, 80, 80, 80); rObjects.Add(shader, GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, lines, GLShapeObjectFactory.CreateLines(new Vector3(-gridsize, -0, -gridsize), new Vector3(-gridsize, -0, gridsize), new Vector3(gridoffset, 0, 0), nolines), new Color4[] { gridcolour }) ); rObjects.Add(shader, GLRenderableItem.CreateVector4Color4(items, PrimitiveType.Lines, lines, GLShapeObjectFactory.CreateLines(new Vector3(-gridsize, -0, -gridsize), new Vector3(gridsize, -0, -gridsize), new Vector3(0, 0, gridoffset), nolines), new Color4[] { gridcolour })); Size bmpsize = new Size(128, 30); var maps = new GLBitmaps("bitmap1", rObjects, bmpsize, 3, OpenTK.Graphics.OpenGL4.SizedInternalFormat.Rgba8, false, false); using (StringFormat fmt = new StringFormat(StringFormatFlags.NoWrap) { Alignment = StringAlignment.Near, LineAlignment = StringAlignment.Center }) { float hsize = 40e6f * 1000 * mscaling; // million km -> m -> scaling float vsize = hsize * bmpsize.Height / bmpsize.Width; Font f = new Font("MS sans serif", 12f); long pos = -nolines / 2 * (gridlines / 1000); for (int i = -nolines / 2; i < nolines / 2; i++) { if (i != 0) { double v = Math.Abs(pos * 1000); long p = Math.Abs(pos); maps.Add(i, (p).ToString("N0"), f, Color.White, Color.Transparent, new Vector3(i * gridoffset + hsize / 2, 0, vsize / 2), new Vector3(hsize, 0, 0), new Vector3(0, 0, 0), fmt); maps.Add(i, (v / oneAU_m).ToString("N1") + "AU", f, Color.White, Color.Transparent, new Vector3(i * gridoffset + hsize / 2, 0, -vsize / 2), new Vector3(hsize, 0, 0), new Vector3(0, 0, 0), fmt); maps.Add(i, (p).ToString("N0"), f, Color.White, Color.Transparent, new Vector3(hsize / 2, 0, i * gridoffset + vsize / 2), new Vector3(hsize, 0, 0), new Vector3(0, 0, 0), fmt); maps.Add(i, (v / oneAU_m).ToString("N1") + "AU", f, Color.White, Color.Transparent, new Vector3(hsize / 2, 0, i * gridoffset - vsize / 2), new Vector3(hsize, 0, 0), new Vector3(0, 0, 0), fmt); } pos += 50000000; } } } var orbitlinesvertshader = new GLPLVertexShaderModelWorldUniform(new Color[] { Color.FromArgb(128, 128, 0, 0), Color.FromArgb(128, 128, 128, 0) }); orbitlineshader = new GLShaderPipeline(orbitlinesvertshader, new GLPLFragmentShaderVSColor()); bodyplaneshader = new GLShaderPipeline(orbitlinesvertshader, new GLPLFragmentShaderVSColor()); // model pos in, with uniform world pos, vectors out, with vs_colour selected by worldpos.w // set up ARB IDs for all images we are going to use.. var tbs = items.NewBindlessTextureHandleBlock(arbblock); var texs = items.NewTexture2D(null, Properties.Resources.golden, SizedInternalFormat.Rgba8); var texp = items.NewTexture2D(null, Properties.Resources.moonmap1k, SizedInternalFormat.Rgba8); var texb = items.NewTexture2D(null, Properties.Resources.dotted, SizedInternalFormat.Rgba8); var texs2 = items.NewTexture2D(null, Properties.Resources.wooden, SizedInternalFormat.Rgba8); tbs.WriteHandles(new IGLTexture[] { texs, texp, texb, texs2 }); // using 0 tex coord, 4 image id and arb text binding var bodyfragshader = new GLPLFragmentShaderBindlessTexture(arbblock, discardiftransparent: true, useprimidover2: false); // takes 0:Vector4 model, 1: vec2 text, 4:matrix, out is 0:tex, 1: modelpos, 2: instance, 4 = matrix[3][3] var bodyvertshader = new GLPLVertexShaderModelMatrixTexture(1000000 * 1000 * mscaling, useeyedistance: false); bodyshader = new GLShaderPipeline(bodyvertshader, bodyfragshader); items.Add(bodyshader); // hold shape var sphereshape = GLSphereObjectFactory.CreateTexturedSphereFromTriangles(3, 1.0f); spherebuffer = items.NewBuffer(); // fill buffer with model co-ords spherebuffer.AllocateFill(sphereshape.Item1); spheretexcobuffer = items.NewBuffer(); // fill buffer with tex coords spheretexcobuffer.AllocateFill(sphereshape.Item2); bodymatrixbuffer = items.NewBuffer(); // this holds the matrix to set position and size GLStorageBlock findbufferresults = items.NewStorageBlock(findblock); var geofind = new GLPLGeoShaderFindTriangles(findbufferresults, 16); // pass thru normal vert/tcs/tes then to geoshader for results findshader = items.NewShaderPipeline(null, bodyvertshader, null, null, geofind, null, null, null); }
public void CreateObjects(GLItemsList items, GLRenderProgramSortedList rObjects, GalacticMapping galmap, GLStorageBlock findbufferresults, bool depthtest) { this.galmap = galmap; // first gets the images and make a 2d array texture for them Bitmap[] images = galmap.RenderableMapTypes.Select(x => x.Image as Bitmap).ToArray(); // 256 is defined normal size var objtex = new GLTexture2DArray(images, bmpmipmaplevels: 1, wantedmipmaplevels: 3, texturesize: new Size(256, 256), internalformat: OpenTK.Graphics.OpenGL4.SizedInternalFormat.Rgba8, alignment: ContentAlignment.BottomCenter); IGLTexture texarray = items.Add(objtex, "GalObjTex"); // now build the shaders const int texbindingpoint = 1; var vert = new GLPLVertexScaleLookat(rotatetoviewer: dorotate, rotateelevation: doelevation, // a look at vertex shader autoscale: 500, autoscalemin: 1f, autoscalemax: 20f); // below 500, 1f, above 500, scale up to 20x var tcs = new GLPLTesselationControl(40f); tes = new GLPLTesselationEvaluateSinewave(1f, 2f); // this uses the world position from the vertex scaler to position the image, w controls image + animation (b16) var frag = new GLPLFragmentShaderTexture2DDiscard(texbindingpoint); // binding - takes image pos from tes. imagepos < 0 means discard objectshader = new GLShaderPipeline(vert, tcs, tes, null, frag); items.Add(objectshader); objectshader.StartAction += (s, m) => { texarray.Bind(texbindingpoint); // bind tex array to, matching above }; // now the RenderControl for the objects GLRenderState rt = GLRenderState.Patches(4); rt.DepthTest = depthtest; // create a quad and all entries of the renderable map objects, zero at this point, with a zero instance count. UpdateEnables will fill it in later // but we need to give it the maximum buffer length at this point const float objsize = 10.0f; // size of object on screen ridisplay = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Patches, rt, GLShapeObjectFactory.CreateQuadTriStrip(objsize, objsize), // quad2 4 vertexts new Vector4[galmap.RenderableMapObjects.Length], // world positions ic: 0, seconddivisor: 1); modelworldbuffer = items.LastBuffer(); int modelpos = modelworldbuffer.Positions[0]; worldpos = modelworldbuffer.Positions[1]; rObjects.Add(objectshader, "galmapobj", ridisplay); // add a find shader to look them up var geofind = new GLPLGeoShaderFindTriangles(findbufferresults, 16); findshader = items.NewShaderPipeline(null, vert, tcs, tes, geofind, null, null, null); // hook to modelworldbuffer, at modelpos and worldpos. UpdateEnables will fill in instance count rifind = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Patches, GLRenderState.Patches(4), modelworldbuffer, modelpos, ridisplay.DrawCount, modelworldbuffer, worldpos, null, ic: 0, seconddivisor: 1); GLStatics.Check(); // Text renderer for the labels textrenderer = new GLBitmaps("bm-galmapobjects", rObjects, new Size(128, 40), depthtest: depthtest, cullface: false, textureformat: OpenTK.Graphics.OpenGL4.SizedInternalFormat.Rgba8); items.Add(textrenderer); // now make the text up for all the objects above using (Font fnt = new Font("Arial", 8.5F)) { using (StringFormat fmt = new StringFormat()) { fmt.Alignment = StringAlignment.Center; var renderablegalmapobjects = galmap.RenderableMapObjects; // list of enabled entries List <Vector3> posset = new List <Vector3>(); float offscale = objsize * (0.5f + (float)textrenderer.BitmapSize.Height / (float)textrenderer.BitmapSize.Width / 2); // this is the nominal centre of the text bitmap, offset in Y to the object for (int i = 0; i < renderablegalmapobjects.Length; i++) { var o = renderablegalmapobjects[i]; float offset = -offscale; for (int j = 0; j < i; j++) // look up previous ones and see if we labeled it before { var d1 = new Vector3(o.points[0].X, o.points[0].Y + offset, o.points[0].Z); var d2 = posset[j]; // where it was placed. var diff = d1 - d2; if (diff.Length < offscale) // close { if (offset > 0) // if offset is positive, flip below and increase again { offset = -offset - offscale; } else { offset *= -1; // flip over top } // System.Diagnostics.Debug.WriteLine($"close {renderablegalmapobjects[i].name} {d1} to {renderablegalmapobjects[j].name} {d2} {diff} select {offset}"); } } Vector3 pos = new Vector3(o.points[0].X, o.points[0].Y + offset, o.points[0].Z); posset.Add(pos); //System.Diagnostics.Debug.WriteLine($"{renderablegalmapobjects[i].name} at {pos} {offset}"); textrenderer.Add(o.id, o.name, fnt, Color.White, Color.FromArgb(0, 255, 0, 255), pos, new Vector3(objsize, 0, 0), new Vector3(0, 0, 0), textformat: fmt, rotatetoviewer: dorotate, rotateelevation: doelevation, alphafadescalar: -100, alphafadepos: 500); // fade in, alpha = 0 at >500, 1 at 400 } } } UpdateEnables(); // fill in worldpos's and update instance count, taking into }
public void Start(string name, int maxstars, float sunsize, float tapesize, GLStorageBlock bufferfindresults, bool depthtest, GLItemsList items, GLRenderProgramSortedList rObjects) { this.MaxStars = maxstars; this.tapesize = tapesize; this.sunsize = sunsize; // first the tape var tapetex = new GLTexture2D(BaseUtils.Icons.IconSet.GetBitmap("GalMap.chevron"), internalformat: OpenTK.Graphics.OpenGL4.SizedInternalFormat.Rgba8); // tape image items.Add(tapetex); tapetex.SetSamplerMode(OpenTK.Graphics.OpenGL4.TextureWrapMode.Repeat, OpenTK.Graphics.OpenGL4.TextureWrapMode.Repeat); // configure the fragger, set the replacement color, and set the distance where the replacement color is used for all pixels tapefrag = new GLPLFragmentShaderTextureTriStripColorReplace(1, Color.FromArgb(255, 206, 0, 0), 1000); // create the vertex shader with the autoscale required var vert = new GLPLVertexShaderWorldTextureTriStripNorm(100, 1, 10000); vert.SetWidth(tapesize); // set the nominal tape width tapeshader = new GLShaderPipeline(vert, tapefrag); items.Add(tapeshader); GLRenderState rts = GLRenderState.Tri(OpenTK.Graphics.OpenGL4.DrawElementsType.UnsignedByte, cullface: false); // set up a Tri strip, Default primitive restart rts.DepthTest = depthtest; // no depth test so always appears // now the renderer, set up with the render control, tape as the points, and bind a RenderDataTexture so the texture gets binded each time var zerotape = new Vector4[] { Vector4.Zero }; // just use an dummy array to get this going ritape = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.TriangleStrip, rts, zerotape, zerotape, new GLRenderDataTexture(tapetex)); tapepointbuf = items.LastBuffer(); // keep buffer for refill ritape.ElementBuffer = items.NewBuffer(); // empty buffer for element index for now ritape.Visible = false; // until its filled, not visible (important, we don't want render to execute unless its been fully set up below) rObjects.Add(tapeshader, name + "-tape", ritape); // add render to object list // now the stars starposbuf = items.NewBuffer(); // where we hold the vertexes for the suns, used by renderer and by finder // the colour index of the stars is selected by the w parameter of the world position vertexes. // we autoscale to make them bigger at greater distances from eye sunvertex = new GLPLVertexShaderModelCoordWorldAutoscale(new Color[] { Color.Yellow, Color.FromArgb(255, 230, 230, 1) }, autoscale: 30, autoscalemin: 1, autoscalemax: 2, useeyedistance: false); sunshader = new GLShaderPipeline(sunvertex, new GLPLStarSurfaceFragmentShader()); items.Add(sunshader); var shape = GLSphereObjectFactory.CreateSphereFromTriangles(2, sunsize); GLRenderState rt = GLRenderState.Tri(); // render is triangles, with no depth test so we always appear rt.DepthTest = depthtest; rt.DepthClamp = true; renderersun = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles, rt, shape, starposbuf, 0, null, 0, 1); renderersun.Visible = false; // until its filled, not visible rObjects.Add(sunshader, name + "-suns", renderersun); // find compute var geofind = new GLPLGeoShaderFindTriangles(bufferfindresults, 16); findshader = items.NewShaderPipeline(null, sunvertex, null, null, geofind, null, null, null); rifind = GLRenderableItem.CreateVector4Vector4(items, OpenTK.Graphics.OpenGL4.PrimitiveType.Triangles, GLRenderState.Tri(), shape, starposbuf, ic: 0, seconddivisor: 1); // Sun names, handled by textrenderer textrenderer = new GLBitmaps(name + "-text", rObjects, BitMapSize, depthtest: depthtest, cullface: false); items.Add(textrenderer); }