1.5M ratings
277k ratings

See, that’s what the app is perfect for.

Sounds perfect Wahhhh, I don’t wanna

Floating Origin in Unity

This technique is used when you need a larger area than the standard range in Unity. Transform position loses precision at around 10km (1 unit = 1 meter). Shadow mapping much closer.

The idea is very similar to old-school games, where the character is always in the center of the screen and the world scrolls under him.

Let’s assume I have a huge map, which somehow consists of world tiles, which are dynamically loaded/generated. I also have a character, some enemies and the camera.

First thing is that all these elements get a 64-bit ‘real’ position, so

{ double x; double y; double z; }

Next, there is a class that moves everything to their world position, which is now relative to the floating origin. The floating origin is a 64-bit coord starting at (0, 0, 0). The space is divided into blocks, for example 128x128x128. Whenever the focus leaves block (0, 0, 0), the floating origin is moved.

An example:

NOTE: I’m using w(…) for world space coordinates, which is transform.position. I’m using r(…) for real space coordinates, which are 64-bit.

floating origin = r(0, 0, 0)

focus world pos = w(127, 0, 5) (the focus is the player)

Now the player moves to w(129, 0, 5). This brings the focus block to (1, 0, 0). The floating origin manager will now do the following:

  • set its floating origin to r(128, 0, 0)

  • move the player, the camera, all the enemies and all the terrain tiles by w(-128, 0, 0). Which means they end up at realCoord - floatingOrigin.

Later, the player moves to w(129, 0, 5) again. This brings the focus block to (2, 0, 0) compared real space, or (1, 0, 0) compared to world space. The floating origin manager will now do the following:

  • set its floating origin to r(256, 0, 0)

  • move the player, the camera, all the enemies and all the terrain tiles by w(-128, 0, 0)

Some notes:

  • it matters when the floating origin manager’s update function executes

  • rigidbodies are a problem. You sometimes need to reset their inertia and it’s best to wait moving the floating origin until none of them are awake and colliding

  • world space particles and trails don’t work

unity3d programming gamedev
procedural-generation
procedural-generation:
“ Space-filling tangent field Sometimes, someone comes up with a technique that seems so obvious in retrospect that you wonder why you haven’t seen it before.
It’s not new (this ACM 2008 paper describes the technique) but if...

procedural-generation:

Space-filling tangent field

Sometimes, someone comes up with a technique that seems so obvious in retrospect that you wonder why you haven’t seen it before.

It’s not new (this ACM 2008 paper describes the technique) but if I’ve seen it before I didn’t remember it. Or maybe I just connected to the context in the right way this time.

So, what the heck is a tangent field and how can you use it to generate a city? A vector field is a field of vectors–that is, for each point in the space there is an arrow pointing in a direction, which can be shorter or longer. This should be fairly easy to understand if you’re already familiar with vectors: it’s just a bunch of vectors that each have a position in space. They can be useful for a lot of things, such as wind simulation, pathfinding, and crowd simulation.

A tangent field is a vector field on a surface, where the vectors are in tangent space–for a flat plane they’re lying flat on the ground. The city generator Stijn Raaijmakers made works by taking the weighted average angle (with the weight as 1/(r*r) where r is the distance to each tangent attractor) and generating a building there either along the tangent angle or perpendicular to it. This creates a densely packed space that nevertheless

Packing problems come up quite a bit in procedural generation, especially where you’re trying to fill a space with content and don’t want any unsightly gaps. (There’s non-spatial applications of packing problems too, but we’ll leave that for another day.) Stijn’s generator reminded me that there’s a lot of useful research to draw on out there.

https://twitter.com/bugshake/status/996509163302866945

procedural-generation

Random tiles in repeating texture

I always found it ugly to have a single “ground” texture endlessly repeating in my landscape. Or the same brick making a wall. I figured it would at least be possible to have a single texture with multiple ‘tiles’ in it, like a sprite atlas and use a random noise texture to randomly pick tiles for every instance of the pattern. Sort of like having a “birds and hearts” wallpaper where every image is either a bird of a heart, but picked at random.

I first made a (ugly) 2x2 tile atlas. Here’s the standard unity shader with it repeating 5x5 times:

image

As you can see, every instance of the tile as actually 4 small tiles: plain sand, a grass patch, a rock patch and a boulder. 

Next is the random pattern of 4 values (0, 0.25, 0.5, 0.75) produced to pick tiles from the atlas:

image

This is converted to a uv offset and combined with the local uv offset to translate the material’s uv to the uv within one atlas tile. Here’s what that looks like:

image

Next, and this required me to dig into the standard shader a bit, I had to inject this uv at the right spot to make sure Unity’s standard shader would still be rendering dropshadows, specular etc. It appears to work, but this is only one of many variants of the shader. Still, I am quite happy with this result!

image

With a proper texture set this will look very nice. Especially once I copy the same code for specular and normal maps.

unity3d shader
Finally got something of a geometry shader working. This is like my earlier post, but it takes a mesh as input. So what you’re seeing on the picture is a standard Unity Sphere that is rendered with a material that outputs billboards at the...

Finally got something of a geometry shader working. This is like my earlier post, but it takes a mesh as input. So what you’re seeing on the picture is a standard Unity Sphere that is rendered with a material that outputs billboards at the vertices.

I started with this $GS example but that didn’t work out for me. The quads were rotated wrong and transformations were done twice. So here are the changed I made:

First I passed the inverse of the view-projection matrix to the material like so:

void Update () {
    Camera camera = Camera.main;
    Matrix4x4 mat = (camera.projectionMatrix * camera.worldToCameraMatrix).inverse;
    Material material = GetComponent().sharedMaterial;
    material.SetMatrix("_ViewProjectInverse", mat);
}

Then, in the shader, I applied that to the up and right vectors to find what those were under the current projection:

float3 up = float3(0,1,0);
float3 right = float3(1,0,0);
right = normalize(mul( _ViewProjectInverse, right ));
up = normalize(mul( _ViewProjectInverse, up ));

Then I noticed it didn’t work with transparent bill boards. It would not compare to the z-buffer properly. Obviously the vertices my geometry shader output had the wrong z-value. That clicked for me when I read this stackoverflow comment which did the trick! Here’s the code:

pIn.pos.z = pIn.pos.z/center.w;

Here, pIn is actually one of the output vertices and center is the input vertex. (I notice people mix those names up a lot in shaders because most structs are both input and output, to different stages in the pipeline).

Then, finally I had this problem and the suggested solution worked. Code:

[ContextMenu("ConvertToPointTopology")]
void ConvertToPointTopology()
{
    Mesh mesh = GetComponent().mesh;
    int[] indices = new int[mesh.vertices.Length];
    for (int i = 0; i < indices.Length; i++)
    {
        indices[i] = i;
    }
    mesh.SetIndices(indices, MeshTopology.Points, 0);
}

void Start()
{
    ConvertToPointTopology();   // it will skip the last rows of vertices if you don't do this (because it will only iterate the triangles and convert them to points)
}

Hope this helps someone, I was quite surprised how hard it was to collect all this info. Took me almost a day to get this thing working.

unity3d shader