private unsafe List <Fragment> LinearInterpolationTriangleStripAdjacency(int count, DrawElementsType type, IntPtr indices, VertexArrayObject vao, ShaderProgram program, GLBuffer indexBuffer, PassBuffer[] passBuffers) { var result = new List <Fragment>(); var gl_PositionArray = (vec4 *)passBuffers[0].Mapbuffer().ToPointer(); var pointers = new void *[passBuffers.Length - 1]; for (int i = 0; i < pointers.Length; i++) { pointers[i] = passBuffers[i + 1].Mapbuffer().ToPointer(); } byte[] indexData = indexBuffer.Data; int indexLength = indexData.Length / ByteLength(type); GCHandle pin = GCHandle.Alloc(indexData, GCHandleType.Pinned); IntPtr pointer = pin.AddrOfPinnedObject(); var groupList = new List <LinearInterpolationInfoGroup>(); ivec4 viewport = this.viewport; // ivec4(x, y, width, height) for (int indexID = indices.ToInt32() / ByteLength(type), c = 0; c < count - 5 && indexID < indexLength - 5; indexID += 2, c += 2) { var group = new LinearInterpolationInfoGroup(6); for (int i = 0; i < 6; i++) { uint gl_VertexID = GetVertexID(pointer, type, indexID + i); vec4 gl_Position = gl_PositionArray[gl_VertexID]; vec3 fragCoord = new vec3((gl_Position.x + 1) / 2.0f * viewport.z + viewport.x, (gl_Position.y + 1) / 2.0f * viewport.w + viewport.y, (gl_Position.z + 1) / 2.0f * (float)(this.depthRangeFar - this.depthRangeNear) + (float)this.depthRangeNear); group.array[i] = new LinearInterpolationInfo(gl_VertexID, fragCoord); } if (groupList.Contains(group)) { continue; } // discard the same line. else { groupList.Add(group); } vec3 fragCoord0 = group.array[0].fragCoord; vec3 fragCoord1 = group.array[2].fragCoord; vec3 fragCoord2 = group.array[4].fragCoord; FindFragmentsInTriangle(fragCoord0, fragCoord1, fragCoord2, pointers, group, passBuffers, result); } for (int i = 0; i < passBuffers.Length; i++) { passBuffers[i].Unmapbuffer(); } return(result); }
private void VertexAttribPointer(uint index, int size, VertexAttribType type, bool normalized, int stride, IntPtr pointer) { // TODO: GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS. if (size != 1 && size != 2 && size != 3 && size != 4 && size != GL.GL_BGRA) { SetLastError(ErrorCode.InvalidValue); return; } if (!Enum.IsDefined(typeof(VertexAttribType), type)) { SetLastError(ErrorCode.InvalidEnum); return; } if (stride < 0) { SetLastError(ErrorCode.InvalidValue); return; } if (size == GL.GL_BGRA) { if (type != VertexAttribType.UnsignedByte && type != VertexAttribType.Int2101010Rev && type != VertexAttribType.UnsignedInt2101010Rev) { SetLastError(ErrorCode.InvalidOperation); return; } if (normalized == false) { SetLastError(ErrorCode.InvalidOperation); return; } } if (type == VertexAttribType.Int2101010Rev || type == VertexAttribType.UnsignedInt2101010Rev) { if (size != 4 && size != GL.GL_BGRA) { SetLastError(ErrorCode.InvalidOperation); return; } } if (type == VertexAttribType.UnsignedInt10f11f11fRev) { if (size != 3) { SetLastError(ErrorCode.InvalidOperation); return; } } VertexArrayObject vao = this.currentVertexArrayObject; if (vao == null) { SetLastError(ErrorCode.InvalidOperation); return; } GLBuffer buffer = this.currentBufferDict[BindBufferTarget.ArrayBuffer]; // GL_INVALID_OPERATION is generated if zero is bound to the GL_ARRAY_BUFFER buffer object binding point and the pointer argument is not NULL. // TODO: why only when "pointer argument is not NULL"? if (buffer == null) { SetLastError(ErrorCode.InvalidOperation); return; } VertexAttribDesc desc = null; if (!vao.LocVertexAttribDict.TryGetValue(index, out desc)) { desc = new VertexAttribDesc(); vao.LocVertexAttribDict.Add(index, desc); } desc.inLocation = index; desc.vbo = buffer; desc.dataSize = size; desc.dataType = (uint)type; desc.normalize = normalized; desc.startPos = (uint)pointer.ToInt32(); desc.stride = (uint)stride; }
private unsafe List <Fragment> LinearInterpolationPoints(int count, DrawElementsType type, IntPtr indices, VertexArrayObject vao, ShaderProgram program, GLBuffer indexBuffer, PassBuffer[] passBuffers) { var result = new List <Fragment>(); int attributeCount = passBuffers.Length - 1; var gl_PositionArray = (vec4 *)passBuffers[0].Mapbuffer().ToPointer(); var pointers = new void *[passBuffers.Length - 1]; for (int i = 0; i < pointers.Length; i++) { pointers[i] = passBuffers[i + 1].Mapbuffer().ToPointer(); } byte[] indexData = indexBuffer.Data; int indexLength = indexData.Length / ByteLength(type); GCHandle pin = GCHandle.Alloc(indexData, GCHandleType.Pinned); IntPtr pointer = pin.AddrOfPinnedObject(); var gl_VertexIDList = new List <uint>(); ivec4 viewport = this.viewport; for (int indexID = indices.ToInt32() / ByteLength(type), c = 0; c < count && indexID < indexLength; indexID++, c++) { uint gl_VertexID = GetVertexID(pointer, type, indexID); if (gl_VertexIDList.Contains(gl_VertexID)) { continue; } else { gl_VertexIDList.Add(gl_VertexID); } vec3 fragCoord = new vec3((gl_PositionArray[gl_VertexID].x + 1) / 2.0f * viewport.z + viewport.x, (gl_PositionArray[gl_VertexID].y + 1) / 2.0f * viewport.w + viewport.y, (gl_PositionArray[gl_VertexID].z + 1) / 2.0f * (float)(this.depthRangeFar - this.depthRangeNear) + (float)this.depthRangeNear); var fragment = new Fragment(fragCoord, attributeCount); for (int i = 0; i < attributeCount; i++) // new pass-buffer objects. { PassType passType = passBuffers[i].elementType; fragment.attributes[i] = new PassBuffer(passType, 1); // only one element. } for (int attrIndex = 0; attrIndex < attributeCount; attrIndex++) // fill data in pass-buffer. { PassBuffer attribute = fragment.attributes[attrIndex]; void * fragmentAttribute = attribute.Mapbuffer().ToPointer(); switch (attribute.elementType) { case PassType.Float: { var fAttr = (float *)fragmentAttribute; var array = (float *)pointers[attrIndex]; fAttr[0] = array[gl_VertexID]; } break; case PassType.Vec2: { var fAttr = (vec2 *)fragmentAttribute; var array = (vec2 *)pointers[attrIndex]; fAttr[0] = array[gl_VertexID]; } break; case PassType.Vec3: { var fAttr = (vec3 *)fragmentAttribute; var array = (vec3 *)pointers[attrIndex]; fAttr[0] = array[gl_VertexID]; } break; case PassType.Vec4: { var fAttr = (vec4 *)fragmentAttribute; var array = (vec4 *)pointers[attrIndex]; fAttr[0] = array[gl_VertexID]; } break; case PassType.Mat2: { var fAttr = (mat2 *)fragmentAttribute; var array = (mat2 *)pointers[attrIndex]; fAttr[0] = array[gl_VertexID]; } break; case PassType.Mat3: { var fAttr = (mat3 *)fragmentAttribute; var array = (mat3 *)pointers[attrIndex]; fAttr[0] = array[gl_VertexID]; } break; case PassType.Mat4: { var fAttr = (mat4 *)fragmentAttribute; var array = (mat4 *)pointers[attrIndex]; fAttr[0] = array[gl_VertexID]; } break; default: throw new NotDealWithNewEnumItemException(typeof(PassType)); } attribute.Unmapbuffer(); } result.Add(fragment); } for (int i = 0; i < passBuffers.Length; i++) { passBuffers[i].Unmapbuffer(); } return(result); }
private List <Fragment> LinearInterpolationPatches(int count, DrawElementsType type, IntPtr indices, VertexArrayObject vao, ShaderProgram program, GLBuffer indexBuffer, PassBuffer[] passBuffers) { var result = new List <Fragment>(); FragmentShader fs = program.FragmentShader; if (fs == null) { return(result); } return(result); }
private List <Fragment> LinearInterpolation(DrawTarget mode, int count, DrawElementsType type, IntPtr indices, VertexArrayObject vao, ShaderProgram program, GLBuffer indexBuffer, PassBuffer[] passBuffers) { List <Fragment> result = null; switch (mode) { case DrawTarget.Points: result = LinearInterpolationPoints(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.Lines: result = LinearInterpolationLines(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.LineLoop: result = LinearInterpolationLineLoop(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.LineStrip: result = LinearInterpolationLineStrip(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.Triangles: result = LinearInterpolationTriangles(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.TriangleStrip: result = LinearInterpolationTriangleStrip(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.TriangleFan: result = LinearInterpolationTriangleFan(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.Quads: result = LinearInterpolationQuads(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.QuadStrip: result = LinearInterpolationQuadStrip(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.Polygon: result = LinearInterpolationPolygon(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.LinesAdjacency: result = LinearInterpolationLinesAdjacency(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.LineStripAdjacency: result = LinearInterpolationLineStripAdjacency(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.TrianglesAdjacency: result = LinearInterpolationTrianglesAdjacency(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.TriangleStripAdjacency: result = LinearInterpolationTriangleStripAdjacency(count, type, indices, vao, program, indexBuffer, passBuffers); break; case DrawTarget.Patches: result = LinearInterpolationPatches(count, type, indices, vao, program, indexBuffer, passBuffers); break; default: throw new NotDealWithNewEnumItemException(typeof(DrawTarget)); } return(result); }
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); } } } }