フラットシェーディング

提供: MonoBook
ナビゲーションに移動 検索に移動

フラットシェーディングとは、3DCGの陰影処理技法のひとつで、法線ポリゴン面単位で保持し、法線はポリゴン面に対して常に垂直なものとして扱うものをいう。1ポリゴンごとに1色で塗りつぶされる。

ポリゴンあたり1法線データ量が非常に少なく、非常に高速に処理できるという利点があり、リアルタイムレンダリングが求められるポリゴンを使った初期のゲームでよく用いられた。現在ではハードウェアT&Lプログラマブルシェーダーの登場でほぼ見かけることはなくなった。

GLSL[編集 | ソースを編集]

GLSLではバーテックスシェーダーの出力変数に「flat修飾子」を付けるとフラットシェーディングとなる。

// 入力
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) ih vec3 VertexNormal;

// 出力(これ)
flat out vec3 Intensity;

// バーテックスシェーダー
void main() 
{
    // フォンシェーディングやグローシェーディングなんかを書いておく
    // 出力変数に「flat out」と書かれていると、ここが頂点1個分しか呼ばれない
}

この場合、バーテックスシェーダーフォンシェーディンググローシェーディングなどをアルゴリズムを書いておいても、ポリゴンを構成する3つの頂点のいずれか1つだけが計算され、その結果がフラグメントシェーダーに渡ってくる。つまりGLSLでは前述の概要で「法線を面単位で持つ」と書いたが「ポリゴンを構成する頂点法線のいずれか1つが使われる」という内容になっている。

HLSL[編集 | ソースを編集]

HLSLにはフラットシェーディングを扱う方法がない。このため普通に3頂点を計算して擬似的にフラットシェーディングを実装することになる。

float4x4 World;
float4x4 View;
float4x4 Projection;

float4 AmbientColor = float4(1, 1, 1, 1);
float  AmbientIntensity = 0.1f;

float3 DiffuseLightDirection = float3(1, 0, 0);
float4 DiffuseColor = float4(1, 1, 1, 1);
float  DiffuseIntensity = 1.0f;

texture ModelTexture;
sampler2D textureSampler = sampler_state {
	Texture = (ModelTexture);
	MinFilter = Linear;
    MagFilter = Linear;
    AddressU  = Clamp;
    AddressV  = Clamp;
};

struct VertexShaderInput
{
    float4 Position : POSITION0;
	float4 Normal : NORMAL0;
	float2 TextureCoordinate : TEXCOORD0;
};

struct VertexShaderOutput
{
    float4 Position : POSITION0;
	float4 PositionWorld : TEXCOORD0;
	float2 TextureCoordinate : TEXCOORD1;
};

VertexShaderOutput VertexShaderFunction(VertexShaderInput input)
{
    VertexShaderOutput output;

    float4 worldPosition = mul(input.Position, World);
    float4 viewPosition = mul(worldPosition, View);
    output.Position = mul(viewPosition, Projection);
	output.PositionWorld = worldPosition;

	output.TextureCoordinate = input.TextureCoordinate;

    return output;
}

float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
	float3 Normal = cross(ddy(input.PositionWorld.xyz), ddx(input.PositionWorld.xyz));
	Normal = normalize(Normal);

	float lightIntensity = dot(Normal, DiffuseLightDirection);
	float4 lightColor = lightIntensity * DiffuseColor * DiffuseIntensity + AmbientColor * AmbientIntensity;
	lightColor.a = 1;

	float4 textureColor = tex2D(textureSampler, input.TextureCoordinate);
	textureColor.a = 1;

    return saturate(textureColor * lightColor);
}

technique FlatTextured
{
    pass Pass1
    {
        VertexShader = compile vs_3_0 VertexShaderFunction();
        PixelShader  = compile ps_3_0 PixelShaderFunction();
    }
}

関連項目[編集 | ソースを編集]