private void DoRender(object sender, PaintEventArgs e) { // Compute the MVP (Model View Projection matrix) { GL.BindBuffer(BufferTarget.UniformBuffer, BufferName[1]);//BufferName[TRANSFORM] var mvpPointer = GL.MapBufferRange(GL.GL_UNIFORM_BUFFER, 0, 64, (uint)(GL.GL_MAP_WRITE_BIT | GL.GL_MAP_INVALIDATE_BUFFER_BIT)); var tmp = new UnmanagedArray <mat4>(1); mat4 projection = this.camera.GetProjectionMat4(); mat4 view = this.camera.GetViewMat4(); //tmp[0] = projection * view; //tmp.CopyTo(Pointer); unsafe { mat4 *array = (mat4 *)mvpPointer.ToPointer(); array[0] = projection * view; } GL.UnmapBuffer(GL.GL_UNIFORM_BUFFER); tmp.Dispose(); } // Clear color buffer //GL.ClearBufferfv(GL_COLOR, 0, &GL.m.vec4(0.0f, 0.0f, 0.0f, 1.0f)[0]); GL.ClearBuffer(GL.GL_COLOR, 0, new float[] { 0.0f, 0.0f, 0.0f, 1.0f }); // First draw, capture the attributes // Disable rasterisation, vertices processing only! GL.Enable(GL.GL_RASTERIZER_DISCARD); transformProgram.Bind(); GL.BindVertexArray(transformArray[0]); //GL.BindBufferBase(GL.GL_UNIFORM_BUFFER, semantic.uniform.TRANSFORM0, BufferName[buffer.TRANSFORM]); GL.BindBufferBase(GL.GL_UNIFORM_BUFFER, 1, BufferName[1]); GL.BindTransformFeedback(GL.GL_TRANSFORM_FEEDBACK, feedbackObj[0]); GL.BeginTransformFeedback(GL.GL_TRIANGLES); GL.DrawArraysInstanced(GL.GL_TRIANGLES, 0, 6, 1);//VertexCount: 6 GL.EndTransformFeedback(); GL.BindTransformFeedback(GL.GL_TRANSFORM_FEEDBACK, 0); GL.Disable(GL.GL_RASTERIZER_DISCARD); // Second draw, reuse the captured attributes feedbackProgram.Bind(); GL.BindVertexArray(feedbackArray[0]); GL.DrawTransformFeedback(GL.GL_TRIANGLES, feedbackObj[0]); }
protected override void DoRender(RenderEventArgs e) { float t = (float)(TimerHelper.GetTickCount() & 0x3FFF) / factor; int n; //// Setup //glEnable(GL_CULL_FACE); //glEnable(GL_DEPTH_TEST); //glDepthFunc(GL_LEQUAL); // Bind the weight VBO and change its data GL.BindBuffer(BufferTarget.ArrayBuffer, model_matrix_buffer[0]); // Set model matrices for each instance IntPtr pointer = GL.MapBuffer(BufferTarget.ArrayBuffer, MapBufferAccess.WriteOnly); unsafe { mat4 *matrices = (mat4 *)pointer.ToPointer(); for (n = 0; n < INSTANCE_COUNT; n++) { float a = 50.0f * (float)(n) / 4.0f; float b = 50.0f * (float)(n) / 5.0f; float c = 50.0f * (float)(n) / 6.0f; matrices[n] = glm.rotate(a + t * 1.0f, new vec3(1, 0, 0)) * glm.rotate(b + t * 1.0f, new vec3(0, 1, 0)) * glm.rotate(c + t * 1.0f, new vec3(0, 0, 1)) * glm.translate(mat4.identity(), new vec3(10.0f + a, 40.0f + b, 50.0f + c)); } } GL.UnmapBuffer(BufferTarget.ArrayBuffer); // Activate instancing program GL.UseProgram(render_prog); // Set up the view and projection matrices //mat4 view_matrix(translate(0.0f, 0.0f, -1500.0f) * rotate(t * 360.0f * 2.0f, 0.0f, 1.0f, 0.0f)); //mat4 projection_matrix(frustum(-1.0f, 1.0f, -aspect, aspect, 1.0f, 5000.0f)); mat4 view_matrix = e.Camera.GetViewMat4(); mat4 projection_matrix = e.Camera.GetProjectionMat4(); GL.UniformMatrix4(view_matrix_loc, 1, false, view_matrix.to_array()); GL.UniformMatrix4(projection_matrix_loc, 1, false, projection_matrix.to_array()); // Render INSTANCE_COUNT objects vboObject.Render(0, INSTANCE_COUNT); }
public static void TypicalScene() { const int count = 1000000; long startTick = 0; long interval, interval2; // 测试float类型 { var floatArray = new UnmanagedArray <float>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { floatArray[i] = i; } for (int i = 0; i < count; i++) { var item = floatArray[i]; if (item != i) { throw new Exception(); } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; float *header = (float *)floatArray.FirstElement(); float *last = (float *)floatArray.LastElement(); float *tailAddress = (float *)floatArray.TailAddress(); int value = 0; for (float *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++) { *ptr = value++; } int i = 0; for (float *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; if (item != i) { throw new Exception(); } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 测试decimal类型 { var decimalArray = new UnmanagedArray <decimal>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { decimalArray[i] = i; } for (int i = 0; i < count; i++) { var item = decimalArray[i]; if (item != i) { throw new Exception(); } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; decimal *header = (decimal *)decimalArray.FirstElement(); decimal *last = (decimal *)decimalArray.LastElement(); decimal *tailAddress = (decimal *)decimalArray.TailAddress(); int value = 0; for (decimal *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++) { *ptr = value++; } int i = 0; for (decimal *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; if (item != i) { throw new Exception(); } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 测试int类型 { var intArray = new UnmanagedArray <int>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { intArray[i] = i; } for (int i = 0; i < count; i++) { var item = intArray[i]; if (item != i) { throw new Exception(); } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; int *header = (int *)intArray.FirstElement(); int *last = (int *)intArray.LastElement(); int *tailAddress = (int *)intArray.TailAddress(); int value = 0; for (int *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++) { *ptr = value++; } int i = 0; for (int *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; if (item != i) { throw new Exception(); } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 测试bool类型 { var boolArray = new UnmanagedArray <bool>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { boolArray[i] = i % 2 == 0; } for (int i = 0; i < count; i++) { var item = boolArray[i]; if (item != (i % 2 == 0)) { throw new Exception(); } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; bool *header = (bool *)boolArray.FirstElement(); bool *last = (bool *)boolArray.LastElement(); bool *tailAddress = (bool *)boolArray.TailAddress(); int value = 0; for (bool *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++) { *ptr = (value % 2 == 0); value++; } int i = 0; for (bool *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; if (item != (i % 2 == 0)) { throw new Exception(); } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 测试vec3类型 { var vec3Array = new UnmanagedArray <vec3>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { vec3Array[i] = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2); } for (int i = 0; i < count; i++) { var item = vec3Array[i]; var old = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2); if (item.x != old.x || item.y != old.y || item.z != old.z) { throw new Exception(); } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; vec3 *header = (vec3 *)vec3Array.FirstElement(); vec3 *last = (vec3 *)vec3Array.LastElement(); vec3 *tailAddress = (vec3 *)vec3Array.TailAddress(); int i = 0; for (vec3 *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++) { *ptr = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2); i++; } i = 0; for (vec3 *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; var old = new vec3(i * 3 + 0, i * 3 + 1, i * 3 + 2); if (item.x != old.x || item.y != old.y || item.z != old.z) { throw new Exception(); } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 测试mat4类型 { var vec3Array = new UnmanagedArray <mat4>(count); startTick = DateTime.Now.Ticks; for (int i = 0; i < count; i++) { vec3Array[i] = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3)); } for (int i = 0; i < count; i++) { var item = vec3Array[i]; var old = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3)); for (int col = 0; col < 4; col++) { for (int row = 0; row < 4; row++) { if (item[col][row] != old[col][row]) { throw new Exception(); } } } } interval = DateTime.Now.Ticks - startTick; unsafe { startTick = DateTime.Now.Ticks; mat4 *header = (mat4 *)vec3Array.FirstElement(); mat4 *last = (mat4 *)vec3Array.LastElement(); mat4 *tailAddress = (mat4 *)vec3Array.TailAddress(); int i = 0; for (mat4 *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++) { *ptr = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3)); i++; } i = 0; for (mat4 *ptr = header; ptr <= last /*or: ptr < tailAddress*/; ptr++, i++) { var item = *ptr; var old = new mat4(new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3), new vec4(i, i + 1, i + 2, i + 3)); for (int col = 0; col < 4; col++) { for (int row = 0; row < 4; row++) { if (item[col][row] != old[col][row]) { throw new Exception(); } } } } interval2 = DateTime.Now.Ticks - startTick; } Console.WriteLine("Ticks: safe: {0} vs unsafe: {1}", interval, interval2); } // 立即释放所有非托管数组占用的内存,任何之前创建的UnmanagedBase数组都不再可用了。 UnmanagedArray <int> .FreeAll(); }