Example #1
0
        public void LoadSubData(IntPtr offset, IntPtr data, int size)
        {
            if (size < 0)
            {
                throw new ArgumentException("Size cannot be less than zero.");
            }
            if (this.bufferSize == 0)
            {
                throw new InvalidOperationException(string.Format(
                                                        "Cannot update {0}, because its storage was not initialized yet.",
                                                        typeof(NativeGraphicsBuffer).Name));
            }
            if ((uint)offset + size > this.bufferSize)
            {
                throw new ArgumentException(string.Format(
                                                "Cannot update {0} with offset {1} and size {2}, as this exceeds the internal " +
                                                "storage size {3}.",
                                                typeof(NativeGraphicsBuffer).Name,
                                                offset,
                                                size,
                                                this.bufferSize));
            }

            NativeGraphicsBuffer prevBound = GetBound(this.type);

            Bind(this.type, this);

            BufferTarget target = ToOpenTKBufferType(this.type);

            GL.BufferSubData(target, offset, size, data);

            Bind(this.type, prevBound);
        }
Example #2
0
        void IDualityBackend.Shutdown()
        {
            if (activeInstance == this)
            {
                activeInstance = null;
            }

            if (DualityApp.ExecContext != DualityApp.ExecutionContext.Terminated)
            {
                DefaultOpenTKBackendPlugin.GuardSingleThreadState();
                if (this.sharedBatchIBO != null)
                {
                    this.sharedBatchIBO.Dispose();
                    this.sharedBatchIBO = null;
                }
            }

            // Since the window outlives the graphics backend in the usual launcher setup,
            // we'll need to unhook early, so Duality can complete its cleanup before the window does.
            if (this.activeWindow != null)
            {
                this.activeWindow.UnhookFromDuality();
                this.activeWindow = null;
            }
        }
Example #3
0
        public static void Bind(GraphicsBufferType type, NativeGraphicsBuffer buffer)
        {
            if (GetBound(type) == buffer)
            {
                return;
            }
            SetBound(type, buffer);

            BufferTarget target = ToOpenTKBufferType(type);

            GL.BindBuffer(target, buffer != null ? buffer.Handle : 0);
        }
Example #4
0
 private static void SetBound(GraphicsBufferType type, NativeGraphicsBuffer buffer)
 {
     if (type == GraphicsBufferType.Vertex)
     {
         boundVertex = buffer;
     }
     else if (type == GraphicsBufferType.Index)
     {
         boundIndex = buffer;
     }
     else
     {
         return;
     }
 }
Example #5
0
        public void SetupEmpty(int size)
        {
            if (size < 0)
            {
                throw new ArgumentException("Size cannot be less than zero.");
            }

            NativeGraphicsBuffer prevBound = GetBound(this.type);

            Bind(this.type, this);

            BufferTarget target = ToOpenTKBufferType(this.type);

            GL.BufferData(target, size, IntPtr.Zero, BufferUsageHint.StreamDraw);

            this.bufferSize = size;

            Bind(this.type, prevBound);
        }
Example #6
0
        /// <summary>
        /// Draws the vertices of a single <see cref="DrawBatch"/>, after all other rendering state
        /// has been set up accordingly outside this method.
        /// </summary>
        /// <param name="buffer"></param>
        /// <param name="ranges"></param>
        /// <param name="mode"></param>
        private void DrawVertexBatch(VertexBuffer buffer, RawList <VertexDrawRange> ranges, VertexMode mode)
        {
            NativeGraphicsBuffer indexBuffer = (buffer.IndexCount > 0 ? buffer.NativeIndex : null) as NativeGraphicsBuffer;
            IndexDataElementType indexType   = buffer.IndexType;

            // Since the QUADS primitive is deprecated in OpenGL 3.0 and not available in OpenGL ES,
            // we'll emulate this with an ad-hoc index buffer object that we generate here.
            if (mode == VertexMode.Quads)
            {
                if (indexBuffer != null)
                {
                    Logs.Core.WriteWarning(
                        "Rendering {0} instances that use index buffers is not supported for quads geometry. " +
                        "To use index buffers, use any other geometry type listed in {1}. Skipping batch.",
                        typeof(DrawBatch).Name,
                        typeof(VertexMode).Name);
                    return;
                }

                NativeGraphicsBuffer.Bind(GraphicsBufferType.Index, this.sharedBatchIBO);

                this.GenerateQuadIndices(ranges, this.sharedBatchIndices);
                this.sharedBatchIBO.LoadData(
                    this.sharedBatchIndices.Data,
                    0,
                    this.sharedBatchIndices.Count);

                GL.DrawElements(
                    PrimitiveType.Triangles,
                    this.sharedBatchIndices.Count,
                    DrawElementsType.UnsignedShort,
                    IntPtr.Zero);

                this.sharedBatchIndices.Clear();
            }
            // Otherwise, run the regular rendering path
            else
            {
                // Rendering using index buffer
                if (indexBuffer != null)
                {
                    if (ranges != null && ranges.Count > 0)
                    {
                        Logs.Core.WriteWarning(
                            "Rendering {0} instances that use index buffers do not support specifying vertex ranges, " +
                            "since the two features are mutually exclusive.",
                            typeof(DrawBatch).Name,
                            typeof(VertexMode).Name);
                    }

                    NativeGraphicsBuffer.Bind(GraphicsBufferType.Index, indexBuffer);

                    PrimitiveType    openTkMode      = GetOpenTKVertexMode(mode);
                    DrawElementsType openTkIndexType = GetOpenTKIndexType(indexType);
                    GL.DrawElements(
                        openTkMode,
                        buffer.IndexCount,
                        openTkIndexType,
                        IntPtr.Zero);
                }
                // Rendering using an array of vertex ranges
                else
                {
                    NativeGraphicsBuffer.Bind(GraphicsBufferType.Index, null);

                    PrimitiveType     openTkMode = GetOpenTKVertexMode(mode);
                    VertexDrawRange[] rangeData  = ranges.Data;
                    int rangeCount = ranges.Count;
                    for (int r = 0; r < rangeCount; r++)
                    {
                        GL.DrawArrays(
                            openTkMode,
                            rangeData[r].Index,
                            rangeData[r].Count);
                    }
                }
            }
        }
Example #7
0
        void IGraphicsBackend.Render(IReadOnlyList <DrawBatch> batches)
        {
            if (batches.Count == 0)
            {
                return;
            }

            this.RetrieveActiveShaders(batches);
            this.SetupSharedParameters(this.renderOptions.ShaderParameters);

            int       drawCalls    = 0;
            DrawBatch lastRendered = null;

            for (int i = 0; i < batches.Count; i++)
            {
                DrawBatch         batch      = batches[i];
                VertexDeclaration vertexType = batch.VertexBuffer.VertexType;

                // Bind the vertex buffer we'll use. Note that this needs to be done
                // before setting up any vertex format state.
                NativeGraphicsBuffer vertexBuffer = batch.VertexBuffer.NativeVertex as NativeGraphicsBuffer;
                NativeGraphicsBuffer.Bind(GraphicsBufferType.Vertex, vertexBuffer);

                bool first        = (i == 0);
                bool sameMaterial =
                    lastRendered != null &&
                    lastRendered.Material.Equals(batch.Material);

                // Setup vertex bindings. Note that the setup differs based on the
                // materials shader, so material changes can be vertex binding changes.
                if (lastRendered != null)
                {
                    this.FinishVertexFormat(lastRendered.Material, lastRendered.VertexBuffer.VertexType);
                }
                this.SetupVertexFormat(batch.Material, vertexType);

                // Setup material when changed.
                if (!sameMaterial)
                {
                    this.SetupMaterial(
                        batch.Material,
                        lastRendered != null ? lastRendered.Material : null);
                }

                // Draw the current batch
                this.DrawVertexBatch(
                    batch.VertexBuffer,
                    batch.VertexRanges,
                    batch.VertexMode);

                drawCalls++;
                lastRendered = batch;
            }

            // Cleanup after rendering
            NativeGraphicsBuffer.Bind(GraphicsBufferType.Vertex, null);
            NativeGraphicsBuffer.Bind(GraphicsBufferType.Index, null);
            if (lastRendered != null)
            {
                this.FinishMaterial(lastRendered.Material);
                this.FinishVertexFormat(lastRendered.Material, lastRendered.VertexBuffer.VertexType);
            }

            if (this.renderStats != null)
            {
                this.renderStats.DrawCalls += drawCalls;
            }

            this.FinishSharedParameters();
        }
Example #8
0
        void IGraphicsBackend.BeginRendering(IDrawDevice device, RenderOptions options, RenderStats stats)
        {
            DebugCheckOpenGLErrors();
            this.CheckRenderingCapabilities();

            this.currentDevice = device;
            this.renderOptions = options;
            this.renderStats   = stats;

            // Prepare a shared index buffer object, in case we don't have one yet
            if (this.sharedBatchIBO == null)
            {
                this.sharedBatchIBO = new NativeGraphicsBuffer(GraphicsBufferType.Index);
            }

            // Prepare the target surface for rendering
            NativeRenderTarget.Bind(options.Target as NativeRenderTarget);

            // Determine whether masked blending should use alpha-to-coverage mode
            if (this.msaaIsDriverDisabled)
            {
                this.useAlphaToCoverageBlend = false;
            }
            else if (NativeRenderTarget.BoundRT != null)
            {
                this.useAlphaToCoverageBlend = NativeRenderTarget.BoundRT.Samples > 0;
            }
            else if (this.activeWindow != null)
            {
                this.useAlphaToCoverageBlend = this.activeWindow.IsMultisampled;
            }
            else
            {
                this.useAlphaToCoverageBlend = this.defaultGraphicsMode.Samples > 0;
            }

            // Determine the available size on the active rendering surface
            Point2 availableSize;

            if (NativeRenderTarget.BoundRT != null)
            {
                availableSize = new Point2(NativeRenderTarget.BoundRT.Width, NativeRenderTarget.BoundRT.Height);
            }
            else if (this.activeWindow != null)
            {
                availableSize = new Point2(this.activeWindow.Width, this.activeWindow.Height);
            }
            else
            {
                availableSize = this.externalBackbufferSize;
            }

            // Translate viewport coordinates to OpenGL screen coordinates (borrom-left, rising), unless rendering
            // to a texture, which is laid out Duality-like (top-left, descending)
            Rect openGLViewport = options.Viewport;

            if (NativeRenderTarget.BoundRT == null)
            {
                openGLViewport.Y = (availableSize.Y - openGLViewport.H) - openGLViewport.Y;
            }

            // Setup viewport and scissor rects
            GL.Viewport((int)openGLViewport.X, (int)openGLViewport.Y, (int)MathF.Ceiling(openGLViewport.W), (int)MathF.Ceiling(openGLViewport.H));
            GL.Scissor((int)openGLViewport.X, (int)openGLViewport.Y, (int)MathF.Ceiling(openGLViewport.W), (int)MathF.Ceiling(openGLViewport.H));

            // Clear buffers
            ClearBufferMask glClearMask = 0;
            ColorRgba       clearColor  = options.ClearColor;

            if ((options.ClearFlags & ClearFlag.Color) != ClearFlag.None)
            {
                glClearMask |= ClearBufferMask.ColorBufferBit;
            }
            if ((options.ClearFlags & ClearFlag.Depth) != ClearFlag.None)
            {
                glClearMask |= ClearBufferMask.DepthBufferBit;
            }
            GL.ClearColor(clearColor.R / 255.0f, clearColor.G / 255.0f, clearColor.B / 255.0f, clearColor.A / 255.0f);
            GL.ClearDepth((double)options.ClearDepth);             // The "float version" is from OpenGL 4.1..
            GL.Clear(glClearMask);

            // Configure Rendering params
            GL.Enable(EnableCap.ScissorTest);
            GL.Enable(EnableCap.DepthTest);
            if (options.DepthTest)
            {
                GL.DepthFunc(DepthFunction.Lequal);
            }
            else
            {
                GL.DepthFunc(DepthFunction.Always);
            }

            // Prepare shared matrix stack for rendering
            Matrix4 viewMatrix       = options.ViewMatrix;
            Matrix4 projectionMatrix = options.ProjectionMatrix;

            if (NativeRenderTarget.BoundRT != null)
            {
                Matrix4 flipOutput = Matrix4.CreateScale(1.0f, -1.0f, 1.0f);
                projectionMatrix = projectionMatrix * flipOutput;
            }

            this.renderOptions.ShaderParameters.Set(
                BuiltinShaderFields.ViewMatrix,
                viewMatrix);
            this.renderOptions.ShaderParameters.Set(
                BuiltinShaderFields.ProjectionMatrix,
                projectionMatrix);
            this.renderOptions.ShaderParameters.Set(
                BuiltinShaderFields.ViewProjectionMatrix,
                viewMatrix * projectionMatrix);
        }