OpenGL de プログラミング - FBO::まとめコード
現在地 >> メニュー >> 基本編10 >> FrameBufferObject >> FBO::まとめコード
関連 >> FBO::作成FBO::描画


問題


オフスクリーンで背景白、物体を描画し、
それをテクスチャとしポリゴンに張り付けよ。

その他条件:
  • オフスクリーンで描画したものは、アニメーションさせる。

答え

#include <iostream>
#include <gl/glew.h>
#include <gl/glut.h>

#pragma comment(lib,"glew32.lib")

//------------ 各種外部変数 ------------//
std::pair<int,int> TextureWH(512,512);
unsigned int texID[1];


//FBO用ID
unsigned int FboID[1];
//RBO用ID
unsigned int RboID[1];



//---------- 各種プロトタイプ -----------//
void display();
void reshape(int w, int h);
void timer(int value);

void createTexture();
void createFBOandRBO();
bool checkFramebufferStatus();


//--------- GLUTの初期化 ---------------//
void GLUT_CALL_FUNCs()
{
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutTimerFunc(0,timer,17);
}


void myOtherInit()
{
	glEnable(GL_DEPTH_TEST);
}

void GLUT_INITs(int *argcp, char **argv)
{
	glutInit(argcp,argv);
	glutInitDisplayMode(GLUT_RGBA| GLUT_DOUBLE | GLUT_DEPTH);
	glutInitWindowSize(TextureWH.first,TextureWH.second);
	glutCreateWindow("render to texture");

	GLUT_CALL_FUNCs();

	myOtherInit();

}

//---------  GLEWの初期設定  ------------//
bool GLEW_INIT()
{
	GLenum err;
	err = glewInit();
	if (err != GLEW_OK){
		std::cerr << glewGetErrorString(err) << "\n";
		return false;
	}
	return true;
}




//--------- メイン関数 ---------//
int main(int argc, char **argv)
{

	GLUT_INITs(&argc,argv);
	if ( GLEW_INIT() == false){	return -1;}

	createTexture();//テクスチャ作成
	createFBOandRBO();//FBO,RBOの作成
	
	glutMainLoop();

	//破棄
	glDeleteTextures(1, &texID[0]);
	glDeleteFramebuffersEXT(1, &FboID[0]);
	glDeleteRenderbuffersEXT(1, &RboID[0]);

	return 0;


}



void display()
{
	static int r = 0;

	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FboID[0]);//描画先の切り替え
	
	glClearColor(1, 1, 1, 1);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	
	glPushMatrix();
	glRotatef(static_cast<float>(r),0,1,0);
	glColor3f(0,1,0);
	glutWireTeapot(0.5);
	glColor3f(1,0,0);
	glutWireCube(0.2);
	glColor3f(1,1,1);
	glPopMatrix();

	//出力先を通常のフレームバッファの戻す
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);

	//これ以降は通常の描画
	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, texID[0]);
	glGenerateMipmapEXT(GL_TEXTURE_2D);//ミップマップの生成
	glBindTexture(GL_TEXTURE_2D, 0);

	
	glClearColor(0, 0, 0, 0);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glBindTexture(GL_TEXTURE_2D, texID[0]);
	glPushMatrix();
	glRotatef(static_cast<float>(r),0,1,0);
	glBegin(GL_QUADS);
	glColor3f(1,1,1);
	glTexCoord2f(1, 1);  glVertex3f(1,1,0);
	glTexCoord2f(0, 1);  glVertex3f(-1,1,0);
	glTexCoord2f(0, 0);  glVertex3f(-1,-1,0);
	glTexCoord2f(1, 0);  glVertex3f(1,-1,0);
	glEnd();
	glPopMatrix();
	glBindTexture(GL_TEXTURE_2D, 0);



	glutSwapBuffers();


	if(++r > 360){ r = 0;}


}

void reshape(int w, int h)
{
	glViewport(0, 0, w, h);  //ビューポートの設定

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0); //視野の設定
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt(0.0, 2.0, 4.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); //視点の設定

}

void timer(int value)
{
	glutPostRedisplay();
	glutTimerFunc(value,timer,17); //タイマー関数
}



//---------- テクスチャオブジェクト作成 ---------//
void createTexture()
{
	glGenTextures(1,&texID[0]);
	glBindTexture(GL_TEXTURE_2D, texID[0]);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);

	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
	glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);  //自動的なミップマップの作成

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, TextureWH.first,TextureWH.second, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
	glBindTexture(GL_TEXTURE_2D, 0);

}

//---------- FBO,RBOの作成 ----------------//
void createFBOandRBO()
{
	//FBO作成
	glGenFramebuffersEXT(1, &FboID[0]);
	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FboID[0]);


	//RBOの作成
	glGenRenderbuffersEXT(1, &RboID[0]);//RGO作成
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, RboID[0]);//バインド

	//メモリ確保
	glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, TextureWH.first,TextureWH.second);
	glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);//RBOのデフォルトへバインド


	/* 関連付け(アタッチメント) */

	//テクスチャ->FBO (GL_COLOR_ATTACHMENT0に接続)
	glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texID[0], 0);
	
	//RBO->FBO
	glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, RboID[0]);



	glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);//FBOのデフォルトへバインド

	//FBOができているかのチェック
	if(checkFramebufferStatus() == false ){
		exit(0);
	}


}


bool checkFramebufferStatus()
{
	// check FBO status
	GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
	switch(status)
	{
	case GL_FRAMEBUFFER_COMPLETE_EXT:
		std::cout << "Framebuffer complete.\n";
		return true;

	case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
		std::cout << "[ERROR] Framebuffer incomplete: Attachment is NOT complete.\n";
		return false;

	case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
		std::cout << "[ERROR] Framebuffer incomplete: No image is attached to FBO.\n";
		return false;

	case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
		std::cout << "[ERROR] Framebuffer incomplete: Attached images have different dimensions.\n";
		return false;
	
	case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
		std::cout << "[ERROR] Framebuffer incomplete: Color attached images have different internal formats.\n";
		return false;

	case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
		std::cout << "[ERROR] Framebuffer incomplete: Draw buffer.\n" ;
		return false;

	case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
		std::cout << "[ERROR] Framebuffer incomplete: Read buffer.\n";
		return false;

	case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
		std::cout << "[ERROR] Unsupported by FBO implementation.\n";
		return false;

	default:
		std::cout << "[ERROR] Unknow error.\n"; 
		return false;
	}
}

メモ


RBOでデプスバッファの関連付けを行わないと、FBO内でデプステストが行われない。