Documentation/Programming Articles/Overview of a GuiRenderer
From NeoAxis Engine Wiki
| Language: | Status: | Approved |
Contents |
Introduction
In this article you will examine the GuiRenderer class that implements GUI rendering. You will learn to display simple objects (such as rectangle, line, triangle and text) as well as use GuiRenderer for viewing debug information and game statistics.
You can also use GuiRenderer for creating GUI classes. You can find more information on creating GUI with GuiRenderer here.
GuiRenderer is available through the OnRenderUI method of the game window class or control class:
public class ActionGameWindow : GameWindow { ... protected override void OnRenderUI(GuiRenderer renderer) { base.OnRenderUI(renderer); ... //Place your code here } }
The GuiRenderer is set as a parameter in the OnRenderUI method.
In the examples below we will be using the OnRenderUI method of the ActionGameWindow class (first- or third-person shooter window), stored in the Game project. This method does already have the code calling its parent OnRenderUI method as well as thirty more lines of code after which you can program the parameters you need.
To see these examples in action you will have to compile the code and start a map using the ActionGameWindow class (e.g. TankDemo).
Rendering a painted rectangle
For rendering a painted rectangle the AddQuad method of the GuiRenderer class is used. It is possible both to paint a rectangle and to put a texture on it.
The list of available methods includes:
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 )
The simple method that paints a rectangle with one color has the following parameters:
| Parameter | Description |
|---|---|
| rectangle | Rectangle position. Coordinates are proportionate to screen size. The coordinates of the upper-left corner of the screen are (0, 0), while those for the lower-right corner are (1, 1). |
| color | Rectangle color. Consists of four components: Red, Green, Blue and Alpha (transparency). |
Now let us examine the AddQuad method (applying textures to a rectangle) and its parameters.
| Parameter | Description |
|---|---|
| rectangle | Rectangle position. Coordinates are proportionate to screen size. The coordinates of the upper-left corner of the screen are (0, 0), while those for the lower-right corner are (1, 1). |
| textureCoordRectangle | The coordinates of the upper-left corner of the screen are (0, 0), while those for the lower-right corner are (1, 1). |
| texture | A texture to be applied to the rectangle. |
| color | Color multiplier. After applying the texture each pixel’s color is multiplied by this value. |
| clamp | Switches texture overlapping on/off. Texture coordinates clamps at 1.0. |
The example below renders two rectangles: a painted one and one with a texture.
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);
Rendering lines and rectangles
The list of available methods includes:
void AddLine( Vec2 start, Vec2 end, ColorValue color ) void AddRectangle( Rect rectangle, ColorValue color )
Lines are rendered using the AddLine method of the GuiRenderer class. The method has three parameters:
| Parameter | Description |
|---|---|
| start | Coordinates of the line origin (proportionate to screen size). |
| end | Coordinates of the line end (proportionate to screen size). |
| color | Color of the line. |
For rendering rectangles the AddRectangle method is used. Unlike the AddQuad method this method does not paint the rectangle. The list of method’s parameters includes:
| Parameter | Description |
|---|---|
| rectangle | Coordinates of the rectangle (proportionate to screen size). |
| color | Rectangle color. |
The example below renders two lines and a rectangle:
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));
Rendering text
There are two methods in the GuiRender class for rendering text: AddText and AddTextLines. While the first one renders a single line, the second one renders a list..
The list of available methods includes:
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 )
There are 4 variants of the AddText method. The list of parameters includes:
| Parameter | Description |
|---|---|
| font | Text font. |
| text | The text to be displayed on the screen. |
| position | Text position on the screen (coordinates should be proportionate to screen size). |
| horizontalAlign | Horizontal alignment. Can be set to: Left, Center and Right. |
| verticalAlign | Vertical alignment. Can be set to: Top, Center and Bottom. |
| color | Font color. |
Not let us examine the parameters of the AddTextLines method used for rendering lists of lines:
| Prameter | Description |
|---|---|
| lines | Line list to be displayed on the screen. |
| pos | Line list position on the screen (coordinates should be proportionate to screen size). |
| step | Text position on the screen (should be proportionate to screen size). |
| horizontalAlign | Horizontal alignment. Can be set to: Top, Center and Bottom. |
| verticalAlign | Vertical alignment. Can be set to: Top, Center and Bottom. |
| color | Font color. |
The example below illustrates the use of both methods:
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));
Now you will learn to render with your own font.
First, declare a variable (make it an element of the ActionGameWindow' class) to store your font in it.
Font myFont;Now you have to load the new font. Do it with the FontManager class (add a code loading the new font at the end of the OnAttach method):
protected override void OnAttach() { base.OnAttach(); ... myFont = FontManager.Instance.LoadFont("PrecompiledImageExample", .1f); }
As you see, you have specified font name and size in the LoadFont method (font side is proportionate to screen size)
Now, render a text with your new font by putting the following code in the end of the OnRenderUI method:
//Text rendering. The first parameter is the font name. renderer.AddText(myFont, "GuiRenderer Test", new Vec2(.5f, .4f), HorizontalAlign.Center, VerticalAlign.Center, new ColorValue(0, 0, 1));
You can learn more about font use in NeoAxis Engine here.
Rendering triangles
Triangle rendering is implemented with the AddTriangles method. This method requires coordinates of three triangle apexes to work.
The list of available methods includes:
void AddTriangles( IList<TriangleVertex> vertices ) void AddTriangles( IList<TriangleVertex> vertices, Texture texture, bool clamp )
The parameter list of the AddTriangles method includes:
| Parameter | Description |
|---|---|
| vertices | The list of triangle vertices. Each vertex has information on its position, color and texture coordinates. When a texture is applied to the triangle, its vertex color is multiplied by texture pixel color. |
| texture | A texture to be applied to the triangle. |
| clamp | Switches texture overlapping on/off. Texture coordinates clamps at 1.0. |
Just as with rectangles you can paint and apply texture to triangles.
The example below renders a gradient triangle and two triangles with applied textures, thus making a parallelogram:
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);
Rendering behind the scene
The GuiRenderer class enables GUI elements rendering behind 3D scene. E.g. you can render 3D objects with some background video on.
To make GUI element render behind a 3D scene you have to call the PushRenderBehindScene method of the GuiRenderer class. In order for the rendering to succeed this method’s parameter has to be set to true. After having rendered all the objects you have to restore this parameter's initial value by calling the PopRenderBehindScene method.
As an example the OnRenderUI method will be implemented in the MainMenuWindow class (stored in the MainMenuWindow.cs file of the Game project).
protected override void OnRenderUI(GuiRenderer renderer) { //Turning the “background rendering” mode on renderer.PushRenderBehindScene(true); //Creating a texture Texture texture = TextureManager.Instance.Load("Types\\StaticObjects\\StaticBox\\StaticBox.dds"); //Creating a rectangle with the applied texture renderer.AddQuad(new Rect(0, 0, 1, 1), new Rect(0, 0, 1, 1), texture); // Turning the “background rendering” mode off renderer.PopRenderBehindScene(); }
Clipping
The GuiRenderer enables clipping in the user-specified region. Using the PushClipRectangle you can set a clipping rectangular (you can set several regions as well).
Below you can see the code that implements clipping:
//Switching clipping mode on renderer.PushClipRectangle(new Rect(.25f, .25f, .75f, .75f)); //Creating a texture Texture texture = TextureManager.Instance.Load("Types\\StaticObjects\\StaticBox\\StaticBox.dds"); //Rendering a rectangle with an applied texture renderer.AddQuad(new Rect(0, 0, 1, 1), new Rect(0, 0, 1, 1), texture); // Switching clipping mode off renderer.PopClipRectangle();
Changing the blending function
While rendering painted rectangles or triangles you can specify the color to paint them with or by which texture pixels will be multiplied. This color has a transparency component used for blending. There are two blending functions you can adjust:
- AlphaBlend – pixel color is mixed with the background color,
- AlphaAdd - pixel color is added to the background color.
You can select the blending function by means of the PushSpecialBlendingType method of the GuiRenderer class. Blending function is a parameter of the BlendingTypes method. After having complete the blending function use, the PopSpecialBlendingType method is called that removes the last added blending function.
The default blending function is AlphaBlend.
The code below is using both blending functions subsequently removing them:
//Creating a texture Texture texture = TextureManager.Instance.Load("Types\\StaticObjects\\StaticBox\\StaticBox.dds"); //Rendering a painted rectangle with the AlphaBlend function. The AlphaBlend is switched on by default. renderer.AddQuad(new Rect(.1f, .375f, .45f, .625f), new Rect(0, 0, 1, 1), texture, new ColorValue(1, 1, 1, .5f)); //Changing the blending function renderer.PushSpecialBlendingType(GuiRenderer.BlendingTypes.AlphaAdd); //Rendering a painted rectangle renderer.AddQuad(new Rect(.55f, .375f, .9f, .625f), new Rect(0, 0, 1, 1), texture, new ColorValue(1, 1, 1, .5f)); //Removing the blending functions renderer.PopSpecialBlendingType();
Custom Shader Mode
In NeoAxis you can process GUI elements using your own shaders. This mode is switched on with the PushCustomShaderMode method of the GuiRenderer class. This method has the following parameters:
| Parameter | Description |
|---|---|
| sourceFileName | Path to the shader file from the Data folder of your project. |
| additionalTextures | The list of additional textures. |
| parameters | The list of parameters transferred to the shader. |
After having rendered all the objects you have to restore this parameter's initial value by calling the PopCustomShaderMode method.
In order to see the UI being processed with shaders call the NeoAxis Engine Demo and press the Gui Test button.
You can find a code using user-shaders in the GuiTestWindow.cs file of the Game project. Below you can see the lines from this code implementing UI processing with shaders:
//The list of additional textures List<GuiRenderer.CustomShaderModeTexture> additionalTextures = new List<GuiRenderer.CustomShaderModeTexture>(); //Adding a texture to the list additionalTextures.Add( new GuiRenderer.CustomShaderModeTexture( "Gui\\Various\\Engine.png", false ) ); //The list of parameters List<GuiRenderer.CustomShaderModeParameter> parameters = new List<GuiRenderer.CustomShaderModeParameter>(); float offsetX = ( EngineApp.Instance.Time / 60 ) % 1; Vec2 mouse = EngineApp.Instance.MousePosition; //Adding a parameter to the list parameters.Add( new GuiRenderer.CustomShaderModeParameter( "testParameter", new Vec4( offsetX, mouse.X, mouse.Y, 0 ) ) ); //Switching the user-shader mode on renderer.PushCustomShaderMode( "Materials\\Common\\CustomGuiRenderingExample.cg_hlsl", additionalTextures, parameters )
You can find the shader code in this file 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; }