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