「フラットシェーディング」の版間の差分
ナビゲーションに移動
検索に移動
Administrator (トーク | 投稿記録) (→HLSL) |
|||
(2人の利用者による、間の3版が非表示) | |||
3行目: | 3行目: | ||
1[[ポリゴン]]あたり1[[法線]]と[[データ]]量が非常に少なく、非常に高速に処理できるという利点があり、[[リアルタイムレンダリング]]が求められる[[ポリゴン]]を使った初期の[[ゲーム]]でよく用いられた。現在では[[ハードウェアT&L]]や[[プログラマブルシェーダー]]の登場でほぼ見かけることはなくなった。 | 1[[ポリゴン]]あたり1[[法線]]と[[データ]]量が非常に少なく、非常に高速に処理できるという利点があり、[[リアルタイムレンダリング]]が求められる[[ポリゴン]]を使った初期の[[ゲーム]]でよく用いられた。現在では[[ハードウェアT&L]]や[[プログラマブルシェーダー]]の登場でほぼ見かけることはなくなった。 | ||
− | == GLSL == | + | ==GLSL== |
− | + | [[GLSL]]では[[バーテックスシェーダー]]の出力変数に「flat修飾子」を付けるとフラットシェーディングとなる。 | |
+ | <syntaxhighlight lang="glsl"> | ||
// 入力 | // 入力 | ||
layout (location = 0) in vec3 VertexPosition; | layout (location = 0) in vec3 VertexPosition; | ||
− | layout (location = 1) | + | layout (location = 1) in vec3 VertexNormal; |
// 出力(これ) | // 出力(これ) | ||
15行目: | 16行目: | ||
void main() | void main() | ||
{ | { | ||
− | // | + | // 出力変数に「flat out」と書かれていると、ここが頂点1個分しか呼ばれない |
} | } | ||
+ | </syntaxhighlight> | ||
− | + | [[バーテックスシェーダー]]の出力値を格納する変数にflat修飾子をつけると、その[[バーテックスシェーダー]]では[[ポリゴン]]を構成する3つの[[頂点]]のいずれか1つだけが計算され、その値が[[フラグメントシェーダー]]に渡ってくる。前述の概要で「[[法線]]を面単位で持つ」と書いたが、GLSLでは「ポリゴンを構成する[[頂点]]の[[法線]]のいずれか1つが使われる」という内容になっている。 | |
+ | |||
+ | == HLSL == | ||
+ | [[HLSL]]にはフラットシェーディングを扱う方法がない。このため普通に3頂点を計算して擬似的にフラットシェーディングを実装することになる。見た目がフラットシェーディング風になるだけなので速度的な利点は一切ない。 | ||
+ | |||
+ | <syntaxhighlight> | ||
+ | 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(); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
==関連項目== | ==関連項目== |
2021年12月10日 (金) 04:41時点における最新版
フラットシェーディングとは、3DCGの陰影処理技法のひとつで、法線をポリゴン面単位で保持し、法線はポリゴン面に対して常に垂直なものとして扱うものをいう。1ポリゴンごとに1色で塗りつぶされる。
1ポリゴンあたり1法線とデータ量が非常に少なく、非常に高速に処理できるという利点があり、リアルタイムレンダリングが求められるポリゴンを使った初期のゲームでよく用いられた。現在ではハードウェアT&Lやプログラマブルシェーダーの登場でほぼ見かけることはなくなった。
GLSL[編集 | ソースを編集]
GLSLではバーテックスシェーダーの出力変数に「flat修飾子」を付けるとフラットシェーディングとなる。
// 入力
layout (location = 0) in vec3 VertexPosition;
layout (location = 1) in vec3 VertexNormal;
// 出力(これ)
flat out vec3 Intensity;
// バーテックスシェーダー
void main()
{
// 出力変数に「flat out」と書かれていると、ここが頂点1個分しか呼ばれない
}
バーテックスシェーダーの出力値を格納する変数にflat修飾子をつけると、そのバーテックスシェーダーではポリゴンを構成する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();
}
}