MMDモデルを使用したデスクトップユーティリティの開発 その7 色表現

前: [その6](http://qiita.com/JI1LDG/items/ab3c5f8804aad016bf64)
次: [その8](http://qiita.com/JI1LDG/items/be6dae46846a08cbc5ca)


ディフューズ・スペキュラ光など、色の表現を追加する。
トゥーンシェーダ、スフィアマッピングを導入する。

マテリアルから必要な情報を取り出し、適切なテクスチャ座標の計算を行うことで、質感の表現ができます。
今回のソースは[こちら](https://github.com/JI1LDG/ModelViewer/tree/39245a35e6e9e27b7e70013ebbedc73d30e4b997)

```hlsl:effect.fx
matrix World;
matrix View;
matrix Projection;
float3 ambientLight;
float4 matDiffuse;
float4 matAmbient;
float4 matSpecular;
float matAlpha;
float matSpecularity;
float3 lightDir;
float3 eyePos;
Texture2D normalTexture;
SamplerState normalSampler {};
Texture2D toonTexture;
SamplerState toonSampler {};
Texture2D sphTexture;
SamplerState sphSampler {};
Texture2D spaTexture;
SamplerState spaSampler {};
bool tex;
bool ton;
bool sph;
bool spa;
bool edge;

struct Vertexes {
	float4 position : SV_Position;
	float4 normal : NORMAL;
	float2 uv : TEXCOORD;
};

struct OutVert {
	float4 position : SV_Position;
	float2 uv : TEXCOORD;
	float4 diffuse : COLOR0;
	float3 specular : COLOR1;
	float2 toonCoord : TEXCOORD1;
	float2 sphereCoord : TEXCOORD2;
};

struct Colors {
	float3 diffuse;
	float3 specular;
	float2 toonCoord;
};

Colors CalcLight(float3 E, float3 N) {
	Colors col = (Colors)0;

	col.diffuse = ambientLight;
	col.specular = 0;

	float3 L = normalize(-lightDir);
	float3 H = normalize(E + L);
	float2 prt = lit(dot(N, L), dot(N, H), matSpecularity).yz;
	col.specular += ambientLight * prt.y;

	col.diffuse *= matDiffuse.rgb;
	col.diffuse += matAmbient.rgb;
	col.diffuse = saturate(col.diffuse);
	col.specular *= matSpecular.rgb;

	col.toonCoord.x = clamp(0.5f - dot(normalize(N), normalize(E)) * 0.5f, 0, 1);
	col.toonCoord.y = clamp(0.5f - dot(normalize(N), normalize(L)) * 0.5f, 0, 1);

	return col;
}

OutVert myVertexShader(Vertexes input) {
	OutVert output = (OutVert)0;

	float4 posW = mul(input.position, World);
	float4 pos = mul(posW, View);
	pos = mul(pos, Projection);
	output.position = pos;
	output.uv = input.uv;

	float3 N = normalize(mul(input.normal, World)).xyz;
	float3 subEye = eyePos - posW.xyz;
	float3 E = normalize(subEye);
	Colors light = CalcLight(E, N);

	output.diffuse = float4(light.diffuse.rgb, matAlpha);
	output.specular = light.specular;

	output.toonCoord = light.toonCoord;
	output.sphereCoord = float2(input.normal.x / 2 + 0.5f, input.normal.y / 2 + 0.5f);

	return output;
}

float4 myPixelShader(OutVert input) : SV_Target {
	float4 color = normalTexture.Sample(normalSampler, input.uv) * input.diffuse + float4(input.specular.rgb, 0);
	if (sph) {
		color.rgb *= sphTexture.Sample(sphSampler, input.sphereCoord).rgb;
	}
	if (spa) {
		color.rgb += spaTexture.Sample(spaSampler, input.sphereCoord).rgb;
	}
	if (ton) {
		color.rgb *= toonTexture.Sample(toonSampler, input.toonCoord).rgb;
	}

	return color;
}

technique10 myTechnique {
	pass myPass {
		SetVertexShader(CompileShader(vs_5_0, myVertexShader()));
		SetPixelShader(CompileShader(ps_5_0, myPixelShader()));
	}
}
```

![cirno.png](https://qiita-image-store.s3.amazonaws.com/0/135830/a229a040-89a5-4e07-f7c8-9701ab5ad795.png)

##さいごに
調べながら色々ためしてみたのですが、なかなか思うようにはいかなかったため、シェーダ部分は色々なところからの寄せ集めです。

次回は、PMX読み込み・表示に取り掛かる予定です。