- •Содержание
- •Очистка буферов графического устройства
- •Избирательная очистка буферов
- •Устранение скрытых дефектов приложения
- •Общие сведения о примитивах
- •Введение в hlsl
- •Типы данных hlsl
- •Функции и семантики hlsl
- •Техники, проходы и профили hlsl
- •IncludeHandler – объект, используемый для обработки директив #include в fx-файле. Так как наш файл не содержит директив #include, мы будем использовать значение null
- •Визуализация объекта, использующего эффект
- •Запускающее приложение
Очистка буферов графического устройства
Теперь нужно прописать код очистки графических буферов перед рисованием нового изображения. Для этого существует метод Clear() графического устройства, имеющий несколько перегрузок. Пока воспользуемся упрощенной перегрузкой этого метода, которая очищает только экранный буфер заданным цветом:
public void Clear(Microsoft.Xna.Framework.Graphics.Color color)
Куда же вставить вызов функции очистки графического устройства? Когда происходит разрушение экрана за счет сворачивания окна или заслонения другими окнами, то при необходимости его восстановления операционная система генерирует событие Paint унаследованного формой класса Controlи мы можем либо подписать обработчик на это событие и туда вставить очистку, либо перекрыть виртуальный метод диспетчеризации OnPaint() формы и в него вставить вызов очистки. Воспользуемся вторым вариантом...
В классе MainForm как член класса наберите ключевое слово override, после введения символа пробела в открывшемся окне подсказчика кода IntalliSense выберите метод диспетчеризации OnPaint() и завершите набор нажатием клавиши Enter
В перекрытом методе диспетчеризации OnPaint() введите код вызова метода очистки устройства
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.Graphics;
namespace Application1
{
public partial class MainForm : Form
{
// Объявим поле графического устройства для видимости в методах
GraphicsDevice device;
public MainForm()
{
InitializeComponent();
// Подпишемся на событие Load формы
this.Load += new EventHandler(MainForm_Load);
}
void MainForm_Load(object sender, EventArgs e)
{
// Создаем объект представления для настройки графического устройства
PresentationParameters presentParams = new PresentationParameters();
// Настраиваем объект представления через его свойства
presentParams.IsFullScreen = false; // Включаем оконный режим
presentParams.BackBufferCount = 1; // Включаем задний буфер
// для двойной буферизации
// Переключение переднего и заднего буферов
// должно осуществляться с максимальной эффективностью
presentParams.SwapEffect = SwapEffect.Discard;
// Устанавливаем размеры заднего буфера по клиентской области окна формы
presentParams.BackBufferWidth = this.ClientSize.Width;
presentParams.BackBufferHeight = this.ClientSize.Height;
// Создадим графическое устройство с заданными настройками
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
this.Handle, presentParams);
}
protected override void OnPaint(PaintEventArgs e)
{
device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);
base.OnPaint(e);
}
}
}
Обратите внимание, что мы были вынуждены прописать полное имя структуры Color во избежании конфликта имен, поскольку точно такая же структура находится в подключенном к файлу пространстве имен System.Drawing.
При завершении работы нашего приложения сборщик мусора GC среды исполнения CLR попытается автоматически освободить графическое устройство. Но сделать это корректно ему не удастся. Дело в том, классы XNA являются тонкой оболочкой API DirectX, а сам DirectX освобождает только те объекты, которые были созданы в его потоке. Сборщик мусора же для своей работы создает новый отдельный поток, который не сможет корректно удалить объекты DirectX, в том числе созданный нами объект device. В связи с этим нам нужно самим позаботиться об удалении таких критичных объектов в нашем приложении.
В конструкторе MainForm() одноименного класса подпишитесь на обработчик события FormClosed и заполните обработчик кодом удаления устройства device
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.Graphics;
namespace Application1
{
public partial class MainForm : Form
{
// Объявим поле графического устройства для видимости в методах
GraphicsDevice device;
public MainForm()
{
InitializeComponent();
// Подпишемся на событие Load формы
this.Load += new EventHandler(MainForm_Load);
// Попишемся на событие FormClosed формы
this.FormClosed += new FormClosedEventHandler(MainForm_FormClosed);
}
void MainForm_FormClosed(object sender, FormClosedEventArgs e)
{
// Удаляем (освобождаем) устройство
device.Dispose();
// На всякий случай присваиваем ссылке на устройство значение null
device = null;
}
void MainForm_Load(object sender, EventArgs e)
{
// Создаем объект представления для настройки графического устройства
PresentationParameters presentParams = new PresentationParameters();
// Настраиваем объект представления через его свойства
presentParams.IsFullScreen = false; // Включаем оконный режим
presentParams.BackBufferCount = 1; // Включаем задний буфер
// для двойной буферизации
// Переключение переднего и заднего буферов
// должно осуществляться с максимальной эффективностью
presentParams.SwapEffect = SwapEffect.Discard;
// Устанавливаем размеры заднего буфера по клиентской области окна формы
presentParams.BackBufferWidth = this.ClientSize.Width;
presentParams.BackBufferHeight = this.ClientSize.Height;
// Создадим графическое устройство с заданными настройками
device = new GraphicsDevice(GraphicsAdapter.DefaultAdapter, DeviceType.Hardware,
this.Handle, presentParams);
}
protected override void OnPaint(PaintEventArgs e)
{
device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);
base.OnPaint(e);
}
}
}
Запустите приложение на выполнение
Пока ничего не произошло и мы не видим графического окна в клиентской области формы, хотя событие Paint исправно срабатывает, в чем можно убедиться, если установить точку останова (Breakpoint) в перекрытом методе диспетчеризации OnPaint().
Всe дело в том, что мы используем двойную буферизацию, то есть наше приложение выполняет все графические построения в заднем невидимом вспомогательном буфере. После окончания визуализации необходимо скопировать информацию из этого вспомогательного буфера на форму. Эту операцию выполняет метод Present() класса GraphicsDevice.
Добавьте вызов метода Present() в перекрытый метод диспетчеризации OnPaint()
protected override void OnPaint(PaintEventArgs e)
{
device.Clear(Microsoft.Xna.Framework.Graphics.Color.CornflowerBlue);
// Копируем задний буфер на экран
device.Present();
base.OnPaint(e);
}
Снова запустите программу на выполнение - на экране появится окно, клиентская область которого закрашена синим цветом, что нам и требовалось
