00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #include "render_particles.h"
00035 #include <GL/glew.h>
00036
00037 #include <math.h>
00038 #include <assert.h>
00039
00040 #include <eq/base/log.h>
00041
00042 #define GL_POINT_SPRITE_ARB 0x8861
00043 #define GL_COORD_REPLACE_ARB 0x8862
00044 #define GL_VERTEX_PROGRAM_POINT_SIZE_NV 0x8642
00045
00046 namespace eqNbody
00047 {
00048 void _checkGLErrors(char *s)
00049 {
00050 GLenum error;
00051 while ((error = glGetError()) != GL_NO_ERROR) {
00052 EQERROR << s << "error - " << std::endl;
00053 exit(EXIT_FAILURE);
00054 }
00055 }
00056
00057 ParticleRenderer::ParticleRenderer()
00058 : m_pos(0),
00059 m_numParticles(0),
00060 m_pointSize(1.0f),
00061 m_spriteSize(1.0f),
00062 m_vertexShader(0),
00063 m_pixelShader(0),
00064 m_program(0),
00065 m_texture(0),
00066 m_pbo(0),
00067 m_vboColor(0)
00068 {
00069 }
00070
00071 ParticleRenderer::~ParticleRenderer()
00072 {
00073 m_pos = 0;
00074 }
00075
00076 void ParticleRenderer::setPositions(float *pos, int numParticles)
00077 {
00078 m_pos = pos;
00079 m_numParticles = numParticles;
00080 }
00081
00082 void ParticleRenderer::setColors(float *color, int numParticles)
00083 {
00084 glBindBuffer(GL_ARRAY_BUFFER_ARB, m_vboColor);
00085 glBufferData(GL_ARRAY_BUFFER_ARB, numParticles * 4 * sizeof(float), color, GL_STATIC_DRAW_ARB);
00086 glBindBuffer( GL_ARRAY_BUFFER_ARB, 0);
00087 }
00088
00089 void ParticleRenderer::setPBO(unsigned int pbo, int numParticles)
00090 {
00091 m_pbo = pbo;
00092 m_numParticles = numParticles;
00093 }
00094
00095 void ParticleRenderer::_drawPoints(bool color)
00096 {
00097 if (!m_pbo)
00098 {
00099 glBegin(GL_POINTS);
00100 {
00101 int k = 0;
00102 for (int i = 0; i < m_numParticles; ++i)
00103 {
00104 glVertex3fv(&m_pos[k]);
00105 k += 4;
00106 }
00107 }
00108 glEnd();
00109 }
00110 else
00111 {
00112 glEnableClientState(GL_VERTEX_ARRAY);
00113
00114 glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_pbo);
00115 glVertexPointer(4, GL_FLOAT, 0, 0);
00116
00117 if (color)
00118 {
00119 glEnableClientState(GL_COLOR_ARRAY);
00120 glBindBufferARB(GL_ARRAY_BUFFER_ARB, m_vboColor);
00121 glColorPointer(4, GL_FLOAT, 0, 0);
00122 }
00123
00124 glDrawArrays(GL_POINTS, 0, m_numParticles);
00125 glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
00126 glDisableClientState(GL_VERTEX_ARRAY);
00127
00128 if (color)
00129 {
00130 glDisableClientState(GL_COLOR_ARRAY);
00131 }
00132 }
00133 }
00134
00135 void ParticleRenderer::draw(DisplayMode mode)
00136 {
00137 switch (mode)
00138 {
00139 case PARTICLE_POINTS:
00140 glColor3f(1, 1, 1);
00141 glPointSize(m_pointSize);
00142 _drawPoints();
00143 break;
00144
00145 case PARTICLE_SPRITES:
00146 default:
00147 {
00148
00149 glEnable(GL_POINT_SPRITE_ARB);
00150 glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
00151 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_NV);
00152 glPointSize(m_spriteSize);
00153 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00154 glEnable(GL_BLEND);
00155 glDepthMask(GL_FALSE);
00156
00157 glUseProgram(m_program);
00158 GLuint texLoc = glGetUniformLocation(m_program, "splatTexture");
00159 glUniform1i(texLoc, 0);
00160
00161 glActiveTextureARB(GL_TEXTURE0_ARB);
00162 glBindTexture(GL_TEXTURE_2D, m_texture);
00163
00164 glColor3f(1, 1, 1);
00165
00166 _drawPoints();
00167
00168 glUseProgram(0);
00169
00170 glDisable(GL_POINT_SPRITE_ARB);
00171 glDisable(GL_BLEND);
00172 glDepthMask(GL_TRUE);
00173 }
00174 break;
00175
00176 case PARTICLE_SPRITES_COLOR:
00177 {
00178
00179 glEnable(GL_POINT_SPRITE_ARB);
00180 glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE);
00181 glEnable(GL_VERTEX_PROGRAM_POINT_SIZE_NV);
00182 glPointSize(m_spriteSize);
00183 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
00184 glEnable(GL_BLEND);
00185 glDepthMask(GL_FALSE);
00186
00187 glUseProgram(m_program);
00188 GLuint texLoc = glGetUniformLocation(m_program, "splatTexture");
00189 glUniform1i(texLoc, 0);
00190
00191 glActiveTextureARB(GL_TEXTURE0_ARB);
00192 glBindTexture(GL_TEXTURE_2D, m_texture);
00193
00194 glColor3f(1, 1, 1);
00195
00196 _drawPoints(true);
00197
00198 glUseProgram(0);
00199
00200 glDisable(GL_POINT_SPRITE_ARB);
00201 glDisable(GL_BLEND);
00202 glDepthMask(GL_TRUE);
00203 }
00204
00205 break;
00206 }
00207
00208 _checkGLErrors("GL error in draw");
00209 }
00210
00211 const char vertexShader[] =
00212 {
00213 "void main() \n"
00214 "{ \n"
00215 " float pointSize = 500.0 * gl_Point.size; \n"
00216 " vec4 vert = gl_Vertex; \n"
00217 " vert.w = 1.0; \n"
00218 " vec3 pos_eye = vec3 (gl_ModelViewMatrix * vert); \n"
00219 " gl_PointSize = max(1.0, pointSize / (1.0 - pos_eye.z)); \n"
00220 " gl_TexCoord[0] = gl_MultiTexCoord0; \n"
00221 " gl_Position = ftransform(); \n"
00222 " gl_FrontColor = gl_Color; \n"
00223 "} \n"
00224 };
00225
00226 const char pixelShader[] =
00227 {
00228 "uniform sampler2D splatTexture; \n"
00229
00230 "void main() \n"
00231 "{ \n"
00232 " vec4 color = (0.6 + 0.4 * gl_Color) * texture2D(splatTexture, gl_TexCoord[0].st); \n"
00233 " gl_FragColor = \n"
00234 " color * mix(vec4(0.1, 0.0, 0.0, color.w), vec4(1.0, 0.7, 0.3, color.w), color.w);\n"
00235 "} \n"
00236 };
00237
00238 void ParticleRenderer::init()
00239 {
00240 m_vertexShader = glCreateShader(GL_VERTEX_SHADER);
00241 m_pixelShader = glCreateShader(GL_FRAGMENT_SHADER);
00242
00243 const char* v = vertexShader;
00244 const char* p = pixelShader;
00245
00246 glShaderSource(m_vertexShader, 1, &v, 0);
00247 glShaderSource(m_pixelShader, 1, &p, 0);
00248
00249 glCompileShader(m_vertexShader);
00250 glCompileShader(m_pixelShader);
00251
00252 m_program = glCreateProgram();
00253
00254 glAttachShader(m_program, m_vertexShader);
00255 glAttachShader(m_program, m_pixelShader);
00256
00257 glLinkProgram(m_program);
00258
00259 _createTexture(32);
00260
00261 glGenBuffers(1, (GLuint*)&m_vboColor);
00262 glBindBuffer( GL_ARRAY_BUFFER_ARB, m_vboColor);
00263 glBufferData( GL_ARRAY_BUFFER_ARB, m_numParticles * 4 * sizeof(float), 0, GL_STATIC_DRAW_ARB);
00264 glBindBuffer( GL_ARRAY_BUFFER_ARB, 0);
00265
00266 }
00267
00268
00269
00270
00271
00276 inline float evalHermite(float pA, float pB, float vA, float vB, float u)
00277 {
00278 float u2=(u*u), u3=u2*u;
00279 float B0 = 2*u3 - 3*u2 + 1;
00280 float B1 = -2*u3 + 3*u2;
00281 float B2 = u3 - 2*u2 + u;
00282 float B3 = u3 - u;
00283 return( B0*pA + B1*pB + B2*vA + B3*vB );
00284 }
00285
00286 unsigned char* createGaussianMap(int N)
00287 {
00288 float *M = new float[2*N*N];
00289 unsigned char *B = new unsigned char[4*N*N];
00290 float X,Y,Y2,Dist;
00291 float Incr = 2.0f/N;
00292 int i=0;
00293 int j = 0;
00294 Y = -1.0f;
00295
00296 for (int y=0; y<N; y++, Y+=Incr)
00297 {
00298 Y2=Y*Y;
00299 X = -1.0f;
00300 for (int x=0; x<N; x++, X+=Incr, i+=2, j+=4)
00301 {
00302 Dist = (float)sqrtf(X*X+Y2);
00303 if (Dist>1) Dist=1;
00304 M[i+1] = M[i] = evalHermite(1.0f,0,0,0,Dist);
00305 B[j+3] = B[j+2] = B[j+1] = B[j] = (unsigned char)(M[i] * 255);
00306 }
00307 }
00308 delete [] M;
00309 return(B);
00310 }
00311
00312 void ParticleRenderer::_createTexture(int resolution)
00313 {
00314 unsigned char* data = createGaussianMap(resolution);
00315 glGenTextures(1, (GLuint*)&m_texture);
00316 glBindTexture(GL_TEXTURE_2D, m_texture);
00317 glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE);
00318 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
00319 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00320 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, resolution, resolution, 0,
00321 GL_RGBA, GL_UNSIGNED_BYTE, data);
00322
00323 }
00324 }