Навигация
· XNA FAQ
· С чего начать
· Конкурсы
· Обратная связь
· XNA Блоги
Сейчас на сайте
· Гостей: 1

· Пользователей: 0

· Всего пользователей: 3,684
· Новый пользователь: headron
Последние фото
Эх, чуть не проспал закрытие.
Эх, чуть не проспал ...
Альбом: XNA Engine

GB
GB
Альбом: XNA Engine

South Park Coon & Friends
South Park Coon & Fr...
Альбом: XNA Games

Блоги
yavshoke
» XboxOne - интерес...
dampirik
» Push уведомления ...
dampirik
» Реклама,статистик...
Chort
» XNA и StartCoroutine
Chort
» Curve Class
dampirik
» Реклама, статисти...
dampirik
» Увеличение скорос...
dampirik
» Реклама, статисти...
general
» Распаковка DxtCom...
general
» Как работать с XN...
Поддержка
microsoft.com
1gb.ru - Дом для вашего сайта
Статистика посещений:

Анимация, эффекты

Лабораторная работа №18. Анимация, эффекты


В этой лабораторной работе мы поговорим о применении графических эффектов в играх и об анимации персонажей.

Цель работы
  • Научиться применять графические эффекты и приемы анимации
Задачи работы
  • Рассмотреть основы анимации трехмерных персонажей
  • Рассмотреть применение графических эффектов в компьютерных играх, созданных на базе XNA
Анимация персонажей

Компьютерные игры наполнены анимированными персонажами. XNA содержит встроенные средства, поддерживающие базовые операции по анимации трехмерных персонажей. В частности, это средства для работы с так называемым скелетом персонажа. Скелет состоит из взаимосвязанных костей, управляя которыми можно анимировать модель. Создание анимированных моделей – это отдельная, достаточно трудоемкая задача, которая требует серьезных познаний в области 3D-моделирования. Для подготовки анимированных трехмерных моделей вы можете использовать практически любой 3D-редактор.

XNA содержит лишь базовые средства для управления скелетами объектов. Так, мы можем получить коллекцию костей объекта и проводить с ними какие-либо преобразования, вызывающие движение модели. Однако, такой подход ограничен – с его использованием весьма сложно создать реалистичное движение для сложных моделей. На основе базовых средств XNA разработаны библиотеки кода, которые содержат компоненты, позволяющие анимировать персонажи на более высоком уровне. В частности, одну из таких библиотек – XNAAnimation – можно найти на сайте http://www.codeplex.com/xnanimation.

Здесь мы рассмотрим базовый подход к анимации модели. Он заключается в следующем. Можно менять параметры отдельных костей модели и выводить ее на экран с учетом этих изменений. Мы использовали бесплатную модель Ballpen.fbx, взятую с сайта http://www.turbosquid.com.

Создадим новый проект P18_1. Загрузим в него модель Ballpen.fbx. На рис. 18.1. представлено окно Solution Explorer нашего нового проекта.


Рис. 18.1. Окно Project Explorer

Код проекта сосредоточен в классе Game1.cs, его код вы можете найти в листинге 18.1.

Листинг 18.1. Код класса Game1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
 
namespace P18_1
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        //Матрицы
        Matrix viewMatrix;
        Matrix projMatrix;
        //Модель
        Model pen;
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
 
        protected override void Initialize()
        {
            base.Initialize();
        }
 
        protected override void LoadContent()
        {
            //Загрузка модели
            pen = Content.Load<Model>("ballpen");
            //Соотношение сторон
            float aspectRatio = (float)graphics.GraphicsDevice.Viewport.Width /
               (float)graphics.GraphicsDevice.Viewport.Height;
            //Устанавливаем камеру
            viewMatrix = Matrix.CreateLookAt(new Vector3(0, 30, 80), new Vector3(-32, 0, 0), new Vector3(0, 1, 0));
            //Устанавливаем проекционную матрицу
            projMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(45.0f), aspectRatio, 1.0f, 1000.0f);
        }
 
        protected override void Update(GameTime gameTime)
        {
            //Перемещение частей ручки
            PenMove();
            base.Update(gameTime);
        }
        //Процедура для перемещения частей ручки
        void PenMove()
        {
            //Получить состояние клавиатуры
            KeyboardState keyboardState = Keyboard.GetState();
            //Поворот зажима - он представлен родительской костью сети №3
            //Умножим его матрицу трансформации на матрицу поворота по оси X
            pen.Meshes[3].ParentBone.Transform = pen.Meshes[3].ParentBone.Transform * Matrix.CreateRotationX(MathHelper.ToRadians(-1.0f));
            //Кнопка ручки перемещается по клавиатурным командам
            //При нажатии кнопки "Влево"
            //Она выходит из ручки
            if (keyboardState.IsKeyDown(Keys.Left))
            {
                //Умножим матрицу трансформации родительской костью сети №1
                //На матрицу трансляции, перемещающей ее на 2 позиции влево по оси Х
                pen.Meshes[1].ParentBone.Transform = pen.Meshes[1].ParentBone.Transform * Matrix.CreateTranslation(new Vector3(-2, 0, 0));
            }
            //При нажатии кнопки "Вправо"
            //Кнопка входит в ручку
            if (keyboardState.IsKeyDown(Keys.Right))
            {
                //Умножим матрицу трансформации родительской кости сети №1
                //На матрицу трансляции, перемещающую ее на 2 позиции по оси X вправо
                pen.Meshes[1].ParentBone.Transform = pen.Meshes[1].ParentBone.Transform * Matrix.CreateTranslation(new Vector3(2, 0, 0));
            }
 
        }
        protected override void Draw(GameTime gameTime)
        {
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
            //Новый массив матриц размером, соответствующим количеству
            //костей в скелете модели
            Matrix[] absoluteTransformations = new Matrix[pen.Bones.Count];
            //Скопировать матрицы трансформации костей в массив матриц
            pen.CopyAbsoluteBoneTransformsTo(absoluteTransformations);
 
            foreach (ModelMesh mesh in pen.Meshes)
            {
                foreach (BasicEffect effect in mesh.Effects)
                {
                    effect.LightingEnabled = true;
                    effect.EnableDefaultLighting();
                    effect.Projection = projMatrix;
                    effect.View = viewMatrix;
                    //Установим новую мировую матрицу для родительской кости текущей сети
                    //это приводит к перемещению кнопки и к перемещению зажима
                    //Так же здесь мы уменьшаем модель, применяя коэффициент масштабирования 0,13
                    effect.World = absoluteTransformations[mesh.ParentBone.Index] * Matrix.CreateScale(0.13f);
                }
                //Выводим подготовленную сеть
                mesh.Draw();
            }
            base.Draw(gameTime);
        }
    }
}

 


На рис. 18.2. вы можете видеть игровой экран проекта P18_1.


Рис. 18.2. Игровой экран проекта P18_1

Эффекты

Простые графические эффекты в XNA можно реализовать при выводе изображений стандартными средствами. Но стандартные эффекты не способны удовлетворить потребности разработчиков. В одной из предыдущих лекций мы уже упоминали о том, что XNA поддерживает использование шейдерных программ, которые позволяют управлять графическими эффектами.
Шейдерные программы или просто шейдеры представлены в виде файлов с расширением FX. Эти файлы можно создавать как с помощью специального ПО для разработки и отладки шейдеров, так и вручную, в редакторе кода Visual Studio. Для описания шейдерных программ существует специальный язык – HLSL – High Level Shader Language – Высокоуровневый язык описания шейдеров.

Шейдерные программы исполняются графическим процессором видеокарты, с их помощью можно создать множество графических эффектов, которыми наполнены современные игры.

Шейдеры принято делить на вершинные (Vertex Shader) и пиксельные (Pixel Shader).
Вершинные работают с вершинами объектов. С их помощью можно осуществить такие операции, как деформацию объектов, анимацию, перемещение и т.д. После того, как вершинный шейдер завершит работу по модификации модели, за дело принимается пиксельный шейдер.

Пиксельные шейдеры применяются к отдельным пикселям изображения. В частности, они отвечают за цвет пикселей, позволяют применять к изображению различные эффекты.

Для того, чтобы создать новый FX-файл в XNA-проект, достаточно выполнить щелчок левой кнопкой мыши по папке Content, выбрать пункт Add(New Item и в появившемся окне выбрать в качестве типа добавляемого файла Effect File. После того, как файл эффектов будет добавлен в проект, он будет содержать некоторые стандартные части, которые представляют собой объявление переменных, необходимых для работы шейдера, объявление точки входа в шейдер и, собственно, шаблоны двух шейдеров – вершинного и пиксельного.

Для того, чтобы разрабатывать шейдеры самостоятельно с помощью XNA-редактора FX-файлов, вам нужно ознакомиться с языком HLSL. Вы можете сделать это, воспользовавшись справочной службой MSDN, в частности, этим разделом: http://msdn2.microsoft.com/en-us/library/bb509561.aspx.

На практике лучше всего пользоваться специализированным ПО для разработки и отладки шейдеров.

Рассмотрим пример работы с шейдерными эффектами – он создан с использованием примера применения шейдеров, приведенного в документации к XNA.

Создадим новый проект P18_2. На рис. 18.3. вы можете видеть его окно Solution Explorer.


Рис. 18.3. Окно Solution Explorer для проекта P18_2

Файл shader.fx содержит код шейдера, файл tex.png используется в качестве текстуры для наложения на модель, созданную программными средствами. Код программы реализован в классе Game1. Рассмотрим его (листинг. 18.2.).

Листинг 18.2. Код класса Game1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
 
namespace P18_2
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        GraphicsDeviceManager graphics;
        //Матрицы
        Matrix WorldMAtrix, ViewMatrix, ProjectionMatrix;
        //Объект для применения эффектов
        Effect effect;
        //Вершины куба
        VertexDeclaration cubeVertexDeclaration;
        //Координаты для наложения текстур
        VertexPositionTexture[] cubeVertices;
        //Вершинный буфер
        VertexBuffer vertexBuffer;
        //Индексный буфер
        IndexBuffer indexBuffer;
        //Массив индексов
        short[] cubeIndices;
        //Номер эффекта в шейдере
        int CurPass;
        //Множитель для текстуры
        float Multiplier;
        //Текстура
        Texture2D texture;
 
        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }
 
        protected override void LoadContent()
        {
            //Мировая матрица
            WorldMAtrix = Matrix.Identity;
            //Матрица вида
            ViewMatrix  = Matrix.CreateLookAt(new Vector3(0, 0, 5), Vector3.Zero,
                Vector3.Up);
            //Матрица проекции
            ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView(
                MathHelper .ToRadians (45.0f),
                (float)graphics.GraphicsDevice.Viewport.Width /
                (float)graphics.GraphicsDevice.Viewport.Height,
                1.0f, 10.0f);
            //Текущий эффект имеет номер 0
            CurPass = 0;
            //Текущий множитель - 1
            Multiplier = 1;
            //Загрузим текстуру
            texture = Content.Load<Texture2D>("tex");
            //Загрузим шейдер shader в переменную типа Effect
            effect = Content.Load<Effect>("shader");
            //Передадим в переменную шейдера UserTexture текстуру
            effect.Parameters["UserTexture"].SetValue(texture);
            //Установим переменную шейдера Multiplier в значение
            //соответствующей игровой переменной
            effect.Parameters["Multiplier"].SetValue(Multiplier);
            //Создадим куб
            InitializeModel();
        }
 
        /// <summary>
        /// Создаем 3D-модель
        /// </summary>
        public void InitializeModel()
        {
            // Переменная типа VertexDeclaration
            cubeVertexDeclaration = new VertexDeclaration(
                graphics.GraphicsDevice, VertexPositionTexture.VertexElements);
 
            //Установка параметров точек, которые будут использованы для рисования фигуры
            Vector3 topLeftFront = new Vector3(-1.0f, 1.0f, 1.0f);
            Vector3 bottomLeftFront = new Vector3(-1.0f, -1.0f, 1.0f);
            Vector3 topRightFront = new Vector3(1.0f, 1.0f, 1.0f);
            Vector3 bottomRightFront = new Vector3(1.0f, -1.0f, 1.0f);
            Vector3 topLeftBack = new Vector3(-1.0f, 1.0f, -1.0f);
            Vector3 topRightBack = new Vector3(1.0f, 1.0f, -1.0f);
            Vector3 bottomLeftBack = new Vector3(-1.0f, -1.0f, -1.0f);
            Vector3 bottomRightBack = new Vector3(1.0f, -1.0f, -1.0f);
 
            // Координаты текстуры
            Vector2 textureTopLeft = new Vector2(0.0f, 0.0f);
            Vector2 textureTopRight = new Vector2(1.0f, 0.0f);
            Vector2 textureBottomLeft = new Vector2(0.0f, 1.0f);
            Vector2 textureBottomRight = new Vector2(1.0f, 1.0f);
 
            // Массив для хранения списка вершин
            // Он используется для передачи данных в вершинный буфер
            cubeVertices = new VertexPositionTexture[36];
 
            // Передняя часть фигуры
            cubeVertices[0] =
                new VertexPositionTexture(
                topLeftFront, textureTopLeft); // 0
            cubeVertices[1] =
                new VertexPositionTexture(
                bottomLeftFront, textureBottomLeft); // 1
            cubeVertices[2] =
                new VertexPositionTexture(
                topRightFront, textureTopRight); // 2
            cubeVertices[3] =
                new VertexPositionTexture(
                bottomRightFront, textureBottomRight); // 3
 
            // Задняя часть фигуры
            cubeVertices[4] =
                new VertexPositionTexture(
                topLeftBack, textureTopRight); // 4
            cubeVertices[5] =
                new VertexPositionTexture(
                topRightBack, textureTopLeft); // 5
            cubeVertices[6] =
                new VertexPositionTexture(
                bottomLeftBack, textureBottomRight); //6
            cubeVertices[7] =
                new VertexPositionTexture(
                bottomRightBack, textureBottomLeft); // 7
 
            // Верхняя часть фигуры
            cubeVertices[8] =
                new VertexPositionTexture(
                topLeftFront, textureBottomLeft); // 8
            cubeVertices[9] =
                new VertexPositionTexture(
                topRightBack, textureTopRight); // 9
            cubeVertices[10] =
                new VertexPositionTexture(
                topLeftBack, textureTopLeft); // 10
            cubeVertices[11] =
                new VertexPositionTexture(
                topRightFront, textureBottomRight); // 11
 
            // Нижняя часть фигуры
            cubeVertices[12] =
                new VertexPositionTexture(
                bottomLeftFront, textureTopLeft); // 12
            cubeVertices[13] =
                new VertexPositionTexture(
                bottomLeftBack, textureBottomLeft); // 13
            cubeVertices[14] =
                new VertexPositionTexture(
                bottomRightBack, textureBottomRight); // 14
            cubeVertices[15] =
                new VertexPositionTexture(
                bottomRightFront, textureTopRight); // 15
 
            // Левая часть фигуры
            cubeVertices[16] =
                new VertexPositionTexture(
                topLeftFront, textureTopRight); // 16
            cubeVertices[17] =
                new VertexPositionTexture(
                bottomLeftFront, textureBottomRight); // 17
            cubeVertices[18] =
                new VertexPositionTexture(
                topRightFront, textureTopLeft); // 18
            cubeVertices[19] =
                new VertexPositionTexture(
                bottomRightFront, textureBottomLeft); // 19
 
            //Создаем вершинный буфер для хранения информации о вершинах
            vertexBuffer = new VertexBuffer(graphics.GraphicsDevice,
                VertexPositionTexture.SizeInBytes * cubeVertices.Length,
                BufferUsage.None
                );
 
            //Добавляем данные в вершинный буфер
            vertexBuffer.SetData<VertexPositionTexture>(cubeVertices);
 
            // С помощью этого массива определяем, к каким частям фигуры
            //Относятся те или иные компоненты массива cubeVertices
            cubeIndices = new short[] {
                                     0,  1,  2,  // Передняя плоскость
                                     1,  3,  2,
                                     4,  5,  6,  // Задняя плоскость
                                     6,  5,  7,
                                     8,  9, 10,  // Верхняя плоскость
                                     8, 11,  9,
                                    12, 13, 14,  // Нижняя плоскость
                                    12, 14, 15,
                                    16, 13, 17,  // Левая плоскость
                                    10, 13, 16,
                                    18, 19, 14,  // Правая плоскость
                                     9, 18, 14 };
 
            //Индексный буфер
            indexBuffer = new IndexBuffer(graphics.GraphicsDevice,
                sizeof(short) * cubeIndices.Length,
                BufferUsage.None,
                IndexElementSize.SixteenBits
                );
 
            //Добавляем данные в индексный буфер
            indexBuffer.SetData<short>(cubeIndices);
        }
 
        protected override void Update(GameTime gameTime)
        {
            //Получим состояние клавиатуры
            KeyboardState Key = Keyboard.GetState();
            //Если нажата клавиша 1 - установить
            //номер прохода эффекта в 0
            if (Key.IsKeyDown (Keys.D1))
            {
                CurPass = 0;
            }
            //Если нажата клавиша 2 - 
            //установить номер прохода в 1
            if (Key.IsKeyDown(Keys.D2))
            {
                CurPass = 1;
            }
            //Если нажата клавиша 3 
            //установить номер прохода в 2
            if (Key.IsKeyDown(Keys.D3))
            {
                CurPass = 2;
            }
            //По нажатию клавиш QWERT
            //Устанавливать различные множители
            //они влияют на размеры текстуры, размещенных
            //на гранях куба
            //Например, если Multiplier=1 - лишь один экземпляр
            //изображения текстуры располагается на грани
            //Если Multiplier=2 - на грани размещается уже
            //4 текстуры и т.д.
            if (Key.IsKeyDown(Keys.Q))
            {
                Multiplier = 10.0f;
            }
            if (Key.IsKeyDown(Keys.W))
            {
                Multiplier = 5.0f;
            }
            if (Key.IsKeyDown(Keys.E))
            {
                Multiplier = 2.0f;
            }
            if (Key.IsKeyDown(Keys.R))
            {
                Multiplier = 1.0f;
            }
            if (Key.IsKeyDown(Keys.T))
            {
                Multiplier = 0.5f;
            }
            //Модифицируем мировую матрицу таким образом, чтобы модель
            //поворачивалась в пространстве с небольшой скоростью
            WorldMAtrix = WorldMAtrix * Matrix.CreateRotationX(0.011f) * 
                Matrix.CreateRotationY(0.012f)*
                Matrix.CreateRotationZ (0.013f);
            //Установить матрицу, которая является результатом умножения мировой, видовой и 
            //проекционной матриц в эффекте
            effect.Parameters["WorldViewProj"].SetValue(WorldMAtrix *ViewMatrix *ProjectionMatrix);
            //Установить переменную Multiplier в эффекте
            effect.Parameters["Multiplier"].SetValue(Multiplier);
            base.Update(gameTime);
        }
 
 
        protected override void Draw(GameTime gameTime)
        {
            //Очистить экран
            graphics.GraphicsDevice.Clear(Color.CornflowerBlue);
            //Выключить режим удаления задних частей треугольников
          graphics.GraphicsDevice.RenderState.CullMode =
                CullMode.None;
            //Установить матрицу вершин
            graphics.GraphicsDevice.VertexDeclaration = cubeVertexDeclaration;
            //Установить матрицу индексов
            graphics.GraphicsDevice.Indices = indexBuffer;
            //Установить вершинный буфер
            graphics.GraphicsDevice.Vertices[0].SetSource(
                vertexBuffer,
                0,
                VertexPositionTexture.SizeInBytes);
 
            //Начало работы эффекта, используемого для вывода изображения
            effect.Begin();
                //Использовать проход шейдера, заданный переменной CurPass
                effect.CurrentTechnique.Passes[CurPass].Begin();
                    //Вывести изображение как набор индексированных 
                    //примитивов, используя настройки буферов, сделанные ранее
                    graphics.GraphicsDevice.DrawIndexedPrimitives(
                        PrimitiveType.TriangleList, 
                        0, 0, cubeVertices.Length, 0, 12);
                //Завершить текущий проход шейдера
                effect.CurrentTechnique.Passes[CurPass].End();
             //Завершить вывод изображений
             effect.End();
            base.Draw(gameTime);
        }
    }
}

 


Теперь рассмотрим код шейдера – в листинге 18.3. вы можете найти код файла shader.fx.

Листинг 18.3. Код файла shader.fx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
//Переменные, устанавливаемые при настройке шейдера
//Матрица - результат перемножений мировой, видовой, проекционной матриц
uniform extern float4x4 WorldViewProj : WORLDVIEWPROJECTION;
//Текстура
uniform extern texture UserTexture;
//Множитель
uniform extern float Multiplier;
 
struct VS_OUTPUT
{
    float4 position  : POSITION;
    float4 textureCoordinate : TEXCOORD0;
};
 
sampler textureSampler = sampler_state
{
	Texture = <UserTexture>;
	mipfilter = LINEAR; 
};
//Вывод вершин текстуры
//Вершинный шейдер, который используется
//во всех вариантах эффекта
VS_OUTPUT Transform(
    float4 Position  : POSITION, 
    float4 TextureCoordinate : TEXCOORD0 )
{
    VS_OUTPUT Out = (VS_OUTPUT)0;
    Out.position = mul(Position, WorldViewProj);
    Out.textureCoordinate = TextureCoordinate*Multiplier;
    return Out;
}
 
//Вывод текстуры без изменений для P0, пиксельный шейдер
//Возврат того же цвета, который был передан
//шейдеру
float4 ApplyTexture(VS_OUTPUT vsout) : COLOR
{
	return tex2D(textureSampler, vsout.textureCoordinate).rgba;
}
 
 
//Вывод размытой текстуры для P1, пиксельный шейдер
//Цвет устанавливается исходя из цвета
//соседних пикселей
//Полученная цветовая информация делится на 5
//для сохранения исходной яркости
float4 ApplyTextureBlur(VS_OUTPUT vsout) : COLOR
{
	float4 Col;
    Col =  tex2D(textureSampler, vsout.textureCoordinate);
	Col += tex2D(textureSampler, vsout.textureCoordinate + (0.01));
	Col += tex2D(textureSampler, vsout.textureCoordinate + (0.02));
	Col += tex2D(textureSampler, vsout.textureCoordinate + (0.03));
	Col += tex2D(textureSampler, vsout.textureCoordinate + (0.04));
	Col = Col / 5;
	//Возвращаем найденный цвет пикселя
	return Col;
}
//Вывод текстуры в оттенках серого для P2 - пиксельный шейдер
//Интенсивность света всех каналов изображения складывается и 
//делится на количество каналов
//Альфа-канал устанавливается равным 1
float4 ApplyTextureGray(VS_OUTPUT vsout) : COLOR
{
	float4 Col;
    Col =  tex2D(textureSampler, vsout.textureCoordinate);
    Col.a=1.0f;
    Col.rgb=(Col.r+Col.g+Col.b)/3;
    return Col;
}
 
//Техника шейдера
technique TransformAndTexture
{
	//Проход P0, имеет индекс 0
    pass P0
    {
	//Вершинный шейдер для данного прохода
        vertexShader = compile vs_2_0 Transform();
        //Пиксельный шейдер для данного прохода
        pixelShader  = compile ps_2_0 ApplyTexture();
    }
    //Проход P1, имеет индекс 1
    pass P1
    {
		vertexShader = compile vs_2_0 Transform();
        pixelShader  = compile ps_2_0 ApplyTextureBlur();
    }
    //Проход P2, имеет индекс 2
    pass P2
    {
		vertexShader = compile vs_2_0 Transform();
        pixelShader  = compile ps_2_0 ApplyTextureGray();
    }
}

 


На рис. 18.4., 18.5., 18.6. вы можете видеть игровое окно проекта в различных режимах применения шейдера.


Рис. 18.4. Наложение текстуры без изменения цвета, с множителем 2


Рис. 18.5. Наложение текстуры с размытием, множитель 1


Рис. 18.6. Текстура в оттенках серого, множитель 1

Вопросы

1) Что такое скелетная анимация?
  • a. Анимация трехмерных персонажей с помощью модификации их видовой матрицы
  • b. Анимация трехмерных персонажей с помощью модификации отдельных частей их скелета с последующим отражением изменений в мировой матрице
  • c. Анимация трехмерных персонажей с помощью модификации параметров проекционной матрицы
2) Какой объект может описывать следующий код: pen.Meshes[3].ParentBone.Transform?
  • a. Кость №3 модели pen
  • b. Сеть №3 модели Pen
  • c. Матрицу трансформации родительской кости для сети №3 модели pen
  • d. Модель pen
3) Метод CopyAbsoluteBoneTransformsTo объекта типа Model предназначен для
  • a. Копирования объекта
  • b. Копирования отдельных сетей объекта
  • c. Копирования матриц трансформаций костей объекта в специально созданную матрицу
  • d. Копирования скелета объекта
4) Что такое HLSL?
  • a. Высокоуровневый язык описания шейдеров
  • b. Библиотека XNA для работы с шейдерами
  • c. Формат моделей, которые поддерживают шейдеры
  • d. Программа для разработки шейдеров
5) Какое расширение имеют файлы эффектов в XNA?
  • a. FBX
  • b. TXT
  • c. X
  • d. FX
6) Какова основная функция вершинных шейдеров?
  • a. Они позволяют копировать информацию о вершинах объекта в файлы
  • b. Они предназначены для модификации трехмерных объектов путем изменения параметров их вершин
  • c. Они позволяют обрабатывать отдельные пиксели объектов, применяя к ним различные графические эффекты
  • d. Они позволяют загружать в игру трехмерные модели
7) Какова основная функция пиксельных шейдеров?
  • a. Они позволяют копировать информацию о вершинах объекта в файлы
  • b. Они предназначены для модификации трехмерных объектов путем изменения параметров их вершин
  • c. Они позволяют обрабатывать отдельные пиксели объектов, применяя к ним различные графические эффекты
  • d. Они позволяют загружать в игру трехмерные модели
8) Можно ли редактировать файлы шейдеров, написанных на HLSL-, используя встроенные средства XNA?
  • a. Да
  • b. Нет
9) Объект какого типа используется для загрузки шейдеров в игру?
  • a. Model
  • b. Texture2D
  • c. Effect
  • d. SpriteBatch

Материал публикуется с разрешения авторов - Ю.В. Дашко, А.А. Заика

Студенческий блог MS Russia
Интернет-Университет Информационных технологий - курс разработан по гранту от Microsoft и ИНТУИТ
сайт ИУБиП
Комментарии
Нет комментариев.
Добавить комментарий
Пожалуйста, залогиньтесь для добавления комментария.
Рейтинги
Рейтинг доступен только для пользователей.

Пожалуйста, залогиньтесь или зарегистрируйтесь для голосования.

Нет данных для оценки.
Авторизация
Логин

Пароль



Вы не зарегистрированы?
Нажмите здесь для регистрации.

Забыли пароль?
Запросите новый здесь.
Мини-чат
Вы должны авторизироваться, чтобы добавить сообщение.

27.08.2014
Я умею немного на asp.net + html и css

22.08.2014
на ASP mvc 3 есть пару проектов. Могу помочь, если нужно. Обидно, если закроется Frown

21.08.2014
я тоже ноль

21.08.2014
Я в вебе только с php занимался да и то на уровне чтоб работало.

21.08.2014
Я в вебе полный ноль…

21.08.2014
Переводить его надо, хоть на ту же азуру. И двиг менять на что-то современное. Если есть веб-разрабы - можем скооперироваться. Один делать не буду.

21.08.2014
не знаю всех нюансов по оплате и все хорошее когда нибудь заканчивается

21.08.2014
А что случилось?

21.08.2014
похоже сайт будет работать до 28го числа

09.08.2014
Апи пока не видел. Но есть приложение в магазине Live Lock Screen BETA, так что думаю скоро будет

08.08.2014
Я про API для Update1. На нем работает это

08.08.2014
А что именно нужно? Чтото и сейчас открыто http://msdn.micro.
...105).aspx

06.08.2014
Кто-нибудь слышал об открытии доступа к Lock Screen Api?

31.07.2014
VPDExpress на базе MVS 2012, ни в какую не ловит исключения. Даже если их сам создаешь. И всех так?

25.07.2014
С днем системного администратора причастных к этой профессии! По случаю - тортик от жены

RSS каналы сайта
XNA - Новости
XNA - Статьи
XNA - Форум
XNA - Галерея
XNA - Файлы
Время загрузки: 0,04 секунд 8,709,543 уникальных посетителей