/// <summary> /// Vertex' attribute buffer's pointer. /// </summary> /// <param name="varNameInVertexShader">此顶点属性VBO对应于vertex shader中的哪个in变量?<para>Mapping variable's name in vertex shader.</para></param> /// <param name="bufferId">用glGenBuffers()得到的VBO的Id。<para>Id got from glGenBuffers();</para></param> /// <param name="config">This <paramref name="config"/> decides parameters' values in glVertexAttribPointer(attributeLocation, size, type, false, 0, IntPtr.Zero); /// </param> /// <param name="length">此VBO含有多个个元素?<para>How many elements?</para></param> /// <param name="byteLength">此VBO中的数据在内存中占用多少个字节?<para>How many bytes in this buffer?</para></param> /// <param name="instancedDivisor">0: not instanced. 1: instanced divisor is 1.</param> /// <param name="patchVertexes">How many vertexes makes a patch? No patch if <paramref name="patchVertexes"/> is 0.</param> internal VertexAttributeBufferPtr(string varNameInVertexShader, uint bufferId, VertexAttributeConfig config, int length, int byteLength, uint instancedDivisor = 0, int patchVertexes = 0) : base(bufferId, length, byteLength) { if (glVertexAttribPointer == null) { glVertexAttribPointer = OpenGL.GetDelegateFor <OpenGL.glVertexAttribPointer>(); glEnableVertexAttribArray = OpenGL.GetDelegateFor <OpenGL.glEnableVertexAttribArray>(); glVertexAttribDivisor = OpenGL.GetDelegateFor <OpenGL.glVertexAttribDivisor>(); glPatchParameteri = OpenGL.GetDelegateFor <OpenGL.glPatchParameteri>(); glPatchParameterfv = OpenGL.GetDelegateFor <OpenGL.glPatchParameterfv>(); } this.VarNameInVertexShader = varNameInVertexShader; this.Config = config; this.InstancedDivisor = instancedDivisor; this.PatchVertexes = patchVertexes; }
/// <summary> /// 在使用<see cref="VertexArrayObject"/>后,此方法只会执行一次。 /// This method will only be invoked once when using <see cref="VertexArrayObject"/>. /// </summary> /// <param name="shaderProgram"></param> public void Standby(ShaderProgram shaderProgram) { int location = shaderProgram.GetAttributeLocation(this.VarNameInVertexShader); if (location < 0) { throw new ArgumentException(); } uint loc = (uint)location; VBOConfigDetail detail = this.Config.Parse(); int patchVertexes = this.PatchVertexes; uint divisor = this.InstancedDivisor; // 选中此VBO // select this VBO. if (glBindBuffer == null) { glBindBuffer = OpenGL.GetDelegateFor <OpenGL.glBindBuffer>(); } glBindBuffer(OpenGL.GL_ARRAY_BUFFER, this.BufferId); for (uint i = 0; i < detail.locationCount; i++) { // 指定格式 // set up data format. switch (detail.pointerType) { case VertexAttribPointerType.Default: if (glVertexAttribPointer == null) { glVertexAttribPointer = OpenGL.GetDelegateFor <OpenGL.glVertexAttribPointer>(); } glVertexAttribPointer(loc + i, detail.dataSize, detail.dataType, false, detail.stride, new IntPtr(i * detail.startOffsetUnit)); break; case VertexAttribPointerType.Integer: if (glVertexAttribIPointer != null) { if (glVertexAttribIPointer == null) { glVertexAttribIPointer = OpenGL.GetDelegateFor <OpenGL.glVertexAttribIPointer>(); } glVertexAttribIPointer(loc + i, detail.dataSize, detail.dataType, detail.stride, new IntPtr(i * detail.startOffsetUnit)); } else { if (glVertexAttribPointer == null) { glVertexAttribPointer = OpenGL.GetDelegateFor <OpenGL.glVertexAttribPointer>(); } glVertexAttribPointer(loc + i, detail.dataSize, detail.dataType, false, detail.stride, new IntPtr(i * detail.startOffsetUnit)); } break; case VertexAttribPointerType.Long: if (glVertexAttribLPointer != null) { if (glVertexAttribLPointer == null) { glVertexAttribLPointer = OpenGL.GetDelegateFor <OpenGL.glVertexAttribLPointer>(); } glVertexAttribLPointer(loc + i, detail.dataSize, detail.dataType, detail.stride, new IntPtr(i * detail.startOffsetUnit)); } else { if (glVertexAttribPointer == null) { glVertexAttribPointer = OpenGL.GetDelegateFor <OpenGL.glVertexAttribPointer>(); } glVertexAttribPointer(loc + i, detail.dataSize, detail.dataType, false, detail.stride, new IntPtr(i * detail.startOffsetUnit)); } break; default: throw new NotImplementedException(); } if (patchVertexes > 0)// tessellation shading. { if (glPatchParameteri != null) { if (glPatchParameteri == null) { glPatchParameteri = OpenGL.GetDelegateFor <OpenGL.glPatchParameteri>(); } glPatchParameteri(OpenGL.GL_PATCH_VERTICES, patchVertexes); } } // 启用 // enable this VBO. if (glEnableVertexAttribArray == null) { glEnableVertexAttribArray = OpenGL.GetDelegateFor <OpenGL.glEnableVertexAttribArray>(); } glEnableVertexAttribArray(loc + i); if (divisor > 0)// instanced rendering. { if (glVertexAttribDivisor == null) { glVertexAttribDivisor = OpenGL.GetDelegateFor <OpenGL.glVertexAttribDivisor>(); } glVertexAttribDivisor(loc + i, divisor); } } glBindBuffer(OpenGL.GL_ARRAY_BUFFER, 0); }
/// <summary> /// 在使用<see cref="VertexArrayObject"/>后,此方法只会执行一次。 /// This method will only be invoked once when using <see cref="VertexArrayObject"/>. /// </summary> /// <param name="shaderProgram"></param> public void Standby(ShaderProgram shaderProgram) { int location = shaderProgram.GetAttributeLocation(this.VarNameInVertexShader); if (location < 0) { throw new ArgumentException(); } uint loc = (uint)location; VBOConfigDetail detail = this.Config.Parse(); int patchVertexes = this.PatchVertexes; uint divisor = this.InstancedDivisor; // 选中此VBO // select this VBO. if (glBindBuffer == null) { glBindBuffer = OpenGL.GetDelegateFor<OpenGL.glBindBuffer>(); } glBindBuffer(OpenGL.GL_ARRAY_BUFFER, this.BufferId); for (uint i = 0; i < detail.locationCount; i++) { // 指定格式 // set up data format. switch (detail.pointerType) { case VertexAttribPointerType.Default: if (glVertexAttribPointer == null) { glVertexAttribPointer = OpenGL.GetDelegateFor<OpenGL.glVertexAttribPointer>(); } glVertexAttribPointer(loc + i, detail.dataSize, detail.dataType, false, detail.stride, new IntPtr(i * detail.startOffsetUnit)); break; case VertexAttribPointerType.Integer: if (glVertexAttribIPointer != null) { if (glVertexAttribIPointer == null) { glVertexAttribIPointer = OpenGL.GetDelegateFor<OpenGL.glVertexAttribIPointer>(); } glVertexAttribIPointer(loc + i, detail.dataSize, detail.dataType, detail.stride, new IntPtr(i * detail.startOffsetUnit)); } else { if (glVertexAttribPointer == null) { glVertexAttribPointer = OpenGL.GetDelegateFor<OpenGL.glVertexAttribPointer>(); } glVertexAttribPointer(loc + i, detail.dataSize, detail.dataType, false, detail.stride, new IntPtr(i * detail.startOffsetUnit)); } break; case VertexAttribPointerType.Long: if (glVertexAttribLPointer != null) { if (glVertexAttribLPointer == null) { glVertexAttribLPointer = OpenGL.GetDelegateFor<OpenGL.glVertexAttribLPointer>(); } glVertexAttribLPointer(loc + i, detail.dataSize, detail.dataType, detail.stride, new IntPtr(i * detail.startOffsetUnit)); } else { if (glVertexAttribPointer == null) { glVertexAttribPointer = OpenGL.GetDelegateFor<OpenGL.glVertexAttribPointer>(); } glVertexAttribPointer(loc + i, detail.dataSize, detail.dataType, false, detail.stride, new IntPtr(i * detail.startOffsetUnit)); } break; default: throw new NotImplementedException(); } if (patchVertexes > 0)// tessellation shading. { if (glPatchParameteri != null) { if (glPatchParameteri == null) { glPatchParameteri = OpenGL.GetDelegateFor<OpenGL.glPatchParameteri>(); } glPatchParameteri(OpenGL.GL_PATCH_VERTICES, patchVertexes); } } // 启用 // enable this VBO. if (glEnableVertexAttribArray == null) { glEnableVertexAttribArray = OpenGL.GetDelegateFor<OpenGL.glEnableVertexAttribArray>(); } glEnableVertexAttribArray(loc + i); if (divisor > 0)// instanced rendering. { if (glVertexAttribDivisor == null) { glVertexAttribDivisor = OpenGL.GetDelegateFor<OpenGL.glVertexAttribDivisor>(); } glVertexAttribDivisor(loc + i, divisor); } } glBindBuffer(OpenGL.GL_ARRAY_BUFFER, 0); }