private void TestUsingUnmanagedArray() { unsafe { vec3 *first = (vec3 *)array.FirstElement(); } }
private void btnUnsafeVSSafe_Click(object sender, EventArgs e) { int count = 1000000; // 测试vec3类型 { var vec3Array = new UnmanagedArray <vec3>(count); long 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(); } } long 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(); } } } long interval2 = DateTime.Now.Ticks - startTick; Console.WriteLine(); MessageBox.Show(string.Format("Ticks: safe: {0} vs unsafe: {1}", interval, interval2), "result"); } }
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(); }
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(); }
// Call this only after the open gl is initialized. public bool ReadFile(string lpDataFile_i, int nWidth_i, int nHeight_i, int nSlices_i) { FileStream file = new FileStream(lpDataFile_i, FileMode.Open, FileAccess.Read); // File has only image data. The dimension of the data should be known. m_uImageCount = nSlices_i; m_uImageWidth = nWidth_i; m_uImageHeight = nHeight_i; // Holds the luminance buffer //byte[] chBuffer = new byte[m_uImageWidth * m_uImageHeight * m_uImageCount]; //UnmanagedArray<byte> chBuffer = new UnmanagedArray<byte>(m_uImageWidth * m_uImageHeight * m_uImageCount); byte[] chBuffer = new byte[m_uImageWidth * m_uImageHeight * m_uImageCount]; // Holds the RGBA buffer UnmanagedArray <byte> pRGBABuffer = new UnmanagedArray <byte>(m_uImageWidth * m_uImageHeight * m_uImageCount * 4); file.Read(chBuffer, 0, chBuffer.Length); // Convert the data to RGBA data. // Here we are simply putting the same value to R, G, B and A channels. // Usually for raw data, the alpha value will be constructed by a threshold value given by the user unsafe { byte *rgbBuffer = (byte *)pRGBABuffer.FirstElement(); for (int nIndx = 0; nIndx < m_uImageWidth * m_uImageHeight * m_uImageCount; ++nIndx) { byte value = chBuffer[nIndx]; //if (value < 20) //{ value = 0; } rgbBuffer[nIndx * 4] = value; rgbBuffer[nIndx * 4 + 1] = value; rgbBuffer[nIndx * 4 + 2] = value; rgbBuffer[nIndx * 4 + 3] = value; } } // If this function is getting called again for another data file. // Deleting and creating texture is not a good idea, // we can use the glTexSubImage3D for better performance for such scenario. // I am not using that now :-) if (0 != m_nTexId[0]) { GL.DeleteTextures(1, m_nTexId); } GL.GenTextures(1, m_nTexId); GL.BindTexture(GL.GL_TEXTURE_3D, m_nTexId[0]); GL.TexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, (int)GL.GL_REPLACE); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_S, (int)GL.GL_CLAMP_TO_BORDER); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_T, (int)GL.GL_CLAMP_TO_BORDER); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_R, (int)GL.GL_CLAMP_TO_BORDER); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_MAG_FILTER, (int)GL.GL_LINEAR); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_MIN_FILTER, (int)GL.GL_LINEAR); //uint target, int level, int internalformat, int width, int height, int depth, int border, uint format, uint type, IntPtr pixels) GL.TexImage3D(GL.GL_TEXTURE_3D, 0, (int)GL.GL_RGBA, m_uImageWidth, m_uImageHeight, m_uImageCount, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pRGBABuffer.Header); GL.BindTexture(GL.GL_TEXTURE_3D, 0); return(true); }
/// <summary> /// 读取数据文件,获取3D纹理 /// </summary> /// <param name="dataFiles"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="slices"></param> /// <returns></returns> public bool ReadFile(string[] dataFiles, int width, int height, int slices) { this.slices = slices; this.width = width; this.height = height; float[] chBuffer = new float[width * height * slices]; float min = 0, max = 0; // 找到数据中的最大、最小值,为配色做准备 { int index = 0; bool minSet = false, maxSet = false; char[] separator = new char[] { ' ', '\t', '\r', '\n' }; for (int i = 0; i < dataFiles.Length; i++) { string filename = dataFiles[i]; using (var sr = new StreamReader(filename)) { while (!sr.EndOfStream) { var line = sr.ReadLine(); var parts = line.Split(separator, StringSplitOptions.RemoveEmptyEntries); foreach (var part in parts) { float value; if (float.TryParse(part, out value)) { if (!minSet) { min = value; minSet = true; } if (!maxSet) { max = value; maxSet = true; } if (value < min) { min = value; } if (max < value) { max = value; } chBuffer[index++] = value; } else { throw new Exception(); } } } } } } // 用非托管数组存储顶点颜色,为创建3D纹理做准备 UnmanagedArray <byte> pRGBABuffer = new UnmanagedArray <byte>(width * height * slices * 4); unsafe { byte *rgbBuffer = (byte *)pRGBABuffer.FirstElement(); for (int nIndx = 0; nIndx < width * height * slices; ++nIndx) { float value = chBuffer[nIndx]; ColorBar bar = ColorBar.GetDefault(); // 默认配色方案 vec3 color = bar.GetColor(min, max, value); // 有数值得到对应的颜色 rgbBuffer[nIndx * 4] = (byte)(color.x * 255); rgbBuffer[nIndx * 4 + 1] = (byte)(color.y * 255); rgbBuffer[nIndx * 4 + 2] = (byte)(color.z * 255); // 适当降低不透明度(此处用 / 10) rgbBuffer[nIndx * 4 + 3] = (byte)((value - min) / (max - min) * 255.0f / 10); } } // 创建3D贴图,为渲染做准备 if (0 != textureId[0]) { GL.DeleteTextures(1, textureId); } GL.GenTextures(1, textureId); GL.BindTexture(GL.GL_TEXTURE_3D, textureId[0]); GL.TexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, (int)GL.GL_REPLACE); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_S, (int)GL.GL_CLAMP_TO_BORDER); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_T, (int)GL.GL_CLAMP_TO_BORDER); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_R, (int)GL.GL_CLAMP_TO_BORDER); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_MAG_FILTER, (int)GL.GL_LINEAR); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_MIN_FILTER, (int)GL.GL_LINEAR); GL.TexImage3D(GL.GL_TEXTURE_3D, 0, (int)GL.GL_RGBA, width, height, slices, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pRGBABuffer.Header); GL.BindTexture(GL.GL_TEXTURE_3D, 0); // 非托管数组要手动释放 pRGBABuffer.Dispose(); return(true); }
// Call this only after the open gl is initialized. public bool ReadFile(string lpDataFile_i, int nWidth_i, int nHeight_i, int nSlices_i) { FileStream file = new FileStream(lpDataFile_i, FileMode.Open, FileAccess.Read); // File has only image data. The dimension of the data should be known. m_uImageCount = nSlices_i; m_uImageWidth = nWidth_i; m_uImageHeight = nHeight_i; // Holds the luminance buffer //byte[] chBuffer = new byte[m_uImageWidth * m_uImageHeight * m_uImageCount]; //UnmanagedArray<byte> chBuffer = new UnmanagedArray<byte>(m_uImageWidth * m_uImageHeight * m_uImageCount); byte[] chBuffer = new byte[m_uImageWidth * m_uImageHeight * m_uImageCount]; // Holds the RGBA buffer UnmanagedArray<byte> pRGBABuffer = new UnmanagedArray<byte>(m_uImageWidth * m_uImageHeight * m_uImageCount * 4); file.Read(chBuffer, 0, chBuffer.Length); // Convert the data to RGBA data. // Here we are simply putting the same value to R, G, B and A channels. // Usually for raw data, the alpha value will be constructed by a threshold value given by the user unsafe { byte* rgbBuffer = (byte*)pRGBABuffer.FirstElement(); for (int nIndx = 0; nIndx < m_uImageWidth * m_uImageHeight * m_uImageCount; ++nIndx) { byte value = chBuffer[nIndx]; //if (value < 20) //{ value = 0; } rgbBuffer[nIndx * 4] = value; rgbBuffer[nIndx * 4 + 1] = value; rgbBuffer[nIndx * 4 + 2] = value; rgbBuffer[nIndx * 4 + 3] = value; } } // If this function is getting called again for another data file. // Deleting and creating texture is not a good idea, // we can use the glTexSubImage3D for better performance for such scenario. // I am not using that now :-) if (0 != m_nTexId[0]) { GL.DeleteTextures(1, m_nTexId); } GL.GenTextures(1, m_nTexId); GL.BindTexture(GL.GL_TEXTURE_3D, m_nTexId[0]); GL.TexEnvi(GL.GL_TEXTURE_ENV, GL.GL_TEXTURE_ENV_MODE, (int)GL.GL_REPLACE); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_S, (int)GL.GL_CLAMP_TO_BORDER); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_T, (int)GL.GL_CLAMP_TO_BORDER); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_WRAP_R, (int)GL.GL_CLAMP_TO_BORDER); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_MAG_FILTER, (int)GL.GL_LINEAR); GL.TexParameteri(GL.GL_TEXTURE_3D, GL.GL_TEXTURE_MIN_FILTER, (int)GL.GL_LINEAR); //uint target, int level, int internalformat, int width, int height, int depth, int border, uint format, uint type, IntPtr pixels) GL.TexImage3D(GL.GL_TEXTURE_3D, 0, (int)GL.GL_RGBA, m_uImageWidth, m_uImageHeight, m_uImageCount, 0, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, pRGBABuffer.Header); GL.BindTexture(GL.GL_TEXTURE_3D, 0); return true; }