public void SetArrayByBlock() { ArrayBufferObjectBase arrayBuffer1 = null, arrayBuffer2 = null, arrayBuffer3 = null; try { arrayBuffer1 = new ArrayBufferObject(VertexBaseType.Float, 3, BufferObjectHint.StaticCpuDraw); arrayBuffer1.Create(16); arrayBuffer2 = new ArrayBufferObjectInterleaved(typeof(ComplexVertexElement), BufferObjectHint.StaticCpuDraw); arrayBuffer2.Create(16); arrayBuffer3 = new ArrayBufferObjectPacked(typeof(ComplexVertexElement), BufferObjectHint.StaticCpuDraw); arrayBuffer3.Create(16); using (VertexArrayObject vertexArray = new VertexArrayObject()) { // Set array buffers to different attributes Assert.DoesNotThrow(delegate() { vertexArray.SetArray(arrayBuffer1, "attribute1", null); }); VertexArrayBufferValues(vertexArray, "attribute1", null, arrayBuffer1, 0); Assert.DoesNotThrow(delegate() { vertexArray.SetArray(arrayBuffer2, "attribute2", null); }); VertexArrayBufferValues(vertexArray, "attribute2", null, arrayBuffer2, 0); Assert.DoesNotThrow(delegate() { vertexArray.SetArray(arrayBuffer2, "attribute3", null); }); VertexArrayBufferValues(vertexArray, "attribute3", null, arrayBuffer2, 0); Assert.DoesNotThrow(delegate() { vertexArray.SetArray(arrayBuffer3, "attribute4", null); }); VertexArrayBufferValues(vertexArray, "attribute4", null, arrayBuffer3, 0); } Assert.IsTrue(arrayBuffer1.IsDisposed); Assert.IsTrue(arrayBuffer2.IsDisposed); Assert.IsTrue(arrayBuffer3.IsDisposed); } finally { if (arrayBuffer1 != null && !arrayBuffer1.IsDisposed) { arrayBuffer1.Dispose(); } if (arrayBuffer2 != null && !arrayBuffer2.IsDisposed) { arrayBuffer2.Dispose(); } if (arrayBuffer3 != null && !arrayBuffer3.IsDisposed) { arrayBuffer3.Dispose(); } } }
/// <summary> /// Allocate an instance of the type. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for allocating the instance. /// </param> /// <returns> /// It returns an instance of a specific type. /// </returns> public override object Allocate(GraphicsContext ctx) { VertexArrayBatchObject vertexArrayObject = new VertexArrayBatchObject(); ArrayBufferObject arrayBufferObject; arrayBufferObject = new ArrayBufferObject(VertexBaseType.Float, 3, BufferObjectHint.StaticCpuDraw); arrayBufferObject.Create(16); vertexArrayObject.SetArray(arrayBufferObject, VertexArraySemantic.Position); arrayBufferObject = new ArrayBufferObject(VertexBaseType.Float, 2, BufferObjectHint.StaticCpuDraw); arrayBufferObject.Create(16); vertexArrayObject.SetArray(arrayBufferObject, VertexArraySemantic.TexCoord); vertexArrayObject.SetElementArray(PrimitiveType.Lines); return(vertexArrayObject); }
public void SetArraySectionByBlock() { ArrayBufferObjectBase arrayBuffer1 = null, arrayBuffer2 = null, arrayBuffer3 = null; try { arrayBuffer1 = new ArrayBufferObject(VertexBaseType.Float, 3, BufferObjectHint.StaticCpuDraw); arrayBuffer1.Create(16); arrayBuffer2 = new ArrayBufferObjectInterleaved(typeof(ComplexVertexElement), BufferObjectHint.StaticCpuDraw); arrayBuffer2.Create(16); arrayBuffer3 = new ArrayBufferObjectPacked(typeof(ComplexVertexElement), BufferObjectHint.StaticCpuDraw); arrayBuffer3.Create(16); using (VertexArrayObject vertexArray = new VertexArrayObject()) { // Set array buffers to different attributes Assert.DoesNotThrow(delegate () { vertexArray.SetArray(arrayBuffer1, 0, "attribute1", null); }); VertexArrayBufferValues(vertexArray, "attribute1", null, arrayBuffer1, 0); Assert.DoesNotThrow(delegate () { vertexArray.SetArray(arrayBuffer2, 0, "attribute2", null); }); VertexArrayBufferValues(vertexArray, "attribute2", null, arrayBuffer2, 0); Assert.DoesNotThrow(delegate () { vertexArray.SetArray(arrayBuffer2, 1, "attribute3", null); }); VertexArrayBufferValues(vertexArray, "attribute3", null, arrayBuffer2, 1); Assert.DoesNotThrow(delegate () { vertexArray.SetArray(arrayBuffer3, 2, "attribute4", null); }); VertexArrayBufferValues(vertexArray, "attribute4", null, arrayBuffer3, 2); } Assert.IsTrue(arrayBuffer1.IsDisposed); Assert.IsTrue(arrayBuffer2.IsDisposed); Assert.IsTrue(arrayBuffer3.IsDisposed); } finally { if (arrayBuffer1 != null && !arrayBuffer1.IsDisposed) arrayBuffer1.Dispose(); if (arrayBuffer2 != null && !arrayBuffer2.IsDisposed) arrayBuffer2.Dispose(); if (arrayBuffer3 != null && !arrayBuffer3.IsDisposed) arrayBuffer3.Dispose(); } }
/// <summary> /// Allocate an instance of the type mocked for spying. /// </summary> /// <param name="ctx"> /// A <see cref="GraphicsContext"/> used for allocating the instance. /// </param> /// <returns> /// It returns an instance of a specific type. /// </returns> public override T AllocateSpy <T>(GraphicsContext ctx) { T arrayBufferObjectSpy = (T)CreateTypeSpy(_InstanceType); VertexArrayBatchObject vertexArrayObject = arrayBufferObjectSpy as VertexArrayBatchObject; if (vertexArrayObject != null) { ArrayBufferObject arrayBufferObject; arrayBufferObject = new ArrayBufferObject(VertexBaseType.Float, 3, BufferObjectHint.StaticCpuDraw); arrayBufferObject.Create(16); vertexArrayObject.SetArray(arrayBufferObject, VertexArraySemantic.Position); arrayBufferObject = new ArrayBufferObject(VertexBaseType.Float, 2, BufferObjectHint.StaticCpuDraw); arrayBufferObject.Create(16); vertexArrayObject.SetArray(arrayBufferObject, VertexArraySemantic.TexCoord); vertexArrayObject.SetElementArray(PrimitiveType.Lines); } return(arrayBufferObjectSpy); }
/// <summary> /// Automatically computes bounding box for the specified vertex arrays. /// </summary> /// <param name="vertexArrayObject"> /// /// </param> /// <returns> /// It returns the <see cref="IBoundingVolume"/> for <paramref name="vertexArrayObject"/>, if possible. /// </returns> private static IBoundingVolume ComputeBoundingVolume(VertexArrayObject vertexArrayObject) { if (vertexArrayObject == null) { throw new ArgumentNullException("vertexArrayObject"); } VertexArrayObject.IVertexArray vertexArray = vertexArrayObject.GetVertexArray(VertexArraySemantic.Position); if (vertexArray == null) { return(null); } ArrayBufferObjectBase positionArray = vertexArray.Array; Type positionArrayType = positionArray.GetType(); if (positionArrayType == typeof(ArrayBufferObject <Vertex4f>)) { ArrayBufferObject <Vertex4f> positionArray4f = (ArrayBufferObject <Vertex4f>)positionArray; Vertex4f min = Vertex4f.Maximum, max = Vertex4f.Minimum; positionArray4f.MinMax(out min, out max); return(new BoundingBox((Vertex3f)min, (Vertex3f)max)); } else if (positionArrayType == typeof(ArrayBufferObject <Vertex3f>)) { ArrayBufferObject <Vertex3f> positionArray3f = (ArrayBufferObject <Vertex3f>)positionArray; Vertex3f min = Vertex3f.Maximum, max = Vertex3f.Minimum; positionArray3f.MinMax(out min, out max); return(new BoundingBox(min, max)); } else { return(null); } }
/// <summary> /// Test <see cref="ArrayBufferObject.ToArray()"/>. /// </summary> /// <param name="vertexBaseType"></param> /// <param name="vertexLength"></param> /// <param name="array"></param> public void TestToArrayCtx_Core(VertexBaseType vertexBaseType, uint vertexLength, Array array) { using (ArrayBufferObject arrayBuffer = new ArrayBufferObject(vertexBaseType, vertexLength, BufferObjectHint.StaticCpuDraw)) { // Without creation, ToArray(GraphicsContext) will throw an exception Assert.Throws <InvalidOperationException>(delegate() { arrayBuffer.ToArray(_Context); }); // Create client buffer arrayBuffer.Create(array); // ToArray() must be equal to array CollectionAssert.AreEqual(array, arrayBuffer.ToArray()); // Without creation, ToArray(GraphicsContext) will throw an exception Assert.Throws <InvalidOperationException>(delegate() { arrayBuffer.ToArray(_Context); }); // Create GPU buffer arrayBuffer.Create(_Context); // ToArray() must be equal to array CollectionAssert.AreEqual(array, arrayBuffer.ToArray(_Context)); // Create a reversed array from test array Array arrayReverse = Array.CreateInstance(array.GetType().GetElementType(), array.Length); Array.Copy(array, arrayReverse, array.Length); Array.Reverse(arrayReverse); CollectionAssert.AreEquivalent(array, arrayReverse); // Update client buffer arrayBuffer.Create(arrayReverse); // Client buffer is updated, but not the GPU buffer CollectionAssert.AreEqual(arrayReverse, arrayBuffer.ToArray()); CollectionAssert.AreNotEqual(arrayReverse, arrayBuffer.ToArray(_Context)); // Update GPU buffer arrayBuffer.Create(_Context); CollectionAssert.AreEqual(arrayReverse, arrayBuffer.ToArray(_Context)); } }
/// <summary> /// Create a <see cref="VertexArrayObject"/> for rendering glyphs. /// </summary> private void LinkSharedResources(GraphicsContext ctx) { CheckCurrentContext(ctx); string resourceClassId = "OpenGL.Objects.FontPatch"; string resourceBaseId = String.Format("{0}.{1}-{2}-{3}", resourceClassId, Family, Size, Style); string vertexArrayId = resourceBaseId + ".VertexArray"; string glyphDbId = resourceBaseId + ".GlyphDb"; #region Vertex Arrays _VertexArrays = (VertexArrayObject)ctx.GetSharedResource(vertexArrayId); Dictionary <char, Glyph> glyphsDb = null; if (_VertexArrays == null) { _VertexArrays = new VertexArrayObject(); List <GlyphPolygons> glyphPolygons = GenerateGlyphs(Family, Size, Style); List <Vertex2f> glyphsVertices = new List <Vertex2f>(); GlyphPolygons gGlyph = null; uint gVertexIndex = 0; glyphsDb = new Dictionary <char, Glyph>(); using (Tessellator tessellator = new Tessellator()) { tessellator.Begin += delegate(object sender, TessellatorBeginEventArgs e) { gVertexIndex = (uint)glyphsVertices.Count; }; tessellator.End += delegate(object sender, EventArgs e) { // Create element (range) int glyphIndex = _VertexArrays.SetElementArray(PrimitiveType.Triangles, gVertexIndex, (uint)glyphsVertices.Count - gVertexIndex); glyphsDb.Add(gGlyph.GlyphChar, new Glyph(gGlyph.GlyphChar, gGlyph.GlyphSize, glyphIndex)); }; tessellator.Vertex += delegate(object sender, TessellatorVertexEventArgs e) { glyphsVertices.Add((Vertex2f)e.Vertex); }; // Tessellate all glyphs foreach (GlyphPolygons glyph in glyphPolygons) { gGlyph = glyph; if (glyph.Contours.Count == 0) { glyphsDb.Add(gGlyph.GlyphChar, new Glyph(gGlyph.GlyphChar, gGlyph.GlyphSize, -1)); continue; } tessellator.BeginPolygon(); foreach (List <Vertex2f> countour in glyph.Contours) { tessellator.AddContour(countour.ToArray(), Vertex3f.UnitZ); } tessellator.EndPolygon(); } } // Element vertices ArrayBufferObject <Vertex2f> gVertexPosition = new ArrayBufferObject <Vertex2f>(BufferObjectHint.StaticCpuDraw); gVertexPosition.Create(glyphsVertices.ToArray()); _VertexArrays.SetArray(gVertexPosition, VertexArraySemantic.Position); // Share ctx.SetSharedResource(vertexArrayId, _VertexArrays); } LinkResource(_VertexArrays); #endregion #region Glyph Metadata _Glyphs = (Dictionary <char, Glyph>)ctx.GetSharedResource(glyphDbId); if (glyphsDb != null) { _Glyphs = glyphsDb; } if (_Glyphs == null) { throw new InvalidProgramException("no glyph metadata"); } // Share ctx.SetSharedResource(glyphDbId, _Glyphs); #endregion }
private SceneObjectGeometry CreateCubeGeometry() { SceneObjectGeometry cubeGeometry = new SceneObjectGeometry("Cube"); #region State cubeGeometry.ObjectState.DefineState(new DepthTestState(DepthFunction.Less)); cubeGeometry.ObjectState.DefineState(new CullFaceState(FrontFaceDirection.Ccw, CullFaceMode.Back)); cubeGeometry.ObjectState.DefineState(new TransformState()); MaterialState cubeMaterialState = new MaterialState(); cubeMaterialState.FrontMaterial = new MaterialState.Material(ColorRGBAF.ColorWhite * 0.5f); cubeMaterialState.FrontMaterial.Ambient = ColorRGBAF.ColorBlack; cubeMaterialState.FrontMaterial.Diffuse = ColorRGBAF.ColorWhite * 0.5f; cubeMaterialState.FrontMaterial.Specular = ColorRGBAF.ColorWhite * 0.5f; cubeMaterialState.FrontMaterial.Shininess = 10.0f; cubeGeometry.ObjectState.DefineState(cubeMaterialState); #endregion #region Vertex Arrays if (_CubeArrayPosition == null) { _CubeArrayPosition = new ArrayBufferObject <Vertex3f>(BufferObjectHint.StaticCpuDraw); _CubeArrayPosition.Create(ArrayPosition); } if (_CubeArrayColor == null) { _CubeArrayColor = new ArrayBufferObject <ColorRGBF>(BufferObjectHint.StaticCpuDraw); _CubeArrayColor.Create(ArrayColors); } if (_CubeArrayNormal == null) { _CubeArrayNormal = new ArrayBufferObject <Vertex3f>(BufferObjectHint.StaticCpuDraw); _CubeArrayNormal.Create(ArrayNormals); } if (_CubeArrays == null) { _CubeArrays = new VertexArrayObject(); _CubeArrays.SetArray(_CubeArrayPosition, VertexArraySemantic.Position); _CubeArrays.SetArray(_CubeArrayColor, VertexArraySemantic.Color); _CubeArrays.SetArray(_CubeArrayNormal, VertexArraySemantic.Normal); _CubeArrays.SetElementArray(PrimitiveType.Triangles); } cubeGeometry.VertexArray = _CubeArrays; #endregion #region Program cubeGeometry.BoundingVolume = new BoundingBox(-Vertex3f.One * _CubeSize, Vertex3f.One * _CubeSize); #endregion return(cubeGeometry); }
public void TestLineShaderRender() { using (ShaderProgram shaderProgram = ShadersLibrary.Instance.CreateProgram("OpenGL.Line")) { Assert.DoesNotThrow(delegate () { shaderProgram.Create(_Context); }); using (VertexArrayObject vao = new VertexArrayObject()) { List<Vertex2f> vertices = new List<Vertex2f>(); for (float y = 0.375f; y < _Framebuffer.Height; y += 2.0f) { vertices.Add(new Vertex2f(0.0f, y)); vertices.Add(new Vertex2f(_Framebuffer.Width, y)); } // Setup ABO (Position) ArrayBufferObject abo = new ArrayBufferObject(VertexBaseType.Float, 2, BufferObjectHint.StaticCpuDraw); abo.Create(vertices.ToArray()); // Setup VAO vao.SetArray(abo, VertexArraySemantic.Position); vao.SetElementArray(PrimitiveType.Lines); vao.Create(_Context); // Draw test Image feedbackImageFixed = null, feedbackImageShader = null; try { Gl.Viewport(0, 0, (int)_Framebuffer.Width, (int)_Framebuffer.Height); #region Fixed pipeline _Framebuffer.SetClearColor(new ColorRGBAF(0.0f, 0.0f, 0.0f)); _Framebuffer.Clear(_Context); Gl.MatrixMode(MatrixMode.Projection); Gl.LoadMatrix(new OrthoProjectionMatrix(0.0f, _Framebuffer.Width, 0.0f, _Framebuffer.Height).ToArray()); Gl.MatrixMode(MatrixMode.Modelview); Gl.LoadIdentity(); Gl.Color3(1.0f, 1.0f, 1.0f); Gl.LineWidth(1.0f); vao.Draw(_Context); feedbackImageFixed = _Framebuffer.ReadColorBuffer(_Context, 0, 0, 0, _Framebuffer.Width, _Framebuffer.Height, PixelLayout.GRAY8); ImageCodec.Instance.Save( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "LineProgram.Fixed.png"), feedbackImageFixed, ImageFormat.Png, null ); #endregion #region Shader pipeline _Framebuffer.SetClearColor(new ColorRGBAF(0.0f, 0.0f, 0.0f)); _Framebuffer.Clear(_Context); shaderProgram.Bind(_Context); shaderProgram.SetUniform(_Context, "hal_ModelViewProjection", RenderProjectionMatrix); shaderProgram.SetUniform(_Context, "hal_UniformColor", new ColorRGBA(1.0f, 1.0f, 1.0f)); shaderProgram.SetUniform(_Context, "hal_LineWidth", 1.0f); shaderProgram.SetUniform(_Context, "hal_ViewportSize", new Vertex2f(_Framebuffer.Width, _Framebuffer.Height)); vao.Draw(_Context, shaderProgram); feedbackImageShader = _Framebuffer.ReadColorBuffer(_Context, 0, 0, 0, _Framebuffer.Width, _Framebuffer.Height, PixelLayout.GRAY8); ImageCodec.Instance.Save( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "LineProgram.Shader.png"), feedbackImageShader, ImageFormat.Png, null ); #endregion // Compare results } finally { if (feedbackImageFixed != null) feedbackImageFixed.Dispose(); if (feedbackImageShader != null) feedbackImageShader.Dispose(); } } //// Get rendering feedback //using (Image feedbackImage = _Framebuffer.ReadColorBuffer(_Context, 0, 0, 0, _Framebuffer.Width, _Framebuffer.Height, PixelLayout.GRAY8)) { // // Drawn only even lines // for (uint y = 0; y < _Framebuffer.Height; y++) { // for (uint x = 0; x < _Framebuffer.Width; x++) { // ColorGRAY8 fragment = (ColorGRAY8)feedbackImage[x, y]; // Assert.AreEqual((y % 2) == 0 ? 255 : 0, fragment.Level, String.Format("Color mismatch at {0}x{1}", x, y)); // } // } //} } }
public VertexArrayObject CreateArrays(ObjContext objContext) { if (objContext == null) { throw new ArgumentNullException("objContext"); } VertexArrayObject vertexArray = new VertexArrayObject(); List <ObjFaceCoord> coords = new List <ObjFaceCoord>(); bool hasTexCoord = Material.DiffuseTexture != null; bool hasNormals = true; bool hasTanCoord = hasTexCoord && Material.NormalTexture != null; foreach (ObjFace f in Faces) { hasTexCoord |= f.HasTexCoord; hasNormals |= f.HasNormal; coords.AddRange(f.Triangulate()); } uint vertexCount = (uint)coords.Count; Vertex4f[] position = new Vertex4f[vertexCount]; Vertex3f[] normal = hasNormals ? new Vertex3f[vertexCount] : null; Vertex2f[] texcoord = new Vertex2f[vertexCount]; for (int i = 0; i < position.Length; i++) { Debug.Assert(coords[i].VertexIndex < objContext.Vertices.Count); position[i] = objContext.Vertices[coords[i].VertexIndex]; if (hasTexCoord) { Debug.Assert(coords[i].TexCoordIndex < objContext.TextureCoords.Count); texcoord[i] = objContext.TextureCoords[coords[i].TexCoordIndex]; } if (hasNormals) { Debug.Assert(coords[i].NormalIndex < objContext.Normals.Count); normal[i] = objContext.Normals[coords[i].NormalIndex]; } } // Position (mandatory) ArrayBufferObject <Vertex4f> positionBuffer = new ArrayBufferObject <Vertex4f>(BufferObjectHint.StaticCpuDraw); positionBuffer.Create(position); vertexArray.SetArray(positionBuffer, VertexArraySemantic.Position); // Layout (triangles) vertexArray.SetElementArray(PrimitiveType.Triangles); // Texture if (hasTexCoord) { ArrayBufferObject <Vertex2f> texCoordBuffer = new ArrayBufferObject <Vertex2f>(BufferObjectHint.StaticCpuDraw); texCoordBuffer.Create(texcoord); vertexArray.SetArray(texCoordBuffer, VertexArraySemantic.TexCoord); } // Normals if (hasNormals) { ArrayBufferObject <Vertex3f> normalBuffer = new ArrayBufferObject <Vertex3f>(BufferObjectHint.StaticCpuDraw); normalBuffer.Create(normal); vertexArray.SetArray(normalBuffer, VertexArraySemantic.Normal); } else { ArrayBufferObject <Vertex3f> normalBuffer = new ArrayBufferObject <Vertex3f>(BufferObjectHint.StaticCpuDraw); normalBuffer.Create(vertexCount); vertexArray.SetArray(normalBuffer, VertexArraySemantic.Normal); vertexArray.GenerateNormals(); } // Tangents if (hasTanCoord) { ArrayBufferObject <Vertex3f> tanCoordBuffer = new ArrayBufferObject <Vertex3f>(BufferObjectHint.StaticCpuDraw); tanCoordBuffer.Create(vertexCount); vertexArray.SetArray(tanCoordBuffer, VertexArraySemantic.Tangent); ArrayBufferObject <Vertex3f> bitanCoordBuffer = new ArrayBufferObject <Vertex3f>(BufferObjectHint.StaticCpuDraw); bitanCoordBuffer.Create(vertexCount); vertexArray.SetArray(bitanCoordBuffer, VertexArraySemantic.Bitangent); vertexArray.GenerateTangents(); } return(vertexArray); }
public void SetArrayByBlock_Exception2() { using (VertexArrayObject vertexArray = new VertexArrayObject()) { using (ArrayBufferObject arrayBuffer = new ArrayBufferObject(VertexBaseType.Float, 3, BufferObjectHint.StaticCpuDraw)) { // arrayBuffer is empty Assert.Throws(Is.InstanceOf(typeof(ArgumentException)), delegate () { vertexArray.SetArray(arrayBuffer, "attributeName", null); }); } } }
/// <summary> /// Create a <see cref="VertexArrayObject"/> for rendering glyphs. /// </summary> /// <param name="fontFamily"></param> /// <param name="emSize"></param> /// <param name="glyphs"></param> /// <returns></returns> private static VertexArrayObject CreateVertexArray(GraphicsContext ctx, FontFamily fontFamily, uint emSize, FontStyle fontStyle, out Dictionary <char, Glyph> glyphs) { CheckCurrentContext(ctx); string resourceBaseId = String.Format("OpenGL.Objects.FontPatch.{0}-{1}-{2}", fontFamily, emSize, fontStyle); string vertexArrayId = resourceBaseId + ".VertexArray"; string glyphDbId = resourceBaseId + ".GlyphDb"; VertexArrayObject vertexArrays = (VertexArrayObject)ctx.GetSharedResource(vertexArrayId); Dictionary <char, Glyph> glyphsDb = (Dictionary <char, Glyph>)ctx.GetSharedResource(glyphDbId); if (vertexArrays != null && glyphsDb != null) { glyphs = glyphsDb; return(vertexArrays); } vertexArrays = new VertexArrayObject(); glyphsDb = new Dictionary <char, Glyph>(); List <GlyphPolygons> glyphPolygons = GenerateGlyphs(fontFamily, emSize, fontStyle); List <Vertex2f> glyphsVertices = new List <Vertex2f>(); GlyphPolygons gGlyph = null; uint gVertexIndex = 0; glyphs = new Dictionary <char, Glyph>(); using (Tessellator tessellator = new Tessellator()) { tessellator.Begin += delegate(object sender, TessellatorBeginEventArgs e) { gVertexIndex = (uint)glyphsVertices.Count; }; tessellator.End += delegate(object sender, EventArgs e) { // Create element (range) int glyphIndex = vertexArrays.SetElementArray(PrimitiveType.Triangles, gVertexIndex, (uint)glyphsVertices.Count - gVertexIndex); glyphsDb.Add(gGlyph.GlyphChar, new Glyph(gGlyph.GlyphChar, gGlyph.GlyphSize, glyphIndex)); }; tessellator.Vertex += delegate(object sender, TessellatorVertexEventArgs e) { glyphsVertices.Add((Vertex2f)e.Vertex); }; // Tessellate all glyphs foreach (GlyphPolygons glyph in glyphPolygons) { gGlyph = glyph; if (glyph.Contours.Count == 0) { glyphsDb.Add(gGlyph.GlyphChar, new Glyph(gGlyph.GlyphChar, gGlyph.GlyphSize, -1)); continue; } tessellator.BeginPolygon(); foreach (List <Vertex2f> countour in glyph.Contours) { tessellator.AddContour(countour.ToArray(), Vertex3f.UnitZ); } tessellator.EndPolygon(); } } // Element vertices ArrayBufferObject <Vertex2f> gVertexPosition = new ArrayBufferObject <Vertex2f>(BufferObjectHint.StaticCpuDraw); gVertexPosition.Create(glyphsVertices.ToArray()); vertexArrays.SetArray(gVertexPosition, VertexArraySemantic.Position); // Returns glyphs database glyphs = glyphsDb; // Share resources ctx.SetSharedResource(vertexArrayId, vertexArrays); ctx.SetSharedResource(glyphDbId, glyphsDb); return(vertexArrays); }
/// <summary> /// /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <param name="dx"></param> /// <param name="dy"></param> /// <returns></returns> public static VertexArrayObject CreatePlane(float x, float y, float z, uint dx, uint dy) { VertexArrayObject vertexArray = new VertexArrayObject(); // Vertex generation Vertex3f[] position = new Vertex3f[(dx + 1) * (dy + 1)]; float x2 = x / 2.0f, y2 = y / 2.0f; float vdx = x / dx, vdy = y / dy; int vidx = 0; for (float vy = -y2; vy <= y2; vy += vdy) { for (float vx = -x2; vx <= x2; vx += vdx) { Debug.Assert(vidx < position.Length); position[vidx++] = new Vertex3f(vx, vy, z); } } // Elements generation List <uint> indices = new List <uint>(); uint vstride = dx + 1; for (uint i = 0; i < dy; i++) { uint yoffset = i * vstride; // Triangle strip start indices.Add(yoffset + vstride); for (uint ix = 0; ix < dx; ix++) { uint xoffset = yoffset + ix; indices.Add(xoffset); indices.Add(xoffset + vstride + 1); } indices.Add(yoffset + vstride - 1); if (Gl.CurrentExtensions.PrimitiveRestart == false) { throw new NotImplementedException(); } else { indices.Add(uint.MaxValue); } } // Buffer definition ArrayBufferObject <Vertex3f> positionBuffer = new ArrayBufferObject <Vertex3f>(BufferObjectHint.StaticCpuDraw); positionBuffer.Create(position); vertexArray.SetArray(positionBuffer, VertexArraySemantic.Position); ElementBufferObject <uint> elementBuffer = new ElementBufferObject <uint>(BufferObjectHint.StaticCpuDraw); elementBuffer.Create(indices.ToArray()); elementBuffer.RestartIndexEnabled = Gl.CurrentExtensions.PrimitiveRestart; vertexArray.SetElementArray(PrimitiveType.TriangleStrip, elementBuffer); return(vertexArray); }
/// <summary> /// Create a <see cref="VertexArrayObject"/> for rendering glyphs. /// </summary> /// <param name="fontFamily"></param> /// <param name="emSize"></param> /// <param name="glyphs"></param> /// <returns></returns> private void LinkSharedResources(GraphicsContext ctx) { CheckCurrentContext(ctx); // Font-wide resources string resourceClassId = "OpenGL.Objects.FontTextureArray2d"; string instanceArrayId = resourceClassId + ".InstanceArray"; string vertexArrayId = resourceClassId + ".VertexArray"; _GlyphInstances = (ArrayBufferObjectInterleaved <GlyphInstance>)ctx.GetSharedResource(instanceArrayId); _VertexArrays = (VertexArrayObject)ctx.GetSharedResource(vertexArrayId); if (_GlyphInstances == null) { _GlyphInstances = new ArrayBufferObjectInterleaved <GlyphInstance>(BufferObjectHint.DynamicCpuDraw); _GlyphInstances.Create(256); // Share ctx.SetSharedResource(instanceArrayId, _GlyphInstances); } LinkResource(_GlyphInstances); if (_VertexArrays == null) { _VertexArrays = new VertexArrayObject(); ArrayBufferObject <Vertex2f> arrayPosition = new ArrayBufferObject <Vertex2f>(BufferObjectHint.StaticCpuDraw); arrayPosition.Create(new Vertex2f[] { new Vertex2f(0.0f, 1.0f), new Vertex2f(0.0f, 0.0f), new Vertex2f(1.0f, 1.0f), new Vertex2f(1.0f, 0.0f), }); _VertexArrays.SetArray(arrayPosition, VertexArraySemantic.Position); _VertexArrays.SetInstancedArray(_GlyphInstances, 0, 1, "glo_GlyphModelViewProjection"); _VertexArrays.SetInstancedArray(_GlyphInstances, 1, 1, "glo_GlyphVertexParams"); _VertexArrays.SetInstancedArray(_GlyphInstances, 2, 1, "glo_GlyphTexParams"); _VertexArrays.SetElementArray(PrimitiveType.TriangleStrip); // Share ctx.SetSharedResource(vertexArrayId, _VertexArrays); } LinkResource(_VertexArrays); // Font resources string resourceBaseId = String.Format("{0}.{1}-{2}-{3}", resourceClassId, Family, Size, Style); string glyphDbId = resourceBaseId + ".GlyphDb"; string textureId = resourceBaseId + ".Texture"; _GlyphDb = (Dictionary <char, Glyph>)ctx.GetSharedResource(glyphDbId); _FontTexture = (TextureArray2d)ctx.GetSharedResource(textureId); StringFormat stringFormat = StringFormat.GenericTypographic; if (_GlyphDb == null) { _GlyphDb = new Dictionary <char, Glyph>(); char[] fontChars = GetFontCharacters().ToCharArray(); uint layer = 0; using (Bitmap bitmap = new Bitmap(1, 1)) using (Graphics g = Graphics.FromImage(bitmap)) using (System.Drawing.Font font = new System.Drawing.Font(Family, Size, Style)) { // Avoid grid fitting g.TextRenderingHint = TextRenderingHint.AntiAlias; float glyphHeight = font.GetHeight(); foreach (char c in fontChars) { SizeF glyphSize; switch (c) { case ' ': glyphSize = g.MeasureString(c.ToString(), font, 0, StringFormat.GenericDefault); break; default: glyphSize = g.MeasureString(c.ToString(), font, 0, stringFormat); break; } Glyph glyph = new Glyph(c, glyphSize, layer++, new SizeF(1.0f, 1.0f)); _GlyphDb.Add(c, glyph); } } // Share ctx.SetSharedResource(glyphDbId, _GlyphDb); } if (_FontTexture == null) { // Get the size required for all glyphs float w = 0.0f, h = 0.0f; uint z = 0; foreach (Glyph glyph in _GlyphDb.Values) { w = Math.Max(w, glyph.GlyphSize.Width); h = Math.Max(h, glyph.GlyphSize.Height); z = Math.Max(z, glyph.Layer); } // Create texture _FontTexture = new TextureArray2d((uint)Math.Ceiling(w), (uint)Math.Ceiling(h), z + 1, PixelLayout.R8); _FontTexture.Create(ctx); using (System.Drawing.Font font = new System.Drawing.Font(Family, Size, Style)) using (Brush brush = new SolidBrush(Color.White)) { foreach (Glyph glyph in _GlyphDb.Values) { using (Bitmap bitmap = new Bitmap((int)_FontTexture.Width, (int)_FontTexture.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb)) using (Graphics g = Graphics.FromImage(bitmap)) { // Recompute texture scaling glyph.TexScale = new SizeF( glyph.GlyphSize.Width / bitmap.Width, glyph.GlyphSize.Height / bitmap.Height ); // Avoid grid fitting g.TextRenderingHint = TextRenderingHint.AntiAlias; g.Clear(Color.Black); g.DrawString(glyph.GlyphChar.ToString(), font, brush, 0.0f, 0.0f, stringFormat); _FontTexture.Create(ctx, PixelLayout.R8, bitmap, glyph.Layer); } } } // Share ctx.SetSharedResource(textureId, _FontTexture); } LinkResource(_FontTexture); }
public void Draw() { Vertex2f[] vertices = new Vertex2f[] { new Vertex2f(0.0f, 0.0f), new Vertex2f(1.0f, 0.0f), new Vertex2f(1.0f, 1.0f), new Vertex2f(0.0f, 1.0f), }; using (VertexArrayObject vao = new VertexArrayObject()) { // Setup ABO (Position) ArrayBufferObject abo = new ArrayBufferObject(VertexBaseType.Float, 2, BufferObjectHint.StaticCpuDraw); abo.Create(vertices); // Setup VAO vao.SetArray(abo, VertexArraySemantic.Position); vao.SetElementArray(PrimitiveType.TriangleStrip); vao.Create(_Context); using (State.GraphicsStateSet currentState = State.GraphicsStateSet.GetDefaultSet()) { // Set transform state State.TransformStateBase stateTransform = (State.TransformStateBase)currentState[State.TransformStateBase.StateId]; // Set normalized orthogonal projection stateTransform.LocalProjection = new OrthoProjectionMatrix(0.0f, 1.0f, 0.0f, 1.0f); // Apply state currentState.Apply(_Context); // Draw Assert.DoesNotThrow(delegate () { vao.Draw(_Context); }); } } }
public void SetArraySectionBySemantic_Exception2() { using (VertexArrayObject vertexArray = new VertexArrayObject()) { using (ArrayBufferObject arrayBuffer = new ArrayBufferObject(VertexBaseType.Float, 3, BufferObjectHint.StaticCpuDraw)) { // arrayBuffer is empty Assert.Throws(Is.InstanceOf(typeof(ArgumentException)), delegate () { vertexArray.SetArray(arrayBuffer, 1, VertexArraySemantic.Position); }); } } }
public void TestLineShaderRender() { using (ShaderProgram shaderProgram = ShadersLibrary.Instance.CreateProgram("OpenGL.Line")) { Assert.DoesNotThrow(delegate() { shaderProgram.Create(_Context); }); using (VertexArrayObject vao = new VertexArrayObject()) { List <Vertex2f> vertices = new List <Vertex2f>(); for (float y = 0.375f; y < _Framebuffer.Height; y += 2.0f) { vertices.Add(new Vertex2f(0.0f, y)); vertices.Add(new Vertex2f(_Framebuffer.Width, y)); } // Setup ABO (Position) ArrayBufferObject abo = new ArrayBufferObject(VertexBaseType.Float, 2, BufferObjectHint.StaticCpuDraw); abo.Create(vertices.ToArray()); // Setup VAO vao.SetArray(abo, VertexArraySemantic.Position); vao.SetElementArray(PrimitiveType.Lines); vao.Create(_Context); // Draw test Image feedbackImageFixed = null, feedbackImageShader = null; try { Gl.Viewport(0, 0, (int)_Framebuffer.Width, (int)_Framebuffer.Height); #region Fixed pipeline _Framebuffer.SetClearColor(new ColorRGBAF(0.0f, 0.0f, 0.0f)); _Framebuffer.Clear(_Context); Gl.MatrixMode(MatrixMode.Projection); Gl.LoadMatrix(new OrthoProjectionMatrix(0.0f, _Framebuffer.Width, 0.0f, _Framebuffer.Height).ToArray()); Gl.MatrixMode(MatrixMode.Modelview); Gl.LoadIdentity(); Gl.Color3(1.0f, 1.0f, 1.0f); Gl.LineWidth(1.0f); vao.Draw(_Context); feedbackImageFixed = _Framebuffer.ReadColorBuffer(_Context, 0, 0, 0, _Framebuffer.Width, _Framebuffer.Height, PixelLayout.R8); ImageCodec.Instance.Save( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "LineProgram.Fixed.png"), feedbackImageFixed, ImageFormat.Png, null ); #endregion #region Shader pipeline _Framebuffer.SetClearColor(new ColorRGBAF(0.0f, 0.0f, 0.0f)); _Framebuffer.Clear(_Context); _Context.Bind(shaderProgram); shaderProgram.SetUniform(_Context, "hal_ModelViewProjection", RenderProjectionMatrix); shaderProgram.SetUniform(_Context, "hal_UniformColor", new ColorRGBA(1.0f, 1.0f, 1.0f)); shaderProgram.SetUniform(_Context, "hal_LineWidth", 1.0f); shaderProgram.SetUniform(_Context, "hal_ViewportSize", new Vertex2f(_Framebuffer.Width, _Framebuffer.Height)); vao.Draw(_Context, shaderProgram); feedbackImageShader = _Framebuffer.ReadColorBuffer(_Context, 0, 0, 0, _Framebuffer.Width, _Framebuffer.Height, PixelLayout.R8); ImageCodec.Instance.Save( Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "LineProgram.Shader.png"), feedbackImageShader, ImageFormat.Png, null ); #endregion // Compare results } finally { if (feedbackImageFixed != null) { feedbackImageFixed.Dispose(); } if (feedbackImageShader != null) { feedbackImageShader.Dispose(); } } } //// Get rendering feedback //using (Image feedbackImage = _Framebuffer.ReadColorBuffer(_Context, 0, 0, 0, _Framebuffer.Width, _Framebuffer.Height, PixelLayout.GRAY8)) { // // Drawn only even lines // for (uint y = 0; y < _Framebuffer.Height; y++) { // for (uint x = 0; x < _Framebuffer.Width; x++) { // ColorGRAY8 fragment = (ColorGRAY8)feedbackImage[x, y]; // Assert.AreEqual((y % 2) == 0 ? 255 : 0, fragment.Level, String.Format("Color mismatch at {0}x{1}", x, y)); // } // } //} } }
public void SetArraySectionByBlock_Exception3() { using (VertexArrayObject vertexArray = new VertexArrayObject()) { using (ArrayBufferObject arrayBuffer = new ArrayBufferObject(VertexBaseType.Float, 3, BufferObjectHint.StaticCpuDraw)) { // Create the array buffer arrayBuffer.Create(16); // sectionIndex is out of range Assert.Throws(Is.InstanceOf(typeof(ArgumentOutOfRangeException)), delegate () { vertexArray.SetArray(arrayBuffer, 1, "attributeName", null); }); } } }