/// <summary> Render setup for primitive Points from a previous RS, with optional control over various parameters of the primitive </summary> static public GLRenderState Points(GLRenderState prev, float pointsize = 1, bool smooth = true) { return(new GLRenderState(prev) { PointSize = pointsize, PointSprite = false, PointSmooth = smooth }); }
/// <summary> Render setup for primitive Patches from a previous RS, with optional control over various parameters of the primitive </summary> static public GLRenderState Patches(GLRenderState prev, int patchsize = 4, FrontFaceDirection frontface = FrontFaceDirection.Ccw, bool cullface = true, PolygonMode polygonmode = PolygonMode.Fill) { return(new GLRenderState(prev) { PatchSize = patchsize, FrontFace = frontface, CullFace = cullface, PolygonModeFrontAndBack = polygonmode }); }
/// <summary> Render setup for primitive Point sprites from a previous RS, with optional control over various parameters of the primitive </summary> static public GLRenderState PointSprites(GLRenderState prev) { return(new GLRenderState(prev) { PointSize = 0, PointSprite = true }); }
/// <summary> Render setup for primitive Lines from a previous RS, with optional control over various parameters of the primitive </summary> static public GLRenderState Lines(GLRenderState prev, float linewidth = 1, bool smooth = true) // vertex 0/1 line, 2/3 line { return(new GLRenderState(prev) { LineWidth = linewidth, LineSmooth = smooth }); }
///<summary> Execute a RenderableItem. /// Use to execute outside of the normal RenderableItemList system. For a compute shader for instance. Or for a finder. /// appliedstate if not null overrides this.RenderState and uses that instead </summary> public void Execute(IGLProgramShader shader, GLRenderState glstate, GLMatrixCalc c = null, GLRenderState appliedstate = null, bool noshaderstart = false) { System.Diagnostics.Debug.Assert(glstate != null && shader != null); if (shader.Enable) { if (!noshaderstart) { shader.Start(c); } GLRenderState curstate = RenderState; if (appliedstate != null) { RenderState = appliedstate; } Bind(glstate, shader, c); Render(); if (!noshaderstart) { shader.Finish(); } RenderState = curstate; } }
/// <summary> Render setup for primitive Triangles from a previous RS and with primitive restart, with optional control over various parameters of the primitive </summary> static public GLRenderState Tri(GLRenderState prev, uint primitiverestart, FrontFaceDirection frontface = FrontFaceDirection.Ccw, bool cullface = true, PolygonMode polygonmode = PolygonMode.Fill, bool polysmooth = false) { return(new GLRenderState(prev) { PrimitiveRestart = primitiverestart, FrontFace = frontface, CullFace = cullface, PolygonModeFrontAndBack = polygonmode, PolygonSmooth = polysmooth }); }
/// <summary> Render setup for primitive Trianges from a previous RS with primitive restart, with optional control over various parameters of the primitive </summary> static public GLRenderState Tri(GLRenderState prev, DrawElementsType primitiverestarttype, FrontFaceDirection frontface = FrontFaceDirection.Ccw, bool cullface = true, PolygonMode polygonmode = PolygonMode.Fill, bool polysmooth = false) { return(new GLRenderState(prev) { PrimitiveRestart = GL4Statics.DrawElementsRestartValue(primitiverestarttype), FrontFace = frontface, CullFace = cullface, PolygonModeFrontAndBack = polygonmode, PolygonSmooth = polysmooth }); }
/// <summary> Render setup for primitive Quads from a previous RS, with optional control over various parameters of the primitive </summary> static public GLRenderState Quads(GLRenderState prev, FrontFaceDirection frontface = FrontFaceDirection.Ccw, bool cullface = true, PolygonMode polygonmode = PolygonMode.Fill, bool polysmooth = false) { return(new GLRenderState(prev) { FrontFace = frontface, CullFace = cullface, PolygonModeFrontAndBack = polygonmode, PolygonSmooth = polysmooth }); }
/// <summary>Create a renderable item. </summary> /// <param name="pt">The primitive type to render</param> /// <param name="rc">The render state to enforce for this draw</param> /// <param name="drawcount">Number of draws</param> /// <param name="va">Vertex array to bind</param> /// <param name="id">Render data to bind at the draw</param> /// <param name="ic">Instance count</param> public GLRenderableItem(PrimitiveType pt, GLRenderState rc, int drawcount, IGLVertexArray va, IGLRenderItemData id = null, int ic = 1) { PrimitiveType = pt; RenderState = rc; DrawCount = drawcount; VertexArray = va; RenderData = id; InstanceCount = ic; }
/// <summary> Called before Render (normally by RenderList::Render) to set up data for the render. /// currentstate may be null, meaning, don't apply /// RenderState may be null, meaning don't change</summary> public void Bind(GLRenderState currentstate, IGLProgramShader shader, GLMatrixCalc matrixcalc) { if (currentstate != null && RenderState != null) // if either null, it means the last render state applied is the same as our render state, so no need to apply { currentstate.ApplyState(RenderState); // else go to this state } VertexArray?.Bind(); // give the VA a chance to bind to GL RenderData?.Bind(this, shader, matrixcalc); // optional render data supplied by the user to bind ElementBuffer?.BindElement(); // if we have an element buffer, give it a chance to bind IndirectBuffer?.BindIndirect(); // if we have an indirect buffer, give it a chance to bind ParameterBuffer?.BindParameter(); // if we have a parameter buffer, give it a chance to bind }
/// <summary> Copy constructor </summary> public GLRenderState(GLRenderState prev) // copy previous fixed settings { PrimitiveRestart = prev.PrimitiveRestart; ClipDistanceEnable = prev.ClipDistanceEnable; DepthTest = prev.DepthTest; DepthFunctionMode = prev.DepthFunctionMode; WriteDepthBuffer = prev.WriteDepthBuffer; DepthClamp = prev.DepthClamp; BlendEnable = prev.BlendEnable; BlendSourceRGB = prev.BlendSourceRGB; BlendDestRGB = prev.BlendDestRGB; BlendSourceA = prev.BlendSourceA; BlendDestA = prev.BlendDestA; BlendEquationRGB = prev.BlendEquationRGB; BlendEquationA = prev.BlendEquationA; Discard = prev.Discard; ColorMasking = prev.ColorMasking; }
/// <summary> Called by WinFormControl, this sets up the initial render state </summary> static public GLRenderState Start() { var startstate = new GLRenderState() // Set the default state we want to be in at start (some state defaults are at bottom) { FrontFace = FrontFaceDirection.Ccw, CullFace = true, PolygonModeFrontAndBack = PolygonMode.Fill, PatchSize = 1, PointSize = 1, PointSprite = false, PointSmooth = true, PolygonSmooth = false, LineWidth = 1, LineSmooth = true, }; var curstate = new GLRenderState() // set to be purposely not default constructor state and the above state { // to make all get set. PrimitiveRestart = 1, ClipDistanceEnable = 1, DepthTest = false, DepthFunctionMode = DepthFunction.Never, WriteDepthBuffer = false, DepthClamp = true, BlendEnable = false, BlendSourceRGB = BlendingFactorSrc.ConstantAlpha, BlendSourceA = BlendingFactorSrc.ConstantAlpha, BlendDestRGB = BlendingFactorDest.ConstantAlpha, BlendDestA = BlendingFactorDest.ConstantAlpha, BlendEquationA = BlendEquationMode.Min, BlendEquationRGB = BlendEquationMode.Min, ColorMasking = 0, Discard = true, }; curstate.ApplyState(startstate); // from curstate, apply state return(startstate); }
/// <summary> Vector4 and Vector2. Second vector can be instance divided. In attributes 0,1</summary> public static GLRenderableItem CreateVector4Vector2(GLItemsList items, PrimitiveType prim, GLRenderState pt, Vector4[] vectors, Vector2[] coords, IGLRenderItemData id = null, int ic = 1, int seconddivisor = 0) { var vb = items.NewBuffer(); vb.AllocateBytes(GLBuffer.Vec4size * vectors.Length + GLBuffer.Vec2size * coords.Length); vb.Fill(vectors); vb.Fill(coords); var va = items.NewArray(); vb.Bind(va, 0, vb.Positions[0], 16); va.Attribute(0, 0, 4, VertexAttribType.Float); vb.Bind(va, 1, vb.Positions[1], 8, seconddivisor); va.Attribute(1, 1, 2, VertexAttribType.Float); return(new GLRenderableItem(prim, pt, vectors.Length, va, id, ic)); }
/// <summary> Vector4 and Vector2 in one buffer, with buffer given and positions given. Second vector can be instance divided. In attributes 0,1</summary> public static GLRenderableItem CreateVector4Vector2(GLItemsList items, PrimitiveType prim, GLRenderState pt, GLBuffer vb, int pos1, int pos2, int drawcount, IGLRenderItemData id = null, int ic = 1, int seconddivisor = 0) { var va = items.NewArray(); vb.Bind(va, 0, vb.Positions[0], 16); va.Attribute(0, 0, 4, VertexAttribType.Float); vb.Bind(va, 1, vb.Positions[1], 8, seconddivisor); va.Attribute(1, 1, 2, VertexAttribType.Float); return(new GLRenderableItem(prim, pt, drawcount, va, id, ic)); }
/// <summary> Vector4 and Vector2 in a tuple, into one buffer. In attributes 0,1</summary> public static GLRenderableItem CreateVector4Vector2(GLItemsList items, PrimitiveType prim, GLRenderState pt, Tuple <Vector4[], Vector2[]> vectors, IGLRenderItemData id = null, int ic = 1, int seconddivisor = 0) { return(CreateVector4Vector2(items, prim, pt, vectors.Item1, vectors.Item2, id, ic, seconddivisor)); }
/// <summary> Vector4 and Vector2 and index array in a tuple. Element index is created. In attributes 0,1. No primitive restart</summary> public static GLRenderableItem CreateVector4Vector2Indexed(GLItemsList items, PrimitiveType prim, GLRenderState pt, Tuple <Vector4[], Vector2[], uint[]> vectors, IGLRenderItemData id = null, int ic = 1, int seconddivisor = 0) { var dt = GL4Statics.DrawElementsTypeFromMaxEID((uint)vectors.Item1.Length - 1); var ri = CreateVector4Vector2(items, prim, pt, vectors.Item1, vectors.Item2, id, ic, seconddivisor); ri.CreateElementIndex(items.NewBuffer(), vectors.Item3, dt); return(ri); }
///<summary> Vector4, Vector2 and Matrix4 in buffers. First is model, second is coords, third is instance matrix translation /// All are supplied by buffer references /// Attributes in 0,1,4-7 set up.</summary> public static GLRenderableItem CreateVector4Vector2Matrix4(GLItemsList items, PrimitiveType prim, GLRenderState pt, GLBuffer vbuf1, GLBuffer vbuf2, GLBuffer vbuf3, int vertexcount, IGLRenderItemData id = null, int ic = 1, int matrixdivisor = 1, int buf1pos = 0, int buf2pos = 0, int buf3pos = 0) { var va = items.NewArray(); vbuf1.Bind(va, 0, buf1pos, 16); va.Attribute(0, 0, 4, VertexAttribType.Float); // bp 0 at 0 vbuf2.Bind(va, 1, buf2pos, 8); va.Attribute(1, 1, 2, VertexAttribType.Float); // bp 1 at 1 va.MatrixAttribute(2, 4); // bp 2 at 4-7 vbuf3.Bind(va, 2, buf3pos, 64, matrixdivisor); // use a binding return(new GLRenderableItem(prim, pt, vertexcount, va, id, ic)); }
/// <summary> Two Vector4s, in separate buffers. Second vector can be instance divided. In attributes 0,1</summary> public static GLRenderableItem CreateVector4Vector4Buf2(GLItemsList items, PrimitiveType prim, GLRenderState pt, Vector4[] vectors, Vector4[] secondvector, IGLRenderItemData id = null, int ic = 1, int seconddivisor = 0) { var v1 = items.NewBuffer(); v1.AllocateBytes(GLBuffer.Vec4size * vectors.Length); v1.Fill(vectors); var v2 = items.NewBuffer(); v2.AllocateBytes(GLBuffer.Vec4size * secondvector.Length); v2.Fill(secondvector); var va = items.NewArray(); v1.Bind(va, 0, v1.Positions[0], 16); va.Attribute(0, 0, 4, VertexAttribType.Float); v2.Bind(va, 1, v2.Positions[0], 16, seconddivisor); va.Attribute(1, 1, 4, VertexAttribType.Float); return(new GLRenderableItem(prim, pt, vectors.Length, va, id, ic)); }
/// <summary> This sets the GL state variables to the render state this object requires. Called by RenderableItem</summary> public void ApplyState(GLRenderState newstate) // apply deltas to GL { // general //System.Diagnostics.Debug.WriteLine("Apply " + newstate.PrimitiveType + " Fixed state " + newstate.ApplyFixed); if (newstate.PrimitiveRestart != PrimitiveRestart) { //System.Diagnostics.Debug.WriteLine("Set PR to {0}", newstate.PrimitiveRestart); if (newstate.PrimitiveRestart.HasValue) // is new state has value { if (PrimitiveRestart == null) // if last was off, turn it on { GL.Enable(EnableCap.PrimitiveRestart); } GL.PrimitiveRestartIndex(newstate.PrimitiveRestart.Value); // set } else { GL.Disable(EnableCap.PrimitiveRestart); // else disable } PrimitiveRestart = newstate.PrimitiveRestart; } if (ClipDistanceEnable != newstate.ClipDistanceEnable) // if changed { if (newstate.ClipDistanceEnable > ClipDistanceEnable) { for (int i = ClipDistanceEnable; i < newstate.ClipDistanceEnable; i++) { GL.Enable(EnableCap.ClipDistance0 + i); } } else if (newstate.ClipDistanceEnable < ClipDistanceEnable) { for (int i = ClipDistanceEnable - 1; i >= newstate.ClipDistanceEnable; i--) { GL.Disable(EnableCap.ClipDistance0 + i); } } ClipDistanceEnable = newstate.ClipDistanceEnable; } if (DepthTest != newstate.DepthTest) { DepthTest = newstate.DepthTest; GLStatics.SetEnable(OpenTK.Graphics.OpenGL.EnableCap.DepthTest, DepthTest); // System.Diagnostics.Debug.WriteLine("Depth Test " + DepthTest); } if (DepthFunctionMode != newstate.DepthFunctionMode) { DepthFunctionMode = newstate.DepthFunctionMode; GL.DepthFunc(DepthFunctionMode); } if (WriteDepthBuffer != newstate.WriteDepthBuffer) { WriteDepthBuffer = newstate.WriteDepthBuffer; GL.DepthMask(WriteDepthBuffer); } if (DepthClamp != newstate.DepthClamp) { DepthClamp = newstate.DepthClamp; GLStatics.SetEnable(OpenTK.Graphics.OpenGL.EnableCap.DepthClamp, DepthClamp); // System.Diagnostics.Debug.WriteLine("Depth Clamp" + DepthClamp.Value); } if (BlendEnable != newstate.BlendEnable) { BlendEnable = newstate.BlendEnable; GLStatics.SetEnable(OpenTK.Graphics.OpenGL.EnableCap.Blend, BlendEnable); } // blend on, we have new values for blend equation if (BlendEnable == true) { if (BlendSourceRGB != newstate.BlendSourceRGB || BlendDestRGB != newstate.BlendDestRGB || BlendSourceA != newstate.BlendSourceA || BlendDestA != newstate.BlendDestA) { BlendSourceRGB = newstate.BlendSourceRGB; BlendDestRGB = newstate.BlendDestRGB; BlendSourceA = newstate.BlendSourceA; BlendDestA = newstate.BlendDestA; GL.BlendFuncSeparate(BlendSourceRGB, BlendDestRGB, BlendSourceA, BlendDestA); } if (BlendEquationRGB != newstate.BlendEquationRGB || BlendEquationA != newstate.BlendEquationA) { BlendEquationRGB = newstate.BlendEquationRGB; BlendEquationA = newstate.BlendEquationA; GL.BlendEquationSeparate(BlendEquationRGB, BlendEquationA); } } if (ColorMasking != newstate.ColorMasking) { ColorMasking = newstate.ColorMasking; GL.ColorMask((ColorMasking & ColorMask.Red) == ColorMask.Red, (ColorMasking & ColorMask.Green) == ColorMask.Green, (ColorMasking & ColorMask.Blue) == ColorMask.Blue, (ColorMasking & ColorMask.Alpha) == ColorMask.Alpha); } if (newstate.Discard != Discard) { Discard = newstate.Discard; GLStatics.SetEnable(OpenTK.Graphics.OpenGL.EnableCap.RasterizerDiscard, Discard); //System.Diagnostics.Debug.WriteLine("RS Discard " + Discard); } // ---------------------------------- Below are default null // Geo shaders if (newstate.PatchSize.HasValue && PatchSize != newstate.PatchSize) { PatchSize = newstate.PatchSize; GL.PatchParameter(PatchParameterInt.PatchVertices, PatchSize.Value); } // points if (newstate.PointSize.HasValue && PointSize != newstate.PointSize) { if (newstate.PointSize > 0) // if fixed point size { if (PointSize == null || newstate.PointSize != PointSize.Value) { GL.PointSize(newstate.PointSize.Value); // set if different } if (PointSize == null || PointSize == 0) // if previous was off { GL.Disable(EnableCap.ProgramPointSize); } } else { GL.Enable(EnableCap.ProgramPointSize); } PointSize = newstate.PointSize; } if (newstate.PointSprite.HasValue && PointSprite != newstate.PointSprite) { PointSprite = newstate.PointSprite; GLStatics.SetEnable(OpenTK.Graphics.OpenGL.EnableCap.PointSprite, PointSprite.Value); } if (newstate.PointSmooth.HasValue && PointSmooth != newstate.PointSmooth) { PointSmooth = newstate.PointSmooth; GLStatics.SetEnable(OpenTK.Graphics.OpenGL.EnableCap.PointSmooth, PointSmooth.Value); } // lines if (newstate.LineWidth.HasValue && LineWidth != newstate.LineWidth) { LineWidth = newstate.LineWidth; GL.LineWidth(LineWidth.Value); } if (newstate.LineSmooth.HasValue && LineSmooth != newstate.LineSmooth) { LineSmooth = newstate.LineSmooth; GLStatics.SetEnable(OpenTK.Graphics.OpenGL.EnableCap.LineSmooth, LineSmooth.Value); } // triangles if (newstate.PolygonModeFrontAndBack.HasValue && PolygonModeFrontAndBack != newstate.PolygonModeFrontAndBack) { PolygonModeFrontAndBack = newstate.PolygonModeFrontAndBack; GL.PolygonMode(MaterialFace.FrontAndBack, PolygonModeFrontAndBack.Value); } if (newstate.PolygonSmooth.HasValue && PolygonSmooth != newstate.PolygonSmooth) { PolygonSmooth = newstate.PolygonSmooth; GLStatics.SetEnable(OpenTK.Graphics.OpenGL.EnableCap.PolygonSmooth, PolygonSmooth.Value); } if (newstate.CullFace.HasValue && CullFace != newstate.CullFace) { CullFace = newstate.CullFace; GLStatics.SetEnable(OpenTK.Graphics.OpenGL.EnableCap.CullFace, CullFace.Value); // System.Diagnostics.Debug.WriteLine("Cull mode " + CullFace.Value); } if (newstate.FrontFace.HasValue && FrontFace != newstate.FrontFace) { FrontFace = newstate.FrontFace; GL.FrontFace(FrontFace.Value); } }
///<summary> Floats packed into buffer with configurable component number (1,2,4) /// Attributes in 0.</summary> public static GLRenderableItem CreateFloats(GLItemsList items, PrimitiveType prim, GLRenderState pt, float[] floats, int components, IGLRenderItemData id = null, int ic = 1) { var vb = items.NewBuffer(); vb.AllocateFill(floats); //float[] ouwt = vb.ReadFloats(0, floats.Length); // test read back var va = items.NewArray(); vb.Bind(va, 0, vb.Positions[0], sizeof(float) * components); va.Attribute(0, 0, components, VertexAttribType.Float); return(new GLRenderableItem(prim, pt, floats.Length / components, va, id, ic)); }
///<summary> Matrix4 as a buffer reference. /// Attributes in 4-7 set up.</summary> public static GLRenderableItem CreateMatrix4(GLItemsList items, PrimitiveType prim, GLRenderState pt, GLBuffer vb, int bufoffset, int drawcount, IGLRenderItemData id = null, int ic = 1, int matrixdivisor = 1) { var va = items.NewArray(); vb.Bind(va, 2, bufoffset, 64, matrixdivisor); // use a binding va.MatrixAttribute(2, 4); // bp 2 at attribs 4-7 return(new GLRenderableItem(prim, pt, drawcount, va, id, ic)); }
///<summary> Matrix4. /// Attributes in 4-7 set up.</summary> public static GLRenderableItem CreateMatrix4(GLItemsList items, PrimitiveType prim, GLRenderState pt, Matrix4[] matrix, int drawcount, IGLRenderItemData id = null, int ic = 1, int matrixdivisor = 1) { var vb = items.NewBuffer(); vb.AllocateBytes(GLBuffer.Mat4size * matrix.Length); vb.Fill(matrix); var va = items.NewArray(); vb.Bind(va, 2, vb.Positions[0], 64, matrixdivisor); // use a binding va.MatrixAttribute(2, 4); // bp 2 at attribs 4-7 return(new GLRenderableItem(prim, pt, drawcount, va, id, ic)); }
///<summary> Vector4 and Matrix4. Both are buffer references. /// Attributes in 0,4-7 set up.</summary> public static GLRenderableItem CreateVector4Matrix4(GLItemsList items, PrimitiveType prim, GLRenderState pt, GLBuffer shape, GLBuffer matrix, int drawcount, IGLRenderItemData id = null, int ic = 1, int matrixdivisor = 1) { var va = items.NewArray(); shape.Bind(va, 0, shape.Positions[0], 16); va.Attribute(0, 0, 4, VertexAttribType.Float); // bp 0 at attrib 0 matrix.Bind(va, 2, matrix.Positions[0], 64, matrixdivisor); // use a binding va.MatrixAttribute(2, 4); // bp 2 at attribs 4-7 return(new GLRenderableItem(prim, pt, drawcount, va, id, ic)); }
///<summary> Vector4 and Matrix4. Matrix4 is a buffer reference. /// Attributes in 0,4-7 set up.</summary> public static GLRenderableItem CreateVector4Matrix4(GLItemsList items, PrimitiveType prim, GLRenderState pt, Vector4[] vectors, GLBuffer matrix, IGLRenderItemData id = null, int ic = 1, int matrixdivisor = 1) { var vb = items.NewBuffer(); vb.AllocateFill(vectors); // push in model vectors var va = items.NewArray(); vb.Bind(va, 0, vb.Positions[0], 16); va.Attribute(0, 0, 4, VertexAttribType.Float); // bp 0 at attrib 0 matrix.Bind(va, 2, matrix.Positions[0], 64, matrixdivisor); // use a binding va.MatrixAttribute(2, 4); // bp 2 at attribs 4-7 return(new GLRenderableItem(prim, pt, vectors.Length, va, id, ic)); }
///<summary> Null Vertex without any data. No data into GL pipeline. /// Used when a uniform buffer gives info for the vertex shader to create vertices /// Or when the vertex shader makes up its own vertexes from draw/instance counts </summary> public static GLRenderableItem CreateNullVertex(PrimitiveType prim, GLRenderState pt, IGLRenderItemData id = null, int drawcount = 1, int instancecount = 1) { return(new GLRenderableItem(prim, pt, drawcount, null, id, instancecount)); // no vertex data. }
/// <summary> Vector4 and Vector2 and Vector4 in a tuple. See Vector4Vector2Vector4</summary> public static GLRenderableItem CreateVector4Vector2Vector4(GLItemsList items, PrimitiveType prim, GLRenderState pt, Tuple <Vector4[], Vector2[]> pos, Vector4[] instanceposition, IGLRenderItemData id = null, int ic = 1, bool separbuf = false, int divisorinstance = 1) { return(CreateVector4Vector2Vector4(items, prim, pt, pos.Item1, pos.Item2, instanceposition, id, ic, separbuf, divisorinstance)); }
/// <summary> Two Vector4s, both in buffers. Second vector can be instance divided. In attributes 0,1</summary> public static GLRenderableItem CreateVector4Vector4(GLItemsList items, PrimitiveType prim, GLRenderState pt, GLBuffer buf1, int buf1off, int drawcount, GLBuffer buf2, int buf2off = 0, IGLRenderItemData id = null, int ic = 1, int seconddivisor = 0) { var va = items.NewArray(); buf1.Bind(va, 0, buf1off, 16); // binding index 0 va.Attribute(0, 0, 4, VertexAttribType.Float); // attribute 0 buf2.Bind(va, 1, buf2off, 16, seconddivisor); // binding index 1 va.Attribute(1, 1, 4, VertexAttribType.Float); // attribute 1 return(new GLRenderableItem(prim, pt, drawcount, va, id, ic)); }
/// <summary>Execute the render list, given the render state, matrix calc. Optional verbose debug output mode </summary> public void Render(GLRenderState currentstate, GLMatrixCalc c, bool verbose = false) { if (verbose) { System.Diagnostics.Trace.WriteLine("***Begin RList"); } GLStatics.Check(); // ensure clear before start GLRenderState lastapplied = null; IGLProgramShader curshader = null; foreach (var shaderri in renderables) // kvp of Key=Shader, Value = list of renderables { // shader must be enabled if (shaderri.Item1.Enable) { if (shaderri.Item2 == null) // indicating its a compute or operation { if (shaderri.Item1 is GLShaderCompute) // if compute { if (curshader != null) // turn off current shader { curshader.Finish(); curshader = null; } if (verbose) { System.Diagnostics.Trace.WriteLine(" Compute Shader " + shaderri.Item1.GetType().Name); } shaderri.Item1.Start(c); // start/finish it shaderri.Item1.Finish(); } else { if (verbose) { System.Diagnostics.Trace.WriteLine(" Operation " + shaderri.Item1.GetType().Name); } shaderri.Item1.Start(c); // operations just start, but don't change the current shader } } else if (shaderri.Item2.Find(x => x.Item2.Visible) != null) // must have a list, all must not be null, and some must be visible { if (curshader != shaderri.Item1) // if a different shader instance { if (curshader != null) // finish the last one if present { curshader.Finish(); } curshader = shaderri.Item1; curshader.Start(c); // start the program - if compute shader, or operation, this executes the code } //System.Diagnostics.Trace.WriteLine("Shader " + kvp.Item1.GetType().Name); foreach (var g in shaderri.Item2) { GLOFC.GLStatics.Check(); if (g.Item2 != null && g.Item2.Visible) // Make sure its visible and not empty slot { if (verbose) { System.Diagnostics.Trace.WriteLine(" Bind " + g.Item1 + " shader " + shaderri.Item1.GetType().Name); } if (g.Item2.RenderState == null) // if no render control, do not change last applied. { g.Item2.Bind(null, shaderri.Item1, c); } else if (object.ReferenceEquals(g.Item2.RenderState, lastapplied)) // no point forcing the test of rendercontrol if its the same as last applied { g.Item2.Bind(null, shaderri.Item1, c); } else { g.Item2.Bind(currentstate, shaderri.Item1, c); // change and remember lastapplied = g.Item2.RenderState; } if (verbose) { System.Diagnostics.Trace.WriteLine(" Render " + g.Item1 + " shader " + shaderri.Item1.GetType().Name); } g.Item2.Render(); //System.Diagnostics.Trace.WriteLine("....Render Over " + g.Item1); } else { if (verbose) { System.Diagnostics.Trace.WriteLine(" Not visible " + g.Item1 + " " + shaderri.Item1.GetType().Name); } } GLOFC.GLStatics.Check(); } } else { if (verbose) { System.Diagnostics.Trace.WriteLine(" No items visible " + shaderri.Item1.GetType().Name); } } } else { if (verbose) { System.Diagnostics.Trace.WriteLine(" Shader disabled " + shaderri.Item1.GetType().Name + " " + shaderri.Item1.Name); } } } if (curshader != null) { curshader.Finish(); } if (verbose) { System.Diagnostics.Trace.WriteLine("***End RList"); } GL.UseProgram(0); // final clean up GL.BindProgramPipeline(0); }
///<summary> Vector3 packed using GLBuffer.FillPacked2vec. Offsets and mult specify range /// Attributes in 0.</summary> public static GLRenderableItem CreateVector3Packed2(GLItemsList items, PrimitiveType prim, GLRenderState pt, Vector3[] vectors, Vector3 offsets, float mult, IGLRenderItemData id = null, int ic = 1) { var vb = items.NewBuffer(); vb.AllocateBytes(sizeof(uint) * 2 * vectors.Length); vb.FillPacked2vec(vectors, offsets, mult); var va = items.NewArray(); vb.Bind(va, 0, vb.Positions[0], 8); va.AttributeI(0, 0, 2, VertexAttribType.UnsignedInt); return(new GLRenderableItem(prim, pt, vectors.Length, va, id, ic)); }
///<summary> Vector4, Vector2 and Matrix4 in buffers. First is model, second is coords, third is instance matrix translation /// if separbuffer = true and instancematrix is null, it makes a buffer for you to fill up externally. /// if separbuffer = true it makes as separate buffer for instancematrix /// if separbuffer = true and instancematrix is null, you fill up the separbuffer yourself outside of this (maybe auto generated). /// You can get this buffer using items.LastBuffer() /// Attributes in 0,1,4-7 set up.</summary> public static GLRenderableItem CreateVector4Vector2Matrix4(GLItemsList items, PrimitiveType prim, GLRenderState pt, Vector4[] vectors, Vector2[] coords, Matrix4[] instancematrix, IGLRenderItemData id = null, int ic = 1, bool separbuf = false, int matrixdivisor = 1) { var va = items.NewArray(); GLBuffer vbuf1 = items.NewBuffer(); GLBuffer vbuf2 = vbuf1; int posi = 2; if (separbuf) { vbuf1.AllocateBytes(GLBuffer.Vec4size * vectors.Length + GLBuffer.Vec2size * coords.Length); vbuf2 = items.NewBuffer(); if (instancematrix != null) { vbuf2.AllocateBytes(GLBuffer.Mat4size * instancematrix.Length); } posi = 0; } else { vbuf1.AllocateBytes(GLBuffer.Vec4size * vectors.Length + GLBuffer.Vec2size * coords.Length + GLBuffer.Vec4size + GLBuffer.Mat4size * instancematrix.Length); // due to alignment, add on a little } vbuf1.Fill(vectors); vbuf1.Fill(coords); if (instancematrix != null) { vbuf2.Fill(instancematrix); } vbuf1.Bind(va, 0, vbuf1.Positions[0], 16); va.Attribute(0, 0, 4, VertexAttribType.Float); // bp 0 at 0 vbuf1.Bind(va, 1, vbuf1.Positions[1], 8); va.Attribute(1, 1, 2, VertexAttribType.Float); // bp 1 at 1 va.MatrixAttribute(2, 4); // bp 2 at 4-7 vbuf2.Bind(va, 2, instancematrix != null ? vbuf2.Positions[posi]: 0, 64, matrixdivisor); // use a binding return(new GLRenderableItem(prim, pt, vectors.Length, va, id, ic)); }