Urho3D Wiki
No edit summary
Tag: rte-wysiwyg
(Typo)
Tags: Visual edit apiedit
 
(15 intermediate revisions by one other user not shown)
Line 1: Line 1:
== Customize materials (per code) & different materials per model ==
 
Normally you assign materials like this:
 
 
<syntaxhighlight lang="cpp">
 
StaticModel* boxObject=boxNode_->CreateComponent<StaticModel>();
 
boxObject->SetModel(cache->GetResource<Model>("Models/Box.mdl"));
 
boxObject->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml"));
 
</syntaxhighlight>
 
You can also load materials, copy them, and/or change parameters:
 
 
<syntaxhighlight lang="cpp">
 
Material* mat1=cache->GetResource<Material>("Materials/Stone.xml");
 
Material* mat2=mat1->Clone(); // copy material
 
// change the ciffuse color
 
mat2->SetShaderParameter("MatDiffColor",Color(0.1,0.4,0.9));
 
boxObject->SetMaterial(mat2);
 
</syntaxhighlight>
 
You can use this to make every model unique by randomizing colors or color models in a team color. You can also pass custom parameters to control things like current weather or different (localized) lighting scenes.
 
 
An example of 400 uniquely colored cubes:
 
[[File:Copy material.jpg|centre|thumb|512x512px]]
 
 
== Custom shader parameters ==
 
You can define and use own shader parameters like this:
 
 
==== '''Define the parameter in the material.xml:''' ====
 
<material>
 
    <technique name="Techniques/skysphere.xml" />
 
    <parameter name="SunDir" value="0.64 0.64 0.64"/>
 
    <parameter name="SkyColor" value="0.9 0.5 0.5 1" />
 
</material>
 
Here I'm adding a Vector3/vec3 called SunDir and a RGBA color called SkyColor. Hint: there is no difference between RGB colors and Vector3/vec3 or between RGBA colors and Vector4/vec4, both are types with 3 respectively 4 floats.
 
 
==== '''In the Shader (here GLSL):''' ====
 
// at the top above and outside all functions:
 
uniform vec3 cSunDir;
 
uniform vec4 cSkyColor;
 
...
 
void PS() // the parameters can also be used in the vertex shader (VS())
 
{
 
float sun_intensity=clamp(dot(vNormal,cSunDir),0.0,1.0); // calculate a float with the dot product of the SunDir parameter and the vertex normal
 
gl_FragColor=cSunColor*sun_intensity; // multiplying a vec4 / RGBA-Color with a float
 
}
 
In shaders the parameter names need to be preceded with a 'c'. See http://urho3d.github.io/documentation/1.32/_shaders.html.
 
 
See http://en.wikibooks.org/wiki/GLSL_Programming/Vector_and_Matrix_Operations for an explanation of some of the shader functions.
 
 
==== '''You can also modify the parameters dynamically in you code:''' ====
 
materialSkySphere->SetShaderParameter("SunDir",Vector3(0,1,0));
 
Using own textures in shaders is very similiar.
 
 
== Expand default terrain material to 4 textures using alpha channel ==
 
It's possible to also use the alpha channel as a color weight to get an additional texture for the terrain (or something else). (Using alpha/transparency makes drawing (at least in Gimp) difficult, see the next section for a better editable improvement with six colors&textures)
 
 
Add another texture to the terrain material "Data/Materials/Terrain.xml" like:
 
<material>
 
<technique name="Techniques/TerrainBlend.xml" />
 
<texture unit="0" name="Textures/TerrainWeights.png" />
 
<texture unit="1" name="Textures/TerrainDetail1.dds" />
 
<texture unit="2" name="Textures/TerrainDetail2.dds" />
 
<texture unit="3" name="Textures/TerrainDetail3.dds" />
 
<texture unit="4" name="Textures/StoneDiffuse.dds" />
 
<parameter name="MatSpecColor" value="0.5 0.5 0.5 16" />
 
<parameter name="DetailTiling" value="16 16" />
 
</material>
 
For OpenGL: Change the "CoreData/Shaders/GLSL/TerrainBlend.glsl" to additionally use the alpha channel:
 
...
 
uniform sampler2D sWeightMap0;
 
uniform sampler2D sDetailMap1;
 
uniform sampler2D sDetailMap2;
 
uniform sampler2D sDetailMap3;
 
uniform sampler2D sDetailMap4; // <- added
 
...
 
void PS()
 
{
 
// Get material diffuse albedo
 
vec4 weights = texture2D(sWeightMap0, vTexCoord).rgba; // <- changed
 
weights.a=1.0-weights.a; // <- added. Alpha should be weight in reverse (easier editing)
 
// with 0 (fully transparent) being full weight.
 
float sumWeights = weights.r + weights.g + weights.b + weights.a; // <- changed
 
weights /= sumWeights;
 
vec4 diffColor = cMatDiffColor * (
 
weights.r * texture2D(sDetailMap1, vDetailTexCoord) +
 
weights.g * texture2D(sDetailMap2, vDetailTexCoord) +
 
weights.b * texture2D(sDetailMap3, vDetailTexCoord) + // <- changed
 
weights.a * texture2D(sDetailMap4, vDetailTexCoord) // <- added
 
);
 
...
 
If you want to use DirectX, also change the HLSL accordingly.
 
 
Use another splatting image (watch out for high red/green/blue values inside the alpha, it should be black with high alpha). My texture weight image and the result look like this:
 
[[File:Rgba terrain.jpg|centre|thumb|730x730px]]
 
 
== Expand default terrain material to 6 textures using the "six basic colors" ==
 
Here I'm using the "six basic colors" red, yellow, green, cyan, blue and magenta to get six separate color weight.
 
 
Urho is currently per default limited to five textures. You need to modify the file "Source/Urho3D/Graphics/GraphicsDefs.h" first to increase this limit:
 
...
 
/// Texture units.
 
enum TextureUnit
 
{
 
TU_DIFFUSE = 0,
 
TU_ALBEDOBUFFER = 0,
 
TU_NORMAL = 1,
 
TU_NORMALBUFFER = 1,
 
TU_SPECULAR = 2,
 
TU_EMISSIVE = 3,
 
TU_ENVIRONMENT = 4,
 
MAX_MATERIAL_TEXTURE_UNITS = 8, // this and the following numbers have been increased
 
TU_LIGHTRAMP = 8, // by 3 each to increase the texture limit from 5 to 8
 
TU_LIGHTSHAPE = 9,
 
TU_SHADOWMAP = 10,
 
TU_FACESELECT = 11,
 
TU_INDIRECTION = 12,
 
TU_DEPTHBUFFER = 13,
 
TU_LIGHTBUFFER = 14,
 
TU_VOLUMEMAP = 15,
 
TU_ZONE = 16,
 
MAX_NAMED_TEXTURE_UNITS = 17,
 
MAX_TEXTURE_UNITS = 19
 
};
 
...
 
Rebuild Urho3D and your project after doing this!
 
 
The Material.xml:
 
<material>
 
<technique name="Techniques/TerrainBlend_6splat.xml" />
 
<texture unit="0" name="Textures/TerrainWeights.png" />
 
<texture unit="1" name="Textures/red.png" />
 
<texture unit="2" name="Textures/yellow.png" />
 
<texture unit="3" name="Textures/green.png" />
 
<texture unit="4" name="Textures/cyan.png" />
 
<texture unit="5" name="Textures/blue.png" />
 
<texture unit="6" name="Textures/magenta.png" />
 
<parameter name="MatSpecColor" value="0.6 0.6 0.6 16" />
 
<parameter name="DetailTiling" value="64 64" />
 
</material>
 
The technique.xml file is identical to the default terrain technique.
 
 
GLSL Shader:
 
...
 
uniform sampler2D sWeightMap0;
 
uniform sampler2D sDetailMap1;
 
uniform sampler2D sDetailMap2;
 
uniform sampler2D sDetailMap3;
 
uniform sampler2D sDetailMap4; // the default terrain shader had only 4 maps (one weight texture + three splatting textures). Added these 3.
 
uniform sampler2D sDetailMap5;
 
uniform sampler2D sDetailMap6;
 
...
 
void PS()
 
{
 
vec3 colors = texture2D(sWeightMap0,vTexCoord).rgb; // I added a second vec3 called weights_ycm to get six weights in total
 
vec3 weights_rgb = colors;
 
vec3 weights_ycm = colors;
 
 
weights_rgb.r=clamp(colors.r-(colors.g+colors.b),0.0,1.0); // it took a while to figure out how to separate the six colors
 
weights_rgb.g=clamp(colors.g-(colors.b+colors.r),0.0,1.0); // it's basically using each RGB colors difference to the other two.
 
weights_rgb.b=clamp(colors.b-(colors.r+colors.g),0.0,1.0);
 
weights_ycm.r=clamp(colors.r*colors.g,0.0,1.0); // yellow
 
weights_ycm.g=clamp(colors.g*colors.b,0.0,1.0); // cyan
 
weights_ycm.b=clamp(colors.b*colors.r,0.0,1.0); // magenta
 
// the "sumWeights" stuff is gone
 
vec4 diffColor = cMatDiffColor * (
 
weights_rgb.r * texture2D(sDetailMap2, vDetailTexCoord) + // red
 
weights_ycm.r * texture2D(sDetailMap3, vDetailTexCoord) + // yellow
 
weights_rgb.g * texture2D(sDetailMap4, vDetailTexCoord) + // green
 
weights_ycm.g * texture2D(sDetailMap5, vDetailTexCoord) + // cyan
 
weights_rgb.b * texture2D(sDetailMap6, vDetailTexCoord) + // blue
 
weights_ycm.b * texture2D(sDetailMap7, vDetailTexCoord) // magenta
 
);
 
...
 
Result:
 
[[File:Terrain 6splat-0.jpg|centre|thumb|720x720px]]
 
Left is the used weight map with the six colors and right the resulting terrain in Urho. It should be possible to also use the alpha channel for another color weight or to separate these six colors again to get twelve color weights.
 
 
This technique with the six colors has one disadvantage: It's not possible to directly/clearly fade from some colors to colors on the opposite site (like red<->green) as you can see on the screenshot. Depending on your settings when drawing the weight map, you can also achieve a black "border" when, for example, drawing red over green instead of the yellow border here.
 
 
== Expand default terrain material to 7 textures using the "six basic colors" and black ==
 
Quite the same as above. Extend Urho's texture limit to at least eight textures (see above, has been increased to eight there).
 
 
Material.xml: Added a new number one for black (and lowered specular brightness and texture repeating to see the textures better in the screenshot).
 
<material>
 
<technique name="Techniques/TerrainBlend_6splat.xml" />
 
<texture unit="0" name="Textures/TerrainWeights.png" />
 
<texture unit="1" name="Textures/black.png" />
 
<texture unit="2" name="Textures/red.png" />
 
<texture unit="3" name="Textures/yellow.png" />
 
<texture unit="4" name="Textures/green.png" />
 
<texture unit="5" name="Textures/cyan.png" />
 
<texture unit="6" name="Textures/blue.png" />
 
<texture unit="7" name="Textures/magenta.png" />
 
<parameter name="MatSpecColor" value="0.1 0.1 0.1 16" />
 
<parameter name="DetailTiling" value="16 16" />
 
</material>
 
The technique.xml file is identical to the default terrain technique.
 
 
GLSL Shader:
 
...
 
uniform sampler2D sWeightMap0;
 
uniform sampler2D sDetailMap1;
 
uniform sampler2D sDetailMap2;
 
uniform sampler2D sDetailMap3;
 
uniform sampler2D sDetailMap4;
 
uniform sampler2D sDetailMap5;
 
uniform sampler2D sDetailMap6;
 
uniform sampler2D sDetailMap7; // eight textures in total for the weight map + seven splatting textures
 
...
 
void PS()
 
{
 
vec3 colors = texture2D(sWeightMap0,vTexCoord).rgb;
 
vec3 weights_rgb = colors;
 
vec3 weights_ycm = colors;
 
 
weights_rgb.r=clamp(colors.r-(colors.g+colors.b),0.0,1.0); // red
 
weights_rgb.g=clamp(colors.g-(colors.b+colors.r),0.0,1.0); // green
 
weights_rgb.b=clamp(colors.b-(colors.r+colors.g),0.0,1.0); // blue
 
weights_ycm.r=clamp(colors.r*colors.g,0.0,1.0); // yellow
 
weights_ycm.g=clamp(colors.g*colors.b,0.0,1.0); // cyan
 
weights_ycm.b=clamp(colors.b*colors.r,0.0,1.0); // magenta
 
float black=1.0-clamp(weights_rgb.r+weights_rgb.g+weights_rgb.b+ // black weight
 
weights_ycm.r+weights_ycm.g+weights_ycm.b,0.0,1.0);
 
 
vec4 diffColor = cMatDiffColor * (
 
black * texture2D(sDetailMap1, vDetailTexCoord) + // black <- added black
 
weights_rgb.r * texture2D(sDetailMap2, vDetailTexCoord) + // red
 
weights_ycm.r * texture2D(sDetailMap3, vDetailTexCoord) + // yellow
 
weights_rgb.g * texture2D(sDetailMap4, vDetailTexCoord) + // green
 
weights_ycm.g * texture2D(sDetailMap5, vDetailTexCoord) + // cyan
 
weights_rgb.b * texture2D(sDetailMap6, vDetailTexCoord) + // blue
 
weights_ycm.b * texture2D(sDetailMap7, vDetailTexCoord) // magenta
 
);
 
...
 
Result:
 
[[File:Terrain 7splat.jpg|centre|thumb|720x720px]]
 
One could also use black as a weight with just the default terrain material with three terrain splatting textures (making it four splatting textures) or with the three plus alpha (making it five).
 
 
Note: there are also texture count limits in OpenGL and DirectX, so you can't increase the texture count endlessly. I heard OpenGL 2.0 should be able to have at least eight textures and OpenGL 3.0 at least 16.__FORCETOC__
 
 
 
 
== How to write text into console ==
 
== How to write text into console ==
Urho implements its own functions for writing text (loging) into console. If you want to use them, first you need to include Log.h
+
Urho implements its own functions for writing text (logging) into console. If you want to use them, first you need to include Log.h
 
#include "Urho3D/IO/Log.h"
 
#include "Urho3D/IO/Log.h"
 
Writing info messages:
 
Writing info messages:
 
LOGINFO(text);
 
LOGINFO(text);
 
Writing debug messages:
 
Writing debug messages:
 
p { margin-bottom: 0.25cm; direction: ltr; color: rgb(0, 0, 0); line-height: 120%; }p.western { font-family: "Liberation Serif","Times New Roman",serif; font-size: 12pt; }p.cjk { font-family: "Droid Sans Fallback"; font-size: 12pt; }p.ctl { font-family: "FreeSans"; font-size: 12pt; }a:link { }
 
 
LOGDEBUG(text);
 
LOGDEBUG(text);
 
Writing error messages:
 
Writing error messages:
 
p { margin-bottom: 0.25cm; direction: ltr; color: rgb(0, 0, 0); line-height: 120%; }p.western { font-family: "Liberation Serif","Times New Roman",serif; font-size: 12pt; }p.cjk { font-family: "Droid Sans Fallback"; font-size: 12pt; }p.ctl { font-family: "FreeSans"; font-size: 12pt; }a:link { }
 
 
LOGERROR(text);
 
LOGERROR(text);
   
 
== Creating and using your own subsystems ==
 
== Creating and using your own subsystems ==
If you have a class inherited from Object you can create a subsystem out of it. The subsystems are helpfull for example when you want to make a class available to every other Object inherited class. In this HowTo I will create a Settings subsystem.
+
If you have a class inherited from Urho's Object class, you can create a subsystem out of it. The subsystems are helpful, for example, when you want to make a class instance available to every other class inheriting from Object. In this HowTo I will create a subsystem of a class called Settings.
   
 
First things to note in subsystem creation (this text is copied from the [https://urho3d.github.io/documentation/1.32/_subsystems.html Urho documentation]):
 
First things to note in subsystem creation (this text is copied from the [https://urho3d.github.io/documentation/1.32/_subsystems.html Urho documentation]):
Line 259: Line 16:
 
Any Object can be registered to the Context as a subsystem, by using the function RegisterSubsystem(). They can then be accessed by any other Object inside the same context by calling GetSubsystem(). Only one instance of each object type can exist as a subsystem.
 
Any Object can be registered to the Context as a subsystem, by using the function RegisterSubsystem(). They can then be accessed by any other Object inside the same context by calling GetSubsystem(). Only one instance of each object type can exist as a subsystem.
   
So, now we can create our own subsystem in just a few steps.
+
So, we can create our own subsystem in just a few steps:
   
1. Create an instance of your desired Object. I am using in this HowTo an Object class called Settings:
+
1. Create an instance of your desired class inheriting from Object. I'm using a class called Settings:
 
Settings* gs = new Settings(context_);
 
Settings* gs = new Settings(context_);
2. Register it to game Context:
+
2. Register it to the Context:
 
context_->RegisterSubsystem(gs);
 
context_->RegisterSubsystem(gs);
So now we have created our own subsystem. We can now use it from any Object class we want, by using GetSubsystem<NameOfSubsystem>()
+
So now we have created our own subsystem. We can now use it from any Object class we want by using GetSubsystem<NameOfSubsystem>()
   
 
Settings* settings = context_->GetSubsystem<Settings>();
 
Settings* settings = context_->GetSubsystem<Settings>();
  +
  +
== How To Enable Post Process Effects ==
  +
Urho comes with several post process effects (screen effects). Some are listed here: http://urho3d.prophpbb.com/topic55.html
  +
  +
You can enable them like this:
  +
RenderPath* effectRenderPath=viewport->GetRenderPath();<br>effectRenderPath->Append(cache->GetResource<XMLFile>("PostProcess/AutoExposure.xml"));<br>effectRenderPath->Append(cache->GetResource<XMLFile>("PostProcess/BloomHDR.xml"));<br>effectRenderPath->Append(cache->GetResource<XMLFile>("PostProcess/FXAA2.xml"));
  +
The linked forum post uses the Clone() function, that crashed when I use it and just appending the effect to the current RenderPath works too.
  +
  +
The difference between the three effects being appended and not: (I configured the effects to be stronger as per default in their .xml so they may be different if you try it.)
  +
[[File:Postprocess effects on.jpg|left|thumb|400x400px]]
  +
[[File:Postprocess effects off.jpg|centre|thumb|400x400px]]

Latest revision as of 01:42, 8 February 2016

How to write text into console[]

Urho implements its own functions for writing text (logging) into console. If you want to use them, first you need to include Log.h

#include "Urho3D/IO/Log.h"

Writing info messages:

LOGINFO(text);

Writing debug messages:

LOGDEBUG(text);

Writing error messages:

LOGERROR(text);

Creating and using your own subsystems[]

If you have a class inherited from Urho's Object class, you can create a subsystem out of it. The subsystems are helpful, for example, when you want to make a class instance available to every other class inheriting from Object. In this HowTo I will create a subsystem of a class called Settings.

First things to note in subsystem creation (this text is copied from the Urho documentation):

Any Object can be registered to the Context as a subsystem, by using the function RegisterSubsystem(). They can then be accessed by any other Object inside the same context by calling GetSubsystem(). Only one instance of each object type can exist as a subsystem.

So, we can create our own subsystem in just a few steps:

1. Create an instance of your desired class inheriting from Object. I'm using a class called Settings:

Settings* gs = new Settings(context_);

2. Register it to the Context:

context_->RegisterSubsystem(gs);

So now we have created our own subsystem. We can now use it from any Object class we want by using GetSubsystem<NameOfSubsystem>()

Settings* settings = context_->GetSubsystem<Settings>();

How To Enable Post Process Effects[]

Urho comes with several post process effects (screen effects). Some are listed here: http://urho3d.prophpbb.com/topic55.html

You can enable them like this:

RenderPath* effectRenderPath=viewport->GetRenderPath();
effectRenderPath->Append(cache->GetResource<XMLFile>("PostProcess/AutoExposure.xml"));
effectRenderPath->Append(cache->GetResource<XMLFile>("PostProcess/BloomHDR.xml"));
effectRenderPath->Append(cache->GetResource<XMLFile>("PostProcess/FXAA2.xml"));

The linked forum post uses the Clone() function, that crashed when I use it and just appending the effect to the current RenderPath works too.

The difference between the three effects being appended and not: (I configured the effects to be stronger as per default in their .xml so they may be different if you try it.)

Postprocess effects on
Postprocess effects off