CrossFilter

今回は、クロスフィルタを載せます。

今回も、ピクセルシェーダーのみを使います。

このシェーダーは、きらきらと光るものを表現するために使われます。
例を出すと、車のヘッドライトや、金属の反射などを表現することができます。

モデルの描画にブリンフォンを使っています。
少々以前紹介したブリンフォンシェーダーと違うので
差異のみ載せておきます

ブリンフォン 差異
//入力ピクセル構造体
struct PS_INPUT
{
	float4 color	: COLOR0; //色
	float3 normal	: TEXCOORD1; //法線
	float3 light	: TEXCOORD0; //ライトベクトル
	float3 view		 : TEXCOORD2; //ビューベクトル
	float3 halfAngle : TEXCOORD3; //二等分ベクトル
};

//出力ピクセル構造体
struct PS_OUTPUT
{
	float4 color0 : COLOR0;
	float4 color1 : COLOR1;
};

//ピクセルシェーダー
PS_OUTPUT ps_main( 
	PS_INPUT input,
	uniform float4 Ambient,
	uniform float4 Diffuse,
	uniform float4 Specular,
	uniform float4 Ka,
	uniform float4 Kd,
	uniform float4 Ks,
	uniform float power
)
{
	PS_OUTPUT output;
	
	//輝度情報設定
	output.color1 = (output.color0 - float4( 1.3, 1.3, 1.3, 0 ) ) * 2.0f;
	
	return output;
 }

追加点は輝度情報設定と出力ピクセル構造体を追加したのみです。

クロスフィルタ
 //グローバル変数宣言
float u;
float v;
float texelSize;
sampler2D target;

//入力ピクセル構造体
struct PS_INPUT
{
	float2 texcoord  : TEXCOORD0; //テクスチャ座標
};

//色の取得
float4 getColor( sampler2D target, float2 texel[10] )
{	
	float4 color = 0.0f;
	
	color += tex2D( target, texel[0] ) * 0.19f;
	color += tex2D( target, texel[1] ) * 0.17f;
	color += tex2D( target, texel[2] ) * 0.15f;
	color += tex2D( target, texel[3] ) * 0.13f;
	color += tex2D( target, texel[4] ) * 0.11f;
	color += tex2D( target, texel[5] ) * 0.09f;
	color += tex2D( target, texel[6] ) * 0.07f;
	color += tex2D( target, texel[7] ) * 0.05f;
	color += tex2D( target, texel[8] ) * 0.03f;
	color += tex2D( target, texel[9] ) * 0.01f;
		
	return color * 4.0f;
}

//ピクセルシェーダー
float4 ps_main( 
	PS_INPUT input,
	uniform float u,
	uniform float v,
	uniform sampler2D target
) : COLOR0
{
	float2 texel[10];
	float4 color = float4( 0, 0, 0, 0 );
	
	texelSize *= 1.5f;
	for( int i = 0 ; i < 10; i++ ){
		texel[i] = input.texcoord + float2( u-(i*texelSize), v-(i*texelSize) );
	}
	color += getColor( target, texel );
	
	for( int i = 0 ; i < 10; i++ ){
		texel[i] = input.texcoord + float2( u+(i*texelSize), v-(i*texelSize) );
	}
	color += getColor( target, texel );
	
	for( int i = 0 ; i < 10; i++ ){
		texel[i] = input.texcoord + float2( u-(i*texelSize), v+(i*texelSize) );
	}
	color += getColor( target, texel );
	
	for( int i = 0 ; i < 10; i++ ){
		texel[i] = input.texcoord + float2( u+(i*texelSize), v+(i*texelSize) );
	}
	color += getColor( target, texel );
		
	return color;
}
 
//テクニックの指定
technique cross
{	
	//パスの指定
	pass Pass_0
	{
		BlendEnable = true; //ブレンドを有効
		BlendFunc = float2( SrcAlpha,One ); //ブレンド関数を設定
		FragmentProgram = compile arbfp1 ps_main( u, v, target );
	}
}

メインプログラム
#include "Matrix4.h"
#include "Color4.h"
#include "Vector2.h"
#include "Vector3.h"
#include "MathUtility.h"
#include "Shader.h"
#include <iostream>
#include <GL/glew.h>
#include <GL/glut.h>
 
#pragma comment( lib, "glew32.lib" )

static void display();
static void idle();
static void key( unsigned char state, int x, int y );
static void initializeGL();
static void initializeCg();
static void drawRect( float x, float y, float w, float h );

namespace {
	//ブリンフォン
	Shader* blinn = NULL;
	//クロスフィルタ
	Shader* cross = NULL;
	//ワールド行列
	Matrix4 World;
	//透視変換行列
	Matrix4 Projection;
	//ビュー行列
	Matrix4 View;
	//回転角度
	float angle;
	//Texture
	unsigned int texture[2];
	//FBO
	unsigned int fbo;

	const float BUFFER_SIZE = 1024.0f;
}

//メイン関数
void main( int argc, char* argv[] )
{
	glutInit( &argc, argv );
	glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
	glutInitWindowPosition( 0, 0 );
	glutInitWindowSize( 640, 480 );
	glutCreateWindow( "Cross Filter Shader" );

	//初期化
	initializeGL();
	initializeCg();

	//関数の登録
	glutDisplayFunc( display );
	glutIdleFunc( idle );
	glutKeyboardFunc( key );
	glutMainLoop();
}

void initializeGL()
{
	glewInit();

	glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
	glViewport( 0, 0, 640, 480 );
	//OpenGLでは何もさせない
	//透視変換行列の設定
	glMatrixMode( GL_PROJECTION );
	glLoadIdentity();

	Projection.setIdentity();
	Projection.setPerspective( 45.0f, 640.0f/480.0f, 0.1f, 100.0f );

	//ビュー行列の設定
	glMatrixMode( GL_MODELVIEW );
	glLoadIdentity();

	View.setIdentity();
	View.setLookAt( 
		Vector3( 0.0f, 0.0f, 5.0f ),
		Vector3( 0.0f, 0.0f, 0.0f ),
		Vector3( 0.0f, 1.0f, 0.0f )
	);

	//回転角度の初期化
	angle = 0.0f;

	//ワールド行列の設定
	Matrix4 translate, scale, rotate;
	translate.setIdentity();
	translate.setTranslate( Vector3( 0.0f, 0.0f, 0.0f ) );
	scale.setIdentity();
	scale.setScale( Vector3( 1.0f, 1.0f, 1.0f ) );
	rotate.setIdentity();
	rotate.setRotateY( angle );
	World = translate * scale * rotate;

	glDisable( GL_DEPTH_TEST );
	glDisable( GL_LIGHTING );
	glDisable( GL_CULL_FACE );

	//テクスチャのバインド
	glGenTextures( 2, texture );
	glBindTexture( GL_TEXTURE_2D, texture[0] );
	
	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_RGBA, BUFFER_SIZE, BUFFER_SIZE, 0, GL_RGBA, GL_FLOAT, 0 );
	
	glBindTexture( GL_TEXTURE_2D, texture[1] );
	
	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_RGBA, BUFFER_SIZE, BUFFER_SIZE, 0, GL_RGBA, GL_FLOAT, 0 );

	glBindTexture( GL_TEXTURE_2D, 0 );
	
	glGenFramebuffersEXT( 1, &fbo );
	glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo );
	glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texture[0], 0 );
	glFramebufferTexture2DEXT( GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, texture[1], 0 );
	glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
}

void initializeCg()
{
	//エフェクトの生成
	blinn = new Shader( "BlinnPhong.cgfx" );
	cross = new Shader( "CrossFilter.cgfx" );

	//テクニックの取得
	blinn->setTechnique( "blinnphong" );
	cross->setTechnique( "cross" );

	//パラメータの取得
	blinn->setParameter( "world", World );
	blinn->setParameter( "view", View );
	blinn->setParameter( "projection", Projection ); 
	cross->setParameter( "v", 1.0f/BUFFER_SIZE );
	cross->setParameter( "u", 1.0f/BUFFER_SIZE );
	cross->setParameter( "texelSize", (1.0f/BUFFER_SIZE+1.0f/BUFFER_SIZE));
	cross->setTexture( "target", texture[1] );
}

//描画
void display()
{
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, fbo );
	glPushAttrib( GL_VIEWPORT_BIT );
	glViewport( 0, 0, BUFFER_SIZE, BUFFER_SIZE );
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

	unsigned int attachments[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT  };
	glDrawBuffers( 2, attachments );

	blinn->begin();
	for( unsigned int pass = 0; pass < blinn->getPassNum(); pass++ )
	{
		blinn->setPass( pass );
		//トーラスの描画
		glutSolidTorus( 0.5f, 1.0f, 3, 3 );
	}
	blinn->end();

	glBindFramebufferEXT( GL_FRAMEBUFFER_EXT, 0 );
	glPopAttrib();

	blinn->begin();
	for( unsigned int pass = 0; pass < blinn->getPassNum(); pass++ )
	{
		blinn->setPass( pass );
		//トーラスの描画
		glutSolidTorus( 0.5f, 1.0f, 3, 3 );
	}
	blinn->end();

	cross->begin();
	for( unsigned int pass = 0; pass < cross->getPassNum(); pass++ )
	{
		cross->setPass( pass );
		drawRect( 0, 480, 640, -480 );
	}
	cross->end();

	cross->setTexture( "target", texture[1] );

	glEnable( GL_TEXTURE_2D );
	glBindTexture( GL_TEXTURE_2D, texture[0] );
	drawRect( 0, 0, 200, 200 );

	glBindTexture( GL_TEXTURE_2D, texture[1] );
	drawRect( 0, 200, 200, 200 );

	glDisable( GL_TEXTURE_2D );

	//バッファの切り替え
	glutSwapBuffers();
}

//更新
void idle()
{
	//回転角度の更新
	angle += 1.0f;

	//ワールド行列の更新
	Matrix4 translate, scale, rotate;
	translate.setTranslate( Vector3( 0.0f, 0.0f, 0.0f ) );
	scale.setScale( Vector3( 1.0f, 1.0f, 1.0f ) );
	rotate.setRotateY( angle );
	World = translate * scale * rotate;

	//パラメータの設定
	blinn->setParameter( "world", World );

	//再描画
	glutPostRedisplay();
}

//キー状態
void key( unsigned char state, int x, int y )
{
	switch( state ){
		//エスケープが押されたら終了
		case '\033':
			delete blinn;
			delete cross;
			exit( 0 );
			break;
	}
}

矩形の描画は以前にも載せているので省きました。

スクリーンショットの中央部分に×印に光が伸びてるのが分かると思います。

最終更新:2009年05月06日 19:08
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。