Destorting text and vertexes with a using GL_MAP2_VERTEX_3

Hi all,

I found the following code, that displays video data corrected for the the Oculus rift lens on to the display of the rift.

https://sourceforge.net/p/oculusriftdk2fpv/code/ci/master/tree/OculusFPV/src/main.cpp#l538

I am changing this application to display HD video data, and that was no problem.
But one of the short comings of this software is that the graphical data text, and lines ( if I add it ) is not correct with the bezier curves, that are applied with GL_MAP2_VERTEX_3 on a mesh of 20 by 20.

I am trying already for more then 1.5 weeks to also be able the correct the renders also in the same way but with no success.
I think I know how to do it but I can’t get it done, the screens stays black always.

what I was trying :

  • Render the text or lines in to a separate texture that is Framebuffer ( FBO )
  • read the pixel data in to a PBO ( like the one used in the original OculusFPV ) with glReadPixels
  • and the render that pixel image on to a a mesh that can be distorted with a separated bezier curve

is this the correct way of doing this ?

if yes can someone help me with details, because I still can’ figure out how opengl textures vertices and FBO, PBO work together.

[QUOTE=amigob;1284964]I found the following code, that displays video data corrected for the the Oculus rift lens on to the display of the rift.

…one of the short comings of this software is that the graphical data text, and lines ( if I add it ) is not correct with the bezier curves…

what I was trying :

  • Render the text or lines in to a separate texture that is Framebuffer ( FBO )
  • read the pixel data in to a PBO ( like the one used in the original OculusFPV ) with glReadPixels
  • and the render that pixel image on to a a mesh that can be distorted with a separated bezier curve [/QUOTE]

I don’t think you need PBOs for what you’re doing. The code you linked uses them as an intermediary to copy video data from the input video device to an OpenGL texture.

If you use OpenGL to render your text or lines (into a texture via an FBO), then you’ll already have them in an OpenGL texture on the GPU. Go straight to rendering that with distortion correction.

So if I replace the

glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, pboIds[index]);

in the Display routine, with a bind to a Framebuffer where I have rendered some graphics in.
It would not show the video any more :-). but the rendered graphics with the distortion?

I am trying this now :slight_smile:

Finally have it working with the use of the vbo example from songho.ca took a lot of time :frowning:

Now I want to get the black background of the frame buffer transparent. what ever I do It always ends up being a solid color, or no rendering
source can be found here https://bitbucket.org/amigobFPV/framebufferrendering/src/42b6bf43a9309e45fabe19b104d57c54d14236a7/src/main.cpp?at=master&fileviewer=file-view-default
here you see where I end up with now a rendered texture in front of a texture with a pbo ( need for the video data )

if have tried to use GL_BLEND and tryed to make the black color transparent.

I got finally this working, with the use of the vbo example from songho.ca

now I am trying to get transparently to work for the texture


I render two textures the front one with vertex graphics and a second one in the back with pixel data ( video in the future )

the black color needs to become transparent, but what ever I do I end up with non transparent as i the picture, or a completely black screen.
I used BLEND functionality but some how it does not work from texture to texture.
the source can be found here https://bitbucket.org/amigobFPV/framebufferrendering/src/42b6bf43a9309e45fabe19b104d57c54d14236a7/src/main.cpp?at=master&fileviewer=file-view-default

Mhh, my post seem not to appear, so trying it gain one by one.

I have success with rendering and then applying a barrel distortion.

Now, I already trying for 2 days to get the black color in the VBO to become transparent, so that the image is visible through the VBO, where I didn’t render any graphics .
What ever I do with
glEnable(GL_BLEND);
glsetcolor(0.0.0.0);
glBlendFunc ( tried a lot of combinations )

I end up with completely nothing on the screen( black )
Or exactly the same as the picture in the previous post.

More readable here: It seems that I can’t post a u_r_l ( Bitbucket ) where the code is 10 times more readable

///////////////////////////////////////////////////////////////////////////////
// main.cpp
// ========
// testing Frame Buffer Object (FBO) for "Render To Texture" with MSAA
// OpenGL draws the scene directly to a texture object.
//
// GL_EXT_framebuffer_object extension is promoted to a core feature of OpenGL
// version 3.0 (GL_ARB_framebuffer_object)
//
//  AUTHOR: Song Ho Ahn ()
// CREATED: 2008-05-16
// UPDATED: 2016-11-14
///////////////////////////////////////////////////////////////////////////////

// in order to get function prototypes from glext.h, define GL_GLEXT_PROTOTYPES before including glext.h
#define GL_GLEXT_PROTOTYPES
#include <GL/glut.h>
#include <GL/glext.h>

#include <iostream>
#include <sstream>
#include <string>
#include <iomanip>
#include <cstdlib>

#include <string.h>
#include <stdio.h>
#include <stdarg.h>

#include "Timer.h"
#include "distortion.h"

using std::stringstream;
using std::string;
using std::cout;
using std::endl;
using std::ends;

   
// GLUT CALLBACK functions ////////////////////////////////////////////////////
void displayCB();
void reshapeCB(int w, int h);
void timerCB(int millisec);
void idleCB();
void keyboardCB(unsigned char key, int x, int y);
void mouseCB(int button, int stat, int x, int y);
void mouseMotionCB(int x, int y);

// CALLBACK function when exit() called ///////////////////////////////////////
void exitCB();

// function declearations /////////////////////////////////////////////////////
void initGL();
int  initGLUT(int argc, char **argv);
bool initSharedMem();
void clearSharedMem();
void initLights();
void setCamera(float posX, float posY, float posZ, float targetX, float targetY, float targetZ);
void drawString(const char *str, int x, int y, float color[4], void *font);
void drawString3D(const char *str, float pos[3], float color[4], void *font);
void showInfo();
void showFPS();
void toOrtho();
void toPerspective();
void draw();

// constants
const int   SCREEN_WIDTH    = 400;
const int   SCREEN_HEIGHT   = 300;
const float CAMERA_DISTANCE = 6.0f;
const int   TEXT_WIDTH      = 8;
const int   TEXT_HEIGHT     = 13;
const int   TEXTURE_WIDTH   = 512;  // NOTE: texture size cannot be larger than
const int   TEXTURE_HEIGHT  = 512;  // the rendering window size in non-FBO mode

// global variables

void *font = GLUT_BITMAP_8_BY_13;
int screenWidth;
int screenHeight;
bool mouseLeftDown;
bool mouseRightDown;
float mouseX, mouseY;
float cameraAngleX = 30;
float cameraAngleY;
float cameraDistance;


int fboSampleCount;
int drawMode;
Timer timer, t1;
float playTime;                     // to compute rotation angle
float renderToTextureTime;          // elapsed time for render-to-texture

GLfloat texpts[2][2][2] ={{{0.0, 0.0},{0.0, 1.0}},{{1.0, 0.0},{1.0, 1.0}}};
distortion video_disto;

typedef struct
{
   GLuint fboId;
   GLuint textureId;
   GLuint depthId;
} OF_SCREEN_DATA;

// global variables
OF_SCREEN_DATA  afhFrameBuffer;


int IMAGE_WIDTH = 1280;
int IMAGE_HEIGHT = 720;
int VIDEO_DATA_SIZE = IMAGE_WIDTH * IMAGE_HEIGHT * 3;

typedef struct
{
   GLubyte *imageData;
   GLuint  pboId;
   GLuint  textureId;
} OF_SCREEN_VIDEO_DATA;

OF_SCREEN_VIDEO_DATA  VideoBuffer;

void stroke_output(GLfloat x, GLfloat y, char *format,...)
{
  va_list args;
  char buffer[200], *p;

  va_start(args, format);
  vsprintf(buffer, format, args);
  va_end(args);
  glPushMatrix();
  glTranslatef(x, y, 0);
  glScalef(0.005, 0.010, 0.005);
  for (p = buffer; *p; p++)
    glutStrokeCharacter(GLUT_STROKE_ROMAN , *p);
  glPopMatrix();
}

void bitmap_output(int x, int y, char *string, void *font)
{
  int len, i;

  glRasterPos2f(x, y);
  len = (int) strlen(string);
  for (i = 0; i < len; i++) 
  {
    glutBitmapCharacter(font, string[i]);
  }
}



///////////////////////////////////////////////////////////////////////////////
// draw a textured cube with GL_TRIANGLES GLuint textId, float translate
///////////////////////////////////////////////////////////////////////////////
void draw1( GLuint textureId )
{
    glBindTexture(GL_TEXTURE_2D, textureId);
    
   // glColorMask( 	GL_TRUE,GL_FALSE, GL_FALSE,GL_TRUE);
    
    glEnable (GL_MAP2_VERTEX_3);
    glEnable (GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glEnable (GL_MAP2_TEXTURE_COORD_2);

    //glColor4f (1.0f, 1.0f, 1.0f, 0.5);
    glColor4f (1.0f, 1.0f, 1.0f, 1);
   
    glMap2f (GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, video_disto.getDistortion ());
    glMap2f (GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, &texpts[0][0][0]);
    glMapGrid2f (20, 0.0, 1.0, 20, 0.0, 1.0);
    glTexSubImage2D (GL_TEXTURE_2D, 0, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, 0);
     
    glShadeModel (GL_SMOOTH);
    
    glEvalMesh2 (GL_FILL, 0, 20, 0, 20);

    glBindTexture(GL_TEXTURE_2D, 0);
}


void draw( GLuint textureId )
{
    glBindTexture(GL_TEXTURE_2D, textureId);

//glColorMask( 	GL_TRUE,GL_TRUE, GL_TRUE,GL_TRUE);

    glEnable (GL_MAP2_VERTEX_3);
    glEnable (GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glEnable (GL_MAP2_TEXTURE_COORD_2);

    //glColor4f (1.0f, 1.0f, 1.0f, 0.5);
    
    glColor4f (1.0f, 1.0f, 1.0f, 1);
   
    glMap2f (GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4, video_disto.getDistortion ());
    glMap2f (GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2, &texpts[0][0][0]);
    glMapGrid2f (20, 0.0, 1.0, 20, 0.0, 1.0);
     
    glShadeModel (GL_SMOOTH);
    
  ///  glTranslatef (1.0, 0, 0);
    
    glEvalMesh2 (GL_FILL, 0, 20, 0, 20);
    glBindTexture(GL_TEXTURE_2D, 0);
}


///////////////////////////////////////////////////////////////////////////////
// copy an image data to texture buffer
///////////////////////////////////////////////////////////////////////////////
void fillPixels (GLubyte * dst)
{
   int* dst_int = NULL;
   if(!dst)
      return;

   dst_int = (int*)dst;

   for(int i = 0; i < ((IMAGE_HEIGHT*IMAGE_WIDTH*3)/4); ++i)
   {
      *dst_int = i;
      dst_int++;
   }
}


void videoRender(GLuint pboId )
{
   glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, pboId);
   glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, VIDEO_DATA_SIZE, 0, GL_STREAM_DRAW_ARB);
   GLubyte * ptr = (GLubyte *) glMapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);

   if (ptr)
   {  // update data directly on the mapped buffer
      fillPixels ( ptr);
      glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB);	// release pointer to mapping buffer
   }
   
}


void afhRender()
{
    glViewport(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(40.0f, 1.0, 0.10f, 20.0f);
    glMatrixMode(GL_MODELVIEW);

   
    // camera transform
    glLoadIdentity();
    glTranslatef(0, 0, -5);
  
    // with FBO
    // render directly to a texture
        // set the rendering destination to FBO
    // clear buffer

    glBindFramebuffer(GL_FRAMEBUFFER, afhFrameBuffer.fboId);

  
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable (GL_BLEND);
    glColor4f(0,  0, 0, 0);
    glBlendFunc(GL_ONE, GL_DST_COLOR);
 
    // draw a rotating teapot at the origin
    glPushMatrix();
    glRotatef(0, 0, 0, 1);
    glTranslatef(0, 0, 0);
       
    glColor4f(1, 0.1, 1, 0.5);
    glBegin(GL_TRIANGLES);
        // front faces
        glNormal3f(0,0,1);
        // face v0-v1-v2
        glVertex3f(0.5, 1,1);
        glVertex3f(-1,1,1);
        glVertex3f(-1,-1,1);
        // face v2-v3-v0
        glVertex3f(-1,-1,1);
        glVertex3f(1,-1,1);
        glVertex3f(1,1,1);
    glEnd();
  
    glColor4f(1.0, 0.0, 0.1, 1);
    
    glPushMatrix();    
      
    glTranslatef(0, 0, -2);
    glRotatef(-90, 0, 0, 1);   
    stroke_output(-2.5, -2.5, "GLUT StrokeFont");
    glPopMatrix();
    
   /* glPushMatrix();
    glTranslatef(0.0, 0.90, 2);  
    bitmap_output(-0.5, 0.5, "GLUT bitmap font", GLUT_BITMAP_TIMES_ROMAN_24);
    glPopMatrix();*/

    glPopMatrix();
}



OF_SCREEN_VIDEO_DATA createVideoPixelBuffer(  )
{
   OF_SCREEN_VIDEO_DATA  video;
   
   video.imageData = new GLubyte[VIDEO_DATA_SIZE];
   memset (video.imageData, 0, VIDEO_DATA_SIZE);
   
   glGenTextures (1, &(video.textureId));
 
   glBindTexture (GL_TEXTURE_2D, video.textureId );
   
   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);
   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
   glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, IMAGE_WIDTH, IMAGE_HEIGHT, 0,
                 GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *) video.imageData);
   glBindTexture (GL_TEXTURE_2D, 0);

   // create a pixel buffer object, you need to delete them when program exits.
   // glBufferDataARB with NULL pointer reserves only memory space.
   glGenBuffersARB (1, &(video.pboId));
   glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, video.pboId);
   glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, VIDEO_DATA_SIZE, 0, GL_STREAM_DRAW_ARB);

   glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB);	// release pointer to mapping buffer
   
   glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, video.pboId);
   glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, VIDEO_DATA_SIZE, 0, GL_STREAM_DRAW_ARB);

   glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0);

   glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB);	// release pointer to mapping buffer

   return video;
}



OF_SCREEN_DATA createOfScreenFrameBuffer( GLuint width, GLuint height)
{
   OF_SCREEN_DATA fbo;
   // create a framebuffer object, you need to delete them when program exits.
   glGenTextures(1, &(fbo.textureId) );

   glBindTexture (GL_TEXTURE_2D, fbo.textureId );
   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);
   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
   glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

   glBindTexture (GL_TEXTURE_2D, 0);

   glGenFramebuffers(1, &fbo.fboId);
   glBindFramebuffer(GL_FRAMEBUFFER, fbo.fboId);

   glGenRenderbuffers(1, &(fbo.depthId));
   glBindRenderbuffer(GL_RENDERBUFFER, fbo.depthId);
   glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
   //glRenderbufferStorageMultisample(GL_RENDERBUFFER, fboSampleCount, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT);
   glBindRenderbuffer(GL_RENDERBUFFER, 0);

   // attach a texture to FBO color attachement point
   glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo.textureId, 0);

   // attach a renderbuffer to depth attachment point
   glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo.depthId);

   glBindFramebuffer(GL_FRAMEBUFFER, 0);
   glBindTexture (GL_TEXTURE_2D, 0 );

   return fbo;
}

///////////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
    // init global vars
    initSharedMem();

    // register exit callback
    atexit(exitCB);

    // init GLUT and GL
    initGLUT(argc, argv);
    initGL();
    video_disto.init(0.3, 0.0);
    // create a texture object
    
    afhFrameBuffer = createOfScreenFrameBuffer(TEXTURE_WIDTH, TEXTURE_HEIGHT);
    VideoBuffer    = createVideoPixelBuffer(); 
    
    // window will be shown and display callback is triggered by events
    // NOTE: this call never return main().
    glutMainLoop(); /* Start GLUT event-processing loop */

    return 0;
}


///////////////////////////////////////////////////////////////////////////////
// initialize GLUT for windowing
///////////////////////////////////////////////////////////////////////////////
int initGLUT(int argc, char **argv)
{
    // GLUT stuff for windowing
    // initialization openGL window.
    // It must be called before any other GLUT routine.
    glutInit(&argc, argv);

    glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH | GLUT_STENCIL);   // display mode

    glutInitWindowSize(screenWidth, screenHeight);              // window size

    glutInitWindowPosition(100, 100);                           // window location

    // finally, create a window with openGL context
    // Window will not displayed until glutMainLoop() is called
    // It returns a unique ID.
    int handle = glutCreateWindow(argv[0]);     // param is the title of window

    // register GLUT callback functions
    glutDisplayFunc(displayCB);
    //glutTimerFunc(33, timerCB, 33);             // redraw only every given millisec
    glutIdleFunc(idleCB);                       // redraw whenever system is idle
    glutReshapeFunc(reshapeCB);
    glutKeyboardFunc(keyboardCB);
    glutMouseFunc(mouseCB);
    glutMotionFunc(mouseMotionCB);

    return handle;
}



///////////////////////////////////////////////////////////////////////////////
// initialize OpenGL
// disable unused features
///////////////////////////////////////////////////////////////////////////////
void initGL()
{
    glShadeModel(GL_SMOOTH);                    // shading mathod: GL_SMOOTH or GL_FLAT
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);      // 4-byte pixel alignment

    // enable /disable features
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
    glHint(GL_POLYGON_SMOOTH_HINT, GL_NICEST);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_TEXTURE_2D);
    glEnable(GL_CULL_FACE);

    glClearStencil(0);                          // clear stencil buffer
    glDepthFunc(GL_LEQUAL);
}


///////////////////////////////////////////////////////////////////////////////
// initialize global variables
///////////////////////////////////////////////////////////////////////////////
bool initSharedMem()
{
    screenWidth = SCREEN_WIDTH;
    screenHeight = SCREEN_HEIGHT;

    mouseLeftDown = mouseRightDown = false;
    mouseX = mouseY = 0;

    cameraAngleX = 0;
    cameraAngleY = 220;
    cameraDistance = 4;

    drawMode = 0; // 0:fill, 1: wireframe, 2:points

    
    
    playTime = renderToTextureTime = 0;

    return true;
}


///////////////////////////////////////////////////////////////////////////////
// clean up global variables
///////////////////////////////////////////////////////////////////////////////
void clearSharedMem()
{
    glDeleteTextures(1, &(afhFrameBuffer.textureId));
    afhFrameBuffer.textureId = 0;

    // clean up FBO, RBO
    glDeleteFramebuffers(1, &(afhFrameBuffer.fboId));
    afhFrameBuffer.fboId = 0;
  
}


///////////////////////////////////////////////////////////////////////////////
// set camera position and lookat direction
///////////////////////////////////////////////////////////////////////////////
void setCamera(float posX, float posY, float posZ, float targetX, float targetY, float targetZ)
{
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(posX, posY, posZ, targetX, targetY, targetZ, 0, 1, 0); // eye(x,y,z), focal(x,y,z), up(x,y,z)
}


///////////////////////////////////////////////////////////////////////////////
// set the projection matrix as perspective
///////////////////////////////////////////////////////////////////////////////
void toPerspective()
{
    // set viewport to be the entire window
    glViewport(0, 0, (GLsizei)screenWidth, (GLsizei)screenHeight);

    // set perspective viewing frustum
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0f, (float)(screenWidth)/screenHeight, 1.0f, 1000.0f); // FOV, AspectRatio, NearClip, FarClip

    // switch to modelview matrix in order to set scene
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}



//=============================================================================
// CALLBACKS
//=============================================================================

void displayCB()
{
    // compute rotation angle
    const float ANGLE_SPEED = 90;   // degree/s
    float angle = ANGLE_SPEED * playTime;
    // adjust viewport and projection matrix to texture dimension
   
    afhRender();

    // back to normal window-system-provided framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind

    ///////////////////////////////////////////////////////////////////////////
    // rendering as normal ////////////////////////////////////////////////////
    // back to normal viewport and projection matrix
    glViewport(0, 0, screenWidth, screenHeight);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0f, (float)(screenWidth)/screenHeight, 1.0f, 100.0f);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    // tramsform camera
    glTranslatef(0, 0, -cameraDistance);
    glRotatef(cameraAngleX, 1, 0, 0);   // pitch
    glRotatef(cameraAngleY, 0, 1, 0);   // heading

    // clear framebuffer
    glClearColor(0, 0, 0, 0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
    
    glPushMatrix();
    // draw frame buffer 
    draw(afhFrameBuffer.textureId);
    glPopMatrix();
    
    glPushMatrix();
    glTranslatef (0.0, 0.0, 0.4);
    
    videoRender(VideoBuffer.pboId);   
    
    draw1(VideoBuffer.textureId);
    glPopMatrix();
    
    glutSwapBuffers();
}


void reshapeCB(int width, int height)
{
    screenWidth = width;
    screenHeight = height;
    toPerspective();
}


void timerCB(int millisec)
{
    glutTimerFunc(millisec, timerCB, millisec);
    glutPostRedisplay();
}


void idleCB()
{
    glutPostRedisplay();
}


void keyboardCB(unsigned char key, int x, int y)
{
    switch(key)
    {
    case 27: // ESCAPE
        exit(0);
        break;

    default:
        break;
    }
}


void mouseCB(int button, int state, int x, int y)
{
    mouseX = x;
    mouseY = y;

    if(button == GLUT_LEFT_BUTTON)
    {
        if(state == GLUT_DOWN)
        {
            mouseLeftDown = true;
        }
        else if(state == GLUT_UP)
            mouseLeftDown = false;
    }

    else if(button == GLUT_RIGHT_BUTTON)
    {
        if(state == GLUT_DOWN)
        {
            mouseRightDown = true;
        }
        else if(state == GLUT_UP)
            mouseRightDown = false;
    }
}


void mouseMotionCB(int x, int y)
{
    if(mouseLeftDown)
    {
        cameraAngleY += (x - mouseX);
        cameraAngleX += (y - mouseY);
        mouseX = x;
        mouseY = y;
    }
    if(mouseRightDown)
    {
        cameraDistance -= (y - mouseY) * 0.2f;
        mouseY = y;
    }
}


void exitCB()
{
    clearSharedMem();
}

Now, I already trying for 2 days to get the black color in the FBO to become transparent, so that the image is visible through the FBO, where I didn’t render any graphics .
What ever I do with
glEnable(GL_BLEND);
glsetcolor(0.0.0.0);
glBlendFunc ( tried a lot of combinations )

I end up with completely nothing on the screen( black )
Or exactly the same as the picture in the previous post.

More readable here: https://bitbucket.org/amigobFPV/framebufferrendering/src/42b6bf43a9309e45fabe19b104d57c54d14236a7/src/main.cpp?at=master&fileviewer=file-view-default

could not get the code posted here, because it complains about using url’s, that are not in the code ??

The texture used as the FBO’s colour buffer needs to have an alpha channel, and it needs to be cleared to transparent, i.e. glClearColor(0,0,0,0). Also, if you are rendering textured primitives into the FBO, their textures need a transparent background. If you’re rendering with a fragment shader, ensure that you’re setting gl_FragColor.a correctly (e.g. basing it upon the source texture’s alpha, not setting it to 1.0).

As far as I know I created the FBO with the alpha channel
But I didn’t do this with the PBO that is always in the back, so this one doesn’t need to be transparent ever.

Is that a problem ?

OF_SCREEN_VIDEO_DATA createVideoPixelBuffer(  )
{
   OF_SCREEN_VIDEO_DATA  video;
   
   video.imageData = new GLubyte[VIDEO_DATA_SIZE];
   memset (video.imageData, 0, VIDEO_DATA_SIZE);
   
   glGenTextures (1, &(video.textureId));
 
   glBindTexture (GL_TEXTURE_2D, video.textureId );
   
   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);
   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
   glTexImage2D (GL_TEXTURE_2D, 0, GL_RGB, IMAGE_WIDTH, IMAGE_HEIGHT, 0,
                 GL_RGB, GL_UNSIGNED_BYTE, (GLvoid *) video.imageData);
   glBindTexture (GL_TEXTURE_2D, 0);

   // create a pixel buffer object, you need to delete them when program exits.
   // glBufferDataARB with NULL pointer reserves only memory space.
   glGenBuffersARB (1, &(video.pboId));
   glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, video.pboId);
   glBufferDataARB (GL_PIXEL_UNPACK_BUFFER_ARB, VIDEO_DATA_SIZE, 0, GL_STREAM_DRAW_ARB);
   glUnmapBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB);	// release pointer to mapping buffer

   glBindBufferARB (GL_PIXEL_UNPACK_BUFFER_ARB, 0);

   return video;
}

OF_SCREEN_DATA createOfScreenFrameBuffer( GLuint width, GLuint height)
{
   OF_SCREEN_DATA fbo;
   // create a framebuffer object, you need to delete them when program exits.
   glGenTextures(1, &(fbo.textureId) );

   glBindTexture (GL_TEXTURE_2D, fbo.textureId );
   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);
   glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
   glTexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);

   glBindTexture (GL_TEXTURE_2D, 0);

   glGenFramebuffers(1, &fbo.fboId);
   glBindFramebuffer(GL_FRAMEBUFFER, fbo.fboId);

   glGenRenderbuffers(1, &(fbo.depthId));
   glBindRenderbuffer(GL_RENDERBUFFER, fbo.depthId);
   glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
   //glRenderbufferStorageMultisample(GL_RENDERBUFFER, fboSampleCount, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT);
   glBindRenderbuffer(GL_RENDERBUFFER, 0);

   // attach a texture to FBO color attachement point
   glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fbo.textureId, 0);

   // attach a renderbuffer to depth attachment point
   glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo.depthId);

   glBindFramebuffer(GL_FRAMEBUFFER, 0);
   glBindTexture (GL_TEXTURE_2D, 0 );

   return fbo;
}

I still don’t have i working but I think I found one mistake, I rendered the back image texture as last.

That should be the first to render ?

got it working

code is uploaded again to bitbucket