Документация/Статьи по программированию/Описание GuiRenderer

From NeoAxis Engine Wiki

Jump to: navigation, search
Перейти на уровень выше

Contents

Введение

В этой статье мы рассмотрим класс GuiRenderer, отвечающий за отрисовку пользовательского интерфейса. Мы научимся выводить на экран несложные объекты вроде прямоугольников, линий, треугольников и текста. С помощью GuiRenderer удобно выводить отладочную информацию, выводить на экран статистику игры.

Также, GuiRenderer используется для создания гуи классов элементов управления. Подробнее об этом можно прочесть здесь.

Использовать GuiRenderer можно через метод OnRenderUI класса игрового окна или элемента управления:

public class ActionGameWindow : GameWindow
{
 
    ...
 
    protected override void OnRenderUI(GuiRenderer renderer)
    {
        base.OnRenderUI(renderer);
 
        ...
 
        //Place your code here
    }
}

В методе OnRenderUI объект класса GuiRenderer передается как параметр.

В последующих примерах мы будем использовать метод OnRenderUI класса ActionGameWindow (окно шутера от первого или третьего лица), который находится в проекте Game. В этом методе уже имеется вызов родительского метода OnRenderUI и три десятка строк кода, после которого можно дописывать код наших примеров.

Чтобы увидеть примеры в действии, нужно скомпилировать проект, запустить его и перейти на карту, использующую ActionGameWindow. Например, на карту TankDemo.

Рисование закрашенных прямоугольников

Для рисования закрашенных прямоугольников в классе GuiRenderer имеется метод AddQuad. В качестве способа закраски может выступать как простое закрашивание сплошным цветом, так и накладывание текстуры.

Доступные методы:

void AddQuad( Rect rectangle, Rect textureCoordRectangle, Texture texture, ColorValue color, bool clamp )
void AddQuad( Rect rectangle, Rect textureCoordRectangle, Texture texture, ColorValue color )
void AddQuad( Rect rectangle, Rect textureCoordRectangle, Texture texture )
void AddQuad( Rect rectangle, ColorValue color )

Простой вариант метода, закрашивающий прямоугольник одним цветом, обладает следующими параметрами:

Параметры Описание
rectangle Координаты отображаемого прямоугольника. Задается в пропорциях экрана. Левому верхнему углу экрана соответствуют координаты (0, 0), правому нижнему - (1, 1).
color Цвет, которым закрашивается прямоугольник. Состоит из четырех компонент: Red (красный), Green (зеленый), Blue (синий), Alpha (прозрачность).

Теперь рассмотрим вариант метода AddQuad с полным набором параметров, который текстурирует прямоугольник.

Параметры Описание
rectangle Координаты отображаемого прямоугольника. Задается в пропорциях экрана. Левому верхнему углу экрана соответствуют координаты (0, 0), правому нижнему - (1, 1).
textureCoordRectangle Текстурные координаты прямоугольника. Левому верхнему углу текстуры соответствуют координаты (0, 0), правому нижнему - (1, 1).
texture Текстура, накладываемая на прямоугольник.
color Цветовой множитель. После текстурирования цвет каждого пикселя прямоугольника умножается на этот параметр.
clamp Включает\отключает дублирование текстуры, если текстурные координаты превышают 1. В значении true, если текстурные координаты превышают 1, текстура выводится лишь один раз, а оставшееся пространство прямоугольника закрашивается цветом крайнего пиксела текстуры.

Следующий пример выводит на экран два прямоугольника: закрашенный и текстурированный.

renderer.AddQuad(new Rect(.3f, .1f, .7f, .4f), new ColorValue(0, 1, 0, .5f));
 
Texture texture = TextureManager.Instance.Load( "Types\\StaticObjects\\StaticBox\\StaticBox.dds" );
renderer.AddQuad(new Rect(.3f, .5f, .7f, .8f), new Rect(0, 0, 1, 1), texture);
Вывод закрашенного прямоугольника на экран

Рисование линий и прямоугольников

Методы:

void AddLine( Vec2 start, Vec2 end, ColorValue color )
void AddRectangle( Rect rectangle, ColorValue color )

Линии рисуются методом AddLine класса GuiRenderer. Метод имеет 3 параметра:

Параметры Описание
start Координаты начала линии. Задаются в пропорциях экрана.
end Координаты конца линии. Задаются в пропорциях экрана.
color Цвет отображаемой линии.

Для рисования прямоугольников используется метод AddRectangle. В отличии от метода AddQuad, нарисованный прямоугольник не закрашиваются. Параметры метода AddRectangle:

Параметры Описание
rectangle Координаты прямоугольника. Задаются в пропорциях экрана.
color Цвет выводимого прямоугольника.

Следующий пример выводит на экран две линии и прямоугольник:

renderer.AddLine(new Vec2(.3f, .3f), new Vec2(.7f, .7f), new ColorValue(1, 0, 0));
renderer.AddLine(new Vec2(.3f, .7f), new Vec2(.7f, .3f), new ColorValue(1, 0, 0));
renderer.AddRectangle(new Rect(.3f, .3f, .7f, .7f), new ColorValue(1, 0, 0));
Вывод на экран линий и прямоугольников

Рисование текста

Для вывода на экран текста в GuiRender есть целых два метода: AddText и AddTextLines. Отличаются они тем, что первый метод выводит одну строку, а второй - список строк.

Доступные методы:

void AddText( Font font, string text, Vec2 position, HorizontalAlign horizontalAlign, VerticalAlign verticalAlign, ColorValue color )
void AddText( string text, Vec2 position, HorizontalAlign horizontalAlign, VerticalAlign verticalAlign, ColorValue color )
void AddText( string text, Vec2 position, HorizontalAlign horizontalAlign, VerticalAlign verticalAlign )
void AddText( string text, Vec2 position )
void AddTextLines( Font font, IList<string> lines, Vec2 pos, Vec2 step, HorizontalAlign horizontalAlign, VerticalAlign verticalAlign, ColorValue color )
void AddTextLines( IList<string> lines, Vec2 pos, Vec2 step, HorizontalAlign horizontalAlign, VerticalAlign verticalAlign, ColorValue color )

Существует 4 варианта метода AddText. Наиболее полный список параметров выглядит так:

Параметр Описание
font Шрифт, которым текст выводится на экран.
text Выводимый на экран текст.
position Положение текста на экране. Задается в пропорциях экрана.
horizontalAlign Выравнивание по горизонтали. Существует три значения: Left (по левой границе), Center (по центру) и Right (по правой границе).
verticalAlign Выравнивание по вертикали. Существует три значения: Top (по верхней границе), Center (по центру) и Bottom (по нижней границе).
color Цвет выводимого текста.

Теперь опишем параметры метода AddTextLines, выводящего на экран список строк:

Параметр Описание
lines Список строк текста, выводимого на экран.
pos Положение текста на экране. Задается в пропорциях экрана.
step Сдвиг очередной строки относительно предыдущей. Задается в пропорциях экрана.
horizontalAlign Выравнивание по горизонтали. Существует три значения: Left (по левой границе), Center (по центру) и Right (по правой границе).
verticalAlign Выравнивание по вертикали. Существует три значения: Top (по верхней границе), Center (по центру) и Bottom (по нижней границе).
color Цвет выводимого текста.

Следующий пример использует оба, приведенных выше, метода:

renderer.AddText(renderer.DefaultFont, "GuiRenderer Test", new Vec2(.5f, .4f), HorizontalAlign.Center, 
    VerticalAlign.Center, new ColorValue(0, 0, 1));
renderer.AddTextLines(new List<string> { "Line #1", "Line #2", "Line #3" }, new Vec2(.4f, .5f), 
    new Vec2(.03f, .02f), HorizontalAlign.Center, VerticalAlign.Top, new ColorValue(0, 1, 0));
Вывод текста на экран

Теперь рассмотрим пример рисования своим шрифтом.

Для начала объявим переменную, член класса ActionGameWindow', в которой будет храниться наш шрифт.

Font myFont;

Теперь загрузим шрифт. Это нужно делать с помощью класса FontManager. Добавим код, загружающий шрифт, в конец метода OnAttach:

protected override void OnAttach()
{
	base.OnAttach();
	...
	myFont = FontManager.Instance.LoadFont("PrecompiledImageExample", .1f);
}

Мы указали методу LoadFont, загружающему шрифт, имя шрифта и его высоту. Высота шрифта указывается в пропорциях экрана.

Теперь нарисуем текст с нашим шрифтом. Код будет располагаться в конце реализации метода OnRenderUI:

//Выводим текст. Указываем шрифт первым параметром.
renderer.AddText(myFont, "GuiRenderer Test", new Vec2(.5f, .4f), HorizontalAlign.Center,
    VerticalAlign.Center, new ColorValue(0, 0, 1));
Рисование своим шрифтом

Подробнее об использовании различных шрифтов в NeoAxis Engine можно узнать здесь.

Рисование треугольников

Для рисования треугольников отвечает метод AddTriangles. На вход этот метод получает список вершин треугольников. Это число, как вы понимаете, должно быть кратно трем - числу вершин треугольника.

Доступные методы:

void AddTriangles( IList<TriangleVertex> vertices )
void AddTriangles( IList<TriangleVertex> vertices, Texture texture, bool clamp )

Вот весь список параметров метода AddTriangles:

Параметр Описание
vertices Список вершин треугольников. Каждая вершина хранит в себе информацию о позиции на экране, цвете и текстурных координатах. Если на треугольники накладывается текстура, то цвет вершины умножается на цвет пикселей текстуры. Если же текстуры нет, то треугольник градиентно закрашивается согласно цветам своих вершин.
texture Текстура, закрашивающая треугольники.
clamp Включает\отключает дублирование текстуры, если текстурные координаты превышают 1. В значении true, если текстурные координаты превышают 1, текстура выводится лишь один раз, а оставшееся пространство прямоугольника закрашивается цветом крайнего пиксела текстуры.

Как и в случае с закрашенными прямоугольниками, треугольники могут закрашиваться цветом или покрываться текстурой.

Следующий пример выводит на экран один градиентно закрашенный треугольник и два текстурированных треугольника, образующих параллелограмм:

List<GuiRenderer.TriangleVertex> vertices1 = new List<GuiRenderer.TriangleVertex>() {
    new GuiRenderer.TriangleVertex(new Vec2(.5f, .1f), new ColorValue(1, 0, 0, .5f)),
    new GuiRenderer.TriangleVertex(new Vec2(.3f, .3f), new ColorValue(0, 1, 0, .5f)),
    new GuiRenderer.TriangleVertex(new Vec2(.7f, .3f), new ColorValue(0, 0, 1, .5f))};
renderer.AddTriangles(vertices1);
 
List<GuiRenderer.TriangleVertex> vertices2 = new List<GuiRenderer.TriangleVertex>() {
    new GuiRenderer.TriangleVertex(new Vec2(.4f, .5f), new ColorValue(1, 1, 1), new Vec2(0, 0)),
    new GuiRenderer.TriangleVertex(new Vec2(.7f, .5f), new ColorValue(1, 1, 1), new Vec2(1, 0)),
    new GuiRenderer.TriangleVertex(new Vec2(.6f, .8f), new ColorValue(1, 1, 1), new Vec2(1, 1)),
    new GuiRenderer.TriangleVertex(new Vec2(.4f, .5f), new ColorValue(1, 1, 1), new Vec2(0, 0)),
    new GuiRenderer.TriangleVertex(new Vec2(.3f, .8f), new ColorValue(1, 1, 1), new Vec2(0, 1)),
    new GuiRenderer.TriangleVertex(new Vec2(.6f, .8f), new ColorValue(1, 1, 1), new Vec2(1, 1))};
Texture texture = TextureManager.Instance.Load("Types\\StaticObjects\\StaticBox\\StaticBox.dds");
renderer.AddTriangles(vertices2, texture, true);
Вывод на экран треугольников

Рисование позади сцены

Класс GuiRenderer позволяет вывод объектов пользовательского интерфейса позади трехмерной сцены. К примеру, вы можете рисовать 3d-объекты поверх фонового видео.

Чтобы объекты интерфейса отрисовывались позади сцены, необходимо вызвать метод PushRenderBehindScene класса GuiRenderer. Для того, чтобы рисовать позади сцены, параметр этого метода должен иметь значение true. После того, как все объекты отрисованы, нужно вернуть параметр в прежнее состояние, вызвав метод PopRenderBehindScene.

В качестве примера, реализуем метод OnRenderUI в классе окна главного меню - MainMenuWindow, расположенного в файле MainMenuWindow.cs проекта Game.

protected override void OnRenderUI(GuiRenderer renderer)
{
    //Включаем режим рисования позади сцены
    renderer.PushRenderBehindScene(true);
 
    //Создаем текстуру
    Texture texture = TextureManager.Instance.Load("Types\\StaticObjects\\StaticBox\\StaticBox.dds");
 
    //Рисуем закрашенный текстурой прямоугольник
    renderer.AddQuad(new Rect(0, 0, 1, 1), new Rect(0, 0, 1, 1), texture);
 
    //Выключаем режим рисования позади сцены
    renderer.PopRenderBehindScene();
}
Вывод пользовательского интерфейса позади сцены

Отсечение элементов

GuiRenderer обладает возможностью отсекать элементы по указанному вами региону. Для указания области отсечения имеется метод PushClipRectangle, который указывает прямоугольную область отсечения. Можно добавлять несколько прямоугольных областей, все они будут последовательно участвовать отсечении.

Ниже приведен код, использующий отсечение элементов:

//Включаем режим отсечения
renderer.PushClipRectangle(new Rect(.25f, .25f, .75f, .75f));
 
//Создаем текстуру
Texture texture = TextureManager.Instance.Load("Types\\StaticObjects\\StaticBox\\StaticBox.dds");
 
//Рисуем закрашенный текстурой прямоугольник
renderer.AddQuad(new Rect(0, 0, 1, 1), new Rect(0, 0, 1, 1), texture);
 
//Выключаем режим отсечения
renderer.PopClipRectangle();
Отсечение элементов пользовательского интерфейса

Изменение функции блендинга

При рисовании закрашенных прямоугольников или треугольников, можно указывать цвет, которым закрашивается фигура или же который умножается на цвета пикселей текстуры. Этот цвет имеет компоненту прозрачности. Компонента прозрачности используется при блендинге. Причем его функции можно изменить. Для рисования элементов пользовательского интерфейса имеется две функции блендинга:

  • AlphaBlend - цвет пикселя смешивается с цветом фона,
  • AlphaAdd - цвет пикселя прибавляется к цвету фона.

Для того чтобы выбрать ту или иную функцию блендинга в классе GuiRenderer имеется метод PushSpecialBlendingType. В качестве параметра метод получает функцию блендинга - BlendingTypes. После завершения использования функции блендинга, вызывается метод PopSpecialBlendingType, удаляющий последнюю добавленную функцию блендинга.

По умолчанию включена функция AlphaBlend.

Следующий код использует поочередно обе функции блендинга, после чего удаляет их:

//Создаем текстуру
Texture texture = TextureManager.Instance.Load("Types\\StaticObjects\\StaticBox\\StaticBox.dds");
 
//Рисуем закрашенный прямоугольник с функцией AlphaBlend. Функция AlphaBlend включена по умолчанию.
renderer.AddQuad(new Rect(.1f, .375f, .45f, .625f), new Rect(0, 0, 1, 1), texture, new ColorValue(1, 1, 1, .5f));
 
//Изменяем функцию блендинга
renderer.PushSpecialBlendingType(GuiRenderer.BlendingTypes.AlphaAdd);
 
//Рисуем закрашенный прямоугольник
renderer.AddQuad(new Rect(.55f, .375f, .9f, .625f), new Rect(0, 0, 1, 1), texture, new ColorValue(1, 1, 1, .5f));
 
//Удаляем использованные фунции блендинга
renderer.PopSpecialBlendingType();
Изменение функции блендинга

Использование пользовательских шейдеров (Custom Shader Mode)

Для особого отображения пользовательского интерфейса в NeoAxis можно обрабатывать изображение с помощью пользовательских (своих) шейдеров. Включить такой режим можно с помощью метода PushCustomShaderMode класса GuiRenderer. Этот метод получает следующие параметры:

Параметр Описание
sourceFileName Путь к файлу с шейдером. Указывается относительно папки Data вашего проекта.
additionalTextures Список дополнительных текстур.
parameters Список параметров, передающихся в шейдер.

Для выключения режима использования пользовательских шейдеров, имеется метод PopCustomShaderMode, удаляющий последнюю добавленную опцию использования пользовательских шейдеров.

Для того, чтобы увидеть обработку пользовательского интерфейса шейдерами в действии, зайдем в главное меню NeoAxis Engine Demo и нажмем кнопку Gui Test.

Gui renderer10.jpg

Код, использующий пользовательские шейдеры, можно найти в проекте Game в файле GuiTestWindow.cs. Ниже приведены строчки кода из этого файла, включающие режим использования пользовательских шейдеров:

//Список дополнительных текстур
List<GuiRenderer.CustomShaderModeTexture> additionalTextures = new List<GuiRenderer.CustomShaderModeTexture>();
//Добавляем в список текстуру
additionalTextures.Add( new GuiRenderer.CustomShaderModeTexture( "Gui\\Various\\Engine.png", false ) );
 
//Список параметров
List<GuiRenderer.CustomShaderModeParameter> parameters = new List<GuiRenderer.CustomShaderModeParameter>();
float offsetX = ( EngineApp.Instance.Time / 60 ) % 1;
Vec2 mouse = EngineApp.Instance.MousePosition;
//Добавляем в список параметр
parameters.Add( new GuiRenderer.CustomShaderModeParameter( "testParameter", new Vec4( offsetX, mouse.X, mouse.Y, 0 ) ) );
 
//Включаем режим использования пользовательских шейдеров
renderer.PushCustomShaderMode( "Materials\\Common\\CustomGuiRenderingExample.cg_hlsl", additionalTextures, parameters )

Код шейдера можно найти в файле Bin\Data\Materials\Common\CustomGuiRenderingExample.cg_hlsl:

// Copyright (C) 2006-2011 NeoAxis Group Ltd.
 
void main_vp(
	uniform float4x4 worldViewProjMatrix,
	uniform float4 viewportSize,
 
	float4 position : POSITION,
	float4 vertexColor : COLOR0,
	float2 texCoord : TEXCOORD0,
 
	out float4 oPosition : POSITION,
	out float2 oTexCoord : TEXCOORD0,
	out float4 oVertexColor : TEXCOORD1,
	out float2 oViewportSizeInPixels : TEXCOORD2,
	out float2 oScreenPosition : TEXCOORD3
	)
{
	oPosition = mul(worldViewProjMatrix, position);
	oTexCoord = texCoord;
	oVertexColor = vertexColor;
	oViewportSizeInPixels = viewportSize.xy;
	oScreenPosition = (float2(position.x, -position.y) + 1) / 2;
}
 
void main_fp(
	float2 texCoord : TEXCOORD0,
	half4 vertexColor : TEXCOORD1,
	float2 viewportSizeInPixels : TEXCOORD2,
	float2 screenPosition : TEXCOORD3,
 
	uniform sampler2D diffuseMap : register(s0),
	uniform sampler2D additionalMap : register(s1),
 
	uniform float4 testParameter,
 
	out half4 oColor : COLOR)
{
/*
	//default code
	oColor = (half4)tex2D(diffuseMap, texCoord) * vertexColor;
*/
 
/*
	//simple example
	vertexColor *= half4(1, 0, 0, vertexColor.a);
	oColor = (half4)tex2D(diffuseMap, texCoord) * vertexColor;
	return;
*/
 
	float aspectRatio = viewportSizeInPixels.x / viewportSizeInPixels.y;
 
	//calculate tex coord for additional map
	float offsetX = testParameter.x;
	float2 additionalMapTexCoord = float2(screenPosition.x, (screenPosition.y - .5f) * 2.2f / aspectRatio + .5f);
	//make scroll and waving
	additionalMapTexCoord.x += offsetX;
	additionalMapTexCoord.y += sin((offsetX - screenPosition.x) * 100) * .01f;
	//clamp by Y
	additionalMapTexCoord.y = saturate(additionalMapTexCoord.y);
 
	//circle
	float2 mouse = testParameter.yz;
	float2 diff = screenPosition - mouse;
	float distance = length(float2(diff.x * aspectRatio, diff.y));
	float alpha = .3f;
	if(distance < .3f)
		alpha = 4;
	if(distance < .29f)
		alpha = 1;
	vertexColor.a *= alpha;
 
	half4 color = (half4)tex2D(diffuseMap, texCoord);
	color.rgb += tex2D(additionalMap, additionalMapTexCoord).rgb;
	oColor = color * vertexColor;
}
Использование пользовательских шейдеров