Документация/Статьи по программированию/Описание GuiRenderer
From NeoAxis Engine Wiki
| Language: | Status: | Approved |
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.
Код, использующий пользовательские шейдеры, можно найти в проекте 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; }