render_particles.cpp

00001 /*
00002  * Copyright 1993-2006 NVIDIA Corporation.  All rights reserved.
00003  *
00004  * NOTICE TO USER:   
00005  *
00006  * This source code is subject to NVIDIA ownership rights under U.S. and 
00007  * international Copyright laws.  
00008  *
00009  * NVIDIA MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE 
00010  * CODE FOR ANY PURPOSE.  IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR 
00011  * IMPLIED WARRANTY OF ANY KIND.  NVIDIA DISCLAIMS ALL WARRANTIES WITH 
00012  * REGARD TO THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF 
00013  * MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE.   
00014  * IN NO EVENT SHALL NVIDIA BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL, 
00015  * OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS 
00016  * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 
00017  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE 
00018  * OR PERFORMANCE OF THIS SOURCE CODE.  
00019  *
00020  * U.S. Government End Users.  This source code is a "commercial item" as 
00021  * that term is defined at 48 C.F.R. 2.101 (OCT 1995), consisting  of 
00022  * "commercial computer software" and "commercial computer software 
00023  * documentation" as such terms are used in 48 C.F.R. 12.212 (SEPT 1995) 
00024  * and is provided to the U.S. Government only as a commercial end item.  
00025  * Consistent with 48 C.F.R.12.212 and 48 C.F.R. 227.7202-1 through 
00026  * 227.7202-4 (JUNE 1995), all U.S. Government End Users acquire the 
00027  * source code with only those rights set forth herein.
00028  */
00029 
00030 /*
00031  * Slightly adapted 2009 by Ph. Robert wrt the Equalizer port
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; // << (char *) gluErrorString(error)
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                 // setup point sprites
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                 // setup point sprites
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     // Function           : EvalHermite
00270     // Description      : 
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         //float mmax = 0;
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 }
Generated on Mon Aug 10 18:58:41 2009 for Equalizer 0.9 by  doxygen 1.5.8