private void GetBufferData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount) where T : struct { GL.BindBuffer(BufferTarget.ArrayBuffer, ibo); REngine.CheckGLError(); var elementSizeInByte = Marshal.SizeOf(typeof(T)); IntPtr ptr = GL.MapBuffer(BufferTarget.ArrayBuffer, BufferAccess.ReadOnly); // Pointer to the start of data to read in the index buffer ptr = new IntPtr(ptr.ToInt64() + offsetInBytes); if (typeof(T) == typeof(byte)) { byte[] buffer = data as byte[]; // If data is already a byte[] we can skip the temporary buffer // Copy from the index buffer to the destination array Marshal.Copy(ptr, buffer, 0, buffer.Length); } else { // Temporary buffer to store the copied section of data byte[] buffer = new byte[elementCount * elementSizeInByte]; // Copy from the index buffer to the temporary buffer Marshal.Copy(ptr, buffer, 0, buffer.Length); // Copy from the temporary buffer to the destination array System.Buffer.BlockCopy(buffer, 0, data, startIndex * elementSizeInByte, elementCount * elementSizeInByte); } GL.UnmapBuffer(BufferTarget.ArrayBuffer); REngine.CheckGLError(); }
private void BufferData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, RVertexDataOptions options) where T : struct { GenerateIfRequired(); var elementSizeInByte = Marshal.SizeOf(typeof(T)); var sizeInBytes = elementSizeInByte * elementCount; var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInByte); var bufferSize = IndexCount * (IndexElementSize == RIndexElementSize.SixteenBits ? 2 : 4); GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo); REngine.CheckGLError(); if (options == RVertexDataOptions.Discard) { // By assigning NULL data to the buffer this gives a hint // to the device to discard the previous content. GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)bufferSize, IntPtr.Zero, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); REngine.CheckGLError(); } GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)bufferSize, dataPtr, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); REngine.CheckGLError(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, 0); REngine.CheckGLError(); dataHandle.Free(); }
private void Build(int width, int height, bool mipMap, RSurfaceFormat preferredFormat, RDepthFormat preferredDepthFormat, int preferredMultiSampleCount, bool shared) { var depth = 0; var stencil = 0; BackBuffer = new RTexture2D(); BackBuffer.Create(width, height, RPixelFormat.Rgba, preferredFormat); GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, BackBuffer.Id, 0); if (preferredDepthFormat != RDepthFormat.None) { DepthBuffer = new RTexture2D(); if (preferredDepthFormat == RDepthFormat.Depth24Stencil8 || preferredDepthFormat == RDepthFormat.Depth32Stencil8) { DepthBuffer.CreateDepth(width, height, RPixelFormat.DepthStencil, preferredDepthFormat); GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthStencilAttachment, TextureTarget.Texture2D, DepthBuffer.Id, 0); } else { DepthBuffer.CreateDepth(width, height, RPixelFormat.DepthComponent, preferredDepthFormat); GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.DepthAttachment, TextureTarget.Texture2D, DepthBuffer.Id, 0); } REngine.CheckGLError(); } if (GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferErrorCode.FramebufferComplete) { throw new Exception("Error creating frame buffer: framebuffer is not complete"); } }
internal void PlatformApplyState() { GL.Enable(EnableCap.Blend); GL.BlendFunc(this.ColorSourceBlend.GetBlendFactor(), this.ColorDestinationBlend.GetBlendFactor()); GL.BlendColor( this.BlendFactor.R / 255.0f, this.BlendFactor.G / 255.0f, this.BlendFactor.B / 255.0f, this.BlendFactor.A / 255.0f); REngine.CheckGLError(); GL.BlendEquationSeparate( this.ColorBlendFunction.GetBlendEquationMode(), this.AlphaBlendFunction.GetBlendEquationMode()); REngine.CheckGLError(); GL.BlendFuncSeparate( this.ColorSourceBlend.GetBlendFactorSrc(), this.ColorDestinationBlend.GetBlendFactorDest(), this.AlphaSourceBlend.GetBlendFactorSrc(), this.AlphaDestinationBlend.GetBlendFactorDest()); REngine.CheckGLError(); GL.ColorMask( (this.ColorWriteChannels & RColorWriteChannels.Red) != 0, (this.ColorWriteChannels & RColorWriteChannels.Green) != 0, (this.ColorWriteChannels & RColorWriteChannels.Blue) != 0, (this.ColorWriteChannels & RColorWriteChannels.Alpha) != 0); REngine.CheckGLError(); }
internal void Draw(PrimitiveType primitiveType, Matrix world) { Threading.EnsureUIThread(); GL.FrontFace(FrontFaceDirection.Ccw); GL.CullFace(CullFaceMode.Back); GL.Enable(EnableCap.CullFace); GL.Enable(EnableCap.DepthTest); GL.DepthFunc(DepthFunction.Less); Material.Shader.Bind(); Material.Apply(); VertexBuffer.BindVertexArray(); VertexBuffer.Bind(); IndexBuffer.Bind(); VertexBuffer.VertexDeclaration.Apply(Material.Shader, IntPtr.Zero); REngine.CheckGLError(); Material.Shader.BindSemantics(Matrix.Identity * world, REngine.camera.View, REngine.camera.Projection); REngine.CheckGLError(); GL.DrawElements(primitiveType, IndexBuffer.IndexCount, DrawElementsType.UnsignedInt, IntPtr.Zero); Material.Shader.Unbind(); IndexBuffer.Unbind(); VertexBuffer.Unbind(); VertexBuffer.UnbindVertexArray(); }
private void SetBufferData <T>(int bufferSize, int elementSizeInBytes, int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride, RVertexDataOptions options) where T : struct { GenerateIfRequired(); var sizeInBytes = elementSizeInBytes * elementCount; GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); REngine.CheckGLError(); if (options == RVertexDataOptions.Discard) { // By assigning NULL data to the buffer this gives a hint // to the device to discard the previous content. GL.BufferData(BufferTarget.ArrayBuffer, (IntPtr)bufferSize, IntPtr.Zero, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); REngine.CheckGLError(); } var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInBytes); GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr)offsetInBytes, (IntPtr)sizeInBytes, dataPtr); REngine.CheckGLError(); dataHandle.Free(); }
/// <summary> /// Runs the given action on the UI thread and blocks the current thread while the action is running. /// If the current thread is the UI thread, the action will run immediately. /// </summary> /// <param name="action">The action to be run on the UI thread</param> internal static void BlockOnUIThread(Action action) { if (action == null) { throw new ArgumentNullException("action"); } // If we are already on the UI thread, just call the action and be done with it if (IsOnUIThread()) { action(); return; } lock (BackgroundContext) { // Make the context current on this thread BackgroundContext.MakeCurrent(WindowInfo); // Execute the action action(); // Must flush the GL calls so the texture is ready for the main context to use GL.Flush(); REngine.CheckGLError(); // Must make the context not current on this thread or the next thread will get error 170 from the MakeCurrent call BackgroundContext.MakeCurrent(null); } }
public void Dispose() { GL.DeleteFramebuffer(Id); DepthBuffer.Dispose(); BackBuffer.Dispose(); REngine.CheckGLError(); }
public void Dispose() { Threading.BlockOnUIThread(() => { GL.DeleteBuffers(1, ref ibo); REngine.CheckGLError(); }); }
protected void CreateProperties(TextureTarget target, bool mipmapped = false) { textureTarget = target; SetTextureMagFilter(RTextureMagFilter.Linear); SetTextureMinFilter(mipmapped ? RTextureMinFilter.LinearMipmapLinear : RTextureMinFilter.Linear); SetTextureWrapMode(RTextureWrapMode.Repeat, RTextureWrapMode.Repeat); REngine.CheckGLError(); }
public void SetData(RColor[] colors, RPixelFormat format, int x, int y, int width, int height) { Bind(); GL.TexSubImage2D <RColor>(textureTarget, 0, x, y, width, height, (PixelFormat)format, PixelType.UnsignedByte, colors); REngine.CheckGLError(); Unbind(); REngine.CheckGLError(); }
public void SetTextureMinFilter(RTextureMinFilter value) { if (Id != 0) { GL.TexParameter(textureTarget, TextureParameterName.TextureMinFilter, (int)value); REngine.CheckGLError(); } }
internal void LoadFromDisk(string filename) { if (Path.GetExtension(filename).ToLower() == ".dds") { try { ImageDDS.LoadFromDisk(RFileSystem.Instance.GetFilePath(filename), out Id, out textureTarget, out pixelFormat, out pixelType); }catch (Exception e) { RLog.Error("Error loading texture from: " + filename); RLog.Error(e); } } else { try { ImageGDI.LoadFromDisk(RFileSystem.Instance.GetFilePath(filename), out Id, out textureTarget, out pixelFormat, out pixelType); }catch (Exception e) { RLog.Error("Error loading texture from: " + filename); RLog.Error(e); return; } } if (Id == 0 || textureTarget == 0) { RLog.Error("Error generating OpenGL texture from: " + filename); return; } // load succeeded, Texture can be used. Bind(); int max_level = 0; int min_level = 0; REngine.CheckGLError(); GL.TexParameterI(textureTarget, TextureParameterName.TextureBaseLevel, ref min_level); REngine.CheckGLError(); GL.TexParameterI(textureTarget, TextureParameterName.TextureMaxLevel, ref max_level); REngine.CheckGLError(); GL.TexParameter(textureTarget, TextureParameterName.TextureMagFilter, (int)RTextureMagFilter.Linear); REngine.CheckGLError(); GL.TexParameter(textureTarget, TextureParameterName.TextureMinFilter, (int)RTextureMinFilter.Linear); REngine.CheckGLError(); GL.TexParameter(textureTarget, TextureParameterName.TextureMaxLod, 0); REngine.CheckGLError(); GL.TexParameter(textureTarget, TextureParameterName.TextureMinLod, 0); REngine.CheckGLError(); int height, width; GL.GetTexLevelParameter(textureTarget, 0, GetTextureParameter.TextureHeight, out height); REngine.CheckGLError(); GL.GetTexLevelParameter(textureTarget, 0, GetTextureParameter.TextureWidth, out width); REngine.CheckGLError(); Bounds = new Reactor.Math.Rectangle(0, 0, width, height); RLog.Info("Texture loaded from: " + filename); }
public void CreateDepth(int width, int height, RPixelFormat format, RDepthFormat depthFormat) { GL.GenTextures(1, out Id); textureTarget = TextureTarget.Texture2D; GL.BindTexture(textureTarget, Id); REngine.CheckGLError(); GL.TexImage2D(textureTarget, 0, GetPixelInternalForDepth(depthFormat), width, height, 0, (PixelFormat)format, GetPixelTypeForDepth(depthFormat), IntPtr.Zero); REngine.CheckGLError(); CreateProperties(textureTarget, false); REngine.CheckGLError(); }
public void SetUniformValue(string name, bool value) { if (value) { GL.Uniform1(GetUniformLocation(name), 1); } else { GL.Uniform1(GetUniformLocation(name), 0); } REngine.CheckGLError(); }
public void Dispose() { if (!IsDisposed) { Threading.BlockOnUIThread(() => { GL.DeleteBuffers(1, ref vbo); REngine.CheckGLError(); }); } IsDisposed = true; }
public void UnbindVertexArray() { if (!Threading.IsOnUIThread()) { Threading.BlockOnUIThread(() => { UnbindVertexArray(); }); } else { GL.BindVertexArray(0); REngine.CheckGLError(); } }
public void Bind() { if (Id != 0) { GL.UseProgram(Id); REngine.CheckGLError(); } else { throw new EngineGLException("You must first compile a shader program before you can bind it"); } }
public void Dispose() { try { if (GL.IsShader(Id)) { GL.DeleteShader(Id); REngine.CheckGLError(); } } catch { } }
public void Unbind() { if (Threading.IsOnUIThread()) { GL.BindBuffer(BufferTarget.ArrayBuffer, 0); REngine.CheckGLError(); } else { Threading.BlockOnUIThread(() => { Unbind(); }); } }
private void GetBufferData <T>(int offsetInBytes, T[] data, int startIndex, int elementCount, int vertexStride) where T : struct { GL.BindBuffer(BufferTarget.ArrayBuffer, vbo); REngine.CheckGLError(); var elementSizeInByte = Marshal.SizeOf(typeof(T)); IntPtr ptr = GL.MapBuffer(BufferTarget.ArrayBuffer, BufferAccess.ReadOnly); REngine.CheckGLError(); // Pointer to the start of data to read in the index buffer ptr = new IntPtr(ptr.ToInt64() + offsetInBytes); if (typeof(T) == typeof(byte)) { byte[] buffer = data as byte[]; // If data is already a byte[] we can skip the temporary buffer // Copy from the vertex buffer to the destination array Marshal.Copy(ptr, buffer, 0, buffer.Length); } else { // Temporary buffer to store the copied section of data byte[] buffer = new byte[elementCount * vertexStride - offsetInBytes]; // Copy from the vertex buffer to the temporary buffer Marshal.Copy(ptr, buffer, 0, buffer.Length); var dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned); var dataPtr = (IntPtr)(dataHandle.AddrOfPinnedObject().ToInt64() + startIndex * elementSizeInByte); // Copy from the temporary buffer to the destination array int dataSize = Marshal.SizeOf(typeof(T)); if (dataSize == vertexStride) { Marshal.Copy(buffer, 0, dataPtr, buffer.Length); } else { // If the user is asking for a specific element within the vertex buffer, copy them one by one... for (int i = 0; i < elementCount; i++) { Marshal.Copy(buffer, i * vertexStride, dataPtr, dataSize); dataPtr = (IntPtr)(dataPtr.ToInt64() + dataSize); } } dataHandle.Free(); //Buffer.BlockCopy(buffer, 0, data, startIndex * elementSizeInByte, elementCount * elementSizeInByte); } GL.UnmapBuffer(BufferTarget.ArrayBuffer); REngine.CheckGLError(); }
public void BindVertexArray() { if (!Threading.IsOnUIThread()) { Threading.BlockOnUIThread(() => { BindVertexArray(); }); } else { GenerateIfRequired(); REngine.CheckGLError(); GL.BindVertexArray(vao); REngine.CheckGLError(); } }
public T[] GetData <T>() where T : struct { GL.ActiveTexture(TextureUnit.Texture0); REngine.CheckGLError(); Bind(); REngine.CheckGLError(); T[] pixels = new T[Bounds.Width * Bounds.Height]; GL.GetTexImage <T>(textureTarget, 0, (PixelFormat)pixelFormat, pixelType, pixels); REngine.CheckGLError(); Unbind(); REngine.CheckGLError(); return(pixels); }
public void SetSamplerValue(RTextureLayer layer, RTexture texture) { int unival = GetTexUniformValue(layer); int loc = GetTexUniformLocation(layer); GL.Uniform1(loc, unival); REngine.CheckGLError(); TextureUnit unit = (TextureUnit)(int)layer; GL.ActiveTexture(unit); REngine.CheckGLError(); texture.Bind(); REngine.CheckGLError(); }
internal void Render(ref RShader shader, ref RVertexBuffer vertexBuffer, ref RIndexBuffer indexBuffer, string text, Vector2 location, RColor color, Matrix matrix) { Vector2 pen = location; pen.Y += MeasureString(text).Height; float x = pen.X; List <RVertexData2D> quads = new List <RVertexData2D>(); foreach (char c in text) { if (c == '\r') { continue; } if (c == '\n') { pen.X = x; pen.Y += LineHeight; continue; } if (c == ' ') { pen.X += SpaceWidth; continue; } if (c == '\t') { pen.X += (SpaceWidth * 3); continue; } RFontGlyph glyph = GetGlyphForChar(c); var dest = new Reactor.Math.Rectangle(); dest.X = (int)(pen.X + glyph.Offset.X); dest.Y = (int)pen.Y - ((int)glyph.Offset.Y); dest.Width = glyph.Bounds.Width; dest.Height = glyph.Bounds.Height; vertexBuffer.SetData <RVertexData2D>(AddQuads(dest, glyph.UVBounds)); vertexBuffer.Bind(); vertexBuffer.BindVertexArray(); indexBuffer.Bind(); vertexBuffer.VertexDeclaration.Apply(shader, IntPtr.Zero); GL.DrawElements(PrimitiveType.Triangles, indexBuffer.IndexCount, DrawElementsType.UnsignedShort, IntPtr.Zero); REngine.CheckGLError(); indexBuffer.Unbind(); vertexBuffer.Unbind(); vertexBuffer.UnbindVertexArray(); pen.X += glyph.Advance; } }
public void SetData <T>(T[] data, RPixelFormat format, int x, int y, int width, int height, bool packAlignment = true) where T : struct { if (!packAlignment) { GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); } Bind(); GL.TexSubImage2D <T>(textureTarget, 0, x, y, width, height, (PixelFormat)format, PixelType.UnsignedByte, data); REngine.CheckGLError(); Unbind(); if (!packAlignment) { GL.PixelStore(PixelStoreParameter.PackAlignment, 1); } }
/// <summary> /// If the IBO does not exist, create it. /// </summary> void GenerateIfRequired() { if (ibo == 0) { var sizeInBytes = IndexCount * (this.IndexElementSize == RIndexElementSize.SixteenBits ? 2 : 4); GL.GenBuffers(1, out ibo); REngine.CheckGLError(); GL.BindBuffer(BufferTarget.ElementArrayBuffer, ibo); REngine.CheckGLError(); GL.BufferData(BufferTarget.ElementArrayBuffer, (IntPtr)sizeInBytes, IntPtr.Zero, _isDynamic ? BufferUsageHint.StreamDraw : BufferUsageHint.StaticDraw); REngine.CheckGLError(); } }
public void SetTextureWrapMode(RTextureWrapMode modeS, RTextureWrapMode modeT) { if (Id != 0) { Bind(); try { GL.TexParameter(textureTarget, TextureParameterName.TextureWrapS, (int)modeS); REngine.CheckGLError(); GL.TexParameter(textureTarget, TextureParameterName.TextureWrapT, (int)modeT); REngine.CheckGLError(); }catch (EngineGLException ex) { } } }
public RFrameBuffer(int width, int height, bool mipMap, RSurfaceFormat preferredFormat, RDepthFormat preferredDepthFormat, int preferredMultiSampleCount, bool shared) { Width = width; Height = height; DepthStencilFormat = preferredDepthFormat; SurfaceFormat = preferredFormat; MultiSampleCount = preferredMultiSampleCount; var id = 0; GL.GenFramebuffers(1, out id); REngine.CheckGLError(); Id = id; Bind(); Build(width, height, mipMap, preferredFormat, preferredDepthFormat, preferredMultiSampleCount, shared); Unbind(); }
internal void Apply(RShader shader, IntPtr offset) { RVertexDeclarationAttributeInfo attrInfo; int shaderHash = shader.GetHashCode(); if (!shaderAttributeInfo.TryGetValue(shaderHash, out attrInfo)) { // Get the vertex attribute info and cache it attrInfo = new RVertexDeclarationAttributeInfo(16); foreach (var ve in _elements) { var attributeLocation = shader.GetAttribLocation(ve.VertexElementUsage); if (attributeLocation >= 0) { attrInfo.Elements.Add(new RVertexDeclarationAttributeInfo.Element() { Offset = ve.Offset, AttributeLocation = attributeLocation, NumberOfElements = RVertexElement.OpenGLNumberOfElements(ve.VertexElementFormat), VertexAttribPointerType = RVertexElement.OpenGLVertexAttribPointerType(ve.VertexElementFormat), Normalized = RVertexElement.OpenGLVertexAttribNormalized(ve), }); attrInfo.EnabledAttributes[attributeLocation] = true; } } shaderAttributeInfo.Add(shaderHash, attrInfo); } // Apply the vertex attribute info foreach (var element in attrInfo.Elements) { GL.EnableVertexAttribArray(element.AttributeLocation); REngine.CheckGLError(); GL.VertexAttribPointer(element.AttributeLocation, element.NumberOfElements, element.VertexAttribPointerType, element.Normalized, this.VertexStride, (IntPtr)(offset.ToInt64() + element.Offset)); REngine.CheckGLError(); } //GraphicsDevice.SetVertexAttributeArray(attrInfo.EnabledAttributes); }