splatrenderer.h
Go to the documentation of this file.
00001 /****************************************************************************
00002 * MeshLab                                                           o o     *
00003 * A versatile mesh processing toolbox                             o     o   *
00004 *                                                                _   O  _   *
00005 * Copyright(C) 2005                                                \/)\/    *
00006 * Visual Computing Lab                                            /\/|      *
00007 * ISTI - Italian National Research Council                           |      *
00008 *                                                                    \      *
00009 * All rights reserved.                                                      *
00010 *                                                                           *
00011 * This program is free software; you can redistribute it and/or modify      *
00012 * it under the terms of the GNU General Public License as published by      *
00013 * the Free Software Foundation; either version 2 of the License, or         *
00014 * (at your option) any later version.                                       *
00015 *                                                                           *
00016 * This program is distributed in the hope that it will be useful,           *
00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
00019 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
00020 * for more details.                                                         *
00021 *                                                                           *
00022 ****************************************************************************/
00023 
00024 #ifndef SPLATRENDERER_H
00025 #define SPLATRENDERER_H
00026 
00027 #include <QObject>
00028 #include <QTextStream>
00029 #include <QFile>
00030 #include <wrap/gl/trimesh.h>
00031 #include <wrap/gl/shaders.h>
00032 #include <wrap/gl/trimesh.h>
00033 #include <QGLFramebufferObject>
00034 #include <vcg/complex/complex.h>
00035 #define GL_TEST_ERR\
00036         {\
00037                         GLenum eCode;\
00038                         if((eCode=glGetError())!=GL_NO_ERROR)\
00039                                         std::cerr << "OpenGL error : " <<  gluErrorString(eCode) << " in " <<  __FILE__ << " : " << __LINE__ << std::endl;\
00040         }
00041 
00042 class QGLFramebufferObject;
00043 
00044 /*
00045         Rendering with Algebraic Point Set Surfaces, by Gael Guennebaud.
00046         paper: Algebraic Point Set Surfaces SIGGRAPH '07 
00047 */
00048 template <class MeshType>
00049 class SplatRenderer 
00050 {
00051         bool mIsSupported;
00052         bool init_called;
00053 
00054         enum {
00055                 DEFERRED_SHADING_BIT    = 0x000001,
00056                 DEPTH_CORRECTION_BIT    = 0x000002,
00057                 OUTPUT_DEPTH_BIT                        = 0x000004,
00058                 BACKFACE_SHADING_BIT    = 0x000008,
00059                 FLOAT_BUFFER_BIT                        = 0x000010
00060         };
00061         int mFlags;
00062         int mCachedFlags;
00063         int mRenderBufferMask;
00064         int mSupportedMask;
00065 
00066         //int mCurrentPass;
00067         int mBindedPass;
00068         GLuint mDummyTexId; // on ATI graphics card we need to bind a texture to get point sprite working !
00069         bool mWorkaroundATI;
00070         bool mBuggedAtiBlending;
00071         GLuint mNormalTextureID;
00072         GLuint mDepthTextureID;
00073         ProgramVF mShaders[3];
00074         QString mShaderSrcs[6];
00075         QGLFramebufferObject* mRenderBuffer;
00076         float mCachedMV[16];
00077         float mCachedProj[16];
00078         GLint mCachedVP[4];
00079 
00080         struct UniformParameters
00081         {
00082                 float radiusScale;
00083                 float preComputeRadius;
00084                 float depthOffset;
00085                 float oneOverEwaRadius;
00086                 vcg::Point2f halfVp;
00087                 vcg::Point3f rayCastParameter1;
00088                 vcg::Point3f rayCastParameter2;
00089                 vcg::Point2f depthParameterCast;
00090 
00091                 void loadTo(Program& prg);
00092                 void update(float* mv, float* proj, GLint* vp);
00093         };
00094 
00095         UniformParameters mParams;
00096 
00097         QString loadSource(const QString& func,const QString& file);
00098         void configureShaders();
00099         void updateRenderBuffer();
00100         void enablePass(int n);
00101         void drawSplats(std::vector<MeshType*> & , vcg::GLW::ColorMode cm,  vcg::GLW::TextureMode tm);
00102         void drawSplats(
00103                 std::vector< std::vector<vcg::Point3f> *                                > & positions,
00104                 std::vector< std::vector<vcg::Point3f> *                                > & normals,
00105                 std::vector< std::vector<vcg::Point3<unsigned char> > * > & colors,
00106                 std::vector<float>  & radius,
00107                 vcg::GLW::ColorMode cm,  vcg::GLW::TextureMode tm);
00108         
00109 
00110 public:
00111 
00112         void Clear();
00113         void Destroy();
00114         bool isSupported() {return mIsSupported;}
00115         void Init(QGLWidget *gla);
00116         void Render( std::vector<MeshType*> &meshes,  vcg::GLW::ColorMode cm,  vcg::GLW::TextureMode tm);
00117 
00118         void Render(
00119                 std::vector< std::vector<vcg::Point3f> *                                > & positions,
00120                 std::vector< std::vector<vcg::Point3f> *                                > & normals,
00121                 std::vector< std::vector<vcg::Point3<unsigned char> > * > & colors,
00122                 std::vector<float>  & radius,
00123                 vcg::GLW::ColorMode cm,  vcg::GLW::TextureMode tm);
00124 
00125 };// end class
00126 
00127 template <class MeshType>
00128 void SplatRenderer<MeshType>:: Destroy(){
00129         delete mRenderBuffer; 
00130         mRenderBuffer = 0;
00131         glDeleteTextures(1,&mDepthTextureID);
00132         glDeleteTextures(1,&mNormalTextureID);
00133         for(int i = 0; i < 3; ++i)
00134                 this->mShaders[i].prog.Del();
00135 
00136         Clear();
00137 }
00138 
00139 template <class MeshType>
00140 void SplatRenderer<MeshType>::Clear()
00141 {
00142         mNormalTextureID = 0;
00143         mDepthTextureID = 0;
00144         mIsSupported = false;
00145         mRenderBuffer = 0;
00146         mWorkaroundATI = false;
00147         mBuggedAtiBlending = false;
00148         mDummyTexId = 0;
00149 
00150         mFlags = DEFERRED_SHADING_BIT | DEPTH_CORRECTION_BIT | FLOAT_BUFFER_BIT | OUTPUT_DEPTH_BIT;
00151         mCachedFlags = ~mFlags;
00152         // union of bits which controls the render buffer
00153         mRenderBufferMask = DEFERRED_SHADING_BIT | FLOAT_BUFFER_BIT;
00154 
00155         init_called = false;
00156 }
00157 
00158 
00159 template <class MeshType>
00160 QString SplatRenderer<MeshType>::loadSource(const QString& func,const QString& filename)
00161 {
00162         QString res;
00163         QFile f(":/SplatRenderer/shaders/" + filename);
00164         if (!f.open(QFile::ReadOnly))
00165         {
00166                 std::cerr << "failed to load shader file " << filename.toUtf8().data() << "\n";
00167                 return res;
00168         }
00169         else qDebug("Succesfully loaded shader func '%s' in file '%s'",qPrintable(func),qPrintable(filename));
00170         QTextStream stream(&f);
00171         res = stream.readAll();
00172         f.close();
00173         res = QString("#define __%1__ 1\n").arg(func)
00174                         + QString("#define %1 main\n").arg(func)
00175                         + res;
00176         return res;
00177 }
00178 template <class MeshType>
00179 void SplatRenderer<MeshType>::configureShaders()
00180 {
00181         const char* passNames[3] = {"Visibility","Attribute","Finalization"};
00182         QString defines = "";
00183         if (mFlags & DEFERRED_SHADING_BIT)
00184                 defines += "#define EXPE_DEFERRED_SHADING\n";
00185         if (mFlags & DEPTH_CORRECTION_BIT)
00186                 defines += "#define EXPE_DEPTH_CORRECTION\n";
00187         if (mFlags & OUTPUT_DEPTH_BIT)
00188                 defines += "#define EXPE_OUTPUT_DEPTH 1\n";
00189         if (mFlags & BACKFACE_SHADING_BIT)
00190                 defines += "#define EXPE_BACKFACE_SHADING\n";
00191         if (mWorkaroundATI)
00192                 defines += "#define EXPE_ATI_WORKAROUND\n";
00193 
00194         QString shading =
00195 "vec4 meshlabLighting(vec4 color, vec3 eyePos, vec3 normal)"
00196 "{"
00197 "       normal = normalize(normal);"
00198 "       vec3 lightVec = normalize(gl_LightSource[0].position.xyz);"
00199 "       vec3 halfVec = normalize( lightVec - normalize(eyePos) );"
00200 "       float aux_dot = dot(normal,lightVec);"
00201 "       float diffuseCoeff = clamp(aux_dot, 0.0, 1.0);"
00202 " float specularCoeff = aux_dot>0.0 ? clamp(pow(clamp(dot(halfVec, normal),0.0,1.0),gl_FrontMaterial.shininess), 0.0, 1.0) : 0.0;"
00203 "       return vec4(color.rgb * ( gl_FrontLightProduct[0].ambient.rgb + diffuseCoeff * gl_FrontLightProduct[0].diffuse.rgb) + specularCoeff * gl_FrontLightProduct[0].specular.rgb, 1.0);"
00204 "}\n";
00205 
00206         for (int k=0;k<3;++k)
00207         {
00208                 QString vsrc = shading + defines + mShaderSrcs[k*2+0];
00209                 QString fsrc = shading + defines + mShaderSrcs[k*2+1];
00210                 mShaders[k].SetSources(mShaderSrcs[k*2+0]!="" ? vsrc.toUtf8().data() : 0,
00211                                                                                                          mShaderSrcs[k*2+1]!="" ? fsrc.toUtf8().data() : 0);
00212                 mShaders[k].prog.Link();
00213                 if (mShaderSrcs[k*2+0]!="")
00214                 {
00215                         std::string compileinfo = mShaders[k].vshd.InfoLog();
00216                         if (compileinfo.size()>0)
00217                                 std::cout << "Vertex shader info (" << passNames[k] << ":\n" << compileinfo << "\n";
00218                 }
00219                 if (mShaderSrcs[k*2+1]!="")
00220                 {
00221                         std::string compileinfo = mShaders[k].fshd.InfoLog();
00222                         if (compileinfo.size()>0)
00223                                 std::cout << "Fragment shader info (" << passNames[k] << ":\n" << compileinfo << "\n";
00224                 }
00225                 std::string linkinfo = mShaders[k].prog.InfoLog();
00226                 if (linkinfo.size()>0)
00227                         std::cout << "Link info (" << passNames[k] << ":\n" << linkinfo << "\n";
00228         }
00229 }
00230 
00231 template <class MeshType>
00232 void SplatRenderer<MeshType>::Init(QGLWidget *gla)
00233 {
00234 
00235         mIsSupported = true;
00236         gla->makeCurrent();
00237         // FIXME this should be done in meshlab !!! ??
00238         glewInit();
00239 
00240         const char* rs = (const char*)glGetString(GL_RENDERER);
00241         QString rendererString("");
00242         if(rs)
00243                 rendererString = QString(rs);
00244         mWorkaroundATI = rendererString.startsWith("ATI") || rendererString.startsWith("AMD");
00245         // FIXME: maybe some recent HW correctly supports floating point blending...
00246         mBuggedAtiBlending = rendererString.startsWith("ATI") || rendererString.startsWith("AMD");
00247 
00248         if (mWorkaroundATI && mDummyTexId==0)
00249         {
00250                 glActiveTexture(GL_TEXTURE0);
00251                 glGenTextures(1,&mDummyTexId);
00252                 glBindTexture(GL_TEXTURE_2D, mDummyTexId);
00253                 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 4, 4, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
00254         }
00255 
00256         // let's check the GPU capabilities
00257         mSupportedMask = DEPTH_CORRECTION_BIT | BACKFACE_SHADING_BIT;
00258         if (!QGLFramebufferObject::hasOpenGLFramebufferObjects ())
00259         {
00260                 mIsSupported = false;
00261                 return;
00262         }
00263         if (GLEW_ARB_texture_float)
00264                 mSupportedMask |= FLOAT_BUFFER_BIT;
00265         else
00266                 std::cout << "Splatting: warning floating point textures are not supported.\n";
00267 
00268         if (GLEW_ARB_draw_buffers && (!mBuggedAtiBlending))
00269                 mSupportedMask |= DEFERRED_SHADING_BIT;
00270         else
00271                 std::cout << "Splatting: warning deferred shading is not supported.\n";
00272 
00273         if (GLEW_ARB_shadow)
00274                 mSupportedMask |= OUTPUT_DEPTH_BIT;
00275         else
00276                 std::cerr << "Splatting: warning copy of the depth buffer is not supported.\n";
00277 
00278         mFlags = mFlags & mSupportedMask;
00279 
00280         // load shader source
00281         mShaderSrcs[0] = loadSource("VisibilityVP","Raycasting.glsl");
00282         mShaderSrcs[1] = loadSource("VisibilityFP","Raycasting.glsl");
00283         mShaderSrcs[2] = loadSource("AttributeVP","Raycasting.glsl");
00284         mShaderSrcs[3] = loadSource("AttributeFP","Raycasting.glsl");
00285         mShaderSrcs[4] = "";
00286         mShaderSrcs[5] = loadSource("Finalization","Finalization.glsl");
00287 
00288         //mCurrentPass = 2;
00289         mBindedPass = -1;
00290         GL_TEST_ERR
00291 }
00292 
00293 template <class MeshType>
00294 void SplatRenderer<MeshType>::updateRenderBuffer()
00295 {
00296         if ( (!mRenderBuffer)
00297                 || (mRenderBuffer->width()!=mCachedVP[2])
00298                 || (mRenderBuffer->height()!=mCachedVP[3])
00299                 || ( (mCachedFlags & mRenderBufferMask) != (mFlags & mRenderBufferMask) ))
00300         {
00301                 delete mRenderBuffer;
00302                 GLenum fmt = (mFlags&FLOAT_BUFFER_BIT) ? GL_RGBA16F_ARB : GL_RGBA;
00303                 mRenderBuffer = new QGLFramebufferObject(mCachedVP[2], mCachedVP[3],
00304                                 (mFlags&OUTPUT_DEPTH_BIT) ? QGLFramebufferObject::NoAttachment : QGLFramebufferObject::Depth,
00305                                 GL_TEXTURE_RECTANGLE_ARB, fmt);
00306 
00307                 if (!mRenderBuffer->isValid())
00308                 {
00309                         std::cout << "SplatRenderer: invalid FBO\n";
00310                 }
00311 
00312                 GL_TEST_ERR
00313                 if (mFlags&DEFERRED_SHADING_BIT)
00314                 {
00315                         // in deferred shading mode we need an additional buffer to accumulate the normals
00316                         if (mNormalTextureID==0)
00317                                 glGenTextures(1,&mNormalTextureID);
00318                         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mNormalTextureID);
00319                         glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, fmt, mCachedVP[2], mCachedVP[3], 0, GL_RGBA, GL_FLOAT, 0);
00320                         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00321                         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00322                         mRenderBuffer->bind();
00323                         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_RECTANGLE_ARB, mNormalTextureID, 0);
00324                         mRenderBuffer->release();
00325                         GL_TEST_ERR
00326                 }
00327 
00328                 if (mFlags&OUTPUT_DEPTH_BIT)
00329                 {
00330                         // to output the depth values to the final depth buffer we need to
00331                         // attach a depth buffer as a texture
00332                         if (mDepthTextureID==0)
00333                                 glGenTextures(1,&mDepthTextureID);
00334                         glBindTexture(GL_TEXTURE_RECTANGLE_ARB, mDepthTextureID);
00335                         glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_DEPTH_COMPONENT24_ARB, mCachedVP[2], mCachedVP[3], 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
00336                         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00337                         glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00338                         mRenderBuffer->bind();
00339                         glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_RECTANGLE_ARB, mDepthTextureID, 0);
00340                         mRenderBuffer->release();
00341                         GL_TEST_ERR
00342                 }
00343         }
00344 }
00345 
00346 
00347 template <class MeshType>
00348 void SplatRenderer<MeshType>::Render(std::vector<MeshType*> & meshes,  vcg::GLW::ColorMode cm,  vcg::GLW::TextureMode tm )
00349 {
00350         if(meshes.empty()) return;
00351 
00352         GL_TEST_ERR
00353 
00354                 /*************** First Pass ***********/
00355                 // this is the first pass of the frame, so let's update the shaders, buffers, etc...
00356                 glGetIntegerv(GL_VIEWPORT, mCachedVP);
00357                 glGetFloatv(GL_MODELVIEW_MATRIX, mCachedMV);
00358                 glGetFloatv(GL_PROJECTION_MATRIX, mCachedProj);
00359 
00360                 updateRenderBuffer();
00361                 if (mCachedFlags != mFlags)
00362                         configureShaders();
00363 
00364                 mCachedFlags = mFlags;
00365 
00366                 mParams.update(mCachedMV, mCachedProj, mCachedVP);
00367                 //float s = meshes[0]->glw.GetHintParamf(vcg::GLW::HNPPointSize);
00368                 //if (s>1)
00369                 //      s = pow(s,0.3f);
00370                 float s = 1.f;
00371                 mParams.radiusScale *= s;
00372 
00373                 // FIXME since meshlab does not set any material properties, let's define some here
00374                 glDisable(GL_COLOR_MATERIAL);
00375                 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64);
00376                 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, vcg::Point4f(0.3, 0.3, 0.3, 1.).V());
00377                 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, vcg::Point4f(0.6, 0.6, 0.6, 1.).V());
00378                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vcg::Point4f(0.5, 0.5, 0.5, 1.).V());
00379 
00380                 mRenderBuffer->bind();
00381                 if (mFlags&DEFERRED_SHADING_BIT)
00382                 {
00383                         GLenum buf[2] = {GL_COLOR_ATTACHMENT0_EXT,GL_COLOR_ATTACHMENT1_EXT};
00384                         glDrawBuffersARB(2, buf);
00385                 }
00386                 glViewport(mCachedVP[0],mCachedVP[1],mCachedVP[2],mCachedVP[3]);
00387                 glClearColor(0,0,0,0);
00388                 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00389                 
00390                 //* End Setup of first Pass Now a simple rendering of all the involved meshes.*/ 
00391                 mParams.loadTo(mShaders[0].prog);
00392                 enablePass(0);
00393                 drawSplats(meshes,cm,tm);
00394 
00395                 // begin second pass 
00396                 mParams.loadTo(mShaders[1].prog);
00397                 enablePass(1);
00398 
00399                 drawSplats(meshes,cm,tm);
00400                 
00401                 //* Start third Pass Setup */ 
00402 
00403                 // this is the last pass: normalization by the sum of weights + deferred shading
00404                 mRenderBuffer->release();
00405                 if (mFlags&DEFERRED_SHADING_BIT)
00406                         glDrawBuffer(GL_BACK);
00407 
00408                 enablePass(2);
00409 
00410                 // switch to normalized 2D rendering mode
00411                 glMatrixMode(GL_PROJECTION);
00412                 glPushMatrix();
00413                 glLoadIdentity();
00414                 glMatrixMode(GL_MODELVIEW);
00415                 glPushMatrix();
00416                 glLoadIdentity();
00417 
00418                 mShaders[2].prog.Uniform("viewport",float(mCachedVP[0]),float(mCachedVP[1]),float(mCachedVP[2]),float(mCachedVP[3]));
00419                 mShaders[2].prog.Uniform("ColorWeight",GLint(0)); // this is a texture unit
00420                 glActiveTexture(GL_TEXTURE0);
00421                 glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mRenderBuffer->texture());
00422 
00423                 if (mFlags&DEFERRED_SHADING_BIT)
00424                 {
00425                         mShaders[2].prog.Uniform("unproj", mCachedProj[10], mCachedProj[14]);
00426                         mShaders[2].prog.Uniform("NormalWeight",GLint(1)); // this is a texture unit
00427                         glActiveTexture(GL_TEXTURE1);
00428                         glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mNormalTextureID);
00429                         GL_TEST_ERR
00430                 }
00431 
00432                 if (mFlags&OUTPUT_DEPTH_BIT)
00433                 {
00434                         mShaders[2].prog.Uniform("Depth",GLint(2)); // this is a texture unit
00435                         glActiveTexture(GL_TEXTURE2);GL_TEST_ERR
00436                         glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mDepthTextureID);GL_TEST_ERR
00437                         GL_TEST_ERR
00438                 }
00439                 else
00440                 {
00441                         glDisable(GL_DEPTH_TEST);
00442                         glDepthMask(GL_FALSE);
00443                 }
00444 
00445                 // draw a quad covering the whole screen
00446     vcg::Point3f viewVec(1./mCachedProj[0], 1./mCachedProj[5], -1);
00447 
00448     glBegin(GL_QUADS);
00449                         glColor3f(1, 0, 0);
00450                         glTexCoord3f(viewVec.X(),viewVec.Y(),viewVec.Z());
00451                         glMultiTexCoord2f(GL_TEXTURE1,1.,1.);
00452                         glVertex3f(1,1,0);
00453 
00454                         glColor3f(1, 1, 0);
00455                         glTexCoord3f(-viewVec.X(),viewVec.Y(),viewVec.Z());
00456                         glMultiTexCoord2f(GL_TEXTURE1,0.,1.);
00457                         glVertex3f(-1,1,0);
00458 
00459                         glColor3f(0, 1, 1);
00460                         glTexCoord3f(-viewVec.X(),-viewVec.Y(),viewVec.Z());
00461                         glMultiTexCoord2f(GL_TEXTURE1,0.,0.);
00462                         glVertex3f(-1,-1,0);
00463 
00464                         glColor3f(1, 0, 1);
00465                         glTexCoord3f(viewVec.X(),-viewVec.Y(),viewVec.Z());
00466                         glMultiTexCoord2f(GL_TEXTURE1,1.,0.);
00467                         glVertex3f(1,-1,0);
00468     glEnd();
00469     if (!(mFlags&OUTPUT_DEPTH_BIT))
00470     {
00471         glEnable(GL_DEPTH_TEST);
00472         glDepthMask(GL_TRUE);
00473     }
00474 
00475                 glUseProgram(0);
00476 
00477                 // restore matrices
00478                 glMatrixMode(GL_PROJECTION);
00479                 glPopMatrix();
00480                 glMatrixMode(GL_MODELVIEW);
00481                 glPopMatrix();
00482                 
00483           GL_TEST_ERR
00484 
00485 }
00486 
00487 
00488 template <class MeshType>
00489 void SplatRenderer<MeshType>::Render(
00490                 std::vector< std::vector<vcg::Point3f> *                                > & positions,
00491                 std::vector< std::vector<vcg::Point3f> *                                > & normals,
00492                 std::vector< std::vector<vcg::Point3<unsigned char> > * > & colors,
00493                 std::vector<float>  & radius,  vcg::GLW::ColorMode cm,  vcg::GLW::TextureMode tm )
00494 {
00495         if(positions.empty()) return;
00496 
00497         GL_TEST_ERR
00498 
00499                 /*************** First Pass ***********/
00500                 // this is the first pass of the frame, so let's update the shaders, buffers, etc...
00501                 glGetIntegerv(GL_VIEWPORT, mCachedVP);
00502                 glGetFloatv(GL_MODELVIEW_MATRIX, mCachedMV);
00503                 glGetFloatv(GL_PROJECTION_MATRIX, mCachedProj);
00504 
00505                 updateRenderBuffer();
00506                 if (mCachedFlags != mFlags)
00507                         configureShaders();
00508 
00509                 mCachedFlags = mFlags;
00510 
00511                 mParams.update(mCachedMV, mCachedProj, mCachedVP);
00512                 //float s = meshes[0]->glw.GetHintParamf(vcg::GLW::HNPPointSize);
00513                 //if (s>1)
00514                 //      s = pow(s,0.3f);
00515                 float s = 1.f;
00516                 mParams.radiusScale *= s;
00517 
00518                 // FIXME since meshlab does not set any material properties, let's define some here
00519                 glDisable(GL_COLOR_MATERIAL);
00520                 glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, 64);
00521                 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, vcg::Point4f(0.3, 0.3, 0.3, 1.).V());
00522                 glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, vcg::Point4f(0.6, 0.6, 0.6, 1.).V());
00523                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, vcg::Point4f(0.5, 0.5, 0.5, 1.).V());
00524 
00525                 mRenderBuffer->bind();
00526                 if (mFlags&DEFERRED_SHADING_BIT)
00527                 {
00528                         GLenum buf[2] = {GL_COLOR_ATTACHMENT0_EXT,GL_COLOR_ATTACHMENT1_EXT};
00529                         glDrawBuffersARB(2, buf);
00530                 }
00531                 glViewport(mCachedVP[0],mCachedVP[1],mCachedVP[2],mCachedVP[3]);
00532                 glClearColor(0,0,0,0);
00533                 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
00534                 
00535                 //* End Setup of first Pass Now a simple rendering of all the involved meshes.*/ 
00536                 mParams.loadTo(mShaders[0].prog);
00537                 enablePass(0);
00538                 drawSplats(positions,normals,colors,radius,cm,tm);
00539 
00540                 // begin second pass 
00541                 mParams.loadTo(mShaders[1].prog);
00542                 enablePass(1);
00543 
00544                 drawSplats(positions,normals,colors,radius,cm,tm);
00545                 
00546                 //* Start third Pass Setup */ 
00547 
00548                 // this is the last pass: normalization by the sum of weights + deferred shading
00549                 mRenderBuffer->release();
00550                 if (mFlags&DEFERRED_SHADING_BIT)
00551                         glDrawBuffer(GL_BACK);
00552 
00553                 enablePass(2);
00554 
00555                 // switch to normalized 2D rendering mode
00556                 glMatrixMode(GL_PROJECTION);
00557                 glPushMatrix();
00558                 glLoadIdentity();
00559                 glMatrixMode(GL_MODELVIEW);
00560                 glPushMatrix();
00561                 glLoadIdentity();
00562 
00563                 mShaders[2].prog.Uniform("viewport",float(mCachedVP[0]),float(mCachedVP[1]),float(mCachedVP[2]),float(mCachedVP[3]));
00564                 mShaders[2].prog.Uniform("ColorWeight",GLint(0)); // this is a texture unit
00565                 glActiveTexture(GL_TEXTURE0);
00566                 glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mRenderBuffer->texture());
00567 
00568                 if (mFlags&DEFERRED_SHADING_BIT)
00569                 {
00570                         mShaders[2].prog.Uniform("unproj", mCachedProj[10], mCachedProj[14]);
00571                         mShaders[2].prog.Uniform("NormalWeight",GLint(1)); // this is a texture unit
00572                         glActiveTexture(GL_TEXTURE1);
00573                         glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mNormalTextureID);
00574                         GL_TEST_ERR
00575                 }
00576 
00577                 if (mFlags&OUTPUT_DEPTH_BIT)
00578                 {
00579                         mShaders[2].prog.Uniform("Depth",GLint(2)); // this is a texture unit
00580                         glActiveTexture(GL_TEXTURE2);GL_TEST_ERR
00581                         glBindTexture(GL_TEXTURE_RECTANGLE_ARB,mDepthTextureID);GL_TEST_ERR
00582                         GL_TEST_ERR
00583                 }
00584                 else
00585                 {
00586                         glDisable(GL_DEPTH_TEST);
00587                         glDepthMask(GL_FALSE);
00588                 }
00589 
00590                 // draw a quad covering the whole screen
00591     vcg::Point3f viewVec(1./mCachedProj[0], 1./mCachedProj[5], -1);
00592 
00593     glBegin(GL_QUADS);
00594                         glColor3f(1, 0, 0);
00595                         glTexCoord3f(viewVec.X(),viewVec.Y(),viewVec.Z());
00596                         glMultiTexCoord2f(GL_TEXTURE1,1.,1.);
00597                         glVertex3f(1,1,0);
00598 
00599                         glColor3f(1, 1, 0);
00600                         glTexCoord3f(-viewVec.X(),viewVec.Y(),viewVec.Z());
00601                         glMultiTexCoord2f(GL_TEXTURE1,0.,1.);
00602                         glVertex3f(-1,1,0);
00603 
00604                         glColor3f(0, 1, 1);
00605                         glTexCoord3f(-viewVec.X(),-viewVec.Y(),viewVec.Z());
00606                         glMultiTexCoord2f(GL_TEXTURE1,0.,0.);
00607                         glVertex3f(-1,-1,0);
00608 
00609                         glColor3f(1, 0, 1);
00610                         glTexCoord3f(viewVec.X(),-viewVec.Y(),viewVec.Z());
00611                         glMultiTexCoord2f(GL_TEXTURE1,1.,0.);
00612                         glVertex3f(1,-1,0);
00613     glEnd();
00614     if (!(mFlags&OUTPUT_DEPTH_BIT))
00615     {
00616         glEnable(GL_DEPTH_TEST);
00617         glDepthMask(GL_TRUE);
00618     }
00619 
00620                 glUseProgram(0);
00621 
00622                 // restore matrices
00623                 glMatrixMode(GL_PROJECTION);
00624                 glPopMatrix();
00625                 glMatrixMode(GL_MODELVIEW);
00626                 glPopMatrix();
00627                 
00628           GL_TEST_ERR
00629 
00630 }
00631 #if 0
00632 void SplatRenderer::Draw(QAction *a, MeshModel &m, RenderMode &rm, QGLWidget * gla)
00633 {
00634         if (m.vert.RadiusEnabled)
00635         {
00636                 if (mCurrentPass==2)
00637                         return;
00638 
00639                 enablePass(mCurrentPass);
00640                 /*if (mCurrentPass==1)*/ drawSplats(m, rm);
00641         }
00642         else if (mCurrentPass==2)
00643         {
00644                 MeshRenderInterface::Draw(a, m, rm, gla);
00645         }
00646 }
00647 #endif
00648 template <class MeshType>
00649 void SplatRenderer<MeshType>::enablePass(int n)
00650 {
00651         if (mBindedPass!=n)
00652         {
00653                 if (mBindedPass>=0)
00654                         mShaders[mBindedPass].prog.Unbind();
00655                 mShaders[n].prog.Bind();
00656                 mBindedPass = n;
00657 
00658                 // set GL states
00659                 if (n==0)
00660                 {
00661                         glDisable(GL_LIGHTING);
00662 //                      glDisable(GL_POINT_SMOOTH);
00663                         glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
00664 
00665                         glAlphaFunc(GL_LESS,1);
00666                         glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
00667                         glDepthMask(GL_TRUE);
00668                         glDisable(GL_BLEND);
00669                         glEnable(GL_ALPHA_TEST);
00670                         glEnable(GL_DEPTH_TEST);
00671 
00672 //                      glActiveTexture(GL_TEXTURE0);
00673 //                      glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
00674 //                      glEnable(GL_POINT_SPRITE_ARB);
00675                 }
00676                 if (n==1)
00677                 {
00678                         glDisable(GL_LIGHTING);
00679                         glEnable(GL_POINT_SMOOTH);
00680                         glActiveTexture(GL_TEXTURE0);
00681                         glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
00682 
00683                         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
00684                         glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ONE,GL_ONE);
00685 //                      //glBlendFuncSeparate(GL_ONE, GL_ZERO, GL_ONE,GL_ZERO);
00686 //                      glBlendFunc(GL_ONE,GL_ZERO);
00687                         glDepthMask(GL_FALSE);
00688                         glEnable(GL_BLEND);
00689                         glEnable(GL_DEPTH_TEST);
00690                         glDisable(GL_ALPHA_TEST);
00691 
00692 //                      glActiveTexture(GL_TEXTURE0);
00693 
00694                 }
00695                 if ( (n==0) || (n==1) )
00696                 {
00697                         // enable point sprite rendering mode
00698                         glActiveTexture(GL_TEXTURE0);
00699                         if (mWorkaroundATI)
00700                         {
00701                                 glBindTexture(GL_TEXTURE_2D, mDummyTexId);
00702                                 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, 2, 2, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);
00703                                 glPointParameterf(GL_POINT_SPRITE_COORD_ORIGIN, GL_LOWER_LEFT);
00704                                 // hm... ^^^^
00705                         }
00706                         glTexEnvf(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
00707                         glEnable(GL_POINT_SPRITE_ARB);
00708                 }
00709                 if (n==2)
00710                 {
00711                         glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
00712                         glDepthMask(GL_TRUE);
00713                         glDisable(GL_LIGHTING);
00714                         glDisable(GL_BLEND);
00715                 }
00716         }
00717 }
00718 
00719 
00720 template <class MeshType>
00721 void SplatRenderer<MeshType>::drawSplats(
00722                 std::vector< std::vector<vcg::Point3f> *                                > & positions,
00723                 std::vector< std::vector<vcg::Point3f> *                                > & normals,
00724                 std::vector< std::vector<vcg::Point3<unsigned char> > * > & colors,
00725                 std::vector<float>  & radius,
00726                 vcg::GLW::ColorMode cm,  vcg::GLW::TextureMode tm)
00727 {
00728         for(unsigned int ii = 0; ii < positions.size();++ii)
00729                 {
00730 
00731                         glBegin(GL_POINTS);
00732                         glMultiTexCoord1f(GL_TEXTURE2, radius[ii] );
00733 
00734                         for(unsigned int  vi= 0;vi<  positions[ii]->size() ;++vi){
00735                                 vcg::Point3<unsigned char> co = (*colors[ii])[vi];
00736                                         glColor3ub ( co[0],co[1],co[2]);
00737                                         glNormal((*normals[ii])[vi]);
00738                                         glVertex( (*positions[ii])[vi]);
00739                                 }
00740                         glEnd();
00741         }
00742 }
00743 
00744 
00745 template <class MeshType>
00746 void SplatRenderer<MeshType>::drawSplats(std::vector<MeshType*> & meshes, vcg::GLW::ColorMode cm,  vcg::GLW::TextureMode tm)
00747 {
00748 
00749         // check if we have to use the immediate mode
00750         if(meshes.empty()) return;
00751         int nV = 0;
00752 
00753         /* temporary patch: If the number of vertices is above IMMEDIATE_MODE_THR,
00754                 use the immediate mode
00755         */
00756         const int IMMEDIATE_MODE_THR = 0;
00757 
00758         unsigned int ii = 0;
00759         for(; ii < meshes.size();++ii){
00760                 nV+=meshes[ii]->vn;
00761                 if((nV>IMMEDIATE_MODE_THR) || (meshes[ii]->vn!=(int) meshes[ii]->vert.size()))
00762                         break; 
00763         }
00764         bool immediatemode =  ii<meshes.size() ;
00765 
00766 
00767         if(immediatemode){
00768                 for(unsigned int ii = 0; ii < meshes.size();++ii)
00769                         {
00770                         MeshType & m = *meshes[ii];
00771                         // immediate mode
00772                          
00773                         if( (cm == vcg::GLW::CMPerFace)  && (!vcg::tri::HasPerFaceColor( m)) )
00774                                 cm=vcg::GLW::CMNone;
00775                         glPushMatrix();
00776                         glMultMatrix( m.Tr);
00777                         typename MeshType::VertexIterator vi;
00778                         glBegin(GL_POINTS);
00779                                 if(cm==vcg::GLW::CMPerMesh)
00780                                         glColor( m.C());
00781 
00782 
00783                                 for(vi= m.vert.begin();vi!= m.vert.end();++vi)
00784                                         if(!(*vi).IsD())
00785                                         {
00786                                                 glMultiTexCoord1f(GL_TEXTURE2, (*vi).cR());
00787                                                 glNormal((*vi).cN());
00788                                                 if (cm==vcg::GLW::CMPerVert) glColor((*vi).C());
00789                                                 glVertex((*vi).P());
00790                                         }
00791                         glEnd();
00792                         glPopMatrix();
00793                         
00794                 }
00795                 return;
00796         }
00797 
00798                 for(unsigned int ii = 0; ii < meshes.size();++ii){
00799                         MeshType & m = *meshes[ii];
00800                         // bind the radius
00801                         glClientActiveTexture(GL_TEXTURE2);
00802                         glTexCoordPointer(
00803                                 1,
00804                                 GL_FLOAT,
00805                                 size_t(&m.vert[1].R())-size_t(&m.vert[0].R()),
00806                                 &m.vert[0].R()
00807                         );
00808                         glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00809                         glClientActiveTexture(GL_TEXTURE0);
00810 
00811                         // draw the vertices
00812                         vcg::GlTrimesh<MeshType> glw;
00813                         glw.m = &m;
00814                         glw.Draw(vcg::GLW::DMPoints,cm,tm);
00815 
00816                         glClientActiveTexture(GL_TEXTURE2);
00817                         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00818                         glClientActiveTexture(GL_TEXTURE0);
00819                 }
00820 }
00821 
00822 template <class MeshType>
00823 void SplatRenderer<MeshType>::UniformParameters::update(float* mv, float* proj, GLint* vp)
00824 {
00825         // extract the uniform scale
00826         float scale = vcg::Point3f(mv[0],mv[1],mv[2]).Norm();
00827 
00828         radiusScale = scale;
00829         preComputeRadius = - std::max(proj[0]*vp[2], proj[5]*vp[3]);
00830         depthOffset = 2.0;
00831         oneOverEwaRadius = 0.70710678118654;
00832         halfVp = vcg::Point2f(0.5*vp[2], 0.5*vp[3]);
00833         rayCastParameter1 =vcg::Point3f(2./(proj[0]*vp[2]), 2./(proj[5]*vp[3]), 0.0);
00834         rayCastParameter2 =vcg::Point3f(-1./proj[0], -1./proj[5], -1.0);
00835         depthParameterCast = vcg::Point2f(0.5*proj[14], 0.5-0.5*proj[10]);
00836 }
00837 template <class MeshType>
00838 void SplatRenderer <MeshType>::UniformParameters::loadTo(Program& prg)
00839 {
00840         prg.Bind();
00841         prg.Uniform("expeRadiusScale",radiusScale);
00842         prg.Uniform("expePreComputeRadius",preComputeRadius);
00843         prg.Uniform("expeDepthOffset",depthOffset);
00844         prg.Uniform("oneOverEwaRadius",oneOverEwaRadius);
00845         prg.Uniform("halfVp",halfVp);
00846         prg.Uniform("rayCastParameter1",rayCastParameter1);
00847         prg.Uniform("rayCastParameter2",rayCastParameter2);
00848         prg.Uniform("depthParameterCast",depthParameterCast);
00849 }
00850 
00851 #endif
00852 


shape_reconstruction
Author(s): Roberto Martín-Martín
autogenerated on Sat Jun 8 2019 18:36:31