さくらみるふぃーゆのブログ

さくらみるふぃーゆのブログ

いや、マジで書きたいことを綴りますよ。
だって、それは『日記』だもの。。

Amebaでブログを始めよう!
C#/WPFではなく、C#のForm画面を作成することになった。
テキストボックスとかのバリデーション処理の実装がしたくなったので、調べてみた。
本当は、枠を赤くしたかったけど、かなり作りこみが必要そうだったので、簡単な方法でを2パターン。

①テキストボックス横にアイコンを表示。
②テキストボックス背景を赤くする。
using System;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
 
// 参考
// https://msdn.microsoft.com/ja-jp/library/system.windows.forms.errorprovider%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396
 
namespace WindowsFormsApp1
{
	/// <summary>
	/// 検証サンプルクラス
	/// </summary>
	public partial class Form1 : Form
	{
		/// <summary>
		/// エラー検証
		/// </summary>
		private System.Windows.Forms.ErrorProvider _errorProvider;
 
		private readonly string _errorMessage = "InputValue is not numeric.";
 
		public Form1()
		{
			InitializeComponent();
 
			_errorProvider = new System.Windows.Forms.ErrorProvider();
			_errorProvider.SetIconAlignment(this.textBox1, ErrorIconAlignment.MiddleRight);// このアイコンは、コントロールの中央とコントロールの右側に表示されます。
			_errorProvider.SetIconPadding(this.textBox1, 2);
			_errorProvider.BlinkRate = 1000;
			_errorProvider.BlinkStyle = System.Windows.Forms.ErrorBlinkStyle.AlwaysBlink;
		}
 
		#region EventMethod
		private void textBox1_Validating(object sender, CancelEventArgs e)
		{
			//int work;
			//if (!int.TryParse(textBox1.Text, out work))
			//{
			//	textBox1.BackColor = Color.Red;
			//	e.Cancel = true;
			//	MessageBox.Show("validationg");
			//}
		}
		private void textBox1_Validated(object sender, EventArgs e)
		{
			//textBox1.BackColor = Color.White;
			if (IsNameValid())
			{
				// Clear the error, if any, in the error provider.
				_errorProvider.SetError(this.textBox1, String.Empty);
			}
			else
			{
				// Set the error if the name is not valid.
				_errorProvider.SetError(this.textBox1, _errorMessage);
			}
		}
		// Functions to verify data.
		private bool IsNameValid()
		{
			// Determine whether the text box contains a zero-length string.
			return (textBox1.Text.Length > 0);
		}
 
		private void textBox2_Validating(object sender, CancelEventArgs e)
		{
			int work;
			if (!int.TryParse(textBox2.Text, out work))
			{
				// 背景を赤色に変更する。
				textBox2.BackColor = Color.Red;
				// カーソルを留める。
				e.Cancel = true;
				MessageBox.Show(_errorMessage);
			}
		}
 
		private void textBox2_Validated(object sender, EventArgs e)
		{
			// 背景をdefaultにする。
			textBox2.BackColor = TextBox.DefaultBackColor;
		}
		#endregion
	}
}

VS2017で久しぶりにC++開発を始めた。

 

一人プロジェクトだけど、まぁまぁ規模があったので、機能毎にプロジェクトを分けた。

メインと他はdll。

 

さて、リンク。

 

エラー。。。

 

え、なんで他のdllシンボルがみつかないの!!

え、えーーーー

 

最近はC#ばかりだったので、感が鈍っていたのかもしれない。

 

そもそもインポートライブラリが生成されてないじゃん。

なんでだろう。

 

ファクトリパターンとかデザインパターンを久しぶりに入れたから、継承関係の成果とおもっていろいろいじってたのに。

C++17のメソッドもガンガンつかったから、そのせいかとおもったのに。

 

全部普通のC++にもどして、やっと気づいた。

dll作ってくれないから、スタティックライブラリに変更した。

もういいや。

 

本社勤務になってから、C++からずっと離れていたが、またやることになった。

 

zip内のファイルを読む必要があるのだが、いちいち解凍なんぞしてらんない。

何万個もあるからね。

 

昔の視聴率システムのときは、zlibを使って読み込みをやっていたが、今回は7zipでやってみようかと思った。

※zlibは思い出しながら、何とか作り直せた(-_-;;

 

 

でも、難しかった。

まず公式サイトから「7-Zip ソースコード」ってのを取得。

https://sevenzip.osdn.jp/download.html

 

解凍して、その後が大変だった。

IDAとか使っていて感覚鈍ったなー。

いろんなサイトを見たが、上手くいかなかった。

\7z1700-src\CPP\Build.mak

を修正して、

LFLAGS = $(LFLAGS) -OPT:NOWIN98

LFLAGS = $(LFLAGS)

 

この後、この\7z1700-src\CPP\Build.makに対して

nmake NEW_COMPILER=1 MY_STATIC_LINK=1 Build.mak
を、VSのコマンドラインで実行してみってのが多かった。
けどだめ。


そんで1日眠らせて、次の日再チャレンジ。
わかった。
「Build.mak」じゃない。「makefile」ってのにnmakeを実行しなきゃだめなんだわ。
以下のサイト見ててわかった。ありがとう!!
How to compile 7-zip with visual studio 2015 rc

https://stackoverflow.com/questions/39689253/how-to-compile-7-zip-with-visual-studio-2015-rc

 

 

ってことで、以下でできました。

 

cd 7z1700-src\CPP\7zip

nmake NEW_COMPILER=1 MY_STATIC_LINK=1

職場でWEBアプリが案件が増えてきた。
その中でオフラインでWEB環境がそろえられるXAMPPの導入をやってみた。
 
というか、ポート80問題の調査のために自宅でも調査をしてみたので、ついでにレポート。
 
①ダウンロード
最新版7.1.1 / PHP 7.1.1をダウンロード。
 
②インストール
 
③コンパネ
取り合えずコントロールパネルを起動します。
おや、これは職場でも出会ったポート80エラー。
[main]     Initializing Modules
[Apache]     Problem detected!
[Apache]     Port 80 in use by "Unable to open process" with PID 4!
[Apache]     Apache WILL NOT start without the configured ports free!
[Apache]     You need to uninstall/disable/reconfigure the blocking application
[Apache]     or reconfigure Apache and the Control Panel to listen on a different port

[main]     Starting Check-Timer
[main]     Control Panel Ready
つまり、
 『ポート80は、プロセスID4のせいでオープンできないプロセスだよ。』
と。
これからが戦いです。。。
ネットで色々調べる度も、解決できず。
IISが悪いとか、Skypeが悪いとか。どれも違ってました。
ローラー作戦しかないよ!という記事を読んで決心。
 
--
ちなみに、httpd.confファイルのポート80を8080や81など開いているポートに変更する手段もやりましたが、結局アパッチ起動にいたらず。
--
コマンドライン、もしくはXAMPPコンパネの"netstat"を起動します。
一番上のプロセスID4が犯人で、システムの何で使われているかをこれから探します。
方法は、サービスウィンドウを起動し、実行中のネットワーク関連サービスを一つずつ停止していきます。
 
根気よく。
その結果、犯人はSQLServerでした。
↑を停止したところ、
とまりました。
やったー。
再度、コンパネに戻って、"start"押下。
正常に起動できました!!

●opencv_lib.hpp

#pragma once

// version
#include <opencv2\core\version.hpp>

// バージョン取得
#define CV_VERSION_STR CVAUX_STR(CV_MAJOR_VERSION) CVAUX_STR(CV_MINOR_VERSION) CVAUX_STR(CV_SUBMINOR_VERSION)

// ビルドモード
#ifdef _DEBUG
#define CV_EXT_STR "d.lib"
#else
#define CV_EXT_STR ".lib"
#endif
#define PREFIX "opencv_"


#define LIB_NAME(STR) PREFIX #STR CV_VERSION_STR CV_EXT_STR


//#define LIB_NAME_RELEASE(__A)  STR(PREFIX_OPENCV) STR(__A) STR(CV_VERSION_MAJOR) STR(CV_VERSION_MINOR) STR(CV_VERSION_REVISION) STR(SUFFIX_LIB)
//#define LIB_NAME_DEBUG(__A)    STR(PREFIX_OPENCV) STR(__A) STR(CV_VERSION_MAJOR) STR(CV_VERSION_MINOR) STR(CV_VERSION_REVISION) "d" STR(SUFFIX_LIB)
//// ライブラリ名生成
//#define LIB_NAME(__A)          STR(__A) STR(SUFFIX_LIB)
//// Staticビルド用ライブラリ名を生成
//#define LIB_NAME_3RD_PARTY_RELEASE(__A)    STR(__A) STR(SUFFIX_LIB)
//#define LIB_NAME_3RD_PARTY_DEBUG(__A)      STR(__A) "d" STR(SUFFIX_LIB)


#pragma comment(lib, LIB_NAME(calib3d))
#pragma comment(lib, LIB_NAME(contrib))
#pragma comment(lib, LIB_NAME(core))
#pragma comment(lib, LIB_NAME(features2d))
#pragma comment(lib, LIB_NAME(flann))
#pragma comment(lib, LIB_NAME(gpu))
#pragma comment(lib, LIB_NAME(highgui))
#pragma comment(lib, LIB_NAME(imgproc))
#pragma comment(lib, LIB_NAME(legacy))
#pragma comment(lib, LIB_NAME(ml))
#pragma comment(lib, LIB_NAME(nonfree))
#pragma comment(lib, LIB_NAME(objdetect))
#pragma comment(lib, LIB_NAME(ocl))
#pragma comment(lib, LIB_NAME(photo))
#pragma comment(lib, LIB_NAME(stitching))
#pragma comment(lib, LIB_NAME(superres))
#pragma comment(lib, LIB_NAME(ts))
#pragma comment(lib, LIB_NAME(video))
#pragma comment(lib, LIB_NAME(videostab))
 

 

 

●main.cpp
#include <opencv2\opencv.hpp>
#include "opencv_lib.hpp"


void main()
{
    cv::Mat image = cv::imread( "..\\data\\lena.jpg" );
    if( image.empty() )
    {
        return;
    }

    cv::imshow( "test", image );
    cv::waitKey( 0 );

}
 

再び勉強していると色々またわかってくるもんだ。
コードをすっきりして見た。

●ただ三角を表示


●4倍に圧縮した場合


*********************************************************************

#include
#include
#include
#include
#pragma comment(lib,"glext.lib")


/************* global *************/
GLuint g_tex[1];
GLuint g_fbo[1];
GLuint g_rbo[1];

#define RATIO 10
#define WIN_WIDTH 1280
#define WIN_HEIGHT 960
#define FBO_WIDTH WIN_WIDTH / RATIO
#define FBO_HEIGHT WIN_HEIGHT / RATIO

#define _FBO 1

/************* prototype *************/
void disp(void);
void reshape(int w, int h);
void Keyboard(unsigned char key, int x, int y);
void createTexture(void);
void createFBO(void);
void createRBO(void);
void relateFBO(void);
bool checkFramebufferStatus(void);

void main(int argc, char *argv)
{
glutInit(&argc, &argv);
glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
glutCreateWindow("texture");

glutDisplayFunc(disp);
glutReshapeFunc(reshape);
glutKeyboardFunc(Keyboard);
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);

createTexture();
createFBO();
createRBO();
relateFBO();

glutMainLoop();

//破棄
glDeleteTextures(1, &g_tex[0]);
glDeleteFramebuffersEXT(1, &g_fbo[0]);
glDeleteRenderbuffersEXT(1, &g_rbo[0]);
}

void disp(void)
{
#if _FBO
//描画先をFBOへ
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_fbo[0]);
//ビューポートの設定
glViewport(0, 0, FBO_WIDTH, FBO_HEIGHT);
#endif//_FBO
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glBegin(GL_POLYGON);
glColor4f(0.0, 1.0, 0.0, 1.0);
//glVertex2f(-1.0, -1.0);
//glVertex2f( 1.0, -1.0);
//glVertex2f( 1.0, 1.0);
//glVertex2f(-1.0, 1.0);
glVertex2f(-0.5f, -0.5f);
glVertex2f(0.5f, -0.5f);
glVertex2f(0.0f, 0.5f);
glEnd();
glPopMatrix();

#if _FBO
glFlush();

//出力先を通常のフレームバッファの戻す
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, g_tex[0]);
glGenerateMipmapEXT(GL_TEXTURE_2D);//ミップマップの生成
glBindTexture(GL_TEXTURE_2D, 0);
//ビューポートの設定
glViewport(0, 0, WIN_WIDTH, WIN_HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_TEXTURE_2D);
glPushMatrix();
glBindTexture(GL_TEXTURE_2D, g_tex[0]);
glBegin(GL_POLYGON);
glTexCoord2d(0.0, 1.0); glVertex2d(-1, 1);
glTexCoord2d(0.0, 0.0); glVertex2d(-1, -1);
glTexCoord2d(1.0, 0.0); glVertex2d( 1, -1);
glTexCoord2d(1.0, 1.0); glVertex2d( 1, 1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glPopMatrix();
glDisable(GL_TEXTURE_2D);

#endif _FBO

glFlush();
glutSwapBuffers();
}

void reshape(int w, int h)
{
glViewport(0, 0, w, h); //ビューポートの設定
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
#if 0
gluPerspective(30.0, (double)w / (double)h, 1.0, 100.0); //視野の設定
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(3.0, 4.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); //視点の設定
#else
glOrtho(-1, 1, -1, 1, -1, 100);
glMatrixMode(GL_MODELVIEW);
#endif
}

void Keyboard(unsigned char key, int x, int y) {
switch (key)
{
case 'Q':
case 'q':
case 0x1B:
exit(0);
break;
default:
break;
}
}


void createTexture(void)
{
glGenTextures(1, &g_tex[0]);
glBindTexture(GL_TEXTURE_2D, g_tex[0]);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);

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, FBO_WIDTH, FBO_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glBindTexture(GL_TEXTURE_2D, 0);
}

void createFBO(void)
{
//FBO作成
glGenFramebuffersEXT(1, &g_fbo[0]);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_fbo[0]);
//FBOのデフォルトへバインド
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
}

void createRBO(void)
{
//RBOの作成
glGenRenderbuffersEXT(1, &g_rbo[0]);
//バインド
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, g_rbo[0]);
//メモリ確保
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, FBO_WIDTH, FBO_HEIGHT);
//RBOのデフォルトへバインド
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);

}
void relateFBO(void)
{
//バインド
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, g_fbo[0]);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, g_rbo[0]);
glBindTexture(GL_TEXTURE_2D, g_tex[0]);

/* 関連付け(アタッチメント) */
//テクスチャ -> FBO (GL_COLOR_ATTACHMENT0に接続)
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, g_tex[0], 0);
//! RBO -> FBO
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, g_rbo[0]);

//FBOができているかのチェック
if (checkFramebufferStatus() == false) {
exit(0);
}
//アンバインド
glBindTexture(GL_TEXTURE_2D, 0);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 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;
}
}
相変わらずFBOです。
もういい加減ますたーになりたいわ。
しかし、なぜか仕事場では思った結果がでなくて、


むかむか。

今回は、「opengl resolution」「glBlitFramebuffer」をキーワードにしてよさげなリンクをはる。


●Desktop 向け OpenGL ES 2.0 / OpenGL ES 3.0 / OpenGL ES 3.1 (AEP) 実行環境
http://dench.flatlib.jp/opengl/glesemulator


●low resolution in OpenGL to mimic older games
http://stackoverflow.com/questions/7071090/low-resolution-in-opengl-to-mimic-older-games

●OpenGL ES 3.0で追加されたAPIまとめ
http://ramemiso.hateblo.jp/entry/2013/09/15/174714

●OpenGLでMSAA
http://blog.techlab-xe.net/archives/3117
ここ最近まで見た映画のランキング
覚えている限り


1. 羊たちの沈黙
2. ハンニバル
3. IT
4. レッドドラゴン
5. スクリーム
6. 記憶探偵と鍵のかかった少女
7. スクリーム 2
8. スクリーム 3
9. スクリーム 4
10. さよならドビュッシー
11. ベイマックス
12. ゴーンガール
13. 名探偵コナン 異次元の狙撃手
14. ハンニバル ライジング
15. バイロケーション
16. エクスクロス

論外. ことりばこ

最近、映画を見るようになった。
ほんと、急に。

しかも段々そのジャンルが偏ってきて、自分でも確認してきた。

それは、

「サスペンス」

「サイコ サスペンス」

「サイト ホラー」
と変わってきた。
これからも変わってくるかもしれない。

自分がわからない。
「マルチサンプリング」をいれるも、機能しなかった。。。

--
#include
#include
#include
#pragma comment(lib,"glext.lib")

#include
#include

//------------ 各種外部変数 ------------//
const std::string filename = "..\\..\\..\\data\\image\\桜咲く.jpg";

GLuint tex_image;


std::pair TextureWH(512, 512);
unsigned int texID[1];

#define TEX_RATIO 5
#define TEX_WIDTH 320*TEX_RATIO
#define TEX_HEIGHT 180*TEX_RATIO

#define WIN_WIDTH 320*5
#define WIN_HEIGHT 180*5

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

int GLframe = 0; //フレーム数
int GLtimenow = 0;//経過時間
int GLtimebase = 0;//計測開始時間

//---------- 各種プロトタイプ -----------//
void display();
void reshape(int w, int h);
void timer(int value);
void idle(void);
void Keyboard(unsigned char key, int x, int y);

void createTexture();
void createFBOandRBO();
bool checkFramebufferStatus();
void createImageTexture(void);
void drawImageTexture(int ratio = 1);


#define _TEST

//--------- メイン関数 ---------//
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitWindowSize(WIN_WIDTH, WIN_HEIGHT);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH| GLUT_MULTISAMPLE);
/* マルチサンプリングの状態の確認 */
GLint bufs, samples;
glGetIntegerv(GL_SAMPLE_BUFFERS, &bufs);
glGetIntegerv(GL_SAMPLES, &samples);
glutCreateWindow("render to texture");
/*http://miffysora.wikidot.com/ja:multisample*/
if (bufs > 0 && samples > 1) {
/* マルチサンプリングを有効にする */
glEnable(GL_MULTISAMPLE);
/* アルファ値をサンプルの被覆率にする */
glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
glSampleCoverage(0.5, GL_FALSE);
}

glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutTimerFunc(0, timer, 17);
glutIdleFunc(idle);
glutKeyboardFunc(Keyboard);

glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_DEPTH_TEST);

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

glutMainLoop();

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

return 0;
}


void display(void)
{
static int r = 0;
#ifdef _TEST
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FboID[0]);//描画先の切り替え
glViewport( 0, 0, TEX_WIDTH*0.2, TEX_HEIGHT*0.2); //ビューポートの設定

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

glEnable(GL_BLEND);
// glEnable(GL_CULL_FACE);//陰面消去しておくとより顕著にわかりやすく見えるのでEnableにした
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//back-to-front
// GL_LINE_SMOOTH_HINT, GL_POINT_SMOOTH_HINT, GL_POLYGON_SMOOTH_HINT
// GL_NICEST,GL_FASTEST,GL_DONT_CASE
glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST);
glEnable(GL_POLYGON_SMOOTH);

#if 1// 0:画像 / 1:ティーポット
glRotatef(static_cast(r), 0, 1, 0);
glColor3f(0, 1, 0);
/* ティーポットを描く */
glutWireTeapot(0.5);
glColor3f(1, 0, 0);
glutWireCube(0.2);
glColor3f(0, 0, 1);
glTranslatef(0, 0, -1);
glutSolidSphere(1.0, 20, 20);
glColor3f(1, 1, 1);
#else
glViewport(0, 0, 320 * 5, 180 * 5); //ビューポートの設定
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex_image);

glBegin(GL_QUADS);
int ratio = 5;
glTexCoord2d(1.0*ratio, 1.0*ratio); glVertex2d(1, 1);
glTexCoord2d(0.0*ratio, 1.0*ratio); glVertex2d(-1, 1);
glTexCoord2d(0.0*ratio, 0.0*ratio); glVertex2d(-1, -1);
glTexCoord2d(1.0*ratio, 0.0*ratio); glVertex2d(1, -1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
#endif
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);
#endif


glViewport(0, 0, WIN_WIDTH, WIN_HEIGHT); //ビューポートの設定
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glEnable(GL_TEXTURE_2D);
glPushMatrix();
#ifdef _TEST
glBindTexture(GL_TEXTURE_2D, texID[0]);
#else
glBindTexture(GL_TEXTURE_2D, tex_image);
#endif
glRotatef(static_cast(r), 0, 1, 0);
glBegin(GL_POLYGON);
glTexCoord2d(0.0, 1.0); glVertex2d(-1, 1);
glTexCoord2d(0.0, 0.0); glVertex2d(-1, -1);
glTexCoord2d(1.0, 0.0); glVertex2d( 1, -1);
glTexCoord2d(1.0, 1.0); glVertex2d( 1, 1);
glEnd();
glBindTexture(GL_TEXTURE_2D, 0);
glPopMatrix();
glDisable(GL_TEXTURE_2D);

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

void reshape(int w, int h)
{
glViewport(0, 0, w, h); //ビューポートの設定
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
#if 0
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); //視点の設定
#else
glOrtho( -1, 1, -1, 1, -1, 100 );
glMatrixMode(GL_MODELVIEW);
#endif
}

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

void idle(void)
{
GLframe++; //フレーム数を+1
GLtimenow = glutGet(GLUT_ELAPSED_TIME);//経過時間を取得

if (GLtimenow - GLtimebase > 1000) //1秒以上たったらfpsを出力
{
printf("fps:%f\r", GLframe*1000.0 / (GLtimenow - GLtimebase));
GLtimebase = GLtimenow;//基準時間を設定
GLframe = 0;//フレーム数をリセット
}
}

void Keyboard(unsigned char key, int x, int y) {
switch (key)
{
case 'Q':
case 'q':
case 0x1B:
exit(0);
break;
default:
break;
}
}
//---------- テクスチャオブジェクト作成 ---------//
void createTexture()
{
glGenTextures(1, &texID[0]);
glBindTexture(GL_TEXTURE_2D, texID[0]);

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);

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, TEX_WIDTH, TEX_HEIGHT, 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_COMPONENT24, TEX_WIDTH, TEX_HEIGHT);
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;
}
}

void createImageTexture( void )
{
cv::Mat image = cv::imread(filename);
if (image.empty()) {
exit(0);
}
cv::flip(image, image, 0);

glEnable(GL_TEXTURE_2D);
glGenTextures(1, &tex_image);
glBindTexture(GL_TEXTURE_2D, tex_image);
glTexImage2D(
GL_TEXTURE_2D, 0, 3, image.cols, image.rows,
0, GL_BGR, GL_UNSIGNED_BYTE, image.data );
/*
GL_NEAREST(最近傍法)
GL_LINEAR(双線形補間)
*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); //拡大フィルタ
/*
GL_NEAREST(最近傍法)
GL_LINEAR(双線形補間)
GL_NEAREST_MIPMAP_NEAREST
GL_NEAREST_MIPMAP_LINEAR
GL_LINEAR_MIPMAP_NEAREST
GL_LINEAR_MIPMAP_LINEAR
*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); //縮小フィルタ
/*
GL_REPEAT → 画像が繰り返されているとするとして画像の色を拾う
GL_CLAMP → 0~1の範囲に固定
GL_CLAMP_TO_EDGE → 画像の端のピクセルの色を使う。
GL_CLAMP_TO_BORDER → 境界の色を設定してそれを使う。(OpenGL 1.3以上)
GL_MIRRORED_REPEAT → 繰り返すとき画像を反転させる (OpenGL 1.4 以上)
*/
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);//左右端
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);//上下端
glBindTexture(GL_TEXTURE_2D, 0);
image.release();
}