現在地メニュー >> Cg >> Cg編08
Index :Cg編07<< Cg編08 >> Cg編09

フラグメントシェーダと画像処理


フラグメントシェーダはピクセル単位の処理である。
従って、画像処理もできる。
例えばグレイスケール画像への変換は次のようになる。

【例】:fragment.cg グレースケール変換
//フラグメントの入力
struct FragmentIn
{
	float4 position : POSITION; //ラスタライズ用(使用しない)
	float3 color : COLOR; 
	… …
};

//フラグメントの出力
struct FragmentOut
{
	float3 color : COLOR;
};

//--------- フラグメントシェーダメイン関数 ------------//
FragmentOut CgFragmentMain(in FragmentIn input, … …)
{
	FragmentOut output;//フラグメント出力

	float gray = dot(input.color.xyz, float3(0.299, 0.587, 0.114));
       
	output.color = float3(gray,gray,gray);
	return output;
}

サンプルコード1


画像処理の仕方


シェーダを使って画像処理を行う場合は、画像をテクスチャにしておく。
処理は、そのテクスチャに対して行う。

表示方法


表示する時は平行投影を使う。
そして、描画の時はウィンドウのサイズに合わせた矩形を描画すればよい。

【例】:表示させる
//画像サイズ情報
struct ImageSizeInfo
{
	int w;
	int h;
};
ImageSizeInfo imgInfo;
… …

void reshape(int w, int h)
{
	glutReshapeWindow(imgInfo.w,imgInfo.h);//画像サイズにウィンドウを合わせる
	glViewport(0, 0, imgInfo.w,imgInfo.h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(0,imgInfo.w,0,imgInfo.h);//平行投影
	glMatrixMode(GL_MODELVIEW);
}
… …
glBegin(GL_QUADS);
glTexCoord2f(0.f,0.f);	
glVertex2f(0.f,0.f);
	
glTexCoord2f(1,0.f);
glVertex2f(imgInfo.w,0.f);
	
glTexCoord2f(1, 1);
glVertex2f(imgInfo.w, imgInfo.h);
	
glTexCoord2f(0.f, 1);	
glVertex2f(0.f, imgInfo.h);
glEnd();
… …

シェーダの書き方


【例】:vertex.cg
//入力頂点
struct VertexIn
{
	float4 position : POSITION;
	float2 texcoord : TEXCOORD0;
};

//出力頂点
struct VertexOut
{
	float4 position : POSITION;
	float2 texcoord : TEXCOORD0;
};

//-------- 頂点シェーダメイン関数 ---------//
VertexOut CgVertexMain(in VertexIn input,uniform float4x4 modelViewProj)
{
	VertexOut output;//出力用
	output.position = mul(modelViewProj, input.position);
	output.texcoord = input.texcoord;

	return output;
}
▲投影変換する+テクスチャ座標をわたす

【例】:fragment.cg
//フラグメントの入力
struct FragmentIn
{
	float4 position : POSITION; //ラスタライズ用(使用しない)
	float2 texcoord : TEXCOORD0;
};

//フラグメントの出力
struct FragmentOut
{
	float3 color : COLOR;
};

//--------- フラグメントシェーダメイン関数 ------------//
FragmentOut CgFragmentMain(in FragmentIn input,
								uniform sampler2D decal : TEX0)//TEX0でも可
{
	FragmentOut output;//フラグメント出力
	output.color = tex2D(decal,input.texcoord);
	return output;
}
▲「tex2D関数」でテクセルを拾えばよい

サンプルコード2

Texture Rectangleを利用する


テクスチャ座標が0〜1の間の値では、ピクセル操作をしにくいかもしれない。
そこでTexture Rectangleを利用することもできる。

表示方法

基本的に平行投影。
違いは、テクスチャ座標の指定方法。画像のサイズをそのまま対応付けることができる。
glBegin(GL_QUADS);
	
glTexCoord2f(0.f,0.f);	
glVertex2f(0.f,0.f);
	
glTexCoord2f(imgInfo.w,0.f);
glVertex2f(imgInfo.w,0.f);
	
glTexCoord2f(imgInfo.w, imgInfo.h);
glVertex2f(imgInfo.w, imgInfo.h);
	
glTexCoord2f(0.f, imgInfo.h);	
glVertex2f(0.f, imgInfo.h);
glEnd();

シェーダの書き方

頂点シェーダはかわらない。
フラグメントシェーダは「texRECT関数」でテクセル値をとってくる。

【例】:fragment.cg
//フラグメントの入力
struct FragmentIn
{
	float4 position : POSITION; //ラスタライズ用(使用しない)
	float2 texcoord : TEXCOORD0;
};

//フラグメントの出力
struct FragmentOut
{
	float3 color : COLOR;
};

//--------- フラグメントシェーダメイン関数 ------------//
FragmentOut CgFragmentMain(in FragmentIn input,
								uniform samplerRECT  decal : TEX0)//TEX0でも可
{
	FragmentOut output;//フラグメント出力
	output.color = texRECT(decal,input.texcoord);
	return output;
}

サンプルコード3

フィルタをかける

【例】:fragment.cg
//フラグメントの入力
struct FragmentIn
{
	float4 position : POSITION; //ラスタライズ用(使用しない)
	float2 texcoord : TEXCOORD0;
};

//フラグメントの出力
struct FragmentOut
{
	float3 color : COLOR;
};


//--------- フラグメントシェーダメイン関数 ------------//
FragmentOut CgFragmentMain(in FragmentIn input,
					uniform samplerRECT  decal : TEX0,
					uniform half Kernels[9])
{
	FragmentOut output;//フラグメント出力

	int k=0;
	for(int y = -1; y < 2; ++y)
	{
		for(int x = -1; x < 2; ++x)
		{
			output.color += texRECT(decal,input.texcoord + half2(y,x)) * Kernels[k];
			++k;
		}
	}

	return output;
}

【例】:main.cpp
CGparameter CgFragmentKernel;//フィルタ用カーネル
float kernelData[9]={-1,-1,-1, -1,9,-1, -1,-1,-1};//係数(鮮鋭化フィルタ)

//名前の関連付けと値設定
CgFragmentKernel = cgGetNamedParameter(CgFragmentProgram, "Kernels");
cgGLSetParameterArray1f(CgFragmentKernel,0,0,kernelData);//配列データを渡す

サンプルコード4

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






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


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

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