現在地: メニュー >> 発展編04 >> 発展編::両面ステンシル1 >> 発展編04::まとめコード2
関連:発展編04::まとめコード1

問題


切断面を表示するプログラムを両面ステンシルを使って実現せよ。
その他条件
  • EXT拡張の両面ステンシルを使用する

答え


#include <iostream>
#include <GL/glew.h> //先に記述する
#include <GL/glut.h>

//-------------各種外部変数 -----------//
const double PlaneEq[]={1.0, 0.0, 0.0, 0.0};


//---------- プロトタイプ宣言 -----------//
void LIGHT_INIT();
void display();
void reshape(int w, int h);
void timer(int value);
void SetMaterialGold();
void SetUpTwoSideStencil();
void DrawStencilFace();

//----------- OpenGLの初期設定 -------------------------//
void GLUT_INIT()
{
	glutInitDisplayMode(GLUT_RGBA| GLUT_DOUBLE | GLUT_DEPTH|GLUT_STENCIL);
	glutInitWindowSize(640,480);
	glutCreateWindow("Two Side Stencil Part 2");
}

bool GLEW_INIT()
{
	GLenum err;
	err = glewInit();
	if (err != GLEW_OK){
		std::cerr << glewGetErrorString(err) << '\n';
		return false;
	}
	return true;
}


void GLUT_CALL_FUNC()
{
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);
	glutTimerFunc(0,timer,17);
}

void MY_INIT()
{
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glClearStencil(0);
	LIGHT_INIT(); //光源設定
	glEnable(GL_NORMALIZE);//法線の有効化
	glEnable(GL_DEPTH_TEST);
}


void LIGHT_INIT()
{
	float Light0Pos[]={3,4,5,0}; //光源の位置
	glLightfv(GL_LIGHT0, GL_POSITION, Light0Pos);//位置だけ設定(あとはデフォルト)

	glEnable(GL_LIGHTING);
	glEnable(GL_LIGHT0);
}

//材質設定
void SetMaterialGold()
{
	static GLfloat gold_amb[] = { 0.24725, 0.1995, 0.0745, 1.0 };
	static GLfloat gold_diff[] = { 0.75164, 0.60648 , 0.22648, 1.0 };
	static GLfloat gold_spe[] = { 0.628281, 0.555802,0.366065,1.0 };
	static GLfloat gold_shin[] = { 51.2 };
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, gold_amb);
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, gold_diff);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, gold_spe);
	glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, gold_shin);
}

//----------- メイン関数 ----------------//
int main(int argc, char **argv)
{
	glutInit(&argc,argv);
	GLUT_INIT();
	if ( GLEW_INIT() == false){
		std::cerr << "Can't init glew\n";
		return -1;
	}
	GLUT_CALL_FUNC();
	MY_INIT();
	glutMainLoop();

	return 0;
}


//--------------- ここからコールバック ----------------------//
void display()
{
	static int r = 0;
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
	glLoadIdentity();

	gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); //視点の設定

	glRotatef(static_cast<float>(r),0,1,0);
        
	glEnable(GL_CLIP_PLANE0);
	glClipPlane(GL_CLIP_PLANE0, PlaneEq);//クリッププレーンを設置
		
	glEnable(GL_STENCIL_TEST);
	glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT); //両面ステンシル開始
		SetUpTwoSideStencil(); //両面ステンシルの設定
		SetMaterialGold();
		glutSolidSphere(1,30,30); //描画
	glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT); //両面ステンシル終了

	glDisable(GL_CLIP_PLANE0);

	DrawStencilFace();//切断面の描画

	glDisable(GL_STENCIL_TEST); //ステンシルテスト無効化

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


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

//------------- ここから各種関数 ----------------//
void SetUpTwoSideStencil()
{
	//これ以降は裏面の設定
	glActiveStencilFaceEXT(GL_BACK);
	glStencilFunc(GL_ALWAYS, 0, ~0);
	glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); //ステンシル値 「+1」
	
	//これ以降は表面の設定
	glActiveStencilFaceEXT(GL_FRONT);
	glStencilFunc(GL_ALWAYS, 0, ~0);
	glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);//ステンシル値「-1」
}

void DrawStencilFace()
{
	//ステンシル値が0でない部分が描画される
	glStencilFunc(GL_NOTEQUAL, 0, ~0); 
	glPushMatrix();
	glRotatef(90,0,1,0);
	glRectf(-10,10,10,-10);
	glPopMatrix();
}

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






▲よろしければ広告のクリックもお願いします


▲ランキングに参加しました

管理人/副管理人のみ編集できます