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();
}