【发布时间】:2019-01-13 23:37:28
【问题描述】:
简介:
我正在制作一个粉末玩具,它利用并行处理来进行游戏物理,它处理 500 x 500 区域的粉末。游戏主要使用 GPU 上的粒子完成所有操作,但它使用 CPU 来渲染粒子(大大降低了速度)。如何在 GPU 而不是 CPU 上渲染粒子?我主要将我的粒子数据保存在 GPU 上,因为大多数操作都发生在那里,而且 cudaMemcpy 非常慢,当它在主机内存上时,项目会无法控制地滞后。
代码:
这是我的显示功能
void display()
{
// Measure performance
mainloopMeasurePerformanceStart(1);
// Clear the screen
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// Copy particle data to render
cudaMemcpy(&particles, d_particles, sizeof(particles), cudaMemcpyDeviceToHost);
// Loop over the sand particles
for(int i=0;i<250000;i++)
{
// Is the sand particle alive
if(particles[i].alive)
{
// Get the position
int pos[2];
id_to_pos(i,pos);
// Draw the pixel
glColor3f(particles[i].color[0],particles[i].color[1],particles[i].color[2]);
glBegin(GL_QUADS);
glVertex2d((pos[0]/500.0-0.5)*2,(pos[1]/500.0-0.5)*2);
glVertex2d((pos[0]/500.0-0.5+0.002)*2,(pos[1]/500.0-0.5)*2);
glVertex2d((pos[0]/500.0-0.5+0.002)*2,(pos[1]/500.0-0.5+0.002)*2);
glVertex2d((pos[0]/500.0-0.5)*2,(pos[1]/500.0-0.5+0.002)*2);
glEnd();
}
}
// Get the mouse position
int m_posX, m_posY;
mousePos(&m_posX, &m_posY);
// Draw the cursor
glColor3f(1.0f, 1.0f, 1.0f);
for(int i=0;i<360;i++)
{
// Calculate the position
double pos[2];
pos[0] = sin(2*PI/360*i)*cursor_radius+m_posX;
pos[1] = cos(2*PI/360*i)*cursor_radius+m_posY;
glBegin(GL_QUADS);
glVertex2d((pos[0]/500.0-0.5)*2,(pos[1]/500.0-0.5)*2);
glVertex2d((pos[0]/500.0-0.5+0.002)*2,(pos[1]/500.0-0.5)*2);
glVertex2d((pos[0]/500.0-0.5+0.002)*2,(pos[1]/500.0-0.5+0.002)*2);
glVertex2d((pos[0]/500.0-0.5)*2,(pos[1]/500.0-0.5+0.002)*2);
glEnd();
}
// Swap the front and back frame buffers
glutSwapBuffers();
// Measure performance
mainloopMeasurePerformanceEnd();
}
以及处理沙子的地方:
__global__ void do_sand(
Sand *particles, bool *mouseStates, unsigned long seed,
int m_pos_x, int m_pos_y, double cursor_radius
){
// Get the overall ID
int id = blockIdx.x*100+threadIdx.x;
// Convert the ID to a position
int pos[2];
id_to_pos(id,pos);
// Convert the mouse position to an array
int m_pos[2];
m_pos[0] = m_pos_x;
m_pos[1] = m_pos_y;
// Is the sand particle alive
if(particles[id].alive)
{
// Is there sand being cleared and is this particle in range
if(mouseStates[GLUT_RIGHT_BUTTON] && distance_between(pos, m_pos) < cursor_radius)
{
// Delete this particle
particles[id].alive = false;
}
// Do physics
bool done = false;
int check;
switch(particles[id].model)
{
// Powder
case 'P':
{
// Is vertical movement valid
if(pos[1]-1 >= 0 && !done)
{
// Get the ID
check = pos_to_id(pos[0], pos[1]-1);
// Is this space free
if(!particles[check].alive)
{
// Move the particle
particles[check] = particles[id];
particles[id].alive = false;
done = true;
}
}
// Randomly pick the sands course
int choice;
if((seed * id * 5423) % 2 == 0) choice=1;
else choice=-1;
// Check left movement
if(pos[0]-choice < 500 && pos[0]-choice >= 0 && pos[1]-1 >= 0 && !done)
{
// Get the ID
check = pos_to_id(pos[0]-choice,pos[1]-1);
// Is this space free
if(
!particles[check].alive &&
!particles[pos_to_id(pos[0]-choice,pos[1])].alive &&
!(
particles[pos_to_id(pos[0]-choice*2,pos[1])].alive &&
particles[pos_to_id(pos[0]-choice*2,pos[1]-1)].alive
)
){
// Move the particle
particles[check] = particles[id];
particles[id].alive = false;
done = true;
}
}
// Check right movement
if(pos[0]+choice < 500 && pos[0]+choice >= 0 && pos[1]-1 >= 0 && !done)
{
// Get the ID
check = pos_to_id(pos[0]+choice,pos[1]-1);
// Is this space free
if(
!particles[check].alive &&
!particles[pos_to_id(pos[0]+choice,pos[1])].alive &&
!(
particles[pos_to_id(pos[0]+choice*2,pos[1])].alive &&
particles[pos_to_id(pos[0]+choice*2,pos[1]-1)].alive
)
){
// Move the particle
particles[check] = particles[id];
particles[id].alive = false;
done = true;
}
}
}
// Fluid
case 'F':
{
}
}
}
// Is there sand being added and is this particle in range
else if(mouseStates[GLUT_LEFT_BUTTON] && distance_between(pos, m_pos) < cursor_radius)
{
// Make this particle
particles[id].alive = true;
particles[id].color[0] = 0.0f;
particles[id].color[1] = 0.0f;
particles[id].color[2] = 0.6f;
particles[id].model = 'P';
}
}
【问题讨论】:
-
this 还有很多 CUDA/OpenGL interop sample codes