Revision: 20099
          
http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=20099
Author:   dfelinto
Date:     2009-05-07 22:00:09 +0200 (Thu, 07 May 2009)

Log Message:
-----------
BGE Dome: Implementation of FBO to handle warp mesh rendering.
We are using an image twice as big to render the fisheye before warping.
It'll slow down warping meshes a little, but we get way more resolution.

Therefore I will bring Truncated Dome mode back in order to avoid using warping 
mesh for that.

Modified Paths:
--------------
    trunk/blender/source/gameengine/Ketsji/KX_Dome.cpp
    trunk/blender/source/gameengine/Ketsji/KX_Dome.h

Modified: trunk/blender/source/gameengine/Ketsji/KX_Dome.cpp
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_Dome.cpp  2009-05-07 19:36:12 UTC 
(rev 20098)
+++ trunk/blender/source/gameengine/Ketsji/KX_Dome.cpp  2009-05-07 20:00:09 UTC 
(rev 20099)
@@ -66,6 +66,7 @@
        m_engine(engine)
 {
        warp.usemesh = false;
+       fboSupported = false;
 
        if (mode >= DOME_NUM_MODES)
                m_mode = DOME_FISHEYE;
@@ -131,16 +132,20 @@
 
        CreateGLImages();
 
+       if(warp.usemesh)
+               fboSupported = CreateFBO();
+
        dlistSupported = CreateDL();
 }
 
 // destructor
 KX_Dome::~KX_Dome (void)
 {
-       GLuint m_numimages = m_numfaces;
-
        ClearGLImages();
 
+       if(fboSupported)
+               glDeleteFramebuffersEXT(1, &warp.fboId);
+
        if(dlistSupported)
                glDeleteLists(dlistId, (GLsizei) m_numimages);
 }
@@ -174,9 +179,9 @@
        }
        if(warp.usemesh){
                glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
-               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagewidth, 
warp.imageheight, 0, GL_RGB8,
+               glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, warp.imagesize, 
warp.imagesize, 0, GL_RGB8,
                                GL_UNSIGNED_BYTE, 0);
-               glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 
warp.imagewidth, warp.imageheight, 0);
+               glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 
warp.imagesize, warp.imagesize, 0);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, 
GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, 
GL_LINEAR);
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 
GL_CLAMP_TO_EDGE);
@@ -227,19 +232,21 @@
        m_imagesize = (1 << i);
 
        if (warp.usemesh){
-               warp.bufferwidth = canvaswidth;
-               warp.bufferheight = canvasheight;
+               // trying to use twice the size of the cube faces
+               GLint glMaxTexDim;
+               glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glMaxTexDim);
 
-               i = 0;
-               while ((1 << i) <= warp.bufferwidth)
-                       i++;
-               warp.imagewidth = (1 << i);
+               if (2 * m_imagesize > glMaxTexDim)
+                       warp.imagesize = m_imagesize;
 
-               i = 0;
-               while ((1 << i) <= warp.bufferheight)
-                       i++;
-               warp.imageheight = (1 << i);
+               else
+                       warp.imagesize = 2 * m_imagesize;
+
+               //if FBO is not working/supported, we use the canvas dimension 
as buffer
+               warp.bufferwidth  = canvaswidth;
+               warp.bufferheight = canvasheight;
        }
+
        //XXX HACK
        canvaswidth  = m_viewport.GetWidth();
        canvasheight = m_viewport.GetHeight();
@@ -320,6 +327,40 @@
        return true;
 }
 
+bool KX_Dome::CreateFBO(void)
+{
+       glGenFramebuffersEXT(1, &warp.fboId);
+       if(warp.fboId==0)
+       {
+               printf("Dome Error: Invalid frame buffer object. Using low 
resolution warp image.");
+               return false;
+       }
+
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId);
+
+       glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+               GL_TEXTURE_2D, domefacesId[m_numfaces], 0);
+
+       GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+
+       if(status == GL_FRAMEBUFFER_UNSUPPORTED_EXT)
+       {
+               printf("Dome Error: FrameBuffer unsupported. Using low 
resolution warp image.");
+               return false;
+       }
+       else if(status != GL_FRAMEBUFFER_COMPLETE_EXT)
+       {
+               glDeleteFramebuffersEXT(1, &warp.fboId);
+               return false;
+       }
+
+       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+
+       //nothing failed: we can use the whole FBO as buffersize
+       warp.bufferwidth = warp.bufferheight = warp.imagesize;
+       return true;
+}
+
 void KX_Dome::GLDrawTriangles(vector <DomeFace>& face, int nfaces)
 {
        int i,j;
@@ -336,9 +377,10 @@
 void KX_Dome::GLDrawWarpQuads(void)
 {
        int i, j, i2;
-       float uv_width = (float)(warp.bufferwidth-1) / warp.imagewidth;
-       float uv_height = (float)(warp.bufferheight-1) / warp.imageheight;
 
+       float uv_width = (float)(warp.bufferwidth) / warp.imagesize;
+       float uv_height = (float)(warp.bufferheight) / warp.imagesize;
+
        if(warp.mode ==2 ){
                glBegin(GL_QUADS);
                for (i=0;i<warp.n_height-1;i++) {
@@ -394,7 +436,7 @@
                }
                glEnd();
        } else{
-               printf("Error: Warp Mode %d unsupported. Try 1 for Polar Mesh 
or 2 for Fisheye.\n", warp.mode);
+               printf("Dome Error: Warp Mode %d unsupported. Try 1 for Polar 
Mesh or 2 for Fisheye.\n", warp.mode);
        }
 }
 
@@ -430,7 +472,7 @@
 
        lines = text.Explode('\n');
        if(lines.size() < 6){
-               printf("Error: Warp Mesh File with insufficient data!\n");
+               printf("Dome Error: Warp Mesh File with insufficient data!\n");
                return false;
        }
        columns = lines[1].Explode(' ');
@@ -438,7 +480,7 @@
                columns = lines[1].Explode('\t');
 
        if(columns.size() !=2){
-               printf("Error: Warp Mesh File incorrect. The second line should 
contain: width height.\n");
+               printf("Dome Error: Warp Mesh File incorrect. The second line 
should contain: width height.\n");
                return false;
        }
 
@@ -448,7 +490,7 @@
        warp.n_height = atoi(columns[1]);
 
        if ((int)lines.size() < 2 + (warp.n_width * warp.n_height)){
-               printf("Error: Warp Mesh File with insufficient data!\n");
+               printf("Dome Error: Warp Mesh File with insufficient data!\n");
                return false;
        }else{
                warp.nodes = vector<vector<WarpMeshNode> > (warp.n_height, 
vector<WarpMeshNode>(warp.n_width));
@@ -470,7 +512,7 @@
                        }
                        else{
                                warp.nodes.clear();
-                               printf("Error: Warp Mesh File with wrong number 
of fields. You should use 5: x y u v i.\n");
+                               printf("Dome Error: Warp Mesh File with wrong 
number of fields. You should use 5: x y u v i.\n");
                                return false;
                        }
                }
@@ -1538,6 +1580,13 @@
 void KX_Dome::Draw(void)
 {
 
+       if (fboSupported){
+               glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, warp.fboId);
+
+               glViewport(0,0,warp.imagesize, warp.imagesize);
+               glScissor(0,0,warp.imagesize, warp.imagesize);
+       }
+
        switch(m_mode){
                case DOME_FISHEYE:
                        DrawDomeFisheye();
@@ -1552,8 +1601,16 @@
 
        if(warp.usemesh)
        {
-               glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
-               glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 
m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth, 
warp.bufferheight);
+               if(fboSupported)
+               {
+                       m_canvas->SetViewPort(0, 0, m_canvas->GetWidth(), 
m_canvas->GetHeight());
+                       glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+               }
+               else
+               {
+                       glBindTexture(GL_TEXTURE_2D, domefacesId[m_numfaces]);
+                       glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 
m_viewport.GetLeft(), m_viewport.GetBottom(), warp.bufferwidth, 
warp.bufferheight);
+               }
                DrawDomeWarped();
        }
 }

Modified: trunk/blender/source/gameengine/Ketsji/KX_Dome.h
===================================================================
--- trunk/blender/source/gameengine/Ketsji/KX_Dome.h    2009-05-07 19:36:12 UTC 
(rev 20098)
+++ trunk/blender/source/gameengine/Ketsji/KX_Dome.h    2009-05-07 20:00:09 UTC 
(rev 20099)
@@ -74,6 +74,7 @@
 
        //openGL checks:
        bool    dlistSupported;
+       bool    fboSupported;
 
        //openGL names:
        GLuint domefacesId[7];          // ID of the images -- room for 7 
images, using only 4 for 180\xBA x 360\xBA dome, 6 for panoramic and +1 for 
warp mesh
@@ -93,8 +94,9 @@
                bool usemesh;
                int mode;
                int n_width, n_height; //nodes width and height
-               int imagewidth, imageheight;
+               int imagesize;
                int bufferwidth, bufferheight;
+               GLuint fboId;
                vector <vector <WarpMeshNode> > nodes;
        } warp;
 
@@ -140,6 +142,8 @@
        void ClearGLImages(void);//called on resize
        bool CreateDL(void); //create Display Lists
        void ClearDL(void);  //remove Display Lists 
+       bool CreateFBO(void);//create FBO (for warp mesh)
+       void ClearFBO(void); //remove FBO
 
        void CalculateCameraOrientation();
        void CalculateImageSize(); //set m_imagesize


_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to