Big Trouble In Little Blender – 1.1 Initial Modeling Notes

blender-socket

 

My last attempts at 3D modelling were for the XNA games I wrote – 2-3 years ago.
Back then I was using the cut-down version of SoftImage that was offered free to XNA subscribers.

I was never that skilled & what I remember is pretty patchy – So moving onto Blender has provided a steep learning curve. Fortunately the models I’m putting together a pretty simple; allowing me to learn as I build.

I’ve made some notes from my first attempt (which I’ve copied below).
These probably won’t be useful for anyone other than myself. I’m planning on building models as required, rather than in one lump – Which means I’ll probably forget everything in the mean time – To avoid that as much as possible, I’m hoping to use this as a reference point – Allowing me to learn new tools & features of blender; rather than constantly relearning the same tools.

Apologies for any obvious mistakes or omissions – These notes were made as I was learning, and not necessarily as I had learnt.

 

blender-edit

 

Useful site: Blender Reference Manual

Use default view.

Currently using the ‘Blender Game‘ rendering engine.

Mesh Create – On the left, create tab to add meshes
Mesh Tools – On the left, Tools tab to manipulate – translate, rotate, scale etc…

Outlier
On the top of the right column
This is the scene tree – showing models, animations, etc.

Mesh Values
To the left of the outlier, there should be a ‘+‘ tab
Pull this out to show specific values for mesh translation, rotation, scale, etc..
These values are only visible in ‘Edit Mode‘ (see below)
In the main modeling window:

Mouse Buttons
Left mouse button moves the 3D cursor – try not to use the left mouse button
Middle mouse button (pressed & move) – rotates the scene
Middle mouse button (scroll wheel) – zoom in/out
Right mouse button selects (e.g click on a mesh to pick up and move the mesh)

Mesh view Shortcuts
Note – to rotate around a specific object/mesh – press ‘.‘ (full stop on the number pad)
Ensure NUMBLOCK is on.

front/left/top windows are not automatically visible.
To save screen real estate – shortcuts for the main window are:
NUMBLOCK ON &
1 = Front view
7 = Top view
3 = Side view
0 = Camera view

Mode Select
At the bottom of the screen, there is a pull down menu.
When modelling there are two main modes;
Object mode: moves & positions meshes
Edit mode: edit faces/vertices/edges etc…

Selection Type –
With ‘edit mode‘ selected, at the bottom of the screen there are three icons
cube with a small orange dot – select this to edive vertices/nodes
cube with orange line – select this to edit edges
cube with one face orange – select this to edit faces/polygons

Once selected
right click to select specific edge, vertices,face
shift-right click to select multipoles edges, vertices,face, etc.
Useful Shortcuts – Press;
A – Select/Deselect everything
Z – Toggle wireframe on/off
CTRL-I – Inverse selection
K – knife tool, Used to add edges.
(use left mouse button to add nodes)
SPACE to save
GG (G twice) – Reposition a vertex.
E – Extends edge, vertices, face (whichever is selected when E is pressed)
W – With an edge, vertices, face selected this opens the ‘Specials’ menu – subdivides face/bevel, etc…

 


 

Next post: 1.2 Initial UV Unwrapping Notes

Contents page.

 


 

Adventures in Unity – 2.6 Pause & Resume

Official_unity_logo

Whenever a bonus is collected a message box is displayed and the game pauses momentarily.

It’s not a function of the game I particularly like; and I probably wouldn’t use it in the final release – But, since the point of this project is to try things out & help me learn Unity, I figured I’d try and replicate it anyway.

Bounder3b

When displaying the message box, the entire game should pause – including problematic functions like particles/physics/etc.. things controlled by the Unity engine.

Google found me a solution pretty quickly – Time.timeScale

To freeze the game set Time.timeScale = 0 – To resume the game set Time.timeScale = 1.

Time.timeScale is a float variable.
Every loop, Unity multiplies Time.deltaTime against Time.timeScale.
This determines the speed of the game – For anything that references Time.deltaTime – Any update that doesn’t reference Time.deltaTime will be unaffected (Though you really should be using Time.deltaTime).

It’s usually used to pause games & tends to be set with values 0 or 1.
Though it can be used to dynamically slow/speed up gameplay – values higher than 1 may legally require that yakety sax be played at all times.


With everything paused; the next problem was how to animate the message box – (fade in, display for x seconds, fade out).

I can run the animation without using Time.DeltaTime – But then I won’t receive any of the benefits.

Another quick google search identified the solution – A homebrew Time.deltaTime using replacement using Time.realtimeSinceStartup.

Unity documentation explains ‘realtimeSinceStartup returns the time since startup, not affected by Time.timeScale. realtimeSinceStartup also keeps increasing while the player is paused (in the background). Using realtimeSinceStartup is useful when you want to pause the game by setting Time.timeScale to zero, but still want to be able to measure time somehow.

I use The replacement Time.deltaTime as a timer;

  IEnumerator PauseTimer(float delay)
  {

     float start = Time.realtimeSinceStartup;
     timerComplete = false;

     while (Time.realtimeSinceStartup < start + delay)
     {
          yield return null;
     }

     timerComplete = true;

}

Bounder2a.gif


Next Post: 2.7 Mesh Fade

Last post: 2.5b Palette Shift

Contents page.


Adventures in Unity – 2.5b Palette Shift

Official_unity_logo

 

For the C64 version of Bounder, the text colour of the start and end tiles bounces between black and white.

Start-2a2

Goal-2a2

 

I wanted to replicate this in my version – But I wasn’t sure how.

I eventually worked through six potential implementations;

  • Colour Lerp.
  • HBSC
  • Palette Swap
  • Quad Cut-Out
  • Shader
  • Texture Sheet Animation.

 

The first three implementations, were covered in the last post.

  • Colour Lerp.
  • HBSC
  • Palette Swap

This post will expand on the second half;

  • Quad Cut-Out
  • Shader
  • Texture Sheet Animation.

 


 

4. Quad Cut-Out

This method uses two textures – One ‘base’ texture displays the standard start/goal tile texture – The other ‘top’ texture; is a copy of the top face of the tile texture; the face showing the start/goal banner image & text – with everything except the letters (start & goal) removed (transparent instead).

 

QuadTexture2a
Left image shows the base tile texture.
Right image shows the quad texture for the same tile.

 

The base texture is used to draw the tile model. The top texture is applied to a quad – a child of the tile – which is positioned just over the top of the base tile.

The colour lerp code is then applied to the the top texture – ensuring only the text changes colour while the background remains the same.

How this works…

First a quad (this will be created locally) and a material holding the quads texture (this will be passed as a reference in the Unity editor) are defined as global variables;

GameObject quad;
public Material material1;

In start, the quad is created & configured.

if (type == Type.Enter || type == Type.Exit)
{

     quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
     rend = quad.GetComponent();
     rend.material = material1;
     quad.transform.parent = transform;
 
      quad.transform.Rotate(90, 0, 0);

}

Since this method uses the colour lerp code, we need somewhere to hold the current colour.

public Color lerpedColor = Color.white;

Then every loop, the position of the quad is updated (to keep up with the tile as it scrolls down the screen). The next colour for the banner flash is calculated and assigned to the quads texture.

quad.transform.position = new Vector3(transform.position.x, transform.position.y + 0.275f, transform.position.z);
lerpedColor = Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time, 1));
quad.GetComponent().material.color = lerpedColor;

This works well, but it does require a quad to be created (another draw call per loop), as well as an extra texture (more work & extra complications)  – Neither is a big issue, but it’s more complications than I think should be required.

I think the result looks fine, though I suspect it would look much better if I’d removed the text from the base texture – As it is, the base text seems to interfere – giving a slight glow – behind the flashing letters of the quads texture.

QuadCutout-1b

 


 

5. Shader

The original version of the shader, I  checked the colour of the current _MainTex pixel – & changed any which were white. This worked horribly – It seems that before I got to the texture it has been already modified somewhere along the pipeline.

2016-08-10-1945-00---adaptive2

Instead I take a more long-winded approach.

How this works…

Alongside the auto-generated input variables (_Color, _MainTex, _Glossiness & _Metallic – all generated by Unity when creating the shader).

The custom input variables are added;
_Color1 – Used to set the start colour in the loop (white)
_Color2 – Used to set the start colour in the loop (black)
_CutOutTex – From the Quad Cut-Out method, this is a copy of _MainTex, but with everything except the letters (start & goal) removed (transparent instead).

 

ShaderTexture2a
Left image shows _MainTex.
Right side shows _CutOutTex

In the surf method, after the colour of the _MainTex is sampled, the equivalent colour from _CutOutTex is identified.

If the alpha values of the sampled _CutOutTex colour is > 0 (not transparent) – Then this is a letter (in the start/goal banner) which needs to be colour shifted – The current colour shift colour is calculated and drawn to the screen.

If the alpha values from the _CutOutTex colour is <= 0 (transparent) – Then this is not part of the banner text and the sample from _MainTex (the default banner texture) is drawn..

Shader "Custom/NewSurfaceShader" {
     Properties {
          _Color ("Color", Color) = (1,1,1,1)
          _MainTex ("Albedo (RGB)", 2D) = "white" {}
          _Glossiness ("Smoothness", Range(0,1)) = 0.5
          _Metallic ("Metallic", Range(0,1)) = 0.0
          _CutOutTex("CutOut", 2D) = "white" { }
          _Color1("Color1", Color) = (1.0, 0.0, 0.0, 1.0)
          _Color2("Color2", Color) = (0.0, 0.0, 1.0, 1.0)
          _Speed("Speed", float) = 0.2
     }

     SubShader {
          Tags { "RenderType"="Opaque" }
          LOD 200
		
          CGPROGRAM
          // Physically based Standard lighting model, and enable shadows on all light types
          #pragma surface surf Standard fullforwardshadows

          // Use shader model 3.0 target, to get nicer looking lighting
          #pragma target 3.0

          sampler2D _MainTex;

          struct Input {
               float2 uv_MainTex;
          };

          half _Glossiness;
          half _Metallic;
          fixed4 _Color;
          sampler2D _CutOutTex;
          uniform fixed4 _Color1;
          uniform fixed4 _Color2;
          uniform float  _Speed;

          void surf (Input IN, inout SurfaceOutputStandard o) {
          // Albedo comes from a texture tinted by color
          fixed4 c = tex2D (_MainTex, IN.uv_MainTex);
          fixed4 c2 = tex2D(_CutOutTex, IN.uv_MainTex);

          if (c2.a > 0) {
               fixed4 c3 = lerp(_Color1, _Color2, abs(fmod(_Time.a * _Speed, 2.0) - 1.0));

               //if (c.r > 0.99 && c.g > 0.99)
                    c = (c * c3) * _Color;
               }
               else
                    c = c * _Color;

               o.Albedo = c.rgb;
               // Metallic and smoothness come from slider variables
               o.Metallic = _Metallic;
               o.Smoothness = _Glossiness;
               o.Alpha = c.a;
          }
          ENDCG
     }

     FallBack "Diffuse"
}

 

I haven’t written anything for shaders in a number of years – last time was HLSL for XNA. So the learning curve here was for both figuring out nity & figuring out Unity’s shaders. I’m not particularly happy with the code I’ve put together – I’m very confident there ere are far more succinct ways to achieve the same result – But the the animation looks okay.

 

Shader2-1b

 


 

6. Texture Sheet Animation.

This is the method I’ve decided to use – It works almost like a traditional animation/flip book – using a series of images, each slightly different from the next – so when they are swapped a speed they appear to show movement.

In this case, the models texture is split into a grid – Each cell of the grid contains a frame of the animation (in this case 8 frames are used).
The model is drawn referencing one cell of the grid\one frame of the animation (UV mapping is explained badly in my last post).
Code (either a Unity script or shader) is used as a timer – to determine when to change to the next frame.

 

withframesLarge
Animation texture – With individual frames/cells highlighted.

 

For the code, I referenced Unity3D wiki – Animating Tiled texture
The page offers six code examples – one java/five C#

I had the most success using AnimateTiledTexture & AnimateSpriteSheet classes
Setting with the AnimateTiledTexture code because it was the easiest for me to tweak in order for it to animate the way I needed…
The goal/start texture have frames from white to black – I use ping-pong setup to run backwards and forward through the animation frames – from white to black, then in reverse from black to white – halving the final texture size.

 

With the code in place I needed to configure the assets – This was much harder to setup than expected – which, for a modern 3D gaming environment was a little disappointing – setting up was more guess work than design – I found it is far easier to setup an animated texture in (the ten year old) XNA.

With first attempt – I made the mistake of using a non-power or two sized texture – This resulted in animated tiles which were blurry, and jitter – jumping around as it forced through each frame – It looked pretty horrible

2016-08-10-2012-47---adaptive2

The image quality improved after resizing the texture to a power of two
and (in the textures Material settings) defining the ‘Tiling’ values to match the frame size
(8 frames in total – 4 columns, 2 rows – Tiling X = 0.25 Y = 0.5 )

This produced a noticeably sharper – non-jittery texture – but displayed a lot of artifacts.
2016-08-10-2017-57---adaptive2
I tried changing the text import settings to advanced; turning off mipmaps, mapping, etc… anything that could be turned off was turnd off – setting the wrap mode to clamp, filter to point – none of which had any effect.

What ultimatly worked for me was setting the texture type to cursor.
I have no idea why cursor settings resolve the issue – or if the next update will break it & put me back to square one.
But for now I have nice, clean, sharp animated start/goals tiles

2016-08-12-2007-58---2

 


 

Next post: 2.6 Pause & Resume

Last post: 2.4 Edge Padding

Contents page.

 


 

Adventures in Unity – 2.5a Palette Shift

Official_unity_logo

 

For the C64 version of Bounder, the text colour of the start and end tiles bounces between black and white.

Start-2a2

Goal-2a2

 

I wanted to replicate this in my version – But I wasn’t sure how.

I eventually worked through six potential implementations;

  1. Colour Lerp.
  2. HBSC
  3. Palette Swap
  4. Quad Cut-Out
  5. Shader
  6. Texture Sheet Animation.

 

This post covers the first three attempts;

  • Colour Lerp.
  • HBSC
  • Palette Swap

 

The next post will expand on the final three.

  • Quad Cut-Out
  • Shader
  • Texture Sheet Animation.

 


 

1. Colour Lerp

The most straight forward approach; it uses the built in method color.lerp alongside Mathf.PingPong to bounce colours between black & white – The result is applied to the start/end textures.

How this works…

The Color lerpedColor holds the colour to be displayed.

public Color lerpedColor = Color.white;

Every loop, color.lerp is used to calculate the current colour – Mathf.PingPong ‘animates’ the colour – bouncing it between (in this case) black & white.

lerpedColor = Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time, 1));
GetComponent<Renderer>().material.color = lerpedColor;

The end results look great; but unsurprisingly the entire texture changes colour, not just the text.

 

ColourLerp-1b

 


 

2. HBSC

Using the HSBColor class, provided in the Unity3D wiki.

The wiki description explains that HSBColor ‘provides a Hue/Saturation/Brightness/Alpha color model in addition to Unity’s built in Red/Green/Blue/Alpha colors. It is useful for interpolating between colors in a more pleasing fashion

Rather than following their usage/setup instructions, I instead just stripped the [System.Serializable] tag & used the code like a standard class.

How this works…

Define a global HSBColor object.

public float time = 2.0f;
private HSBColor hsbc;

Which is initialized in the start method.

hsbc = HSBColor.FromColor(color);

Then, every loop the next colour to display is calculated (I think it rotates through six different colours)

hsbc.h = (hsbc.h + Time.deltaTime / time) % 1.0f;
GetComponent().material.color = HSBColor.ToColor(hsbc);

The result may give you a headache;

HSBC-1a

 


 

3. Palette Swap

This reuses the Palette Swap code I wrote for the Spectrum tiles – I really like the effect – (Though I’d need to figure out why some white pixels have turned yellow when being displayed). I’d expected a huge performance hit with this method, but when tested, the game ran at a good pace.

How this works…

Each tile prefab has a material component attached. Each material component has a texture attached. This is the texture used when drawing the tile to screen.

Since the intention is to change the colours of the materials texture, the script keeps a master copy that is unaffected by the paletteSwap code – paletteSwap code uses this master copy as a reference every loop/colour update.

(Rather than using a reference textures; the script could instead, store a copy of the last colour applied and pass that to the paletteSwap code to change every loop – Unfortunately the banner letters lerp between black and white – & the texture has some black pixels in place which may accidently get caught up in the animation).

 

First the script defines a global texture to be used to hold the master/base texture;

Texture2D paletteSwapTexture;

A copy of this texture is assigned to paletteSwapTexture – (I’m guessing it’s a copy and not a reference, since changing the colours in rend.material.maintexture has no effect on the contents of paletteSwapTexture)

rend = GetComponent();
paletteSwapTexture = (Texture2D) rend.material.mainTexture;

The ‘toColour‘ colour array is defined – This is used to identify which colour in the texture to look for (index 0) & what colour to change it to (index 1).

Color[] toColour = new Color[2] { Color.white, Color.white };

Then, every loop ‘Colour Lerp’ (& Mathf.PingPong) calculates the next colour to display – This is then passed to the PaletteSwap method.

toColour[1] = Color.Lerp(Color.white, Color.black, Mathf.PingPong(Time.time, 1));
Renderer rend = GetComponent();
rend.material.mainTexture = PaletteSwap(toColour, paletteSwapTexture);

Which swaps the colours and returns a new Start/Goal tile texture;

Texture PaletteSwap(Color[] toColours, Texture2D inTexture)
{

     Texture2D source = inTexture;
     Texture2D destination = new Texture2D(source.width, source.height);

     //---

     Color[] pixels = source.GetPixels(0, 0, source.width, source.height);

     int pixelsLength = pixels.Length;
     for (int counter = 0; counter < pixelsLength; counter++)      {           //if (pixels[counter] == toColours[0])           if (pixels[counter].r >= 0.98 && pixels[counter].g >= 0.99)
          pixels[counter] = toColours[1];

     }

     destination.SetPixels(0, 0, destination.width, destination.height, pixels);
     destination.Apply();

     //---

     return (Texture)destination;

     //---

}

Which ultimatly looks like this – Nice effect, pain in the arse yellow pixels;

PaletteSwap-1b

 


 

Next post: 2.5a Palette Shift

Last post: 2.4 Edge Padding

Contents page.

 


 

Adventures in Unity – 2.4 Edge Padding

Official_unity_logo

The levels in this project are made up of tiles – I’d working with about four different tile types to when constructing the basic game framework;

 

TileFloorA
1. Default Floor Tile
TileBonusA
2. Bonus Tile
TileStartA
3. Start Tile
TileGoalA
4. Goal Tile

 

The floor tiles looked great – But the start, goal & bonus tiles were a little out of place & had seams showing;

Seams1

 


 

Googling around, I discovered I wasn’t the first person to have this issue – & everyone seems to have their own resolution…

Some people offered sensible first steps advice, such as ensuring the in the texture setting clamp rather than repeat was selected – Others suggesting ideas like merging the tiles into one model, drawing with a custom shader, deleting all offscreen model faces, recalculating the models normals, turning off anti aliasing, turning off mip-mapping, etc..

After trying, a failing with quite a range potential solutions; what eventually worked for me was edge padding.

Edge padding, as the Unity docs explain;
Unity renders a scene using a process known as downsampling which uses texture filtering to smoothly render the textures. If the ‘gutters’ (blank areas between UV’s) have colors/transparencies that are very different from the colors inside the UV’d areas, then those colors can ‘bleed’ together which creates seams on the model. This problem will also occur when neighbouring UV shells have different colors; as the texture is downsampled eventually those colors start to mix.

To avoid this problem, edge padding should be added to the empty spaces around each UV shell. Edge padding is the process of dilating the pixels along the inside of the UV edge to spread the colors outward, forming a border of similar colors around the UV shell.

 


 

UV Mapping is the process of projecting a texture onto a 3D object – It identifies what area in a texture/image a model faces uses as it’s texture.

So, for example, in the image below the right side shows a model with one face selected (outlined in orange & shaded slightly) .

The left hand side shows the texture being used – The orange square (on the top left quarter) shows what part of the texture will be used to ‘paint’ the select face

UV Mapping 2

 


 

In my case, my original textures looked like this;

TileBasicX1B

My uv texture mapping looked like this;

TileBasicX2B

The problem was the UV areas I’d setup were too tight – so when Unity rendered the textures onto the models, it would sometime collect colour information outside my defined UV area – causing seams to be displayed.

The fix was to reposition the UV mapping & add a border to accommodate the potential bleeding effect.

TileBasicYB
My initial attempt at edge padding resolved 90% of the problem – but I found the enter/exit tiles didn’t quite match up.

Seams2

 


 

For ‘complex’ textures, instead of continuing that edge colour, I instead just continued the pattern.

Instead of using this;

TileBasicYB

I setup the texture to look like this;

TileBasicZB

Which worked perfectly;

Seams3

 


 

Note: My textures & UV mapping are pretty simple- I used that to my advantage when edge padding – padding far more of the texture than I really needed to.

The amount of padding actually required depends on the size of the texture used – (I think the smaller the texture, the higher the chance of seams)- For this game, my textures are 64×64 – I found I needed a 3-4 pixel buffer to completely remove seams.

 


 

Ultimately, edge padding provides a satisfying fix – going forward, as long as I keep padding in mind when creating textures, it should have almost no further impact on this project.

 


 

Next post: 2.5b Palette Shift

Last post: 2.3 Palette Swap

Contents page.