bate's blog

調べたこと実装したことなどを取りとめもなく書きます。

FXComposer超入門3

ランバート反射をやってみます。
ライティングはピクセルシェーダーでやります。
ランバート反射の理論部分は、詳しい文献がいくらでもあるので説明しません。



1.FXComposerで新しいプロジェクトを作る。
2.バーにある[Teapot]を押します。
3.下の絵1の状態になっていることを確認する。

4.バーにある[Effect]を押す。
5.CgFXの新しいファイルを作り、[Empty]を選ぶ。
6.左の[Effects]にある新しく作ったファイルを開く。
7.下のコード1になるように変更する。

/*

% Description of my shader.
% Second line of description for my shader.

keywords: material classic

date: YYMMDD

*/

float4x4 WIT : WorldInverseTranspose <string UIWidget = "none";>;
float4x4 WVP : WorldViewProjection <string UIWidget = "none";>;
float4x4 W : World <string UIWidget = "none";>;
float4x4 VI : ViewInverse <string UIWidget = "none";>;


// Light
float4 PointLightPos : Position
<
	string UIName = "Point Light Pos";
	//string UIWidget = "none";
	string Space = "World";
> = { 5.0f, 0.0f, 0.0f, 1.0f };

float4 PointLightColor : Diffuse
<
	string UIName = "Point Light Color";
	string UIWidget = "Color";
	string Object = "PointLight";
> = { 1.0f, 0.5f, 0.4f, 1.0f };

float4 AmbientLight : Ambient
<
	string UIName = "Ambient Light";
	string UIWidget = "Color";
> = { 0.3f, 0.3f, 0.78f, 1.0f };

// Sphere
float4 Kd : Diffuse
<
	string UIName = "Sphere Diffuse";
	string UIWidget = "Color";
> = { 0.1f, 0.7f, 0.2f, 1.0f };

float4 Ka
<
	string UIName = "Sphere Ambient";
	string UIWidget = "Color";
> = { 1.0f, 1.0f, 1.0f, 1.0f };


// struct
struct appdata
{
	float4 Pos		: POSITION;
	float3 Normal	: NORMAL0;
};

struct V2Pdata
{
	float4 HPos		: POSITION;
	float3 LightDir	: TEXCOORD0;
	float3 WNormal	: TEXCOORD1;
};

V2Pdata mainVS(appdata IN)
{
	V2Pdata OUT = (V2Pdata)0;
	
	OUT.HPos = mul(WVP, IN.Pos);
	
	float3 normal = normalize(IN.Normal);
	OUT.WNormal = mul((float3x3)WIT, normal).xyz;
	float3 wpos = mul(W, IN.Pos).xyz;
	OUT.LightDir = normalize(PointLightPos.xyz-wpos);
	
	return OUT;
}

float4 mainPS(V2Pdata IN) :COLOR
{
	float3 L = IN.LightDir;
	float3 N = IN.WNormal.xyz;
	float4 amb = AmbientLight * Ka;
	float4 dif = PointLightColor * Kd;
	return amb + dif * max(0, dot(L,N));
}

technique technique0 {
	pass p0 {
		CullFaceEnable = true;
		DepthTestEnable = true;
		VertexProgram = compile vp40 mainVS();
		FragmentProgram = compile fp40 mainPS();
	}
}

8.左側の[Materials]にある「(新しいファイル名)_Material」をTeapotにドラックアンドドロップする。
9.下の絵2の状態になっていることを確認する。

10.頂点シェーダでライティング処理したい場合は、下のコード2のように変更します。

/*

% Description of my shader.
% Second line of description for my shader.

keywords: material classic

date: YYMMDD

*/

float4x4 WIT : WorldInverseTranspose <string UIWidget = "none";>;
float4x4 WVP : WorldViewProjection <string UIWidget = "none";>;
float4x4 W : World <string UIWidget = "none";>;
float4x4 VI : ViewInverse <string UIWidget = "none";>;


// Light
float4 PointLightPos : Position
<
	string UIName = "Point Light Pos";
	//string UIWidget = "none";
	string Space = "World";
> = { 5.0f, 0.0f, 0.0f, 1.0f };

float4 PointLightColor : Diffuse
<
	string UIName = "Point Light Color";
	string UIWidget = "Color";
	string Object = "PointLight";
> = { 1.0f, 0.5f, 0.4f, 1.0f };

float4 AmbientLight : Ambient
<
	string UIName = "Ambient Light";
	string UIWidget = "Color";
> = { 0.3f, 0.3f, 0.78f, 1.0f };

// Sphere
float4 Kd : Diffuse
<
	string UIName = "Sphere Diffuse";
	string UIWidget = "Color";
> = { 0.1f, 0.7f, 0.2f, 1.0f };

float4 Ka
<
	string UIName = "Sphere Ambient";
	string UIWidget = "Color";
> = { 1.0f, 1.0f, 1.0f, 1.0f };


// struct
struct appdata
{
	float4 Pos		: POSITION;
	float3 Normal	: NORMAL0;
};

struct V2Pdata
{
	float4 HPos		: POSITION;
	float4 Color	: COLOR0;
};

V2Pdata mainVS(appdata IN)
{
	V2Pdata OUT = (V2Pdata)0;
	
	OUT.HPos = mul(WVP, IN.Pos);
	
	float3 normal = normalize(IN.Normal);
	normal = mul((float3x3)WIT, normal).xyz;
	float3 wpos = mul(W, IN.Pos).xyz;
	
	float3 L = normalize(PointLightPos.xyz-wpos);
	float3 N = normal;
	float4 amb = AmbientLight * Ka;
	float4 dif = PointLightColor * Kd;
	OUT.Color = amb + dif * max(0, dot(L,N));
	
	return OUT;
}

float4 mainPS(V2Pdata IN) :COLOR
{
	return IN.Color;
}

technique technique0 {
	pass p0 {
		CullFaceEnable = true;
		DepthTestEnable = true;
		VertexProgram = compile vp40 mainVS();
		FragmentProgram = compile fp40 mainPS();
	}
}

11.下の絵3の状態になっていることを確認する。

12.頂点とピクセルどちらで処理してもあまり変わりません。頂点からピクセルに渡る際にラスタライザの補間が上手く処理してくれているようです。
13.おしまし。