volumeRender.cu
上传用户:liuping58
上传日期:2022-06-05
资源大小:105k
文件大小:14k
源码类别:

3D图形编程

开发平台:

Visual C++

  1. /*
  2. * Copyright 1993-2008 NVIDIA Corporation.  All rights reserved.
  3. *
  4. * NOTICE TO USER:
  5. *
  6. * This source code is subject to NVIDIA ownership rights under U.S. and
  7. * international Copyright laws.
  8. *
  9. * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE
  10. * CODE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR
  11. * IMPLIED WARRANTY OF ANY KIND.  NVIDIA DISCLAIMS ALL WARRANTIES WITH
  12. * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF
  13. * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.
  14. * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL,
  15. * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  16. * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  17. * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  18. * OR PERFORMANCE OF THIS SOURCE CODE.
  19. *
  20. * U.S. Government End Users.  This source code is a "commercial item" as
  21. * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting  of
  22. * "commercial computer software" and "commercial computer software
  23. * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995)
  24. * and is provided to the U.S. Government only as a commercial end item.
  25. * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through
  26. * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the
  27. * source code with only those rights set forth herein.
  28. */
  29. /*
  30.     Volume rendering sample
  31.     This sample loads a 3D volume from disk and displays it using
  32.     ray marching and 3D textures.
  33. */
  34. #include <stdlib.h>
  35. #include <stdio.h>
  36. #include <string.h>
  37. #include <math.h>
  38. #include <GL/glew.h>
  39. #if defined (__APPLE__) || defined(MACOSX)
  40. #include <GLUT/glut.h>
  41. #else
  42. #include <GL/glut.h>
  43. #endif
  44. #include <cuda_gl_interop.h>
  45. #include <cutil_inline.h>
  46. #include <cuda_runtime.h>
  47. #include <cutil.h>
  48. typedef unsigned int uint;
  49. typedef unsigned char uchar;
  50. #include <volumeRender_kernel.cu>
  51. #include <kernel.cu>
  52. #define ITERATIONS   500
  53. #define THRESHOLD  150
  54. #define EPSILON  50
  55. #define BLOCKDIM_X  32
  56. #define BLOCKDIM_Y  4
  57. #define BLOCKDIM_Z  1
  58. #define RITS  5
  59. char *volumeFilename = "brain.raw";
  60. char *maskFilename = "phi.raw";
  61. char *outputFilename= "output.raw";
  62. cudaExtent volumeSize = make_cudaExtent(181,217,181);
  63. float *phi, *D, *contour;
  64. char *path;
  65. size_t size, pitchbytes;
  66. unsigned char *input,*output;
  67. int imageW, imageH, imageD, N, pitch;
  68. float *d_phi, *d_phi1, *d_D;
  69. int its=0;
  70. unsigned int Timer = 0;
  71. unsigned int IterationTimer = 0;
  72. int i,j,k;
  73. uint width = 600, height = 600;
  74. dim3 blockSize(16, 16);
  75. dim3 gridSize(width / blockSize.x, height / blockSize.y);
  76. float3 viewRotation;
  77. float3 viewTranslation = make_float3(0.0, 0.0, -4.0f);
  78. float invViewMatrix[12];
  79. float density = 0.1f;
  80. float brightness = 0.9f;
  81. float transferOffset = -0.5f;
  82. float transferScale = 0.02f;
  83. bool linearFiltering = true;
  84. cudaArray *d_volumeArray = 0;
  85. cudaArray *d_transferFuncArray;
  86. GLuint pbo = 0;     // OpenGL pixel buffer object
  87. void initPixelBuffer();
  88. __global__ void updatephi( float *d_phi, float *d_phi1, float *d_D, int imageW, int imageH, int imageD, int pitch);
  89. // render image using CUDA
  90. void render()
  91. {
  92.     cutilSafeCall( cudaMemcpyToSymbol(c_invViewMatrix, invViewMatrix, sizeof(float4)*3) );
  93.     // map PBO to get CUDA device pointer
  94.     uint *d_output;
  95.     cutilSafeCall(cudaGLMapBufferObject((void**)&d_output, pbo));
  96.     cutilSafeCall(cudaMemset(d_output, 0, width*height*4));
  97.     // call CUDA kernel, writing results to PBO
  98.     d_render<<<gridSize, blockSize>>>(d_output, width, height, density, brightness, transferOffset, transferScale);
  99.     cutilCheckMsg("kernel failed");
  100.     cutilSafeCall(cudaGLUnmapBufferObject(pbo));
  101. }
  102. void initCuda(float *h_volume, cudaExtent volumeSize)
  103. {
  104.     // create 3D array
  105.     cudaChannelFormatDesc channelDesc = cudaCreateChannelDesc<float>();
  106.     cutilSafeCall( cudaMalloc3DArray(&d_volumeArray, &channelDesc, volumeSize) );
  107.     // copy data to 3D array
  108.     cudaMemcpy3DParms copyParams = {0};
  109.     copyParams.srcPtr   = make_cudaPitchedPtr((void*)h_volume, volumeSize.width*sizeof(float), volumeSize.width, volumeSize.height);
  110.     copyParams.dstArray = d_volumeArray;
  111.     copyParams.extent   = volumeSize;
  112.     copyParams.kind     = cudaMemcpyHostToDevice;
  113.     cutilSafeCall( cudaMemcpy3D(&copyParams) );  
  114.     // set texture parameters
  115.     tex.normalized = true;                      // access with normalized texture coordinates
  116.     tex.filterMode = cudaFilterModeLinear;      // linear interpolation
  117.     tex.addressMode[0] = cudaAddressModeClamp;  // wrap texture coordinates
  118.     tex.addressMode[1] = cudaAddressModeClamp;
  119.     // bind array to 3D texture
  120.     cutilSafeCall(cudaBindTextureToArray(tex, d_volumeArray, channelDesc));
  121.     // create transfer function texture
  122.     float4 transferFunc[] = {
  123.         {  0.0, 0.0, 0.0, 0.0, },
  124.         {  1.0, 0.0, 0.0, 1.0, },
  125.         {  1.0, 0.5, 0.0, 1.0, },
  126.         {  1.0, 1.0, 0.0, 1.0, },
  127.         {  0.0, 1.0, 0.0, 1.0, },
  128.         {  0.0, 1.0, 1.0, 1.0, },
  129.         {  0.0, 0.0, 1.0, 1.0, },
  130.         {  1.0, 0.0, 1.0, 1.0, },
  131.         {  0.0, 0.0, 0.0, 0.0, },
  132.     };
  133.     cudaChannelFormatDesc channelDesc2 = cudaCreateChannelDesc<float4>();
  134.     cudaArray* d_transferFuncArray;
  135.     cutilSafeCall(cudaMallocArray( &d_transferFuncArray, &channelDesc2, sizeof(transferFunc)/sizeof(float4), 1)); 
  136.     cutilSafeCall(cudaMemcpyToArray( d_transferFuncArray, 0, 0, transferFunc, sizeof(transferFunc), cudaMemcpyHostToDevice));
  137.     transferTex.filterMode = cudaFilterModeLinear;
  138.     transferTex.normalized = true;    // access with normalized texture coordinates
  139.     transferTex.addressMode[0] = cudaAddressModeClamp;   // wrap texture coordinates
  140.     // Bind the array to the texture
  141.     cutilSafeCall( cudaBindTextureToArray( transferTex, d_transferFuncArray, channelDesc2));
  142. }
  143. // display results using OpenGL (called by GLUT)
  144. void cuda_update(){
  145. dim3 dimGrid( ((imageW-1)/BLOCKDIM_X) + 1, ((imageH-1)/BLOCKDIM_Y) +1);
  146. dim3 dimBlock(BLOCKDIM_X, BLOCKDIM_Y, BLOCKDIM_Z);
  147. updatephi<<< dimGrid, dimBlock>>>(d_phi, d_phi1, d_D,  imageW, imageH, imageD, pitch);
  148. d_phi1=d_phi;
  149. CUT_CHECK_ERROR("Kernel execution failedn");
  150. cudaThreadSynchronize();
  151. }
  152. void display()
  153. {
  154. if(its<ITERATIONS){
  155. cuda_update();
  156. if(its%RITS==0){
  157. cudaMemcpy2D(phi, sizeof(float)*imageW, d_phi1, pitchbytes, sizeof(float)*imageW, imageH*imageD, cudaMemcpyDeviceToHost);
  158. for(i=0;i<N;i++){
  159. if(phi[i]<0){contour[i] = 25;} else {contour[i]=0;}
  160. }
  161. cutilSafeCall(cudaFreeArray(d_volumeArray));
  162. cutilSafeCall(cudaFreeArray(d_transferFuncArray));
  163. initCuda(contour, volumeSize);
  164. }
  165. }
  166. // use OpenGL to build view matrix
  167. GLfloat modelView[16];
  168. glMatrixMode(GL_MODELVIEW);
  169. glPushMatrix();
  170. glLoadIdentity();
  171. glRotatef(-viewRotation.x, 1.0, 0.0, 0.0);
  172. glRotatef(-viewRotation.y, 0.0, 1.0, 0.0);
  173. glTranslatef(-viewTranslation.x, -viewTranslation.y, -viewTranslation.z);
  174. glGetFloatv(GL_MODELVIEW_MATRIX, modelView);
  175. glPopMatrix();
  176. invViewMatrix[0] = modelView[0]; invViewMatrix[1] = modelView[4]; invViewMatrix[2] = modelView[8]; invViewMatrix[3] = modelView[12];
  177. invViewMatrix[4] = modelView[1]; invViewMatrix[5] = modelView[5]; invViewMatrix[6] = modelView[9]; invViewMatrix[7] = modelView[13];
  178. invViewMatrix[8] = modelView[2]; invViewMatrix[9] = modelView[6]; invViewMatrix[10] = modelView[10]; invViewMatrix[11] = modelView[14];
  179. render();
  180. // display results
  181. glClear(GL_COLOR_BUFFER_BIT);
  182. // draw image from PBO
  183. glDisable(GL_DEPTH_TEST);
  184. glRasterPos2i(0, 0);
  185. glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
  186. glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, 0);
  187. glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
  188. glutSwapBuffers();
  189. glutReportErrors();
  190. glutPostRedisplay();
  191. its++;
  192. }
  193. void idle()
  194. {
  195. }
  196. void keyboard(unsigned char key, int x, int y)
  197. {
  198.     switch(key) {
  199.         case 27:
  200.             exit(0);
  201.             break;
  202.         case 'f':
  203.             linearFiltering = !linearFiltering;
  204.             tex.filterMode = linearFiltering ? cudaFilterModeLinear : cudaFilterModePoint;
  205.             break;
  206.         case '=':
  207.             density += 0.01;
  208.             break;
  209.         case '-':
  210.             density -= 0.01;
  211.             break;
  212.         case '+':
  213.             density += 0.1;
  214.             break;
  215.         case '_':
  216.             density -= 0.1;
  217.             break;
  218.         case ']':
  219.             brightness += 0.1;
  220.             break;
  221.         case '[':
  222.             brightness -= 0.1;
  223.             break;
  224.         case ';':
  225.             transferOffset += 0.01;
  226.             break;
  227.         case ''':
  228.             transferOffset -= 0.01;
  229.             break;
  230.         case '.':
  231.             transferScale += 0.01;
  232.             break;
  233.         case ',':
  234.             transferScale -= 0.01;
  235.             break;
  236.         default:
  237.             break;
  238.     }
  239.     printf("density = %.2f, brightness = %.2f, transferOffset = %.2f, transferScale = %.2fn", density, brightness, transferOffset, transferScale);
  240.     glutPostRedisplay();
  241. }
  242. int ox, oy;
  243. int buttonState = 0;
  244. void mouse(int button, int state, int x, int y)
  245. {
  246.     if (state == GLUT_DOWN)
  247.         buttonState |= 1<<button;
  248.     else if (state == GLUT_UP)
  249.         buttonState = 0;
  250.     ox = x; oy = y;
  251.     glutPostRedisplay();
  252. }
  253. void motion(int x, int y)
  254. {
  255.     float dx, dy;
  256.     dx = x - ox;
  257.     dy = y - oy;
  258.     if (buttonState == 3) {
  259.         // left+middle = zoom
  260.         viewTranslation.z += dy / 100.0;
  261.     } 
  262.     else if (buttonState & 2) {
  263.         // middle = translate
  264.         viewTranslation.x += dx / 100.0;
  265.         viewTranslation.y -= dy / 100.0;
  266.     }
  267.     else if (buttonState & 1) {
  268.         // left = rotate
  269.         viewRotation.x += dy / 5.0;
  270.         viewRotation.y += dx / 5.0;
  271.     }
  272.     ox = x; oy = y;
  273.     glutPostRedisplay();
  274. }
  275. void reshape(int x, int y)
  276. {
  277.     width = x; height = y;
  278.     initPixelBuffer();
  279.     glViewport(0, 0, x, y);
  280.     glMatrixMode(GL_MODELVIEW);
  281.     glLoadIdentity();
  282.     glMatrixMode(GL_PROJECTION);
  283.     glLoadIdentity();
  284.     glOrtho(0.0, 1.0, 0.0, 1.0, 0.0, 1.0); 
  285. }
  286. void cleanup()
  287. {
  288.     cutilSafeCall(cudaFreeArray(d_volumeArray));
  289.     cutilSafeCall(cudaFreeArray(d_transferFuncArray));
  290. cutilSafeCall(cudaGLUnregisterBufferObject(pbo));    
  291. glDeleteBuffersARB(1, &pbo);
  292. }
  293. int iDivUp(int a, int b){
  294.     return (a % b != 0) ? (a / b + 1) : (a / b);
  295. }
  296. void initPixelBuffer()
  297. {
  298.     if (pbo) {
  299.         // delete old buffer
  300.         cutilSafeCall(cudaGLUnregisterBufferObject(pbo));
  301.         glDeleteBuffersARB(1, &pbo);
  302.     }
  303.     // create pixel buffer object for display
  304.     glGenBuffersARB(1, &pbo);
  305. glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
  306. glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, width*height*sizeof(GLubyte)*4, 0, GL_STREAM_DRAW_ARB);
  307. glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
  308. cutilSafeCall(cudaGLRegisterBufferObject(pbo));
  309.     // calculate new grid size
  310.     gridSize = dim3(iDivUp(width, blockSize.x), iDivUp(height, blockSize.y));
  311. }
  312. // Load raw data from disk
  313. uchar *loadRawFile(char *filename, size_t size)
  314. {
  315. FILE *fp = fopen(filename, "rb");
  316.     if (!fp) {
  317.         fprintf(stderr, "Error opening file '%s'n", filename);
  318.         return 0;
  319.     }
  320. uchar *data = (uchar *) malloc(size);
  321. size_t read = fread(data, 1, size, fp);
  322. fclose(fp);
  323.     printf("Read '%s', %d bytesn", filename, read);
  324.     return data;
  325. }
  326. float *loadMask(char *filename, size_t size){
  327. FILE *fp = fopen(filename, "rb");
  328.     if (!fp) {
  329.         fprintf(stderr, "Error opening file '%s'n", filename);
  330.         exit(EXIT_FAILURE);
  331.     }
  332. float *data = (float *) malloc(size*sizeof(float));
  333. size_t read = fread(data, 4, size, fp);
  334. fclose(fp);
  335.     printf("Read '%s', %d elementsn", filename, read);
  336.     return data;
  337. }
  338. void initseg(){
  339. size = volumeSize.width*volumeSize.height*volumeSize.depth;
  340. input = loadRawFile(volumeFilename, size);
  341. phi = loadMask(maskFilename, size);
  342. imageW=volumeSize.width;
  343. imageH=volumeSize.height;
  344. imageD=volumeSize.depth;
  345. N=imageW*imageH*imageD;
  346. if((D = (float *)malloc(imageW*imageH*imageD*sizeof(float)))==NULL)printf("ME_Dn");
  347. for(i=0;i<N;i++){
  348. D[i] = EPSILON - abs(input[i] - THRESHOLD);
  349. }
  350. // Set up CUDA Timer
  351. cutCreateTimer(&Timer);
  352. cutCreateTimer(&IterationTimer);
  353. cutStartTimer(Timer);
  354. if((contour= (float *)malloc(imageW*imageH*imageD*sizeof(float)))==NULL)printf("ME_Dn");
  355. // Allocate Memory on Device
  356. cudaMallocPitch((void**)&d_D,   &pitchbytes, sizeof(float)*imageW, imageH*imageD);
  357. cudaMallocPitch((void**)&d_phi,           &pitchbytes, sizeof(float)*imageW, imageH*imageD);
  358. cudaMallocPitch((void**)&d_phi1,          &pitchbytes, sizeof(float)*imageW, imageH*imageD);
  359. pitch=pitchbytes/sizeof(float);
  360. // Copy Host Thresholding Data to Device Memory
  361. cudaMemcpy2D(d_D,    pitchbytes, D,   sizeof(float)*imageW, sizeof(float)*imageW, imageH*imageD, cudaMemcpyHostToDevice);
  362. cudaMemcpy2D(d_phi1, pitchbytes, phi, sizeof(float)*imageW, sizeof(float)*imageW, imageH*imageD, cudaMemcpyHostToDevice);
  363. }
  364. ////////////////////////////////////////////////////////////////////////////////
  365. // Program main
  366. ////////////////////////////////////////////////////////////////////////////////
  367. int
  368. main( int argc, char** argv) 
  369. {
  370. initseg();
  371.     
  372.     
  373.     printf("Press '=' and '-' to change densityn"
  374.            "      ']' and '[' to change brightnessn"
  375.            "      ';' and ''' to modify transfer function offsetn"
  376.            "      '.' and ',' to modify transfer function scalen");
  377.     // initialize GLUT callback functions
  378.     glutInit(&argc, argv);
  379.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
  380.     glutInitWindowSize(width, height);
  381.     glutCreateWindow("CUDA volume rendering");
  382.     glutDisplayFunc(display);
  383.     glutKeyboardFunc(keyboard);
  384.     glutMouseFunc(mouse);
  385.     glutMotionFunc(motion);
  386.     glutReshapeFunc(reshape);
  387.     glutIdleFunc(idle);
  388.     glewInit();
  389.     if (!glewIsSupported("GL_VERSION_2_0 GL_ARB_pixel_buffer_object")) {
  390.         fprintf(stderr, "Required OpenGL extensions missing.");
  391.         exit(-1);
  392.     }
  393.     initPixelBuffer();
  394.     atexit(cleanup);
  395.     glutMainLoop();
  396.     cudaThreadExit();
  397.     return 0;
  398. }