XSI Mod Tool でシェーダプログラミング

雑記

色々中途半端にやっています。

Cgfx と XSI Mod Tool を使ってシェーダプログラミングをします。本当は FX Composer を使おうと思っていたのですが、なぜか私のPCでは 2.5 は起動できず、2.0 は OpenGL でエラーが出ます。

まあ、UI は XSI の方が好きなので。

で、シェーダプログラミングですがこんな感じ。

 

2011-12-06 01h28_32

 

手順をすぐ忘れるのでメモ。

 

リアルタイムシェーダで表示

ビューの右上メニューから「Realtime Shaders」→「OpenGL」を選択。

 

Cgfx プログラムを適用する

 

「View」→「Render Tree」を選択。

何も表示されていない場合は、適用したいオブジェクトを選択して、更新ボタン 2011-12-06 01h50_28を押す。

左側のリストから「RealTime」→「Cg」を選択し、「Cg Fx」をドラッグ&ドロップする。

CgFx ノードをダブルクリックして、CgFx ファイルを選択する。

CgFx ノードの出力を、マテリアルの RealTime につなげる。

CgFx ノードを開いて、「Compile」を押す。

 

ここまで上手くいっていれば CgFx ノードを開くと次のようなパネルになる。

2011-12-06 01h30_36

 

ノードツリーは次のようになっている。

2011-12-06 01h28_35

 

UV, Tangent, Binormal を作成

オブジェクトを選択して、「Property」→「Texture Map」でテクスチャ座標生成。私はトーラスを作成して「Cylindrical」を選択。

Tangent, Binormal は 「Property」→「Tangent」、または「Binormal」を選択。

 

2011-12-06 01h29_41  2011-12-06 01h29_56  2011-12-06 01h30_06

 

作成した UV, Tangent, Binormal をシェーダに渡すには CgFx ノードを開いて IN.UV, IN.Tangent, IN.Binormal (これらはシェーダ内の記述によって変わることがある)に設定する。

2011-12-06 01h30_36

 

ここにある CgFx プログラムは XSI 内のライトを参照しているので、そのライトを作成する。

ライトは 「Primitive」→「Light」→「Infinite」 で作成。適当な向きに設定する。

 

2011-12-06 01h31_18

 

Technique で、ランバート、ハーフランバート、フォン、ブリンを選べます。テクスチャはカラーマップ、ノーマルマップ、環境マップがありますので、適当に設定してください。これでおしまい。

CgFx のコードは以下。

// #define _XSI_
//#include "quad.cgh"

float4x4 WorldXf : World < string UIWidget="none"; >;
float4x4 WorldITXf : WorldInverseTranspose < string UIWidget="none"; >;
float4x4 WvpXf : WorldViewProjection < string UIWidget="none"; >;
float4x4 ViewIXf : ViewInverse < string UIWidget="none"; >;

float3 DirLight0_dir : SAS.DIRECTIONALLIGHT[0].DIRECTION;
float3 DirLight0_col : SAS.DIRECTIONALLIGHT[0].COLOR;

float3 Ka
<
	string UIName = "Ambient";
	string UIObject = "RGB";
	string UIWidget = "Color";
> = {0.0,0.0,0.0};

float3 Kd
<
	string UIName = "Diffuse";
	string UIObject = "RGB";
	string UIWidget = "Color";
> = {1.0,1.0,1.0};

float Ks
<
	string UIName = "Specular";
	string UIObject = "Slider";
	float UIMin = 0.0;
	float UIMax = 1.0;
	float UIStep = 0.05;
> = 0.4;
/*
float3 Emissive
<
	string UIName = "Specular";
	string UIObject = "RGB";
	string UIWidget = "Color";
> = {1.0,1.0,1.0};
*/
float SpecExpon
<
	string UIName = "Specular Power";
	string UIObject = "Slider";
	float UIMin = 1.0;
	float UIMax = 128.0;
	float UIStep = 1.0;
> = 55.0;

float Eccentricity
<
	string UIName = "Eccentricity";
	string UIObject = "Slider";
	float UIMin = 0.0;
	float UIMax = 1.0;
	float UIStep = 0.1;
> = 0.3;
/*
float3 RimColor
<
	string UIName = "RimColor";
	string UIObject = "RGB";
	string UIWidget = "Color";
> = {0.0,0.0,0.0};

float3 RimContrib
<
	string UIName = "RimContrib";
	string UIObject = "RGB";
	string UIWidget = "Color";
> = {0.0,0.0,0.0};

float RimPower
<
	string UIName = "Rim Power";
	string UIObject = "Slider";
	float UIMin = 1.0;
	float UIMax = 128.0;
	float UIStep = 1.0;
> = 55.0;
*/
float Bump
<
	string UIName = "Bumpiness";
	string UIObject = "Slider";
	float UIMin = 0.0;
	float UIMax = 3.0;
	float UIStep = 0.01;
> = 1.0;

float Kr
<
	string UIName = "Reflection Strength";
	string UIObject = "Slider";
	float UIMin = 0.0;
	float UIMax = 1.0;
	float UIStep = 0.01;
> = 0.5;

texture ColorTexture <
	string ResourceName = "default_color.dds";
	string ResourceType = "2D";
>;

sampler2D ColorSampler = sampler_state {
	Texture = <ColorTexture>;
	MinFilter = LinearMipMapFilter;
	MagFilter = Linear;
	WrapS = Repeat;
	WrapT = Repeat;
};

texture NormalTexture <
	string ResourceName = "default_bump_normal.dds";
	string ResourceType = "2D";
>;

sampler2D NormalSampler = sampler_state {
	Texture = <NormalTexture>;
	MinFilter = LinearMipMapFilter;
	MagFilter = Linear;
	WrapS = Repeat;
	WrapT = Repeat;
};

texture EnvTexture : ENVIRONMENT <
	string ResourceName = "default_reflection.dds";
	string ResourceType = "Cube";
>;

samplerCUBE EnvSampler = sampler_state {
	Texture = <EnvTexture>;
	MinFilter = LinearMipMapFilter;
	MagFilter = Linear;
	WrapS = ClampToEdge;
	WrapT = ClampToEdge;
};

// data from application vertex buffer
struct appdata
{
	float4 Position : POSITION;
	float4 UV       : TEXCOORD0;
	float4 Normal   : NORMAL;
	float4 Tangent  : TANGENT0;
	float4 Binormal : BINORMAL0;
};

// data passed from vertex shader to pixel shader
struct vertexOutput
{
	float4 HPosition     : POSITION;
	float2 UV            : TEXCOORD0;
	float3 LightVec      : TEXCOORD1;
	float3 WorldNormal   : TEXCOORD2;
	float3 WorldTangent  : TEXCOORD3;
	float3 WorldBinormal : TEXCOORD4;
	float3 WorldView     : TEXCOORD5;
	float  Fog           : FOG;
};

//------------------------------------------------------------

void phong_shading(vertexOutput IN,
				   float3 LightColor,
				   float3 Nn,
				   float3 Ln,
				   float3 Vn,
				   out float3 DiffuseContrib,
				   out float3 SpecularContrib)
{
	float3 Rn = -Vn + 2.0f*dot(Nn,Vn)*Nn;
	float4 litV = lit(dot(Ln,Nn), dot(Ln,Rn), SpecExpon);
	DiffuseContrib = litV.y * LightColor;
	SpecularContrib = litV.y * litV.z * Ks * LightColor;
}

void blinn_phong_shading(vertexOutput IN,
				   float3 LightColor,
				   float3 Nn,
				   float3 Ln,
				   float3 Vn,
				   out float3 DiffuseContrib,
				   out float3 SpecularContrib)
{
	float3 Hn = normalize(Vn + Ln);
	float4 litV = lit(dot(Ln,Nn), dot(Hn,Nn), SpecExpon);
	DiffuseContrib = litV.y * LightColor;
	SpecularContrib = litV.y * litV.z * Ks * LightColor;
}

void blinn_shading(vertexOutput IN,
				   float3 LightColor,
				   float3 Nn,
				   float3 Ln,
				   float3 Vn,
				   out float3 DiffuseContrib,
				   out float3 SpecularContrib)
{
	float3 Hn = normalize(Ln + Vn);
	float ndv = dot(Nn, Vn);
	float ndh = dot(Nn, Hn);
	float vdh = dot(Vn, Hn);
	float ndl = dot(Nn, Ln);
	float ldh = dot(Ln, Hn);

	// Beckmann
	const float m = 0.35f;
	float ndh2 = ndh*ndh;
	float D = exp(-(1-ndh2)/(ndh2*m*m))/(4*m*m*ndh2*ndh2);
/*	
	float3 R = reflect(-Ln, Nn);
	float rdv = dot(R, Vn);
	rdv = max(rdv, 0.001);
	float esq = Eccentricity * Eccentricity;
	float D = esq / (rdv * rdv * (esq - 1.0) + 1.0);
	D = D*D;
*/

	//
	float Gb = 2.0 * ndh * ndv / vdh;
	float Gc = 2.0 * ndh * ndl / vdh;
	float Ga = min(1.0, min(Gb,Gc));

	// Fresnel
	/*
	float n = 20.0f;
	float g = sqrt(n*n*ldh*ldh-1);
	float gpc = g + ldh;
	float gnc = g - ldh;
	float cgpc = ldh * gpc - 1;
	float cgnc = ldh * gnc + 1;
	float F = 0.5 * gnc * gnc * (1+cgpc*cgpc/(cgnc*cgnc))/(gpc*gpc);
	*/
	
	float F = 1.0 - pow(ndv, 5.0);

	ndh = D * Ga * F / ndv;
	DiffuseContrib = ndl * LightColor;
	SpecularContrib = ndh * Ks * LightColor;
}

//------------------------------------------------------------

vertexOutput std_phong_vp(appdata IN)
{
	vertexOutput OUT;

	OUT.WorldNormal   = mul(WorldITXf, IN.Normal).xyz;
	OUT.WorldTangent  = mul(WorldITXf, IN.Tangent).xyz;
	OUT.WorldBinormal = mul(WorldITXf, IN.Binormal).xyz;
	
	float4 Po = float4(IN.Position.xyz, 1.0);
	float3 Pw = mul(WorldXf, Po).xyz;
	OUT.LightVec = -DirLight0_dir;
	OUT.UV = IN.UV.xy;
	OUT.WorldView = normalize(float3(ViewIXf[0].w, ViewIXf[1].w, ViewIXf[2].w) - Pw);
	OUT.HPosition = mul(WvpXf, Po);
	OUT.Fog = OUT.HPosition.w;

	return OUT;
}


float4 std_lambert_fp(vertexOutput IN) : COLOR
{
	float3 Ln = normalize(IN.LightVec);
	float3 Nn = normalize(IN.WorldNormal);
	float ldn = max(dot(Ln,Nn),0.0);
	//float ldn = max(dot(Ln,Nn),0.0) * 0.5 + 0.5;
	float3 diffuseContrib = ldn * DirLight0_col * Kd;
	float3 diffuseColor = tex2D(ColorSampler, IN.UV).rgb;
	float3 ambientContrib = DirLight0_col * Ka;
	float3 result = diffuseColor * (diffuseContrib + ambientContrib);
	//float fogColor = 1.0 - saturate(IN.Fog / 1000.0);
	//return float4(result * fogColor,1.0);
	return float4(result, 1.0);
}

float4 std_half_lambert_fp(vertexOutput IN) : COLOR
{
	float3 Ln = normalize(IN.LightVec);
	float3 Nn = normalize(IN.WorldNormal);
	//float ldn = max(dot(Ln,Nn),0.0);
	float ldn = max(dot(Ln,Nn),0.0) * 0.5 + 0.5;
	float3 diffuseContrib = ldn * DirLight0_col * Kd;
	float3 diffuseColor = tex2D(ColorSampler, IN.UV).rgb;
	float3 ambientContrib = DirLight0_col * Ka;
	float3 result = diffuseColor * (diffuseContrib + ambientContrib);
	float fogColor = 1.0 - saturate(IN.Fog / 1000.0);
	return float4(result * fogColor,1.0);
}

float4 std_phong_fp(vertexOutput IN) : COLOR
{
	float3 diffContrib;
	float3 specContrib;
	float3 Ln = normalize(IN.LightVec);
	float3 Vn = normalize(IN.WorldView);
	float3 Nn = normalize(IN.WorldNormal);
	float3 Tn = normalize(IN.WorldTangent);
	float3 Bn = normalize(IN.WorldBinormal);
	float3 bump = Bump * (tex2D(NormalSampler, IN.UV).rgb - float3(0.5,0.5,0.5));
	Nn = Nn + bump.x*Tn + bump.y*Bn;
	Nn = normalize(Nn);
	phong_shading(IN, DirLight0_col, Nn, Ln, Vn, diffContrib, specContrib);
	// ambient
	float3 ambientContrib = Ka;
	// rim lighting
	//diffContrib += RimColor * RimContrib * pow(1-dot(Nn,Vn), RimPower);
	// decal map
	float3 diffuseColor = tex2D(ColorSampler, IN.UV).rgb;
	float3 result = specContrib + (diffuseColor * (diffContrib + ambientContrib));
	// environment
	float3 R = reflect(Vn,Nn);
	float3 reflectColor = Kr * texCUBE(EnvSampler,R.xyz).rgb;
	result += diffuseColor * reflectColor;
	// fog
	float fogColor = 1.0 - saturate(IN.Fog / 1000.0);
//	return float4(diffuse,1.0);
	return float4(result * fogColor,1.0);
//	return float4(fogColor, fogColor, fogColor, 1.0);
//	return float4(ldn, ldn, ldn, 1.0);
//	return float4(Ln, 1.0);
//	return float4(1.0,1.0,1.0,1.0);
}

float4 std_blinn_phong_fp(vertexOutput IN) : COLOR
{
	float3 diffContrib;
	float3 specContrib;
	float3 Ln = normalize(IN.LightVec);
	float3 Vn = normalize(IN.WorldView);
	float3 Nn = normalize(IN.WorldNormal);
	blinn_phong_shading(IN, DirLight0_col, Nn, Ln, Vn, diffContrib, specContrib);
	float3 diffuseColor = tex2D(ColorSampler, IN.UV).rgb;
	float3 result = specContrib + (diffuseColor * (diffContrib + Ka * DirLight0_col));
	float fogColor = 1.0 - saturate(IN.Fog / 1000.0);
	return float4(result * fogColor,1.0);
}

float4 std_blinn_fp(vertexOutput IN) : COLOR
{
	float3 Ln = normalize(IN.LightVec);
	float3 Vn = normalize(IN.WorldView);
	float3 Nn = normalize(IN.WorldNormal);
	float3 diffContrib;
	float3 specContrib;
	blinn_shading(IN, DirLight0_col, Nn, Ln, Vn, diffContrib, specContrib);
	float3 ambientColor = Ka;
	float3 diffuseColor = tex2D(ColorSampler, IN.UV).rgb;
	float3 result = specContrib + diffuseColor * (diffContrib * Kd + ambientColor);
	float fogColor = 1.0 - saturate(IN.Fog / 1000.0);
	return float4(result * fogColor,1.0);
//	return float4(1.0,1.0,1.0,1.0);
}

//------------------------------------------------------------

technique lambert
{
	pass p0
	{
		VertexProgram = compile vp40 std_phong_vp();
		FragmentProgram = compile fp40 std_lambert_fp();

		AlphaTestEnable = true;
		DepthTestEnable = true;
		DepthFunc = LEqual;
		DepthMask = true;

		BlendEnable = false;
		BlendFunc = int2(SrcAlpha, OneMinusSrcAlpha);
		BlendEquation = FuncAdd;

		CullFaceEnable = true;
		CullFace = back;
	}
}

technique half_lambert
{
	pass p0
	{
		VertexProgram = compile vp40 std_phong_vp();
		FragmentProgram = compile fp40 std_half_lambert_fp();

		AlphaTestEnable = true;
		DepthTestEnable = true;
		DepthFunc = LEqual;
		DepthMask = true;

		BlendEnable = false;
		BlendFunc = int2(SrcAlpha, OneMinusSrcAlpha);
		BlendEquation = FuncAdd;

		CullFaceEnable = true;
		CullFace = back;
	}
}

technique phong
{
	pass p0
	{
		VertexProgram = compile vp40 std_phong_vp();
		FragmentProgram = compile fp40 std_phong_fp();

		AlphaTestEnable = true;
		DepthTestEnable = true;
		DepthFunc = LEqual;
		DepthMask = true;

		BlendEnable = false;
		BlendFunc = int2(SrcAlpha, OneMinusSrcAlpha);
		BlendEquation = FuncAdd;

		CullFaceEnable = true;
		CullFace = back;
	}
}

technique blinn_phong
{
	pass p0
	{
		VertexProgram = compile vp40 std_phong_vp();
		FragmentProgram = compile fp40 std_blinn_phong_fp();

		AlphaTestEnable = true;
		DepthTestEnable = true;
		DepthFunc = LEqual;
		DepthMask = true;

		BlendEnable = false;
		BlendFunc = int2(SrcAlpha, OneMinusSrcAlpha);
		BlendEquation = FuncAdd;

		CullFaceEnable = true;
		CullFace = back;
	}
}

technique blinn
{
	pass p0
	{
		VertexProgram = compile vp40 std_phong_vp();
		FragmentProgram = compile fp40 std_blinn_fp();

		AlphaTestEnable = true;
		DepthTestEnable = true;
		DepthFunc = LEqual;
		DepthMask = true;

		BlendEnable = false;
		BlendFunc = int2(SrcAlpha, OneMinusSrcAlpha);
		BlendEquation = FuncAdd;

		CullFaceEnable = true;
		CullFace = back;
	}
}

ダウンロードはこちら。stdshader.zip


« »

コメントは受け付けていません。