/// <summary> /// Draw the elements instances /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for drawing. /// </param> /// <param name="instances"> /// A <see cref="UInt32"/> that specify the number of instances to draw. /// </param> public override void DrawInstanced(GraphicsContext ctx, uint instances) { CheckCurrentContext(ctx); ArrayBufferObjectBase.IArraySection arraySection = ArrayIndices.GetArraySection(0); Debug.Assert(arraySection != null); // Element array must be (re)bound ctx.Bind(ArrayIndices, true); // Enable restart primitive? if (ArrayIndices.RestartIndexEnabled) { if (PrimitiveRestart.IsPrimitiveRestartSupported(ctx)) { // Enable primitive restart PrimitiveRestart.EnablePrimitiveRestart(ctx, ArrayIndices.ElementsType); // Draw elements as usual DrawElementsInstanced(ctx, arraySection.Pointer, instances); // Disable primitive restart PrimitiveRestart.DisablePrimitiveRestart(ctx); } else { throw new NotSupportedException(); } } else { uint count = (ElementCount == 0) ? ArrayIndices.ItemCount : ElementCount; Debug.Assert(count - ElementOffset <= ArrayIndices.ItemCount, "element indices array out of bounds"); // Draw vertex arrays by indices DrawElementsInstanced(ctx, arraySection.Pointer, instances); } }
/// <summary> /// Draw the elements. /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for drawing. /// </param> public override void Draw(GraphicsContext ctx) { CheckCurrentContext(ctx); ArrayBufferObjectBase.IArraySection arraySection = ArrayIndices.GetArraySection(0); Debug.Assert(arraySection != null); // Element array must be (re)bound ctx.Bind(ArrayIndices, true); // Enable restart primitive? if (ArrayIndices.RestartIndexEnabled) { if (PrimitiveRestart.IsPrimitiveRestartSupported(ctx)) { // Draw elements with primitive restart PrimitiveRestart.EnablePrimitiveRestart(ctx, ArrayIndices.ElementsType); DrawElements(ctx, arraySection.Pointer); PrimitiveRestart.DisablePrimitiveRestart(ctx); } else { // Note: uses MultiDrawElements to emulate the primitive restart feature; PrimitiveRestartOffsets and // PrimitiveRestartCounts are computed at element buffer creation time Gl.MultiDrawElements(ElementsMode, ArrayIndices.PrimitiveRestartOffsets, ArrayIndices.ElementsType, ArrayIndices.PrimitiveRestartCounts, ArrayIndices.PrimitiveRestartOffsets.Length); } } else { uint count = (ElementCount == 0) ? ArrayIndices.ItemCount : ElementCount; Debug.Assert(count - ElementOffset <= ArrayIndices.ItemCount, "element indices array out of bounds"); // Draw vertex arrays by indices DrawElements(ctx, arraySection.Pointer); } }
/// <summary> /// Draw a specific element set. /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for rendering. /// </param> /// <param name="shader"> /// The <see cref="ShaderProgram"/> used for drawing the vertex arrays. /// </param> /// <param name="elementIndex"> /// A <see cref="Int32"/> that specifies the index of the element to draw. If it is less than 0, it draws /// all elements set. The index can be obtained by the value returned by <see cref="SetElementArray"/>. /// </param> /// <param name="offset"> /// A <see cref="UInt32"/> that specifies the offset of the first element to draw. /// </param> /// <param name="count"> /// A <see cref="UInt32"/> that specifies the number of items to draw. /// </param> public void Draw(GraphicsContext ctx, ShaderProgram shader, int elementIndex, uint offset, uint count) { Element drawElement = GetElementArray(elementIndex) as Element; if (drawElement == null) { throw new InvalidOperationException("no element at index " + elementIndex); } CheckThisExistence(ctx); // Set vertex arrays SetVertexArrayState(ctx, shader); // Fixed or programmable pipeline? if (shader != null) { ctx.Bind(shader); } else { ctx.ResetProgram(); } if (_FeedbackBuffer != null) { _FeedbackBuffer.Begin(ctx, drawElement.ElementsMode); } drawElement.Draw(ctx, offset, count); if (_FeedbackBuffer != null) { _FeedbackBuffer.End(ctx); } }
/// <summary> /// Draw a character sequence. /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for drawing. /// </param> /// <param name="modelview"> /// The <see cref="Matrix4x4"/> the model-view-projection matrix for the first character of <paramref name="s"/>. /// </param> /// <param name="color"> /// The <see cref="ColorRGBAF"/> that specifies the glyph color. /// </param> /// <param name="s"> /// A <see cref="String"/> that specifies the characters for be drawn. /// </param> private void DrawStringCore(GraphicsContext ctx, Matrix4x4 modelview, ColorRGBAF color, string s) { ModelMatrix charModel = new ModelMatrix(modelview); ctx.Bind(_FontProgram); _FontProgram.SetUniform(ctx, "glo_UniformColor", color); if (ctx.Extensions.ShaderDrawParameters_ARB) { List <VertexArrayObject.IElement> glyphElements = new List <VertexArrayObject.IElement>(); int drawInstanceId = 0; foreach (char c in s) { Glyph glyph; if (_Glyphs.TryGetValue(c, out glyph) == false) { continue; } if (glyph.ElementIndex >= 0) { // Collect draw instance element glyphElements.Add(_VertexArrays.GetElementArray(glyph.ElementIndex)); // Set model-view _FontProgram.SetUniform(ctx, "glo_CharModelViewProjection[" + drawInstanceId + "]", charModel); // Next instance drawInstanceId++; } // Move next charModel.Translate(glyph.GlyphSize.Width, 0.0f); } // Draw using Multi-Draw primitive VertexArrayObject.IElement multiElement = _VertexArrays.CombineArrayElements(glyphElements); _VertexArrays.Draw(ctx, _FontProgram, multiElement); } else { foreach (char c in s) { Glyph glyph; if (_Glyphs.TryGetValue(c, out glyph) == false) { continue; } if (glyph.ElementIndex >= 0) { // Set model-view _FontProgram.SetUniform(ctx, "glo_ModelViewProjection", charModel); // Rasterize it _VertexArrays.Draw(ctx, _FontProgram, glyph.ElementIndex); } // Move next charModel.Translate(glyph.GlyphSize.Width, 0.0f); } } }
/// <summary> /// Set the vertex arrays state for the shader program. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> on which the shader program is bound. /// </param> /// <param name="shaderProgram"> /// A <see cref="ShaderProgram"/> on which the vertex arrays shall be bound. /// </param> private void SetVertexArrayState(GraphicsContext ctx, ShaderProgram shaderProgram) { CheckThisExistence(ctx); // Set vertex array state all at once... ctx.Bind(this, true); if (shaderProgram != null) { ICollection <string> activeAttributes = shaderProgram.ActiveAttributes; uint attributesSet = 0; // Set vertex array state foreach (string attributeName in activeAttributes) { IVertexArray shaderVertexArray = GetVertexArray(attributeName, shaderProgram); if (shaderVertexArray == null) { continue; } ShaderProgram.AttributeBinding attributeBinding = shaderProgram.GetActiveAttribute(attributeName); IVertexArray currentVertexArray = _VertexArrayState[attributeBinding.Location]; //if (ReferenceEquals(shaderVertexArray, currentVertexArray) == false) { shaderVertexArray.SetVertexAttribute(ctx, attributeBinding, attributeName); _VertexArrayState[attributeBinding.Location] = shaderVertexArray; //} attributesSet++; } if (attributesSet == 0) { throw new InvalidOperationException("no attribute is set"); } } else { IVertexArray attributeArray; // No shader program: using fixed pipeline program. ATM enable all attributes having a semantic if ((attributeArray = GetVertexArray(VertexArraySemantic.Position)) == null) { throw new InvalidOperationException("no position semantic array defined"); } attributeArray.SetVertexAttribute(ctx, null, VertexArraySemantic.Position); // Optional attributes if ((attributeArray = GetVertexArray(VertexArraySemantic.Color)) != null) { attributeArray.SetVertexAttribute(ctx, null, VertexArraySemantic.Color); } if ((attributeArray = GetVertexArray(VertexArraySemantic.Normal)) != null) { attributeArray.SetVertexAttribute(ctx, null, VertexArraySemantic.Normal); } if ((attributeArray = GetVertexArray(VertexArraySemantic.TexCoord)) != null) { attributeArray.SetVertexAttribute(ctx, null, VertexArraySemantic.TexCoord); } } }
/// <summary> /// Apply this TransformStateBase. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> which has defined the shader program <paramref name="shaderProgram"/>. /// </param> /// <param name="shaderProgram"> /// The <see cref="ShaderProgram"/> which has the state set. /// </param> public override void Apply(GraphicsContext ctx, ShaderProgram shaderProgram) { GraphicsResource.CheckCurrentContext(ctx); if (shaderProgram == null) { // Fixed pipeline rendering requires server state #if !MONODROID if (ctx.Extensions.DirectStateAccess_EXT) { // Set projection and model-view matrix Gl.MatrixLoadEXT(MatrixMode.Projection, Projection.ToArray()); Gl.MatrixLoadEXT(MatrixMode.Modelview, ModelView.ToArray()); } else { // Set projection matrix Gl.MatrixMode(MatrixMode.Projection); Gl.LoadMatrix(Projection.ToArray()); // Set model-view matrix Gl.MatrixMode(MatrixMode.Modelview); Gl.LoadMatrix(ModelView.ToArray()); } #else throw new NotSupportedException("fixed pipeline not supported"); #endif } else { // Shader implementation (TransformState.glsl) ctx.Bind(shaderProgram); // Usual matrices Debug.Assert(ModelViewProjection != null, "no model-view-projection matrix"); shaderProgram.SetUniform(ctx, "glo_ModelViewProjection", ModelViewProjection); if (shaderProgram.IsActiveUniform("glo_NormalMatrix")) { shaderProgram.SetUniform(ctx, "glo_NormalMatrix", NormalMatrix); } if (Projection != null) { shaderProgram.SetUniform(ctx, "glo_Projection", Projection); } if (shaderProgram.IsActiveUniform("glo_Model")) { shaderProgram.SetUniform(ctx, "glo_Model", Model); } if (shaderProgram.IsActiveUniform("glo_ModelView")) { shaderProgram.SetUniform(ctx, "glo_ModelView", ModelView); } if (shaderProgram.IsActiveUniform("glo_InverseProjection")) { shaderProgram.SetUniform(ctx, "glo_InverseProjection", InverseProjection); } if (shaderProgram.IsActiveUniform("glo_InverseModelView")) { shaderProgram.SetUniform(ctx, "glo_InverseModelView", InverseModelView); } if (shaderProgram.IsActiveUniform("glo_InverseModelViewProjection")) { shaderProgram.SetUniform(ctx, "glo_InverseModelViewProjection", InverseModelViewProjection); } if (Projection != null) { shaderProgram.SetUniform(ctx, "glo_DepthDistances", DepthDistances); } } }
/// <summary> /// Actually create this BufferObject resources. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for allocating resources. /// </param> /// <exception cref="ArgumentNullException"> /// Exception thrown if <paramref name="ctx"/> is null. /// </exception> /// <exception cref="ArgumentException"> /// Exception thrown if <paramref name="ctx"/> is not current on the calling thread. /// </exception> /// <exception cref="InvalidOperationException"> /// Exception thrown if this BufferObject has not client memory allocated and the hint is different from /// <see cref="BufferObjectHint.StaticCpuDraw"/> or <see cref="BufferObjectHint.DynamicCpuDraw"/>. /// </exception> /// <exception cref="InvalidOperationException"> /// Exception thrown if this BufferObject is currently mapped. /// </exception> protected override void CreateObject(GraphicsContext ctx) { CheckCurrentContext(ctx); if ((ClientBufferAddress == IntPtr.Zero) && ((Hint != BufferObjectHint.StaticCpuDraw) && (Hint != BufferObjectHint.DynamicCpuDraw))) { throw new InvalidOperationException("no client buffer"); } // Determine the client buffer size uint clientBufferSize = _ClientBufferSize; if (ClientBufferAddress != IntPtr.Zero) { clientBufferSize = ClientBufferSize; } Debug.Assert(clientBufferSize > 0); // Buffer must be bound ctx.Bind(this, true); if (ctx.Extensions.VertexBufferObject_ARB) { if (IsMapped) { throw new InvalidOperationException("mapped"); } // Define buffer object (type, size and hints) AllocateGpuBuffer(clientBufferSize, null); // Define buffer object contents if (ClientBufferAddress != IntPtr.Zero) { // Provide buffer contents Gl.BufferSubData(BufferType, IntPtr.Zero, _GpuBufferSize, ClientBufferAddress); // Release memory, if it is not required anymore if (_MemoryBufferAutoDispose) { ReleaseClientBuffer(); } } } else { // Discard previous GPU buffer, if any if (_GpuBuffer != null) { _GpuBuffer.Dispose(); } if (ClientBufferAddress == IntPtr.Zero) { // Note: GPU buffer size specified by _ClientBufferSize Debug.Assert(_ClientBufferSize > 0); // Allocate simulated GPU buffer _GpuBuffer = new AlignedMemoryBuffer(_ClientBufferSize, MinimumBufferAlignment); } else { // Let a virtual implementation decide how pass information from the client buffer and the "GPU" buffer UploadClientBuffer(); } // Store GPU buffer size _GpuBufferSize = _GpuBuffer.Size; } // Reset requested client buffer size _ClientBufferSize = 0; }
/// <summary> /// Set the vertex arrays state for the shader program. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> on which the shader program is bound. /// </param> /// <param name="shaderProgram"> /// A <see cref="ShaderProgram"/> on which the vertex arrays shall be bound. /// </param> private void SetVertexArrayState(GraphicsContext ctx, ShaderProgram shaderProgram) { CheckThisExistence(ctx); ctx.Bind(this, true); if (shaderProgram != null) { ICollection <string> activeAttributes = shaderProgram.ActiveAttributes; // Note: when the GL_ARB_vertex_array_object is supported, there's no need to define vertex attributes each time if (ctx.Extensions.VertexArrayObject_ARB && !_VertexArrayDirty) { // CheckVertexAttributes(ctx, shaderProgram); return; } uint attributesSet = 0; // Set vertex array state foreach (string attributeName in activeAttributes) { IVertexArray shaderVertexArray = GetVertexArray(attributeName, shaderProgram); if (shaderVertexArray == null) { continue; } // Set array attribute shaderVertexArray.SetVertexAttribute(ctx, shaderProgram, attributeName); attributesSet++; } if (attributesSet == 0) { throw new InvalidOperationException("no attribute is set"); } _VertexArrayCount = attributesSet; } else { IVertexArray attributeArray; // No shader program: using fixed pipeline program. ATM enable all attributes having a semantic if ((attributeArray = GetVertexArray(VertexArraySemantic.Position)) == null) { throw new InvalidOperationException("no position semantic array defined"); } attributeArray.SetVertexAttribute(ctx, null, VertexArraySemantic.Position); // Optional attributes if ((attributeArray = GetVertexArray(VertexArraySemantic.Color)) != null) { attributeArray.SetVertexAttribute(ctx, null, VertexArraySemantic.Color); } if ((attributeArray = GetVertexArray(VertexArraySemantic.Normal)) != null) { attributeArray.SetVertexAttribute(ctx, null, VertexArraySemantic.Normal); } if ((attributeArray = GetVertexArray(VertexArraySemantic.TexCoord)) != null) { attributeArray.SetVertexAttribute(ctx, null, VertexArraySemantic.TexCoord); } } // Next time do not set inputs if GL_ARB_vertex_array_object is supported _VertexArrayDirty = false; }
/// <summary> /// Apply this TransformState. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> which has defined the shader program <paramref name="shaderProgram"/>. /// </param> /// <param name="shaderProgram"> /// The <see cref="ShaderProgram"/> which has the state set. /// </param> public override void Apply(GraphicsContext ctx, ShaderProgram shaderProgram) { GraphicsResource.CheckCurrentContext(ctx); if (!ctx.Extensions.UniformBufferObject_ARB) { if (shaderProgram == null) { // Fixed pipeline rendering requires server state throw new NotImplementedException(); } else { // Custom implementation ctx.Bind(shaderProgram); if (shaderProgram.IsActiveUniform("glo_LightModel")) { LightModel.ApplyState(ctx, shaderProgram, "glo_LightModel"); } for (int i = 0; i < Lights.Count; i++) { string uniformName = "glo_Light[" + i + "]"; if (shaderProgram.IsActiveUniform(uniformName) == false) { break; } Lights[i].ApplyState(ctx, shaderProgram, uniformName); } shaderProgram.SetUniform(ctx, "glo_LightsCount", LightsCount); } } else { base.Apply(ctx, shaderProgram); // Uniform block } // Dummy shadow map: Texture2D // Note: necessary to avoid undefined behavior on glo_ShadowMap2D samplers string resourceClassId = "OpenGL.Objects.ShadowMap.DummyTexture2d"; Texture2D dummyShadowMap = (Texture2D)ctx.GetSharedResource(resourceClassId); if (dummyShadowMap == null) { dummyShadowMap = new Texture2D(1, 1, PixelLayout.Depth16); dummyShadowMap.SamplerParams.CompareMode = true; dummyShadowMap.SamplerParams.CompareFunc = DepthFunction.Never; dummyShadowMap.Create(ctx); ctx.SetSharedResource(resourceClassId, dummyShadowMap); } // Dummy shadow map: TextureCube // Apply depth maps bool[] tex2dSet = new bool[4]; for (int i = 0; i < tex2dSet.Length; i++) { if (i >= Lights.Count || Lights[i].ShadowMap2D == null) { continue; } int shadowMapIndex = Lights[i].ShadowMapIndex; shaderProgram.SetUniform(ctx, "glo_ShadowMap2D[" + shadowMapIndex + "]", Lights[i].ShadowMap2D); tex2dSet[shadowMapIndex] = true; } // Avoid undefined behavior for (int i = 0; i < tex2dSet.Length; i++) { if (tex2dSet[i] == false) { shaderProgram.SetUniform(ctx, "glo_ShadowMap2D[" + i + "]", dummyShadowMap); } } }
/// <summary> /// Map a range of the GPU buffer allocated by this Buffer. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> required for mapping this Buffer. /// </param> /// <param name="mask"> /// A <see cref="BufferAccessMask"/> that specify the map access. /// </param> /// <exception cref="InvalidOperationException"> /// Exception thrown if this Buffer is already mapped. /// </exception> /// <exception cref="InvalidOperationException"> /// Exception thrown if this Buffer does not exist for <paramref name="ctx"/>. /// </exception> public void Map(GraphicsContext ctx, BufferAccessMask mask, IntPtr offset = default(IntPtr), uint size = 0) { CheckThisExistence(ctx); uint mapSize = size != 0 ? size : Size; if (IsMapRangeSupported(ctx)) { #if !MONODROID if (ctx.Extensions.DirectStateAccess_ARB || ctx.Version.IsCompatible(Gl.Version_450)) { if ((MappedBuffer = Gl.MapNamedBufferRange(ObjectName, offset, mapSize, mask)) == IntPtr.Zero) { Gl.CheckErrors(); } } else { #endif ctx.Bind(this); if ((MappedBuffer = Gl.MapBufferRange(Target, offset, mapSize, mask)) == IntPtr.Zero) { Gl.CheckErrors(); } #if !MONODROID } #endif } else { if (GpuBuffer == null) { throw new GlException(ErrorCode.InvalidOperation); } if (GpuBuffer.AlignedBuffer == IntPtr.Zero) { throw new GlException(ErrorCode.InvalidOperation); } MappedBuffer = new IntPtr(GpuBuffer.AlignedBuffer.ToInt64() + offset.ToInt64()); } // Determine map access if (mask.HasFlag(BufferAccessMask.MapReadBit) && mask.HasFlag(BufferAccessMask.MapWriteBit)) { _Access = BufferAccess.ReadWrite; } else if (mask.HasFlag(BufferAccessMask.MapReadBit)) { _Access = BufferAccess.ReadOnly; } else if (mask.HasFlag(BufferAccessMask.MapWriteBit)) { _Access = BufferAccess.WriteOnly; } else { _Access = 0; } Debug.Assert(MappedBuffer != IntPtr.Zero); MapOffset = offset; MapSize = mapSize; _AccessMask = mask; }
private void VisionControl_Render(object sender, OpenGL.GlControlEventArgs e) { #region Draw Basic Picture // Update image input _Framebuffer.BindDraw(_GraphicsContext); Gl.Viewport(0, 0, (int)_Framebuffer.Width, (int)_Framebuffer.Height); _Framebuffer.Clear(_GraphicsContext, ClearBufferMask.ColorBufferBit); { // Draw a quad Matrix4x4f quadProj = Matrix4x4f.Ortho2D(-1.0f, +1.0f, -1.0f, +1.0f); Matrix4x4f quadModel = new Matrix4x4f(); _Angle += 1.0f; quadModel.RotateZ(10.0f * (float)Math.Cos(Angle.ToRadians(_Angle))); _GraphicsContext.Bind(_ProgramStd); _ProgramStd.SetUniform(_GraphicsContext, "glo_ModelViewProjection", quadProj * quadModel); _ProgramStd.SetUniform(_GraphicsContext, "glo_UniformColor", Vertex4f.One); _ArraysQuad.Draw(_GraphicsContext, _ProgramStd); } _Framebuffer.UnbindDraw(_GraphicsContext); #endregion #region Track Corners // Read back image input pixels using (OpenGL.Objects.Image imageInput = _FramebufferTexture.Get(_GraphicsContext, PixelLayout.RGB24, 0)) { // Copy the input RGB frame from OpenGL to OpenVX Rectangle cv_rgb_image_region = new Rectangle(); cv_rgb_image_region.StartX = 0; cv_rgb_image_region.StartY = 0; cv_rgb_image_region.EndX = imageInput.Width; cv_rgb_image_region.EndY = imageInput.Height; ImagePatchAddressing cv_rgb_image_layout = new ImagePatchAddressing(); cv_rgb_image_layout.StrideX = 3; cv_rgb_image_layout.StrideY = (int)imageInput.Stride; VX.CopyImagePatch(_ImageInput, ref cv_rgb_image_region, 0, ref cv_rgb_image_layout, imageInput.ImageBuffer, Accessor.WriteOnly, MemoryType.Host); } // Now that input RGB image is ready, just run a graph. // Run Harris at the beginning to initialize the previous keypoints, // on other frames run the tracking graph. VX.ProcessGraph(_DetectCorners ? _GraphHarris : _GraphTrack); _DetectCorners = false; #endregion #region Store Markers on GPU // To mark the keypoints in display, you need to access the output // keypoint array and draw each item on the output window using gui.DrawArrow(). UIntPtr num_corners = UIntPtr.Zero; uint num_tracking = 0; _KeypointsPrevious = VX.GetReferenceFromDelay(_KeypointsDelay, -1); _KeypointsCurrent = VX.GetReferenceFromDelay(_KeypointsDelay, 0); VX.Query(_KeypointsPrevious, ArrayAttribute.Numitems, out num_corners); if (num_corners.ToUInt64() > 0) { UIntPtr kp_old_stride = UIntPtr.Zero, kp_new_stride = UIntPtr.Zero; MapId kp_old_map = new MapId(), kp_new_map = new MapId(); IntPtr kp_old_buf, kp_new_buf; VX.MapArrayRange(_KeypointsPrevious, (UIntPtr)0, num_corners, ref kp_old_map, ref kp_old_stride, out kp_old_buf, Accessor.ReadOnly, MemoryType.Host, 0); VX.MapArrayRange(_KeypointsCurrent, (UIntPtr)0, num_corners, ref kp_new_map, ref kp_new_stride, out kp_new_buf, Accessor.ReadOnly, MemoryType.Host, 0); _BufferOpticalMarkers.Map(_GraphicsContext, BufferAccess.WriteOnly); for (uint i = 0; i < num_corners.ToUInt64(); i++) { KeyPoint kp_old = VX.ArrayItem <KeyPoint>(kp_old_buf, i, kp_old_stride); KeyPoint kp_new = VX.ArrayItem <KeyPoint>(kp_new_buf, i, kp_new_stride); if (kp_new.TrackingStatus != 0) { Vertex2f vOld = new Vertex2f(kp_old.X / 1024.0f, kp_old.Y / 1024.0f); Vertex2f vNew = new Vertex2f(kp_new.X / 1024.0f, kp_new.Y / 1024.0f); _BufferOpticalMarkers.SetElement(vOld, (num_tracking * 2) + 0, 0); _BufferOpticalMarkers.SetElement(vNew, (num_tracking * 2) + 1, 0); num_tracking++; } } _BufferOpticalMarkers.Unmap(_GraphicsContext); VX.UnmapArrayRange(_KeypointsPrevious, kp_old_map); VX.UnmapArrayRange(_KeypointsCurrent, kp_new_map); } #endregion Gl.Viewport(0, 0, VisionControl.Width, VisionControl.Height); Gl.ClearColor(1.0f, 0.0f, 0.0f, 0.0f); Gl.Clear(ClearBufferMask.ColorBufferBit); #region Draw Input Image _GraphicsContext.Bind(_ProgramStdTex); _ProgramStdTex.SetUniform(_GraphicsContext, "glo_ModelViewProjection", Matrix4x4f.Ortho2D(0.0f, 1.0f, 0.0f, 1.0f)); _ProgramStdTex.SetUniform(_GraphicsContext, "glo_Texture", _FramebufferTexture); _ArraysPostQuad.Draw(_GraphicsContext, _ProgramStdTex); #endregion #region Draw Markers if (num_tracking > 0) { _GraphicsContext.Bind(_ProgramStd); _ProgramStd.SetUniform(_GraphicsContext, "glo_ModelViewProjection", Matrix4x4f.Ortho2D(0.0f, 1.0f, 0.0f, 1.0f)); _ProgramStd.SetUniform(_GraphicsContext, "glo_UniformColor", new Vertex4f(1.0f, 0.0f, 0.0f, 1.0f)); _ArraysOpticalMarkers.Draw(_GraphicsContext, _ProgramStd, 0, 0, num_tracking * 2); } #endregion // Increase the age of the delay objects to make the current entry become previous entry VX.AgeDelay(_PyramidDelay); VX.AgeDelay(_KeypointsDelay); }
/// <summary> /// Draw a character sequence (base method). /// </summary> /// <param name="ctx"> /// The <see cref="GraphicsContext"/> used for drawing. /// </param> /// <param name="modelview"> /// The <see cref="Matrix4x4"/> the model-view-projection matrix for the first character of <paramref name="s"/>. /// </param> /// <param name="color"> /// The <see cref="ColorRGBAF"/> that specifies the glyph color. /// </param> /// <param name="s"> /// A <see cref="String"/> that specifies the characters for be drawn. /// </param> private void DrawStringCore(GraphicsContext ctx, Matrix4x4 modelview, TextureArray2d texture, ColorRGBAF color, string s) { ModelMatrix charModel = new ModelMatrix(modelview); ctx.Bind(_FontProgram); // Set uniforms _FontProgram.SetUniform(ctx, "glo_UniformColor", color); _FontProgram.SetUniform(ctx, "glo_FontGlyph", texture); // Set instances char[] fontChars = s.ToCharArray(); uint instances = 0; _GlyphInstances.Map(ctx, BufferAccessARB.WriteOnly); try { for (int i = 0; i < fontChars.Length; i++) { Glyph glyph; if (_GlyphMetadata.TryGetValue(fontChars[i], out glyph) == false) { continue; } // Set instance information Matrix4x4f modelViewProjection = new Matrix4x4f( new Vertex4f(charModel.GetColumn(0)), new Vertex4f(charModel.GetColumn(1)), new Vertex4f(charModel.GetColumn(2)), new Vertex4f(charModel.GetColumn(3)) ); Vertex3f glyphVertexParams = new Vertex3f( glyph.GlyphSize.Width, glyph.GlyphSize.Height, glyph.Layer ); Vertex2f glyphTexParams = new Vertex2f( glyph.TexScale.Width, glyph.TexScale.Height ); _GlyphInstances.SetElement(modelViewProjection, instances, 0); _GlyphInstances.SetElement(glyphVertexParams, instances, 1); _GlyphInstances.SetElement(glyphTexParams, instances, 2); // Count the instance instances++; // Move next charModel.Translate(glyph.GlyphSize.Width, 0.0f); } } finally { _GlyphInstances.Unmap(ctx); } // Rasterize it using (State.BlendState stateBlend = State.BlendState.AlphaBlending) { stateBlend.ApplyState(ctx, _FontProgram); _VertexArrays.DrawInstanced(ctx, _FontProgram, instances); } }