- •Содержание
- •Очистка буферов графического устройства
- •Избирательная очистка буферов
- •Устранение скрытых дефектов приложения
- •Общие сведения о примитивах
- •Введение в hlsl
- •Типы данных hlsl
- •Функции и семантики hlsl
- •Техники, проходы и профили hlsl
- •IncludeHandler – объект, используемый для обработки директив #include в fx-файле. Так как наш файл не содержит директив #include, мы будем использовать значение null
- •Визуализация объекта, использующего эффект
- •Запускающее приложение
effectFile – имя загружаемого файла с эффектом
preprocessorDefines – массив макроопределений (аналогов директивы #define ), используемых при компиляции эффекта. Мы будем использовать значение null
IncludeHandler – объект, используемый для обработки директив #include в fx-файле. Так как наш файл не содержит директив #include, мы будем использовать значение null
options – опции компилятора HLSL, задаваемые с использованием перечислимого типа CompilerOptions. Члены типа CompilerOptions являются битовыми флагами, что позволяет комбинировать их с использованием побитовой операции OR. В качестве этого параметра, как правило, передается значение CompilerOptions.None
platform – значение перечислимого типа TargetPlatform, указывающее платформу, для которой компилируется эффект. Мы будем использовать значение TargetPlatform.Windows
Результат компиляции, возвращаемый методом CompileEffectFromFile(), нужно сохранить в экземпляре compiledEffect структуры типаCompiledEffect. Если компиляция прошла успешно, то булево свойство compiledEffect.Success принимает значение true. Если возникли проблемы с открытием fx -файла (например, файл не найден), то будет сгенерировано одно из исключений, производных от System.IO.IOException (например,System.IO.FileNotFoundException или System.IO.DirectoryNotFoundException ).
В дальнейшем объект compiledEffect нам понадобится, чтобы передать с помощью вызова метода compiledEffect.GetEffectCode()скомпилированный байт-код в одну из перегрузок конструктора класса Effect при создании объекта эффекта
public Effect(
Microsoft.Xna.Framework.Graphics.GraphicsDevice graphicsDevice,
byte[] effectCode,
Microsoft.Xna.Framework.Graphics.CompilerOptions options,
Microsoft.Xna.Framework.Graphics.EffectPool pool)
graphicsDevice - устройство Direct3D, которое будет использоваться для работы с эффектом
effectCode - код эффекта, предварительно скомпилированный при помощи метода CompileEffectFromFile()
options - опции компилятора, определяемые перечислимым типом CompilerOptions. Довольно часто в качестве этого параметра передается значение CompilerOptions.NotCloneable. Оно запрещает клонирование (создание копии) эффекта при помощи метод Clone(). Это уменьшает объем используемой памяти, так как в оперативной памяти видеокарты не хранится информация, необходимая для клонирования эффекта. При этом экономия оперативной памяти достигает 50%
pool - экземпляр класса EffectPool, позволяющий нескольким эффектам использовать общие параметры. Мы используем один fx-файл и этот параметр будет равен null
Имена всех техник, указанные в fx -файле, при создании объекта effect, помещаются в его свойство-коллекцию Techniques типаEffectTechniqueCollection. Коллекция содержит объекты техник effectTechnique типа EffectTechnique. Перебрав все объекты этой коллекции можно проверить с помощью метода CurrentTechnique.Validate(), поддерживаются ли указанные техники видеокартой текущего компьютера.
Если эффект содержит лишь единственную технику, как в нашем случае, то задача упрощается. Дело в том, что конструктор класса Effect при создании экземпляра эффекта автоматически находит первую попавшуюся технику и присваивает ее свойству CurrentTechnique. Поэтому приложению для получения информации об этой технике достаточно обратиться к свойству CurrentTechnique и с помощью методаCurrentTechnique.Validate() проверить возвращаемый им булев флаг, поддерживает GPU видеокарты данную технику или нет.
В панели Solution Explorer вызовите контекстное меню для узла References проекта Application2 и командой Add Reference добавьте через одноименное окно из вкладки Recent окна (недавно выбранные) библиотеку Microsoft.Xna.Framework.dll
Через контекстное меню переведите форму в режим редактирования View Code и добавьте в файл MainForm.cs следующий код
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using XNAGraphics = Microsoft.Xna.Framework.Graphics;
using System.IO;
namespace Application2
{
public partial class MainForm : Form
{
// Вспомогательные поля
const string effectFileName = "Data\\ColorFill.fx";
GraphicsDevice device = null;
PresentationParameters presentParams = new PresentationParameters();
Effect effect = null;
VertexDeclaration decl = null;
VertexPositionColor[] vertices = new VertexPositionColor[3];
bool closing = false;
public MainForm()
{
InitializeComponent();
}
}
}
Добавьте в класс MainForm метод с именем CreateDeviceAndEffect() и заполните его следующим кодом
void CreateDeviceAndEffect()
{
// Отключить у панели автоматическую очистку фона и задать
// автоматический вызов события Paint при изменении размеров
xnaPanel1.SetStyle(ControlStyles.Opaque | ControlStyles.ResizeRedraw, true);
// Настраиваем объект представления через его свойства
presentParams.IsFullScreen = false; // Включаем оконный режим
presentParams.BackBufferCount = 1; // Включаем задний буфер
// для двойной буферизации
// Переключение переднего и заднего буферов
// должно осуществляться с максимальной эффективностью
presentParams.SwapEffect = SwapEffect.Discard;
// Устанавливаем размеры заднего буфера по клиентской области панели
presentParams.BackBufferWidth = xnaPanel1.ClientSize.Width;
presentParams.BackBufferHeight = xnaPanel1.ClientSize.Height;
// Создадим графическое устройство с заданными настройками
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
xnaPanel1.Handle, presentParams);
// Создаем декларацию о формате применяемого хранилища вершин
decl = new VertexDeclaration(device, VertexPositionColor.VertexElements);
// Загружаем и компилируем эффект из файла
CompiledEffect compiledEffect;
try
{
compiledEffect = Effect.CompileEffectFromFile(effectFileName,
null, null, CompilerOptions.None, TargetPlatform.Windows);
}
catch (IOException ex)
{
closing = true;
MessageBox.Show(ex.Message, "Ошибка при загрузке эффекта",
MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Idle += new EventHandler(Application_Idle);
return;
}
// Проверяем, нормально ли откомпилирован эффект
if (!compiledEffect.Success)
{
closing = true;
MessageBox.Show(String.Format(
"Ошибка при компиляции эффекта:\n{0}", compiledEffect.ErrorsAndWarnings),
"Критическая ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Idle += new EventHandler(Application_Idle);
return;
}
// Создаем объект эффекта
effect = new Effect(device, compiledEffect.GetEffectCode(),
CompilerOptions.NotCloneable, null);
// Проверяем, поддерживается ли видеокартой указанная в эффекте техника
if (!effect.CurrentTechnique.Validate())
{
closing = true;
MessageBox.Show(String.Format("Ошибка при проверке техники \"{0}\" эффекта \"{1}\"\n" +
"Скорее всего, функциональность шейдера превышает возможности GPU",
effect.CurrentTechnique.Name, effectFileName),
"Критическая ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Idle += new EventHandler(Application_Idle);
return;
}
}
void Application_Idle(object sender, EventArgs e)
{
this.Close();
}
Поместите вызов метода CreateDeviceAndEffect() в конструктор класса после кода инициализации компонентов формы
public MainForm()
{
InitializeComponent();
// Создание устройства и эффекта
CreateDeviceAndEffect();
}
Теперь создадим обработчики нужных событий и заполним их кодом.
