要約
Summary
In the previous tutorials, the world looks boring because all the objects are lit in the same way.
This tutorial will introduce the concept of simple lighting and how it can be applied.
The technique used will be lambertian lighting.
The outcome of this tutorial will modify the previous example to include a light source.
This light source will be attached to the cube in orbit. The effects of the light can be seen on the center cube.
以前のチュートリアルでは全てのオブジェクトが同じように照らされているため、世界は退屈に見えます。このチュートリアルでは、単純なライティングの概念およびその適用方法について説明します。この技法は、ランバートライティングとなります。
このチュートリアルでは、結果として、光源を含むように前の例を変更します。この光源は、軌道内の立方体に関連付けられます。ライトの効果は、中央の立方体で確認できます。
ライティング
Lighting
In this tutorial, the most basic type of lighting will be introduced: lambertian lighting.
このチュートリアルでは、ランバートライティングという最も基本的な種類のライトを紹介します。
Lambertian lighting has uniform intensity irrespective of the distance away from the light.
ランバートライティングでは、ライトからの距離に関係なく、強度は均一になります。
When the light hits the surface, the amount of light reflected is calculated by the angle of incidence the light has on the surface.
光が面(ポリゴン表面)にヒットした時、その入射角により光の反射率が計算されます。
When a light is shined directly on a surface, it is shown to reflect all the light back, with maximum intensity.
光が面に対して垂直に照射される時、全ての光が反射して最大の強さとなります。
However, as the angle of the light is increased, the intensity of the light will fade away.
しかしながら、光の角度が上がるに連れ、光の強さは弱まります。
To calculate the intensity that a light has on a surface, the angle between the light direction and the normal of the surface has to be calculated.
光が面上で輝く強さを計算するには、ライトの方向と面の法線の間の角度を計算する必要があります。
The normal for a surface is defined as a vector that is perpendicular to the surface.
面の法線は面に垂直なベクトルとして定義されます。
The calculation of the angle can be done with a simple dot product, which will return the projection of the light direction vector onto the normal.
角度の計算は 法線に対する光の方向のベクトルの射影を返す単純な内積で出来ます。
The wider the angle, the smaller the projection will be.
角度が広がるに連れて、射影は小さくなります。
Thus, this gives us the correct function to modulate the diffused light with.
このようにして、拡散した光を調整する適切な関数が提供されます。
The light source used in this tutorial is an approximation of directional lighting.
このチュートリアルで使われる光源は指向性照射の近似です。
The vector which describes the light source determines the direction of the light.
光源を定義するベクトルが光の方向を決定します。
Since it's an approximation, no matter where an object is, the direction in which the light shines towards it is the same.
これは近似なので、オブジェクトが何処にあってもそれを照らす光の照射方向は同じです。
An example of this light source is the sun. The sun is always seen to be shining in the same direction for all objects in a scene.
この光源の一つの例が太陽です。太陽はいつも同じ方向からシーン中の全てのオブジェクトを照らしているように見えます。
In addition, the intensity of the light on individual objects is not taken into consideration.
また、個々のオブジェクトに対するライトの強弱は考慮されません。
Other types of light include point lights, which radiate uniform light from their centers, and spot lights, which are directional but not uniform across all objects.
この他のライトの種類には、中心から均一の光を照射するポイント ライトと、指向性だが全てのオブジェクトに対して均一なわけではないスポット ライトがあります。
ライトの初期化
Initializing the Lights
In this tutorial, there will be two light sources.
このチュートリアルには2つの光源があります。
One will be statically placed above and behind the cube, and another one will be orbiting the center cube.
一つは一つの立方体の後ろ上に静的に置かれ、そしてもう一つは中央の立方体を公転します。
Note that the orbiting cube in the previous tutorial has been replaced with this light source.
前のチュートリアルで軌道を回っていた立方体が、この光源で置き換えられていることに注目してください。
Since lighting is computed by the shaders, the variables would have to be declared and then bound to the variables within the technique.
ライティングはシェーダによって計算されるので、変数を宣言してそれをテクニック内の変数と結ぶ必要があります。
In this sample, we just require the direction of the light source, as well as its color value.
このサンプルでは、光源の方向と色値だけが必要になります。
The first light is grey and not moving, while the second one is an orbiting red light.
1 つ目のライトは灰色のライトであり、移動しません。一方、2 つ目のライトは軌道を回る赤いライトです。
// ライトの設定
XMFLOAT4 vLightDirs[2] =
{
XMFLOAT4( -0.577f, 0.577f, -0.577f, 1.0f ),
XMFLOAT4( 0.0f, 0.0f, -1.0f, 1.0f ),
};
XMFLOAT4 vLightColors[2] =
{
XMFLOAT4( 0.5f, 0.5f, 0.5f, 1.0f ),
XMFLOAT4( 0.5f, 0.0f, 0.0f, 1.0f )
};
The orbiting light is rotated just like the cube in the last tutorial.
軌道を回るライトは、直前のチュートリアルの立方体と同様に回転させます。
The rotation matrix applied will change the direction of the light, to show the effect that it is always shining towards the center.
適用される回転行列により、常に中心に向って照射するようにライトの方向が変更されます。
Note that function XMVector3Transform is used to multiply a matrix with a vector.
関数XMVector3Transformは行列をベクトルに掛けるために使われる事に注目して下さい。
In the previous tutorial, we multiplied just the transformation matrices into the world matrix, then passed into the shader for transformation.
前回のチュートリアルでは、座標変換行列をワールド行列に掛けてから座標変換のためにシェーダーに渡しました。
However, for simplicity's sake in this case, we're actually doing the world transform of the light in the CPU.
しかしながら、この場合は単純化のために、実際にライトのワールド変換をCPUで行います。
// Rotate the second light around the origin
XMMATRIX mRotate = XMMatrixRotationY( -2.0f * t );
XMVECTOR vLightDir = XMLoadFloat4( &vLightDirs[1] );
vLightDir = XMVector3Transform( vLightDir, mRotate );
XMStoreFloat4( &vLightDirs[1], vLightDir );
The lights' direction and color are both passed into the shader just like the matrices.
ライトの方向と色の両方を、行列と同様にシェーダーへ渡します。
The associated variable is called to set, and the parameter is passed in.
関連する変数を設定のために呼び出し、それにパラメーターを渡します。
//
// Update matrix variables and lighting variables
// 行列変数とライティング変数の更新
ConstantBuffer cb1;
cb1.mWorld = XMMatrixTranspose( g_World );
cb1.mView = XMMatrixTranspose( g_View );
cb1.mProjection = XMMatrixTranspose( g_Projection );
cb1.vLightDir[0] = vLightDirs[0];
cb1.vLightDir[1] = vLightDirs[1];
cb1.vLightColor[0] = vLightColors[0];
cb1.vLightColor[1] = vLightColors[1];
cb1.vOutputColor = XMFLOAT4(0, 0, 0, 0);
g_pImmediateContext->UpdateSubresource( g_pConstantBuffer, 0, NULL, &cb1, 0, 0 );
ピクセルシェーダでのライトの描画
Rendering the Lights in the Pixel Shader
Once we have all the data set up and the shader properly fed with data, we can compute the lambertian lighting term on each pixel from the light sources.
すべてのデータを設定し、シェーダーに正しくデータを渡したら、光源から各ピクセルのランバート ライティング項を計算できます。
We'll be using the dot product rule discussed previously.
既に説明してある内積のルールを使用します。
Once we've taken the dot product of the light versus the normal, it can then be multiplied with the color of the light to calculate the effect of that light.
一旦ライトの法線に対する内積を得たら、そのライトのエフェクトを計算するためにライトの色とそれを掛けることが出来ます。
That value is passed through the saturate function, which converts the range to [0, 1].Finally, the results from the two separate lights are summed together to create the final pixel color.
この値を、範囲を [0, 1] に変換する saturate 関数を通じて渡します。最後に、2 つの別個のライトの結果を、最終的なピクセル カラーを作成するために合計します。
Consider that the material of the surface itself is not factored into this light calculation. The final color of the surface is a result of the light's colors.
表面の材質自体はこのライトの計算の要素にはならない事を考慮して下さい。 最終的な表面の色はライトの色となります。
//
// ピクセルシェーダー
//
float4 PS( PS_INPUT input) : SV_Target
{
float4 finalColor = 0;
//do NdotL lighting for 2 lights
for(int i=0; i<2; i++)
{
finalColor += saturate( dot( (float3)vLightDir[i],input.Norm) * vLightColor[i] );
}
return finalColor;
}
Once through the pixel shader, the pixels will be modulated by the lights, and you can see the effect of each light on the cube surface.
一旦ピクセルシェーダを通過すると、ピクセルはライトによって調整され、 立方体の表面における それぞれのライトの効果が現れます。
Note that the light in this case looks flat because pixels on the same surface will have the same normal.
同じ面上のピクセルは同じ法線を持つため、この場合のライトは平面的に見えるということに注意してください。
Diffuse is a very simple and easy lighting model to compute.
ディフューズ(放散・拡散)は計算するのがとても簡単なライティングモデルです。
You can use more complex lighting models to achieve richer and more realistic materials.
あなたはもっとリッチでリアルな質感を表現するために、もっと複雑なライティングモデルを使うことも出来ます。
0 件のコメント:
コメントを投稿