private void DisableVertexAttribArray(uint index) { // TODO: GL_INVALID_VALUE is generated if index is greater than or equal to GL_MAX_VERTEX_ATTRIBS. VertexArrayObject vao = this.currentVertexArrayObject; if (vao == null) { SetLastError(ErrorCode.InvalidOperation); return; } VertexAttribDesc desc = null; if (vao.LocVertexAttribDict.TryGetValue(index, out desc)) { desc.enabled = false; } }
private void VertexAttribLPointer(uint index, int size, VertexAttribLType type, 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) { SetLastError(ErrorCode.InvalidValue); return; } if (!Enum.IsDefined(typeof(VertexAttribLType), type)) { SetLastError(ErrorCode.InvalidEnum); return; } if (stride < 0) { SetLastError(ErrorCode.InvalidValue); 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 = false; // not needed. desc.startPos = (uint)pointer.ToInt32(); desc.stride = (uint)stride; }
private unsafe PassBuffer[] VertexShaderStage(int count, DrawElementsType type, IntPtr indices, VertexArrayObject vao, ShaderProgram program, GLBuffer indexBuffer) { PassBuffer[] passBuffers = null; VertexShader vs = program.VertexShader; if (vs == null) { return(passBuffers); } // init pass-buffers to record output from vertex shader. FieldInfo[] outFieldInfos = (from item in vs.outVariableDict select item.Value.fieldInfo).ToArray(); uint vertexCount = GetVertexCount(vao, indexBuffer, type); //int vertexSize = GetVertexSize(outFieldInfos); passBuffers = new PassBuffer[1 + outFieldInfos.Length]; void *[] pointers = new void *[1 + outFieldInfos.Length]; { // the first pass-buffer stores gl_Position. var passBuffer = new PassBuffer(PassType.Vec4, (int)vertexCount); pointers[0] = (void *)passBuffer.Mapbuffer(); passBuffers[0] = passBuffer; } for (int i = 1; i < passBuffers.Length; i++) { var outField = outFieldInfos[i - 1]; PassType passType = outField.FieldType.GetPassType(); var passBuffer = new PassBuffer(passType, (int)vertexCount); pointers[i] = (void *)passBuffer.Mapbuffer(); passBuffers[i] = passBuffer; } // execute vertex shader for each vertex. 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>(); 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); } var instance = vs.CreateCodeInstance() as VertexCodeBase; // an executable vertex shader. instance.gl_VertexID = (int)gl_VertexID; // setup gl_VertexID. // setup "in SomeType varName;" vertex attributes. Dictionary <uint, VertexAttribDesc> locVertexAttribDict = vao.LocVertexAttribDict; foreach (InVariable inVar in vs.inVariableDict.Values) // Dictionary<string, InVariable>.Values { VertexAttribDesc desc = null; if (locVertexAttribDict.TryGetValue(inVar.location, out desc)) { byte[] dataStore = desc.vbo.Data; int byteIndex = desc.GetDataIndex(gl_VertexID); VertexAttribType vertexAttribType = (VertexAttribType)desc.dataType; object value = dataStore.ToStruct(inVar.fieldInfo.FieldType, byteIndex); inVar.fieldInfo.SetValue(instance, value); } } // setup "uniform SomeType varName;" in vertex shader. Dictionary <string, UniformValue> nameUniformDict = program.nameUniformDict; foreach (UniformVariable uniformVar in vs.UniformVariableDict.Values) { string name = uniformVar.fieldInfo.Name; UniformValue obj = null; if (nameUniformDict.TryGetValue(name, out obj)) { if (obj.value != null) { uniformVar.fieldInfo.SetValue(instance, obj.value); } } } instance.main(); // execute vertex shader code. // copy data to pass-buffer. { PassBuffer passBuffer = passBuffers[0]; var array = (vec4 *)pointers[0]; array[gl_VertexID] = instance.gl_Position; } for (int i = 1; i < passBuffers.Length; i++) { var outField = outFieldInfos[i - 1]; var obj = outField.GetValue(instance); switch (outField.FieldType.GetPassType()) { case PassType.Float: { var array = (float *)pointers[i]; array[gl_VertexID] = (float)obj; } break; case PassType.Vec2: { var array = (vec2 *)pointers[i]; array[gl_VertexID] = (vec2)obj; } break; case PassType.Vec3: { var array = (vec3 *)pointers[i]; array[gl_VertexID] = (vec3)obj; } break; case PassType.Vec4: { var array = (vec4 *)pointers[i]; array[gl_VertexID] = (vec4)obj; } break; case PassType.Mat2: { var array = (mat2 *)pointers[i]; array[gl_VertexID] = (mat2)obj; } break; case PassType.Mat3: { var array = (mat3 *)pointers[i]; array[gl_VertexID] = (mat3)obj; } break; case PassType.Mat4: { var array = (mat4 *)pointers[i]; array[gl_VertexID] = (mat4)obj; } break; default: throw new NotImplementedException(); } // a general way to do this: //var obj = outField.GetValue(instance); //byte[] bytes = obj.ToBytes(); //PassBuffer passBuffer = passBuffers[i]; //var array = (byte*)passBuffer.AddrOfPinnedObject(); //for (int t = 0; t < bytes.Length; t++) //{ // array[gl_VertexID * vertexSize + t] = bytes[t]; //} } } pin.Free(); for (int i = 0; i < passBuffers.Length; i++) { passBuffers[i].Unmapbuffer(); } return(passBuffers); }