Personal Projects

Hxaria, Infinite Terrain [HaXe, WebGL,dat.GUI]

So I have been working on my “Terraria like Terrain” project “Hxaria” again.

Following on from the last post, I have now made it so that each particle can have its texture changed. This completes the functionality required to render each tile as a point sprite, as talked about in my previous post.

The way it works is that the entire world is recorded in a 2×2 array Tilemap. This 2×2 array holds a single Tile object for every single tile in the world:

  1. class Tile
  2. {
  3. public var x : Int;
  4. public var y : Int;
  5. public var type : Int;
  6.  
  7. public function new(x:Int, y:Int, type:Int) { this.x = x; this.y = y; this.type = type; }
  8. }

 

When the TileRenderer needs to render it asks this Tilemap for a Tile that represents that screen coordinate, the Tilemap then offsets the position due to the camera movement and returns a tile. So it looks something like:

The tile type is then passed to the shader in attribute buffers per point sprite / tile along with all the tiles which are stored on a single texture:

The shader then performs the neccessary calculations to work out what the UV coordinate in the texture. The Vertex Shader:

  1. uniform float amplitude;
  2. uniform float tileSize;
  3. uniform float texTilesWide;
  4. uniform float texTilesHigh;
  5. uniform float invTexTilesWide;
  6. uniform float invTexTilesHigh;
  7.  
  8. attribute float size;
  9. attribute vec3 customColor;
  10. attribute float tileType;
  11.  
  12. varying vec3 vColor;
  13. varying vec2 vTilePos;
  14.  
  15. void main()
  16. {
  17. vColor = customColor;
  18.  
  19. float t = floor(tileType/texTilesWide);
  20. vTilePos = vec2(tileType-(t*texTilesWide), t); // +(.5/tileSize)
  21.  
  22. gl_PointSize = size;
  23. gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
  24. }

 

And the Fragment Shader:

  1. uniform vec3 color;
  2. uniform sampler2D texture;
  3. uniform float invTexTilesWide;
  4. uniform float invTexTilesHigh;
  5.  
  6. varying vec3 vColor;
  7. varying vec2 vTilePos;
  8.  
  9. void main()
  10. {
  11. vec2 uv = vec2( gl_PointCoord.x*invTexTilesWide + invTexTilesWide*vTilePos.x, gl_PointCoord.y*invTexTilesHigh + invTexTilesHigh*vTilePos.y);
  12.  
  13. gl_FragColor = texture2D( texture, uv );
  14. }

So it works in a way very much like a raster engine. You only have to render as many particles as the screen can contain.

If the screen area moves beyond the extent of the Tilemap then more tiles are randomly generated:

The new tiles are randomly selected from 4 different types, Dirt, Gold, Diamonds and Rock. I have added some controls to the demo that allow you to tweak these values to demonstrate the random tile generation:

The UI may look familiar to people that have seen any experiments anyone who has worked with Three.js before, its the very popular dat.GUI. Its a really simple library written in javascript for creating controls that can be used to tweak experiments, perfect for me!

To get dat.GUI to work with haxe, I used the awesome Extern feature of HaXe. This means that all I have to do is provide a stub interface to dat.GUI rather than a full implementation in haXe. This is great as it allows me to rapidly begin to use the library but also have the type safety of HaXe. It didnt take long to stub out the bits of the library I needed in an extern:

  1. package dat;
  2.  
  3. /**
  4.  * ...
  5.  * @author Mike Cann
  6.  */
  7.  
  8. extern class GUI
  9. {
  10.  
  11. public function new(options:Dynamic) : Void;
  12. public function add(options:Dynamic, name:String) : GUI;
  13. public function name(value:String) : GUI;
  14. public function min(value:Float) : GUI;
  15. public function max(value:Float) : GUI;
  16. public function step(value:Float) : GUI;
  17. public function onFinishChange(f:Void -> Void) : GUI;
  18. public function listen() : GUI;
  19. }

Then I used it like:

package ;
import dat.GUI;
 
/**
 * ...
 * @author
 */
 
class GUIManager
{
	public var goldChance : Float;
	public var rockChance : Float;
	public var diamondsChance : Float;
	public var mapWidth : Int;
	public var mapHeight : Int;
 
	private var gui : GUI;
	private var game : Game;
 
	public function new(game:Game)
	{
		this.game = game;
 
		gui = new GUI( { height : 5 * 32 - 1 } );
 
		goldChance = game.tilemap.goldSpawnChance;
		rockChance = game.tilemap.rockSpawnChance;
		diamondsChance = game.tilemap.diamondsSpawnChance;
		game.tilemap.mapResized = onTilemapResized;
		mapWidth = 0;
		mapHeight = 0;
 
		gui.add(this, 'goldChance').name("Gold").min(0).max(1).step(0.001).onFinishChange(function() { game.tilemap.goldSpawnChance = goldChance; } );
		gui.add(this, 'rockChance').name("Rock").min(0).max(1).step(0.001).onFinishChange(function() { game.tilemap.rockSpawnChance = rockChance; } );
		gui.add(this, 'diamondsChance').name("Diamond").min(0).max(1).step(0.001).onFinishChange(function() { game.tilemap.diamondsSpawnChance = diamondsChance; } );
		gui.add(this, 'mapWidth').listen();
		gui.add(this, 'mapHeight').listen();
	}
 
	private function onTilemapResized(mapW:Int, mapH:Int):Void
	{
		mapWidth = mapW;
		mapHeight = mapH;
	}
}

Simples!

Anyways you can check the final result out on this page: http://mikecann.co.uk/projects/hxaria/02/
(Click and drag to move the camera about)

I have also uploaded a quick video too:

I have also uploaded the source again to my github page: https://github.com/mikecann/Hxaria
(I have also created a tag, incase the source changes in the future)

Next up, lighting!

Hxaria, Terraria like terrain in HaXe and WebGL

I woke up the other day thinking about Terraria. No idea why as I haven’t played it in ages, but its the type of game I really enjoy so it must have snuck into my dreams during the night.

Anyways, it got my thinking if it would be possible to make something similar to it in the browser using WebGL. For those not aware of Terraria, it looks something like this:

To produce the above you need several layers of tilemaps (background, water, foreground etc) that can potentially change every single frame (due to lighting environment effects etc). To do that at 1680×1050 at 16×16 per tile with only one layer changing each frame will be 6800 tile draws per frame.

Having calculated that I got thinking about the best way to render lots of tiles.

My first thought was to render each tile as a separate quad. That would certainty work, however it would mean that for each tile I would need 4 vertices, times that by say 4 layers that’s 108,800 vertices. Its not a massive massive amount but sizable enough for me to wonder if there was a more efficient way.

My next thought was that I could share vertices by using vertex indices in a triangle-strip, that way at best each tile will only require just over one vertex per tile then arrange them in a lattice so that the vertices are shard between tiles:

This would then only require about 27,200 vertices which is really nice. I was hover having difficulties imagining how I would reference each tile individually in the shader so I could apply texture and color transformations and started wondering if another technique might work..

Having recently done some work with Point Sprite Particles I knew that the GPU was really good at rendering Point Sprites. So I thought to myself, why not just make each tile a point sprite. That way I could then represent each tile as a vertex then I could pass custom properties such as texture and color to the shader as vertex buffer attributes. Doing it this way means that you only need as many vertices as there are visible tiles (about 27,200 for 4 layers) and I can reference each tile individually in the attribute buffer.

So armed with the theory I set to work bashing out some code. Having worked with raw WebGL in haXe on my last few experiments I decided I didnt want to go through all that pain again just for the sake of a little more performance, so I decided to give Three.js another go in HaXe. Thankfully this time I was treading a known path so I could learn from existing threejs point-sprite particle samples. The bulk of the custom particle system logic I took from this rather excellent sample:

(http://alteredqualia.com/three/examples/webgl_custom_attributes_particles.html)

So once I had the project setup it took me no time at all to bash out a sample that showed that I could easily have 27k+ tiles changing size and color each frame:

http://mikecann.co.uk/projects/Hxaria/01/index.html

Pretty aint it?

What you are looking at is 40,000 point sprites changing to a random colour and size every frame, well above the 27k needed. As part of my testing I found that it can actually handle a lot more (hundreds of thousands) of individually updating tiles!

Im planning to continue work on this sample, my next step is to get each particle using a different tile type and changing each frame.

I have uploaded the source to github for your perousal: https://github.com/mikecann/Hxaria

Enjoy!

 

Terrainicles [WebGL & HaXe]

I have been playing with this thing, tweaking it, making changes for weeks. Theres so many different things I want to add. Different options, scenarios, optimisations etc. I decided however just to follow the ‘release early and often’ mantra and get this thing out now.

Before I go any further check out what im talking about here:

http://mikecann.co.uk/projects/WebGLTerrainicles/
(You will need a WebGL compatible browser, that means no IE) 

Its a continuation of my earlier work on GPU particles using WebGL and HaXE. Im trying to emulate some work I did years ago in XNA, on the LieroXNA project.

It uses the same techniques for updating and rendering particles entirely on the GPU as my previous post. What that means is that is possible have millions of particles interacting updating and rendering simultaneously as all the operations are performed on the GPU.

What I have added this time is another texture for the particles to collide with as they move. I was originally working with the same dirt and grass texture as my XNA project but I thought as it was Halloween I would get into the spirit a little ;)

There are several options on the right hand side that can be used to tweak the properties of the simulation. I spent alot of time playing around with these, there are some really cool effects you can achieve with just simple modifications.

There are so many things I could add to improve this. You can see some of them in a video I made years ago:

There we have some cool stuff like Bloom, forces and multiple rendering layers going on. It would be nice to get those in this sample too.

For now however I think im going to have a break from this sample. I have spent quite a few weeks to get to this point so far, and I think I need a break for a little bit so I can work on other things. I may come back to it soon tho If people are interested or if (probably more likely) I think of some ‘cool new thing’ that will ‘only take 5 mins’.

I have uploaded the source for this sample to Github for people to lookat/fork if they wish:

https://github.com/mikecann/WebGLTerrainicles

Enjoy!

 

 

 

1 2 3 4 5 6 7 8 9  Scroll to top