Norėdami piešti daugiakampius, naudokite žibintus
suvestinė
Šviesos (šviesos šaltiniai) naudojamos daugiakampiams užtemdyti.
Darbo aplinka
Būtinosios sąlygos
Palaikomos XNA versijos |
|
Palaikomos platformos |
|
"Windows" reikalinga "Vertex Shader" versija | 2.0 |
"Windows" reikalinga "Pixel Shader" versija | 2.01 |
Darbo aplinka
platforma |
|
medžiaga
Apie "Lights"
Štai keletas dalykų, kuriuos galite padaryti naudodami žibintus.
medžiaga
Paprastai tariant, medžiaga yra medžiagos spalva. Medžiagos dažnai naudojamos kartu su "Lights", o "BasicEffects" taip pat leidžia nustatyti medžiagos ir šviesos parametrus. Tačiau tai netaikoma, jei rašote savo šešėlių programą, ir jūs galite ją laisvai koreguoti. Taip pat atkreipkite dėmesį, kad medžiagos spalva skiriasi nuo viršūnių spalvos.
Medžiagos paprastai turi šiuos elementus.
Difuzinis | Pagrindinės medžiagų spalvos |
Aplinkos | Spalvos spalva veikiant aplinkos šviesai (matoma, net jei šviesa nešviečia tiesiai ant jos) |
Spektrinis | Spekuliacinė atspindinti šviesa (stipriai šviečia kaip automobilio blizgesys ir pan.) |
SpecularPower | Atspindintis stipris (spektrinis stiprumas) |
Emissive | Skirtinga šviesa (šviečia savaime) |
Šviesos ir normalūs
Jei norite naudoti šviesą, jums reikės kažko, kas vadinama "normaliu". Šviesos padėtis normalios atžvilgiu lemia objekto ryškumą. Normalus bus nustatytas kaip viršūnės duomenys.
Jis yra ryškesnis, jei veidas nukreiptas į šviesos kryptį, ir tamsesnis, jei jis yra atvirkščiai. Tai pasakytina ir apie tai, jei veido kryptį pakeisite viršūne. Šių veidų ir viršūnių orientacija vadinama "normalia".
Dabar normalių dalykų kryptis nėra aiškiai apibrėžta, o laukelyje reikia nustatyti du pagrindinius normalumus: žemiau.
Yra skirtumas tarp kairės ir dešinės, kai naudojama šviesa.
Jei metodas yra kairėje, tarpas tarp veidų bus kampinis. Taip yra todėl, kad jis yra visiškai orientuotas ta pačia kryptimi, kaip ir normalus veidas. Tačiau šis metodas turi trūkumą, kad viršūnės negali būti bendrinamos.
Taikant metodą dešinėje, tarpas tarp paviršių bus šiek tiek suapvalintas, atsižvelgiant į tai, kaip naudojama šviesa. Kadangi viršūnės yra bendrinamos, yra privalumas, kad sumažėja duomenų kiekis. Trūkumas yra tas, kad viršūnės normalumas nėra tas pats, kas veido kryptis, todėl net jei šviesa šviečia tiesiai iš viršaus, pavyzdžiui, viršutinis paviršius nebus 100% paveiktas šviesos.
Sunku suprasti, net jei tai paaiškinate sakiniu, todėl patikrinkite toliau pateiktą diagramą, kad pamatytumėte skirtumą.
Jis rodomas su modeliavimo programine įranga, vadinama Metasequoia
Matote, kad išvaizda yra gana skirtinga. Pavyzdyje mes sukursime laukelį tinkamu būdu, kad kodas nebūtų nereikalingas.
laukas
<summary>
基本エフェクト
</summary>
private BasicEffect basicEffect = null;
<summary>
頂点バッファ
</summary>
private VertexBuffer vertexBuffer = null;
<summary>
インデックスバッファ
</summary>
private IndexBuffer indexBuffer = null;
<summary>
インデックスバッファの各頂点番号配列
</summary>
private static readonly Int16[] vertexIndices = new Int16[] {
2, 0, 1, 1, 3, 2, 4, 0, 2, 2, 6, 4, 5, 1, 0, 0, 4, 5,
7, 3, 1, 1, 5, 7, 6, 2, 3, 3, 7, 6, 4, 6, 7, 7, 5, 4 };
Dėžutė sukurta naudojant viršūnės buferį ir indekso buferį.
kūrinys
// エフェクトを作成
this.basicEffect = new BasicEffect(this.GraphicsDevice);
// エフェクトでライトを有効にする
this.basicEffect.LightingEnabled = true;
// デフォルトのライトの設定を使用する
this.basicEffect.EnableDefaultLighting();
// スペキュラーを無効
this.basicEffect.SpecularColor = Vector3.Zero;
// 2番目と3番目のライトを無効
this.basicEffect.DirectionalLight1.Enabled = false;
this.basicEffect.DirectionalLight2.Enabled = false;
"BasicEffect" yra keli elementai, nustatantys šviesą.
Pirmiausia nustatykite ypatybę LightingEnabled į true, kad nurodytumėte apskaičiuoti šviesą.
Kai iškviečiate "EnableDefaultLighting" metodą, šviesos ar medžiagos spalva nustatoma automatiškai. Tačiau naudojant numatytąją šio langelio lemputę yra per ryški, todėl išjungiau spektrinę spalvą ir išjungiau antrą ir trečią lemputes.
// 頂点の数
int vertexCount = 8;
// 頂点バッファ作成
this.vertexBuffer = new VertexBuffer(this.GraphicsDevice,
typeof(VertexPositionNormalTexture), vertexCount, BufferUsage.None);
// 頂点データを作成する
VertexPositionNormalTexture[] vertives = new VertexPositionNormalTexture[vertexCount];
vertives[0] = new VertexPositionNormalTexture(
new Vector3(-2.0f, 2.0f, -2.0f),
Vector3.Normalize(new Vector3(-1.0f, 1.0f, -1.0f)),
Vector2.Zero);
vertives[1] = new VertexPositionNormalTexture(
new Vector3(2.0f, 2.0f, -2.0f),
Vector3.Normalize(new Vector3(1.0f, 1.0f, -1.0f)),
Vector2.Zero);
vertives[2] = new VertexPositionNormalTexture(
new Vector3(-2.0f, 2.0f, 2.0f),
Vector3.Normalize(new Vector3(-1.0f, 1.0f, 1.0f)),
Vector2.Zero);
vertives[3] = new VertexPositionNormalTexture(
new Vector3(2.0f, 2.0f, 2.0f),
Vector3.Normalize(new Vector3(1.0f, 1.0f, 1.0f)),
Vector2.Zero);
vertives[4] = new VertexPositionNormalTexture(
new Vector3(-2.0f, -2.0f, -2.0f),
Vector3.Normalize(new Vector3(-1.0f, -1.0f, -1.0f)),
Vector2.Zero);
vertives[5] = new VertexPositionNormalTexture(
new Vector3(2.0f, -2.0f, -2.0f),
Vector3.Normalize(new Vector3(1.0f, -1.0f, -1.0f)),
Vector2.Zero);
vertives[6] = new VertexPositionNormalTexture(
new Vector3(-2.0f, -2.0f, 2.0f),
Vector3.Normalize(new Vector3(-1.0f, -1.0f, 1.0f)),
Vector2.Zero);
vertives[7] = new VertexPositionNormalTexture(
new Vector3(2.0f, -2.0f, 2.0f),
Vector3.Normalize(new Vector3(1.0f, -1.0f, 1.0f)),
Vector2.Zero);
// 頂点データを頂点バッファに書き込む
this.vertexBuffer.SetData(vertives);
Tai šiek tiek ilgas kodo gabalas, tačiau jis sukuria viršūnių duomenis. Šį kartą naudojama viršūnių duomenų struktūra yra "VertexPositionNormalTexture" su "position", "normal" ir "texture coordinates" duomenimis. Kadangi "XNA Framework" nesuteikia struktūros tik su "padėtimi" ir "normalia", "Vector2.Zero" yra nurodytas visoms tekstūros koordinačių viršūnėms. (Žinoma, jei suprantate, galite sukurti savo struktūrą.)
Kalbant apie įprastą, kaip parodyta ankstesniame paveikslėlyje, jis nustatytas nukreipti įstrižai. Kadangi normalūs yra duomenų apibrėžimai, kurie pateikiami tik pagal orientaciją, kryptis nurodoma ir normalizuojama metodu Vector3.Normal.
VertexPositionNormalTexture
Konstruktorius
Sukurkite struktūros "VertexPositionNormalTexture" egzempliorių su viršūnių duomenimis apie padėtį ir normalias bei tekstūros koordinates.
Poziciją | Vektorius3 | Viršūnės padėtis |
įprastas | Vektorius3 | Vertex normalūs |
tekstūraKoordinatė | Vektorius2 | Viršūnių tekstūros koordinatės |
Vector3.Normalize
metodas
Sukuria vieneto vektorių iš nurodyto vektoriaus.
vertė | Vektorius3 | Šaltinio vektorius normalizuoti |
Reikšmių grąžinimas | Vektorius3 | Vieneto vektorius |
// インデックスバッファを作成
this.indexBuffer = new IndexBuffer(this.GraphicsDevice,
IndexElementSize.SixteenBits, 3 * 12, BufferUsage.None);
// 頂点インデックスを書き込む
this.indexBuffer.SetData(vertexIndices);
Indekso buferio kūrimas nesiskiria.
piešinys
// 描画に使用する頂点バッファをセット
this.GraphicsDevice.SetVertexBuffer(this.vertexBuffer);
// インデックスバッファをセット
this.GraphicsDevice.Indices = this.indexBuffer;
// パスの数だけ繰り替えし描画
foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
{
// パスの開始
pass.Apply();
// ボックスを描画する
this.GraphicsDevice.DrawIndexedPrimitives(
PrimitiveType.TriangleList,
0,
0,
8,
0,
12
);
}
Kadangi viršūnės informacija yra nustatyta iš anksto, piešimo kode nėra nieko ypatingo.
Visi kodai
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
#if WINDOWS_PHONE
using Microsoft.Xna.Framework.Input.Touch;
#endif
namespace BoxReceivedLight
{
<summary>
ゲームメインクラス
</summary>
public class GameMain : Microsoft.Xna.Framework.Game
{
<summary>
グラフィックデバイス管理クラス
</summary>
private GraphicsDeviceManager graphics = null;
<summary>
スプライトのバッチ化クラス
</summary>
private SpriteBatch spriteBatch = null;
<summary>
基本エフェクト
</summary>
private BasicEffect basicEffect = null;
<summary>
頂点バッファ
</summary>
private VertexBuffer vertexBuffer = null;
<summary>
インデックスバッファ
</summary>
private IndexBuffer indexBuffer = null;
<summary>
インデックスバッファの各頂点番号配列
</summary>
private static readonly Int16[] vertexIndices = new Int16[] {
2, 0, 1, 1, 3, 2, 4, 0, 2, 2, 6, 4, 5, 1, 0, 0, 4, 5,
7, 3, 1, 1, 5, 7, 6, 2, 3, 3, 7, 6, 4, 6, 7, 7, 5, 4 };
<summary>
GameMain コンストラクタ
</summary>
public GameMain()
{
// グラフィックデバイス管理クラスの作成
this.graphics = new GraphicsDeviceManager(this);
// ゲームコンテンツのルートディレクトリを設定
this.Content.RootDirectory = "Content";
#if WINDOWS_PHONE
// Windows Phone のデフォルトのフレームレートは 30 FPS
this.TargetElapsedTime = TimeSpan.FromTicks(333333);
// バックバッファサイズの設定
this.graphics.PreferredBackBufferWidth = 480;
this.graphics.PreferredBackBufferHeight = 800;
// フルスクリーン表示
this.graphics.IsFullScreen = true;
#endif
}
<summary>
ゲームが始まる前の初期化処理を行うメソッド
グラフィック以外のデータの読み込み、コンポーネントの初期化を行う
</summary>
protected override void Initialize()
{
// TODO: ここに初期化ロジックを書いてください
// コンポーネントの初期化などを行います
base.Initialize();
}
<summary>
ゲームが始まるときに一回だけ呼ばれ
すべてのゲームコンテンツを読み込みます
</summary>
protected override void LoadContent()
{
// テクスチャーを描画するためのスプライトバッチクラスを作成します
this.spriteBatch = new SpriteBatch(this.GraphicsDevice);
// エフェクトを作成
this.basicEffect = new BasicEffect(this.GraphicsDevice);
// エフェクトでライトを有効にする
this.basicEffect.LightingEnabled = true;
// デフォルトのライトの設定を使用する
this.basicEffect.EnableDefaultLighting();
// スペキュラーを無効
this.basicEffect.SpecularColor = Vector3.Zero;
// 2番目と3番目のライトを無効
this.basicEffect.DirectionalLight1.Enabled = false;
this.basicEffect.DirectionalLight2.Enabled = false;
// ビューマトリックスをあらかじめ設定 ((6, 6, 12) から原点を見る)
this.basicEffect.View = Matrix.CreateLookAt(
new Vector3(6.0f, 6.0f, 12.0f),
Vector3.Zero,
Vector3.Up
);
// プロジェクションマトリックスをあらかじめ設定
this.basicEffect.Projection = Matrix.CreatePerspectiveFieldOfView(
MathHelper.ToRadians(45.0f),
(float)this.GraphicsDevice.Viewport.Width /
(float)this.GraphicsDevice.Viewport.Height,
1.0f,
100.0f
);
// 頂点の数
int vertexCount = 8;
// 頂点バッファ作成
this.vertexBuffer = new VertexBuffer(this.GraphicsDevice,
typeof(VertexPositionNormalTexture), vertexCount, BufferUsage.None);
// 頂点データを作成する
VertexPositionNormalTexture[] vertives = new VertexPositionNormalTexture[vertexCount];
vertives[0] = new VertexPositionNormalTexture(
new Vector3(-2.0f, 2.0f, -2.0f),
Vector3.Normalize(new Vector3(-1.0f, 1.0f, -1.0f)),
Vector2.Zero);
vertives[1] = new VertexPositionNormalTexture(
new Vector3(2.0f, 2.0f, -2.0f),
Vector3.Normalize(new Vector3(1.0f, 1.0f, -1.0f)),
Vector2.Zero);
vertives[2] = new VertexPositionNormalTexture(
new Vector3(-2.0f, 2.0f, 2.0f),
Vector3.Normalize(new Vector3(-1.0f, 1.0f, 1.0f)),
Vector2.Zero);
vertives[3] = new VertexPositionNormalTexture(
new Vector3(2.0f, 2.0f, 2.0f),
Vector3.Normalize(new Vector3(1.0f, 1.0f, 1.0f)),
Vector2.Zero);
vertives[4] = new VertexPositionNormalTexture(
new Vector3(-2.0f, -2.0f, -2.0f),
Vector3.Normalize(new Vector3(-1.0f, -1.0f, -1.0f)),
Vector2.Zero);
vertives[5] = new VertexPositionNormalTexture(
new Vector3(2.0f, -2.0f, -2.0f),
Vector3.Normalize(new Vector3(1.0f, -1.0f, -1.0f)),
Vector2.Zero);
vertives[6] = new VertexPositionNormalTexture(
new Vector3(-2.0f, -2.0f, 2.0f),
Vector3.Normalize(new Vector3(-1.0f, -1.0f, 1.0f)),
Vector2.Zero);
vertives[7] = new VertexPositionNormalTexture(
new Vector3(2.0f, -2.0f, 2.0f),
Vector3.Normalize(new Vector3(1.0f, -1.0f, 1.0f)),
Vector2.Zero);
// 頂点データを頂点バッファに書き込む
this.vertexBuffer.SetData(vertives);
// インデックスバッファを作成
this.indexBuffer = new IndexBuffer(this.GraphicsDevice,
IndexElementSize.SixteenBits, 3 * 12, BufferUsage.None);
// 頂点インデックスを書き込む
this.indexBuffer.SetData(vertexIndices);
}
<summary>
ゲームが終了するときに一回だけ呼ばれ
すべてのゲームコンテンツをアンロードします
</summary>
protected override void UnloadContent()
{
// TODO: ContentManager で管理されていないコンテンツを
// ここでアンロードしてください
}
<summary>
描画以外のデータ更新等の処理を行うメソッド
主に入力処理、衝突判定などの物理計算、オーディオの再生など
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Update(GameTime gameTime)
{
// Xbox 360 コントローラ、Windows Phone の BACK ボタンを押したときに
// ゲームを終了させます
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
{
this.Exit();
}
// TODO: ここに更新処理を記述してください
// 登録された GameComponent を更新する
base.Update(gameTime);
}
<summary>
描画処理を行うメソッド
</summary>
<param name="gameTime">このメソッドが呼ばれたときのゲーム時間</param>
protected override void Draw(GameTime gameTime)
{
// 画面を指定した色でクリアします
this.GraphicsDevice.Clear(Color.CornflowerBlue);
// 描画に使用する頂点バッファをセット
this.GraphicsDevice.SetVertexBuffer(this.vertexBuffer);
// インデックスバッファをセット
this.GraphicsDevice.Indices = this.indexBuffer;
// パスの数だけ繰り替えし描画
foreach (EffectPass pass in this.basicEffect.CurrentTechnique.Passes)
{
// パスの開始
pass.Apply();
// ボックスを描画する
this.GraphicsDevice.DrawIndexedPrimitives(
PrimitiveType.TriangleList,
0,
0,
8,
0,
12
);
}
// 登録された DrawableGameComponent を描画する
base.Draw(gameTime);
}
}
}