martes, 7 de diciembre de 2010

Simple OPENGL con CUDA

Aca les dejo un simple ejemplo con OpenGL es el mismo de la pagina de CUDA pero no tiene referenciado nada de sus liberias CUTIL es solo CUDA :). Para compilarlo ejecuta esto "nvcc mesh.cu -o mesh -lglut -lGLEW"

Espero les ayude.





/*
* Copyright 1993-2010 NVIDIA Corporation. All rights reserved.
*
* Please refer to the NVIDIA end user license agreement (EULA) associated
* with this source code for terms and conditions that govern your use of
* this software. Any use, reproduction, disclosure, or distribution of
* this software and related documentation outside the terms of the EULA
* is strictly prohibited.
*
*/

/*
This example demonstrates how to use the Cuda OpenGL bindings to
dynamically modify a vertex buffer using a Cuda kernel.

The steps are:
1. Create an empty vertex buffer object (VBO)
2. Register the VBO with Cuda
3. Map the VBO for writing from Cuda
4. Run Cuda kernel to modify the vertex positions
5. Unmap the VBO
6. Render the results using OpenGL

Host code
*/

// includes, system
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

// includes, GL
#include <GL/glew.h>


#include <GL/glut.h>

// includes
#include <cudaGL.h>
#include <cuda.h>
#include <cuda_runtime.h>
#include <vector_types.h>
#include <cuda_gl_interop.h>
#include <unistd.h>




////////////////////////////////////////////////////////////////////////////////
// constants
const unsigned int window_width = 512;
const unsigned int window_height = 512;

const unsigned int width = 256;
const unsigned int height = 256;

// vbo variables
GLuint vbo;
struct cudaGraphicsResource *cuda_vbo_resource;

// mouse controls
int mouse_old_x, mouse_old_y;
int mouse_buttons = 0;
float rotate_x = 0.0, rotate_y = 0.0;
float translate_z = -3.0;

float time1=0.0;


struct cudaGraphicsResource* positionsVBO_CUDA;

/*blocks ands grids*/
dim3 dimBlock(8,8,1);
dim3 dimGrid(width/dimBlock.x,height/dimBlock.y,1);
float4* positions;

////////////////////////////////////////////////////////////////////////////////
//! Keyboard events handler
////////////////////////////////////////////////////////////////////////////////
void keyboard(unsigned char key, int /*x*/, int /*y*/)
{
switch(key) {
case(27) :
exit(0);
break;
}
}

////////////////////////////////////////////////////////////////////////////////
//! Mouse event handlers
////////////////////////////////////////////////////////////////////////////////
void mouse(int button, int state, int x, int y)
{
if (state == GLUT_DOWN) {
mouse_buttons |= 1<<button;
} else if (state == GLUT_UP) {
mouse_buttons = 0;
}

mouse_old_x = x;
mouse_old_y = y;
glutPostRedisplay();
}

void motion(int x, int y)
{
float dx, dy;
dx = x - mouse_old_x;
dy = y - mouse_old_y;

if (mouse_buttons & 1) {
rotate_x += dy * 0.2;
rotate_y += dx * 0.2;
} else if (mouse_buttons & 4) {
translate_z += dy * 0.01;
}

mouse_old_x = x;
mouse_old_y = y;
}


void deleteVBO()
{
cudaGraphicsUnregisterResource(positionsVBO_CUDA);
glDeleteBuffers(1,&vbo);
}

__global__ void createVertices(float4* positions,float time1,unsigned int width,unsigned int height)
{
unsigned int x=blockIdx.x*blockDim.x+threadIdx.x;
unsigned int y=blockIdx.y*blockDim.y+threadIdx.y;

//calculae uv coordinates
float u=x/(float)width;
float v=y/(float)height;

u=u*2.0f-1.0f;
v=v*2.0f-1.0f;

//calculate simple sine wave pattern

float freq=4.0f;
float w=sinf(u*freq+time1)*cosf(v*freq+time1)*0.5f;

//write pòsitions
positions[y*width+x]=make_float4(u,w,v,1.0f);
}


/////////////////////////////////////////////////////////////////////////////////
//Display
////////////////////////////////////////////////////////////////////////////////


void init()
{

cudaGraphicsMapResources(1,&positionsVBO_CUDA,0);
size_t num_bytes;
cudaGraphicsResourceGetMappedPointer((void**)&positions,&num_bytes,positionsVBO_CUDA);




}
void display()
{

//Execute kernel
createVertices<<<dimGrid,dimBlock>>>(positions,time1,width,height);

cudaFree(&positions);
//unmap buffer object

cudaGraphicsUnmapResources(1,&positionsVBO_CUDA,0);

//render from buffer object
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glTranslatef(0.0, 0.0, translate_z);
glRotatef(rotate_x, 1.0, 0.0, 0.0);
glRotatef(rotate_y, 0.0, 1.0, 0.0);

glBindBuffer(GL_ARRAY_BUFFER,vbo);
glVertexPointer(4,GL_FLOAT,0,0);
glEnableClientState(GL_VERTEX_ARRAY);

glColor3f(1.0,0.0,0.0);
glDrawArrays(GL_POINTS,0,width*height);
glDisableClientState(GL_VERTEX_ARRAY);

//swap buffers

glutSwapBuffers();
glutPostRedisplay();


time1+=0.01;
usleep(1000); //sleel 1000 us
}


////////////////////////////////////////////////////////////////////////////////
// Program main
////////////////////////////////////////////////////////////////////////////////

int main(int argc, char** argv)
{

/*paramets to init opengl*/
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
glutInitWindowSize(window_width, window_height);
glutCreateWindow("Cuda GL ");



// initialize necessary OpenGL extensions
glewInit();
if (! glewIsSupported("GL_VERSION_2_0 ")) {
fprintf(stderr, "ERROR: Support for necessary OpenGL extensions missing.");
fflush(stderr);
return -1;
}

// default initialization
glClearColor(0.0, 0.0, 0.0, 1.0);
glDisable(GL_DEPTH_TEST);

// set viewport
glViewport(0, 0, window_width, window_height);

// projection
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(60.0, (GLfloat)window_width / (GLfloat) window_height, 0.1, 10.0);


//set device NVIDIA

cudaGLSetGLDevice(0);




//create buffer object and register with cuda
glGenBuffers(1,&vbo);
glBindBuffer(GL_ARRAY_BUFFER,vbo); //bind object with vbo
unsigned int size=width*height*4*sizeof(float);
glBufferData(GL_ARRAY_BUFFER,size,0,GL_DYNAMIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER,0);
cudaGraphicsGLRegisterBuffer(&positionsVBO_CUDA,vbo,cudaGraphicsMapFlagsWriteDiscard);
init(); //map object with cuda

glutDisplayFunc(display);
glutKeyboardFunc(keyboard);
glutMotionFunc(motion);
glutMouseFunc(mouse);

glutMainLoop();
return 0;
}



Unas imagenes de como salio ;)


No hay comentarios: