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; } }
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); } } } }