private void FramebufferRenderbuffer(BindFramebufferTarget target, uint attachmentPoint, uint renderbufferTarget, uint renderbufferName)
        {
            if (!Enum.IsDefined(typeof(BindFramebufferTarget), target))
            {
                SetLastError(ErrorCode.InvalidEnum); return;
            }
            if (renderbufferTarget != GL.GL_RENDERBUFFER)
            {
                SetLastError(ErrorCode.InvalidEnum); return;
            }
            // TODO: GL_INVALID_OPERATION is generated if zero is bound to target.
            Dictionary <uint, Renderbuffer> dict = this.nameRenderbufferDict;

            if ((renderbufferName != 0) && (!dict.ContainsKey(renderbufferName)))
            {
                SetLastError(ErrorCode.InvalidOperation); return;
            }

            Renderbuffer renderbuffer = null;

            if (renderbufferName != 0)
            {
                if (!dict.TryGetValue(renderbufferName, out renderbuffer))
                {
                    SetLastError(ErrorCode.InvalidOperation); return;
                }
            }

            Framebuffer framebuffer = this.currentFramebuffer;

            if (framebuffer == null)
            {
                return;
            }
            if (framebuffer.Target != target)
            {
                // TODO: what should I do? Or should multiple current framebufer object exist?
            }

            if (attachmentPoint == GL.GL_DEPTH_ATTACHMENT)
            {
                framebuffer.DepthbufferAttachment = renderbuffer;
            }
            else if (attachmentPoint == GL.GL_STENCIL_ATTACHMENT)
            {
                framebuffer.StencilbufferAttachment = renderbuffer;
            }
            else if (attachmentPoint == GL.GL_DEPTH_STENCIL_ATTACHMENT)
            {
                framebuffer.DepthbufferAttachment   = renderbuffer;
                framebuffer.StencilbufferAttachment = renderbuffer;
            }
            else // color attachment points.
            {
                if (attachmentPoint < GL.GL_COLOR_ATTACHMENT0)
                {
                    SetLastError(ErrorCode.InvalidOperation); return;
                }
                uint index = attachmentPoint - GL.GL_COLOR_ATTACHMENT0;
                if (framebuffer.ColorbufferAttachments.Length <= index)
                {
                    SetLastError(ErrorCode.InvalidOperation); return;
                }

                framebuffer.ColorbufferAttachments[index] = renderbuffer;
            }
        }
Example #2
0
        private void DrawElements(DrawTarget mode, int count, DrawElementsType type, IntPtr indices)
        {
            if (!Enum.IsDefined(typeof(DrawTarget), mode) || !Enum.IsDefined(typeof(DrawElementsType), type))
            {
                SetLastError(ErrorCode.InvalidEnum); return;
            }
            if (count < 0)
            {
                SetLastError(ErrorCode.InvalidValue); return;
            }
            // TODO: GL_INVALID_OPERATION is generated if a geometry shader is active and mode​ is incompatible with the input primitive type of the geometry shader in the currently installed program object.
            // TODO: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to an enabled array or the element array and the buffer object's data store is currently mapped.

            VertexArrayObject vao = this.currentVertexArrayObject; // data structure.

            if (vao == null)
            {
                return;
            }
            ShaderProgram program = this.currentShaderProgram; // algorithm.

            if (program == null)
            {
                return;
            }
            GLBuffer indexBuffer = this.currentBufferDict[BindBufferTarget.ElementArrayBuffer];

            if (indexBuffer == null)
            {
                return;
            }

            // execute vertex shader for each vertex!
            // This is a low effetient implementation.
            // passBuffers is input for the next stage: linear interpolation.
            // passBuffers[0] is gl_Position.
            // passBuffers[others] are attributes of vertexes.
            PassBuffer[] passBuffers = VertexShaderStage(count, type, indices, vao, program, indexBuffer);
            if (passBuffers == null)
            {
                return;
            }                                    // this stage failed.

            Framebuffer framebuffer = this.currentFramebuffer;

            if (framebuffer == null)
            {
                throw new Exception("This should not happen!");
            }

            ClipSpace2NormalDeviceSpace(passBuffers[0]);
            // linear interpolation.
            List <Fragment> fragmentList = LinearInterpolation(mode, count, type, indices, vao, program, indexBuffer, passBuffers);

            // execute fargment shader for each fragment!
            // This is a low effetient implementation.
            FragmentShaderStage(program, fragmentList);
            {
                int index = 0;
                while (index < fragmentList.Count)
                {
                    if (fragmentList[index].discard)
                    {
                        fragmentList.RemoveAt(index);
                    }
                    else
                    {
                        index++;
                    }
                }
            }
            // Scissor test

            // Multisampel fragment operations

            // Stencil test

            // Depth test
            DepthTest(fragmentList);

            //Blending

            // Dithering

            // Logical operations

            // write fragments to framebuffer's colorbuffer attachment(s).
            {
                uint[] drawBufferIndexes = framebuffer.DrawBuffers.ToArray();
                foreach (var fragment in fragmentList)
                {
                    if (fragment.depthTestFailed)
                    {
                        continue;
                    }

                    for (int i = 0; i < fragment.outVariables.Length && i < drawBufferIndexes.Length; i++)
                    {
                        PassBuffer  outVar     = fragment.outVariables[i];
                        IAttachable attachment = framebuffer.ColorbufferAttachments[drawBufferIndexes[i].ToIndex()];
                        attachment.Set((int)fragment.gl_FragCoord.x, (int)fragment.gl_FragCoord.y, outVar);
                    }
                }
            }
        }