372 22.GPGPUClothSimulationUsing GLSL,OpenCL,andCUDA
22.6GLSLImplementation
This section describes the implementation of the algorithm in GLSL 1.2. The
source code for the vertex and fragment shaders is provided in the files
ver-
let_cloth.vs
and verlet_cloth.fs, respectively, on the website. The position
and velocity arrays are each stored in a different texture having
nn
dimensions.
In such textures, each particle corresponds to a single texel. The textures are up-
loaded to the GPU, and then the computation is carried out in the fragment
shader, where each particle is handled in a separate thread. The updated state
(i.e., positions, previous positions, and normal vectors) is written to three distinct
render targets.
Frame buffer objects (FBOs) are employed for efficiently storing and access-
ing the input textures and the output render targets. The ping-pong technique is
applied through the use of two frame buffer objects, FBO1 and FBO2. Each FBO
contains three textures storing the state of the particles. These three textures are
attached to their corresponding FBOs as color buffers using the following code,
where
fb is the index of the FBO and texid[0], texid[1], and texid[2] are
the indices of the textures storing the current positions, the previous positions,
and the normal vectors of the particles, respectively:
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo->fb);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texid[0], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, texid[1], 0);
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT,
GL_COLOR_ATTACHMENT2_EXT, GL_TEXTURE_2D, texid[2], 0);
In the initialization phase, both of the FBOs holding the initial state of the
particles are uploaded to video memory. When the algorithm is run, one of the
FBOs is used as input and the other one as output. The fragment shader reads
the data from the input FBO and writes the results in the render targets of the
output FBO (stored in the color buffers). We declare the output render targets by
using the following code, where
fb_out is the FBO that stores the output:
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_out);
GLenum mrt[] = {GL_COLOR_ATTACHMENT0_EXT,
GL_COLOR_ATTACHMENT1_EXT, GL_COLOR_ATTACHMENT2_EXT};
glDrawBuffers(3, mrt);